Skip to content

Commit 7eeabb8

Browse files
committed
Xlm Macro deobfuscation
1 parent d78926f commit 7eeabb8

File tree

7 files changed

+119
-1
lines changed

7 files changed

+119
-1
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import logging
2+
3+
from api_app.script_analyzers.classes import FileAnalyzer
4+
from celery.exceptions import SoftTimeLimitExceeded
5+
import subprocess
6+
from pathlib import Path
7+
import json
8+
9+
logger = logging.getLogger(__name__)
10+
11+
12+
class XlmMacroDeobfuscator(FileAnalyzer):
13+
def set_config(self, additional_config_params):
14+
self.passwords_to_check = []
15+
additional_passwords_to_check = additional_config_params.get(
16+
"passwords_to_check", []
17+
)
18+
if isinstance(additional_passwords_to_check, list):
19+
self.passwords_to_check.extend(additional_passwords_to_check)
20+
elif isinstance(additional_passwords_to_check, str):
21+
self.passwords_to_check.append(additional_passwords_to_check)
22+
23+
def run(self):
24+
results = {}
25+
try:
26+
if not self.passwords_to_check:
27+
results = self.decrypt()
28+
else:
29+
for password in self.passwords_to_check:
30+
results = self.decrypt(password)
31+
if results:
32+
break
33+
if not results:
34+
results["errors"] = "Unable to deobfuscate"
35+
except SoftTimeLimitExceeded as e:
36+
error_message = (
37+
f"job_id:{self.job_id} analyzer:{self.analyzer_name} md5:{self.md5}"
38+
f"filename: {self.filename}. Soft Time Limit Exceeded Error {e}"
39+
)
40+
logger.error(error_message)
41+
self.report["errors"].append(str(e))
42+
self.report["success"] = False
43+
return results
44+
45+
def decrypt(self, password=""):
46+
cmd = [
47+
"xlmdeobfuscator",
48+
"--file",
49+
self.filepath,
50+
"--export-json",
51+
"result.json",
52+
]
53+
pwd_cmd = ["--password", password] if password else []
54+
subprocess.run(cmd + pwd_cmd, stdout=subprocess.PIPE).stdout.decode("utf-8")
55+
path = Path("result.json")
56+
if not path.exists():
57+
return {}
58+
with path.open("r") as f:
59+
results = json.load(f)
60+
path.unlink()
61+
results["correct_password"] = password
62+
return results

configuration/analyzer_config.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,22 @@
938938
"directories_with_rules": ["/opt/deploy/yara/rules"]
939939
}
940940
},
941+
"Xlm_Macro_Deobfuscator": {
942+
"type": "file",
943+
"supported_filetypes": [
944+
"application/vnd.ms-office",
945+
"application/vnd.ms-excel.addin.macroEnabled",
946+
"application/x-mspublisher",
947+
"application/vnd.ms-excel",
948+
"application/vnd.ms-excel.sheet.macroEnabled.12",
949+
"application/excel"
950+
],
951+
"decription": "Xlm macro deobfuscator",
952+
"python_module": "xlm_deobfuscator_run",
953+
"additional_config_params": {
954+
"passwords_to_check": ["agenzia", "inps"]
955+
}
956+
},
941957
"Yara_Scan_Florian": {
942958
"type": "file",
943959
"description": "scan a file with Neo23x0 yara rules",

docs/source/Usage.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ The following is the list of the available analyzers you can run out-of-the-box:
3737
* `Rtf_Info`: static RTF analysis
3838
* `Doc_Info`: static generic document analysis
3939
* `Doc_Info_Experimental`: static document analysis with new features to analyze XLM macros, encrypted macros and more
40+
* `Xlm_Macro_Deobfuscator`: [XlmMacroDeobfuscator](https://github.com/DissectMalware/XLMMacroDeobfuscator) deobfuscate xlm macros
4041
* `PE_Info`: static PE analysis
4142
* `Signature_Info`: PE signature extractor
4243
* `Speakeasy`: Speakeasy binary emulation

intel_owl/tasks.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
apkid,
2323
quark_engine,
2424
unpac_me,
25+
xlm_macro_deobfuscator,
2526
)
2627
from api_app.script_analyzers.observable_analyzers import (
2728
abuseipdb,
@@ -612,6 +613,15 @@ def docinfo_run(
612613
).start()
613614

614615

616+
@shared_task(soft_time_limit=30)
617+
def xlm_deobfuscator_run(
618+
analyzer_name, job_id, filepath, filename, md5, additional_config_params
619+
):
620+
xlm_macro_deobfuscator.XlmMacroDeobfuscator(
621+
analyzer_name, job_id, filepath, filename, md5, additional_config_params
622+
).start()
623+
624+
615625
@shared_task(soft_time_limit=30)
616626
def rtfinfo_run(
617627
analyzer_name, job_id, filepath, filename, md5, additional_config_params

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,5 @@ djangorestframework-guardian==0.3.0
8080
flake8==3.8.2
8181
black==19.10b0
8282
quark-engine==20.8
83-
git+git://github.com/DissectMalware/XLMMacroDeobfuscator.git@c78b9e443e2667399470462fd863ebe4e2b8c978
83+
git+git://github.com/DissectMalware/XLMMacroDeobfuscator.git@89fbce0c87014a4b5a22c1aef09c8b3ea9bf16c0
8484
speakeasy-emulator==1.4.4

tests/test_files.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
apkid,
2828
quark_engine,
2929
unpac_me,
30+
xlm_macro_deobfuscator,
3031
)
3132
from api_app.script_analyzers.observable_analyzers import vt3_get
3233

@@ -295,6 +296,34 @@ def test_speakeasy_dll(self):
295296
self.assertEqual(report.get("success", False), True)
296297

297298

299+
class FileAnalyzersExcelTests(TestCase):
300+
def setUp(self):
301+
params = {
302+
"source": "test",
303+
"is_sample": True,
304+
"file_mimetype": "application/vnd.ms-excel",
305+
"force_privacy": False,
306+
"analyzers_requested": ["test"],
307+
}
308+
filename = "document.xls"
309+
test_job = _generate_test_job_with_file(params, filename)
310+
self.job_id = test_job.id
311+
self.filepath, self.filename = utils.get_filepath_filename(self.job_id)
312+
self.runtime_configuration = test_job.runtime_configuration
313+
self.md5 = test_job.md5
314+
315+
def test_xlm_macro_deobfuscator_excel(self):
316+
report = xlm_macro_deobfuscator.XlmMacroDeobfuscator(
317+
"Xlm_Macro_Deobfuscator",
318+
self.job_id,
319+
self.filepath,
320+
self.filename,
321+
self.md5,
322+
{},
323+
).start()
324+
self.assertEqual(report.get("success", False), True)
325+
326+
298327
class FileAnalyzersDocTests(TestCase):
299328
def setUp(self):
300329
params = {

tests/test_files.zip

224 KB
Binary file not shown.

0 commit comments

Comments
 (0)