Skip to content

Commit 28a41d7

Browse files
author
Corb3nik
committed
Adds working 64bit malware hunter
1 parent 89f6cac commit 28a41d7

File tree

4 files changed

+32
-18
lines changed

4 files changed

+32
-18
lines changed

analysis_tools/opcache_disassembler.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ def create_ast(self, filename):
179179

180180
# Main OP array
181181
for idx, opcode in enumerate(main_op_array['opcodes']):
182-
opcode = OPcode(str(idx), opcode, main_op_array, opcache, is_64_bit)
182+
opcode = OPcode(str(idx), opcode, main_op_array, opcache, self.is_64_bit)
183183
ast.paste("main_op_array", opcode)
184184

185185
# Function Table
@@ -248,8 +248,8 @@ def print_syntax_tree(self, ast):
248248

249249
ast.show(key=lambda a: "")
250250

251-
def disassemble(self, file, is_64_bit):
252-
disassembler = OPcacheDisassembler(is_64_bit)
251+
def disassemble(self, file):
252+
disassembler = OPcacheDisassembler(self.is_64_bit)
253253
ast = disassembler.create_ast(file)
254254
final = ""
255255
final += disassembler.convert_branch_to_pseudo_code(ast, 'class_table', 0)

analysis_tools/opcache_malware_hunt.py

+19-11
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
# Copyright (c) 2016 GoSecure Inc.
44

55
from opcache_disassembler import OPcacheDisassembler
6-
from opcache_parser import OPcacheParser
6+
import hashlib
7+
import opcache_parser
8+
import opcache_parser_64
79
import sys
810
import os
911
import subprocess
@@ -232,7 +234,7 @@ def compare_parsed_files(file1, file2):
232234

233235
return True
234236

235-
def create_diff_report(file1, file2, report_name, from_desc, to_desc, is_64_bit):
237+
def create_diff_report(file1, file2, file_name, from_desc, to_desc, is_64_bit):
236238

237239
""" Create a report showing the differences between two files
238240
@@ -252,14 +254,16 @@ def create_diff_report(file1, file2, report_name, from_desc, to_desc, is_64_bit)
252254
html_differ = difflib.HtmlDiff()
253255

254256
# Generate the report and write into a file
255-
report_name = report_name.replace("/", "%2f") + '.html'
256-
with open(hunt_report + "/" + report_name, "w") as f:
257-
f.write(html_differ.make_file(disassembled_1, disassembled_2, from_desc, to_desc))
257+
file_name = file_name.replace("/", "%2f") + '.html'
258+
hash_name = hashlib.sha1(file_name).hexdigest()
259+
with open(hunt_report + "/" + hash_name + ".html", "w") as f:
260+
content = html_differ.make_file(disassembled_1, disassembled_2, from_desc, to_desc)
261+
f.write(content)
258262

259263
# Return the name of the report
260-
return report_name
264+
return (file_name, hash_name + ".html")
261265

262-
def create_index(report_names):
266+
def create_index(file_names, report_names):
263267

264268
""" Create an index file containing the list of all the reports generated by create_diff_report
265269
@@ -279,9 +283,9 @@ def create_index(report_names):
279283

280284
# The list of links towards each report
281285
body = "<ul>"
282-
for report_name in report_names:
286+
for index, report_name in enumerate(report_names):
283287
link = report_name.replace("%2f", "%252f")
284-
link_name = report_name.replace("%2f", "/")[:-5]
288+
link_name = file_names[index].replace("%2f", "/")[:-5]
285289
body += "<li><a href='{0}'>{1}</a></li>".format(link, link_name)
286290
body += "</ul>"
287291

@@ -317,8 +321,10 @@ def show_help():
317321
is_64_bit = False
318322
if architecture == "-a64":
319323
is_64_bit = True
324+
OPcacheParser = opcache_parser_64.OPcacheParser
320325
elif architecture == "-a32":
321326
is_64_bit = False
327+
OPcacheParser = opcache_parser.OPcacheParser
322328

323329

324330
# Setup a new phpini for compilation
@@ -365,13 +371,15 @@ def show_help():
365371
print ""
366372
print "Potentially infected files : "
367373
reports = []
374+
file_names = []
368375
for idx, file, new_cache_file in flagged_files:
369376
print " - " + file
370377

371-
report = create_diff_report(new_cache_file, file, opcache_files[idx], "Source Code", "Cache", is_64_bit)
378+
(file_name, report) = create_diff_report(new_cache_file, file, opcache_files[idx], "Source Code", "Cache", is_64_bit)
372379
reports += [report]
380+
file_names += [file_name]
373381

374-
create_index(reports)
382+
create_index(file_names, reports)
375383
else:
376384
print "No infected files found."
377385

analysis_tools/opcache_parser.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ def Z_Val(name, callback = None, unserialize = True):
2121
if not callback:
2222
callback = Empty
2323

24+
callback_name = ""
25+
if callback == unserialize_zend_function:
26+
callback_name = "op_array"
27+
elif callback == unserialize_class:
28+
callback_name = "class"
29+
2430
return name / Struct(Zend_Value("value"),
2531
"u1" / Struct("type" / Byte,
2632
"type_flags" / Byte,
@@ -29,13 +35,13 @@ def Z_Val(name, callback = None, unserialize = True):
2935
),
3036
"u2" / Int32ul,
3137

32-
If(lambda z: z.u1.type == 6 and unserialize,
38+
"string" / If(lambda z: z.u1.type == 6 and unserialize,
3339
Pointer(lambda z: (z.value.w1 & ~1) +
3440
(meta['mem_size'] if meta['str_size'] != 0 else 0) +
3541
Meta.sizeof(),
3642
Zend_String("string")
3743
)),
38-
If(lambda z: z.u1.type == 17 and unserialize,
44+
callback_name / If(lambda z: z.u1.type == 17 and unserialize,
3945
Pointer(lambda z: z.value.w1 + Meta.sizeof(), callback()))
4046
)
4147

analysis_tools/opcache_parser_64.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ def Z_Val(name, callback = None, unserialize = True):
3535
),
3636
"u2" / Int32ul,
3737

38-
If(lambda z: z.u1.type == 6 and unserialize,
39-
"string" / Pointer(lambda z: (z.value.w1 & ~1) +
38+
"string" / If(lambda z: z.u1.type == 6 and unserialize,
39+
Pointer(lambda z: (z.value.w1 & ~1) +
4040
(meta['mem_size'] if meta['str_size'] != 0 else 0) +
4141
Meta.sizeof(),
4242
Zend_String("string")

0 commit comments

Comments
 (0)