-
Notifications
You must be signed in to change notification settings - Fork 28
/
Win32.Ransomware.Venis.Unpacker.py
118 lines (94 loc) · 3.39 KB
/
Win32.Ransomware.Venis.Unpacker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import sys
import pype32
import time
from datetime import datetime
from pype32 import consts
from capstone import *
from capstone.x86_const import *
XOR_KEY = "0xDEADBEEF"
KEY_LEN = 0x0A
def get_imp_function_address(p, func_name):
impts = p.ntHeaders.optionalHeader.dataDirectory[consts.IMPORT_DIRECTORY]
func_addr = 0
indx = 0
for module in impts.info:
for iat_entry in module.iat:
if iat_entry.name.value == func_name:
func_addr = module.firstThunk + p.ntHeaders.optionalHeader.imageBase + indx * 4
break
indx += 1
return func_addr
def get_xor_data_offset(text_section_code, func_addr):
offset = -1
md = Cs(CS_ARCH_X86, CS_MODE_32)
md.detail = True
call_found = False
SIZE = len(text_section_code)
nop_cnt = 0
for ins in md.disasm(text_section_code, SIZE):
if ins.mnemonic == "call" and ins.operands[0].mem.disp == func_addr:
call_found = True
call_addr = ins.address
if call_found and ins.mnemonic == "nop":
nop_cnt += 1
if call_found and nop_cnt >= 0x26:
if ins.address > call_addr:
if ins.mnemonic == "add" and ins.operands[0].type == X86_OP_REG and (ins.operands[0].reg == X86_REG_ESI or ins.operands[0].reg == X86_REG_EBX) and ins.operands[1].type == X86_OP_IMM:
offset = ins.operands[1].value.imm.real
break
return offset
def write_file(filename, data):
fd = open(filename, "wb")
fd.write(data)
fd.close()
def get_section_data(p, section_name):
data = ''
for i in range(len(p.sectionHeaders)):
if p.sectionHeaders[i].name.value.find(section_name) >= 0:
data = p.sections[i]
break
return data
print "+++ Unpacker for Venis ransomware +++\n"
print "-- written by +NCR/CRC! [ReVeRsEr]"
print "crackinglandia[at]gmail.com\n"
if len(sys.argv) < 2:
print "Usage: %s <filename>" % __file__
sys.exit(1)
filename = sys.argv[1]
print "[-] Processing %s" % filename
p = pype32.PE(filename)
print "[-] Getting .text section data..."
text_section_code = get_section_data(p, ".text")
print "[-] Done."
func_name = "SizeofResource"
print "[-] Searching %s function on the IMPORT_DIRECTORY..." % func_name
func_addr = get_imp_function_address(p, func_name)
if func_addr != 0:
print "[-] %s found at 0x%x" % (func_name, func_addr)
print "[-] Searching for XORED_DATA_OFFSET value..."
XORED_DATA_OFFSET = get_xor_data_offset(text_section_code, func_addr)
if XORED_DATA_OFFSET != -1:
print "[-] XORED_DATA_OFFSET found: 0x%x" % XORED_DATA_OFFSET
print "[-] Looking for .rsrc section..."
rsrc_section_data = get_section_data(p, ".rsrc")
if rsrc_section_data != '':
print "[-] .rsrc section found. Starting decryption..."
print "[-] Searching encrypted data magic value..."
magic_offset = rsrc_section_data.find("BM6")
if magic_offset >= 0:
print "[-] Magic value found at: 0x%x" % magic_offset
rsrc_section_data = rsrc_section_data[magic_offset+XORED_DATA_OFFSET:]
data_len = len(rsrc_section_data)
result = []
for i in range(data_len):
b = ord(rsrc_section_data[i]) ^ ord(XOR_KEY[i%KEY_LEN])
result.append(chr(b))
d = ''.join(result)
f = "unpacked_%s_%s.bin" % (datetime.now().strftime('%Y.%m.%d-%H.%M.%S'), filename)
print "[-] Saving decrypted data to %s" % f
write_file(f, d)
print "[+] Done."
"""
References:
- https://www.arbornetworks.com/blog/asert/mindshare-statically-extracting-malware-c2s-using-capstone-engine/
"""