malduck
malduck copied to clipboard
Add support for embedded Yara rules
This PR introduces the capability to embed Yara rules within Extractors. This capability opens the door to shipping the Extractors as standalone scripts not relying on Karton. The Citadel example can be modified as follow, while remaining compatible with Karton's config extractor.
import argparse
import json
from malduck import Extractor
from malduck.extractor import ExtractManager, ExtractorModules
@Extractor.yara(r"""
rule citadel
{
meta:
author = "mak"
module = "citadel"
strings:
$briankerbs = "Coded by BRIAN KREBS for personal use only. I love my job & wife."
$cit_aes_xor = {81 30 [4] 0F B6 50 03 0F B6 78 02 81 70 04 [4] 81 70 08 [4] 81 70 0C [4] C1 E2 08 0B D7 }
$cit_salt = { 8A D1 80 E2 07 C0 E9 03 47 83 FF 04 }
$cit_login = { 30 [1-2] 8A 8? [4] 32 }
$cit_getpes = { 68 [2] 00 00 8D ( 84 24 | 85) [4] 50 8D ( 85 ?? ?? ?? ?? | 44 24 ?? ) 50 E8 [4] B8 [2] 00 00 50 68 }
$cit_base_off = { 5? 8D 85 [4] E8 [4] 6A 20 68 [4] 8D [2] 50 E8 [4] 8D 85 [4] 50 }
condition:
3 of them
}
""")
class Citadel(Extractor):
family = "citadel"
@Extractor.string("briankerbs")
def citadel_found(self, p, addr, match):
log.info('[+] `Coded by Brian Krebs` str @ %X' % addr)
return True
@Extractor.string
def cit_login(self, p, addr, match):
log.info('[+] Found login_key xor @ %X' % addr)
hit = p.uint32v(addr + 4)
print(hex(hit))
if p.is_addr(hit):
return {'login_key': p.asciiz(hit)}
hit = p.uint32v(addr + 5)
print(hex(hit))
if p.is_addr(hit):
return {'login_key': p.asciiz(hit)}
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('input', type=str)
args = parser.parse_args()
manager = ExtractManager(ExtractorModules())
manager.push_file(args.input)
for config in manager.config:
print(json.dumps(config))
Fixes #36