Skip to content

Instantly share code, notes, and snippets.

@sysopfb
Last active January 2, 2020 15:24
Show Gist options
  • Save sysopfb/11e6fb8c1377f13ebab09ab717026c87 to your computer and use it in GitHub Desktop.
Save sysopfb/11e6fb8c1377f13ebab09ab717026c87 to your computer and use it in GitHub Desktop.
remcos static decoder update
"""
Remcos sample without SETTINGS rsrc section and a new idx field number
Converted JPCert memory scan code into a static decoder
License message below from MalConfScan file
# LICENSE
# Please refer to the LICENSE.txt in the https://github.com/JPCERTCC/MalConfScan/
"""
import sys
import pefile
import re
from collections import OrderedDict
from Crypto.Cipher import ARC4
#From JPCERT
FLAG = {"\x00": "Disable", "\x01": "Enable"}
#From JPCERT
idx_list = {
0: "Host:Port:Password",
1: "Assigned name",
2: "Connect interval",
3: "Install flag",
4: "Setup HKCU\\Run",
5: "Setup HKLM\\Run",
6: "Setup HKLM\\Explorer\\Run",
7: "Setup HKLM\\Winlogon\\Shell",
8: "Setup HKLM\\Winlogon\\Userinit",
9: "Install path",
10: "Copy file",
11: "Startup value",
12: "Hide file",
13: "Unknown13",
14: "Mutex",
15: "Keylog flag",
16: "Keylog path",
17: "Keylog file",
18: "Keylog crypt",
19: "Hide keylog file",
20: "Screenshot flag",
21: "Screenshot time",
22: "Take Screenshot option",
23: "Take screenshot title",
24: "Take screenshot time",
25: "Screenshot path",
26: "Screenshot file",
27: "Screenshot crypt",
28: "Mouse option",
29: "Unknown29",
30: "Delete file",
31: "Unknown31",
32: "Unknown32",
33: "Unknown33",
34: "Unknown34",
35: "Unknown35",
36: "Audio record time",
37: "Audio path",
38: "Audio folder",
39: "Unknown39",
40: "Unknown40",
41: "Connect delay",
42: "Unknown42",
43: "Unknown43",
44: "Unknown44",
45: "Unknown45",
46: "Unknown46",
47: "Unknown47",
48: "Copy folder",
49: "Keylog folder",
50: "Unknown50",
51: "Unknown51",
52: "Unknown52",
53: "Unknown53",
54: "Keylog file max size",
55: "Unknown55"
}
#From JPCERT
setup_list = {
0: "Temp",
2: "Root",
3: "Windows",
4: "System32",
5: "Program Files",
6: "AppData",
7: "User Profile",
8: "Application path",
}
def get_rsrc(pe):
ret = []
for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
if resource_type.name is not None:
name = str(resource_type.name)
else:
name = str(pefile.RESOURCE_TYPE.get(resource_type.struct.Id))
if name == None:
name = str(resource_type.struct.name)
if hasattr(resource_type, 'directory'):
for resource_id in resource_type.directory.entries:
if hasattr(resource_id, 'directory'):
for resource_lang in resource_id.directory.entries:
data = pe.get_data(resource_lang.data.struct.OffsetToData,resource_lang.data.struct.Size)
ret.append((name,data,resource_lang.data.struct.Size,resource_type))
return ret
def decoder(data):
pe = pefile.PE(data=data)
r = get_rsrc(pe)
for rsrc in r:
if 'SETTINGS' in rsrc[0] or 'RCDATA' in rsrc[0]:
blob = rsrc[1]
break
keylen = ord(blob[0])
key = blob[1:keylen+1]
rc4 = ARC4.new(key)
config = rc4.decrypt(blob[keylen+1:])
p_data = OrderedDict()
#From JPCERT
configs = re.split("\x1E|@@", config)
for i, cont in enumerate(configs):
if cont == "\x00" or cont == "\x01":
p_data[idx_list[i]] = FLAG[cont]
else:
if i in [9, 16, 25, 37]:
p_data[idx_list[i]] = setup_list[int(cont)]
else:
p_data[idx_list[i]] = cont
out = {}
for id, param in p_data.items():
try:
out[id] = param.decode('utf-16').decode('ascii')
except:
out[id] = param
return({"CONFIG": out})
if __name__ == "__main__":
data = open(sys.argv[1], 'rb').read()
t = decoder(data)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment