Open buffer opened 3 years ago
In order to better investigate shellcode emulation issues I converted a Python code I used long time ago while developing Pylibemu to use Speakeasy. The first analysis I performed seems to indicate that Unicorn detects some invalid memory read operations for a good number of the tested shellcodes which is probably something you may want to look at. Hope this helps.
Thanks for the info, I'll look into this shortly.
@drewvis just wanted to point out that version 1.4.8 totally broke up shellcode emulation. Apparently this started happening after the last set of PEB patches. Following an example of the same shellcode emulation using versions 1.4.7 and 1.4.8
{'arch': 'x86',
'emu_version': '1.4.7',
'emulation_total_runtime': 0.79,
'entry_points': [{'apihash': 'a1e6b57d6d581e4866f8a99c621af48bd3de9706fb75650495b2de9e59b62723',
'apis': [{'api_name': 'kernel32.LoadLibraryA',
'args': ['ws2_32'],
'pc': '0x1078',
'ret_val': '0x78c00000'},
{'api_name': 'ws2_32.WSAStartup',
'args': ['0x2', '0x1203dc4'],
'pc': '0x108d',
'ret_val': '0x0'},
{'api_name': 'ws2_32.WSASocketA',
'args': ['AF_INET',
'SOCK_STREAM',
'0x0',
'0x0',
'0x0',
'0x0'],
'pc': '0x10a0',
'ret_val': '0x4'},
{'api_name': 'ws2_32.bind',
'args': ['0x4', '0.0.0.0:4444', '0x10'],
'pc': '0x10b7',
'ret_val': '0x0'},
{'api_name': 'ws2_32.listen',
'args': ['0x4', '0x2'],
'pc': '0x10c3',
'ret_val': '0x0'},
{'api_name': 'ws2_32.accept',
'args': ['0x4', '0x1203f9c', '0x1203fa0'],
'pc': '0x10d1',
'ret_val': '0x8'},
{'api_name': 'ws2_32.closesocket',
'args': ['0x4'],
'pc': '0x10dd',
'ret_val': '0x0'},
{'api_name': 'kernel32.CreateProcessA',
'args': ['0x0',
'cmd',
'0x0',
'0x0',
'0x1',
'0x0',
'0x0',
'0x0',
'0x1203f40',
'0x1203f84'],
'pc': '0x111a',
'ret_val': '0x1'},
{'api_name': 'kernel32.WaitForSingleObject',
'args': ['0x220', '0xffffffff'],
'pc': '0x1128',
'ret_val': '0x0'},
{'api_name': 'ws2_32.closesocket',
'args': ['0x8'],
'pc': '0x1133',
'ret_val': '0x0'},
{'api_name': 'kernel32.SetUnhandledExceptionFilter',
'args': ['0x77000000'],
'pc': '0x113d',
'ret_val': '0x0'}],
'dynamic_code_segments': [],
'ep_args': ['0x41420000',
'0x41421000',
'0x41422000',
'0x41423000'],
'ep_type': 'shellcode',
'error': {'address': '0x77000000',
'instr': 'dec ebp',
'pc': '0x77000000',
'regs': {'eax': '0x00000000',
'ebp': '0x01203f94',
'ebx': '0x77000000',
'ecx': '0x00000000',
'edi': '0x01203f84',
'edx': '0x00000008',
'eip': '0x77000000',
'esi': '0x00001009',
'esp': '0x01203f8c'},
'stack': ['sp+0x00: 0xfeedf000',
'sp+0x04: 0x00007180 -> '
'emu.struct.EXCEPTION_POINTERS.0x7180',
'sp+0x08: 0x5f048af0',
'sp+0x0c: 0x78c00000 -> '
'emu.module.ws2_32.0x78c00000',
'sp+0x10: 0x79c679e7',
'sp+0x14: 0x0302010a',
'sp+0x18: 0x78c00000 -> '
'emu.module.ws2_32.0x78c00000',
'sp+0x1c: 0x498649e5',
'sp+0x20: 0x78c00000 -> '
'emu.module.ws2_32.0x78c00000',
'sp+0x24: 0xe92eada4',
'sp+0x28: 0x78c00000 -> '
'emu.module.ws2_32.0x78c00000',
'sp+0x2c: 0xc7701aa4',
'sp+0x30: 0x5c110002',
'sp+0x34: 0x00000000',
'sp+0x38: 0x78c00000 -> '
'emu.module.ws2_32.0x78c00000',
'sp+0x3c: 0xadf509d9'],
'traceback': 'Traceback (most recent call last):\n'
' File '
'"/Users/buffer/.pyenv/versions/3.9.0/lib/python3.9/site-packages/speakeasy/windows/winemu.py", '
'line 397, in start\n'
' '
'self.emu_eng.start(self.curr_run.start_addr, '
'timeout=self.timeout,\n'
' File '
'"/Users/buffer/.pyenv/versions/3.9.0/lib/python3.9/site-packages/speakeasy/engines/unicorn_eng.py", '
'line 210, in start\n'
' return self.emu.emu_start(addr, '
'0xFFFFFFFF, timeout=timeout, '
'count=count)\n'
' File '
'"/Users/buffer/.pyenv/versions/3.9.0/lib/python3.9/site-packages/unicorn-1.0.2rc4-py3.9.egg/unicorn/unicorn.py", '
'line 317, in emu_start\n'
' raise UcError(status)\n'
'unicorn.unicorn.UcError: Invalid '
'memory read '
'(UC_ERR_READ_UNMAPPED)\n',
'type': 'Invalid memory read '
'(UC_ERR_READ_UNMAPPED)'},
'network_events': {'dns': [],
'traffic': [{'method': 'winsock.bind',
'port': 4444,
'proto': 'tcp',
'server': '0.0.0.0',
'type': 'bind'},
{'method': 'winsock.accept',
'port': 4444,
'proto': 'tcp',
'server': '10.1.2.3',
'type': 'accept'}]},
'process_events': [{'cmdline': 'cmd',
'event': 'create',
'path': 'C:\\Windows\\system32\\cmd',
'pid': 1252}],
'ret_val': '0x0',
'start_addr': '0x1000'}],
'mem_tag': 'emu.shellcode.9bd7da29b4dc95cc0cd93274a80362c2e8aee0b7e5f88c47d7c9e948799bccd9',
'os_run': 'windows.6_1',
'path': None,
'report_version': '1.1.0',
'sha256': '9bd7da29b4dc95cc0cd93274a80362c2e8aee0b7e5f88c47d7c9e948799bccd9',
'size': 317,
'strings': {'in_memory': {'ansi': ['w@? ', ';ws2_32'], 'unicode': []},
'static': {'ansi': [';T$(u',
'fSfh32hws2_T',
'SSSSSCSCS',
'PTTU',
'fjdfhcm',
'jPY)',
'[WRQQQj',
'QQUQ'],
'unicode': []}},
'timestamp': 1607509727}
{'arch': 'x86',
'emu_version': '1.4.8',
'emulation_total_runtime': 0.626,
'entry_points': [{'apihash': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
'apis': [],
'dynamic_code_segments': [],
'ep_args': ['0x41420000',
'0x41421000',
'0x41422000',
'0x41423000'],
'ep_type': 'shellcode',
'error': {'address': '0x4d234567',
'instr': 'lodsb al, byte ptr [esi]',
'pc': '0x1028',
'regs': {'eax': '0x00000000',
'ebp': '0x7c000000',
'ebx': '0x7c000b78',
'ecx': '0xffffff3f',
'edi': '0x7c000870',
'edx': '0x00000000',
'eip': '0x00001028',
'esi': '0x4d234567',
'esp': '0x01203fb4'},
'stack': ['sp+0x00: 0x00000000',
'sp+0x04: 0x00001009 -> '
'emu.shellcode.9bd7da29b4dc95cc0cd93274a80362c2e8aee0b7e5f88c47d7c9e948799bccd9.0x1000',
'sp+0x08: 0x01203fff -> '
'emu.stack.0x1200000',
'sp+0x0c: 0x01203fd4 -> '
'emu.stack.0x1200000',
'sp+0x10: 0x00000000',
'sp+0x14: 0x00000000',
'sp+0x18: 0x00000400',
'sp+0x1c: 0x7c000000 -> '
'emu.module.ntdll.0x7c000000',
'sp+0x20: 0x0000106a -> '
'emu.shellcode.9bd7da29b4dc95cc0cd93274a80362c2e8aee0b7e5f88c47d7c9e948799bccd9.0x1000',
'sp+0x24: 0x7c000000 -> '
'emu.module.ntdll.0x7c000000',
'sp+0x28: 0xec0e4e8e',
'sp+0x2c: 0xffffffeb',
'sp+0x30: 0xfeedf000',
'sp+0x34: 0x41420000 -> '
'emu.shellcode_arg_0.0x41420000',
'sp+0x38: 0x41421000 -> '
'emu.shellcode_arg_1.0x41421000',
'sp+0x3c: 0x41422000 -> '
'emu.shellcode_arg_2.0x41422000'],
'type': 'invalid_read'},
'ret_val': '0x0',
'start_addr': '0x1000'}],
'mem_tag': 'emu.shellcode.9bd7da29b4dc95cc0cd93274a80362c2e8aee0b7e5f88c47d7c9e948799bccd9',
'os_run': 'windows.6_1',
'path': None,
'report_version': '1.1.0',
'sha256': '9bd7da29b4dc95cc0cd93274a80362c2e8aee0b7e5f88c47d7c9e948799bccd9',
'size': 317,
'strings': {'in_memory': {'ansi': [], 'unicode': []},
'static': {'ansi': [';T$(u',
'fSfh32hws2_T',
'SSSSSCSCS',
'PTTU',
'fjdfhcm',
'jPY)',
'[WRQQQj',
'QQUQ'],
'unicode': []}},
'timestamp': 1607509818}
Hey thanks, I'm looking into this right now. Other shellcode samples I have locally as tests still appear to be working. That example appears to be similar to a metasploit tcp bind shell. Can I reproduce this bug with that?
Yes, that shellcode was generated using Metasploit. Attaching you a potentially useful Python script. Using the option -s you can select a shellcode to emulate (the example I posted was generated by running python sctest.py -s 1). Already commented out the code that performs shellcode analysis with pylibemu. Feel free to uncomment if you are interested in comparing the results.
Ok, I believe I fixed the issue. What happened was the InInitializationOrderModuleList was corrected in the lasted release to remove the EXE from the linked list. However, the sample you are emulated appears to always expect kernel32 to be the 2nd loaded module in this list. By simply updating the default JSON config (https://github.com/fireeye/speakeasy/commit/86d7d71d409ba3b1f393e44772799229280ee6bb), the sample now emulates.
Thanks for taking care of it. I performed a couple of tests and can confirm the patch fixes the issue.
While attempting to build Speakeasy support in Thug [1] I spotted a potential shellcode emulation issue. Still had no time to investigate it (will do soon) but just wanted to point it out.
While analyzing a local sample I got these results
The shellcode profile is generated by libemu/pylibemu in this case. When attempting to analyze the exact same shellcode with Speakeasy I get
Let me point out this does not happen for every Thug local exploit sample but just a few of them.
[1] https://github.com/buffer/thug