Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated shellcode is executable but not runnable with runshc64 #38

Closed
Path-17 opened this issue Jul 4, 2023 · 4 comments
Closed

Generated shellcode is executable but not runnable with runshc64 #38

Path-17 opened this issue Jul 4, 2023 · 4 comments

Comments

@Path-17
Copy link

Path-17 commented Jul 4, 2023

Hi, I am running into some issues generating shellcode from my rust binary.

It works when run in a copy of the same process using a built-in shellcode runner command (VirtualAlloc, CreateThread), but when executed in the context of another process, either injected or using runshc64, it does not work.

I am thinking that it could be some kind of pre-main entrypoint that is relying on the current process' environment but I cannot figure out how to skip over it the past few days.

Have you run into this before?

For context the raw code can be found here https://github.com/Path-17/diet-c2/tree/main/implants/implant-v2/src

Thank you! I attached a copy of the executable (not the output of pe2shc.exe) as well

implant-v2.zip

@Path-17
Copy link
Author

Path-17 commented Jul 4, 2023

To follow up, I found a solution that I think confirms my suspicion.

The default rust toolchain uses Visual Studio build tools (MSVC), switching to the gnu build tools fixes the issues I was coming across.

Just run "rustup toolchain install stable-x86_64-pc-windows-gnu" then set it to your default with "rustup default stable-gnu".

Testing further on the MSVC toolchain, even the simplest println!("Hello world") doesn't work with pe2shc.exe / runshc64.exe.

I will test further with side by side with a debugger injecting into notepad.exe to see what the cause of the crash is!

@hasherezade
Copy link
Owner

hi @Path-17 ! Thank you for reporting. It is true that sometimes the compiler choice affects whether or not the executable is convertible without any issues. For example: #29

I will look into your particular case soon, and see what was the immediate cause.

@hasherezade
Copy link
Owner

@Path-17 : I did some quick tests today, and it seems to me that the problem lies in the TLS.
First I tried to load the runshc64.exe <shellcode_path> under the debugger, and run it. There is an access violation:

tls_err

This is at RVA = 8E80F in the implant. Seeing it in IDA:

fetch_from_tls

So it seems that the value couldn't be fetched from the TLS.

Another check I did, by tracing the original application vs the shellcodified version vs the original one with TLS removed. Those are the results (fragments of the tracelogs).

Shellcodified:

> 13377339000+d82;kernel32.GetCurrentThread
> 13377339000+d70;kernel32.GetModuleHandleA
> 13377310000+cb7;kernel32.GetProcAddress
GetProcAddress:
	Arg[0] = ptr 0x00007ffc88c70000 -> {MZ\x90\x00\x03\x00\x00\x00}
	Arg[1] = ptr 0x00000133773951a9 -> "SetThreadDescription"

> 13377310000+cdc;kernelbase.SetThreadDescription
SetThreadDescription:
	Arg[0] = 0xfffffffffffffffe = 18446744073709551614
	Arg[1] = ptr 0x0000013362bdbaa0 -> L"main"

> 13377288000+c96;kernel32.HeapFree
> 13377288000+c1b;ntdll.RtlAllocateHeap
> 1337733a000+8c5;vcruntime140.memmove
> 13377288000+c1b;ntdll.RtlAllocateHeap
> 13377288000+c96;kernel32.HeapFree
> 13377288000+c96;kernel32.HeapFree
> 1337730f000+d6f;kernel32.GetStdHandle
> 1337730f000+dd1;kernel32.GetConsoleMode
> 13377310000+208;kernel32.MultiByteToWideChar
> 13377310000+245;kernel32.WriteConsoleW
WriteConsoleW:
	Arg[0] = 0x0000000000000058 = 88
	Arg[1] = ptr 0x0000000fe21fd0e0 -> L"thread panicked while processing panic. aborting.
"

Original:

b9d82;kernel32.GetCurrentThread
b9d70;kernel32.GetModuleHandleA
90cb7;kernel32.GetProcAddress
GetProcAddress:
	Arg[0] = ptr 0x00007ffc88c70000 -> {MZ\x90\x00\x03\x00\x00\x00}
	Arg[1] = ptr 0x00007ff6a3ef51a9 -> "SetThreadDescription"

90cdc;kernelbase.SetThreadDescription
8c96;kernel32.HeapFree
8c1b;ntdll.RtlAllocateHeap
ba8c5;vcruntime140.memmove
8c1b;ntdll.RtlAllocateHeap
8c1b;ntdll.RtlAllocateHeap
23f4;kernel32.GetComputerNameExW
8c1b;ntdll.RtlAllocateHeap
240b;kernel32.GetComputerNameExW
8c1b;ntdll.RtlAllocateHeap
ba8c5;vcruntime140.memmove

Original with TLS directory removed:

b9d82;kernel32.GetCurrentThread
b9d70;kernel32.GetModuleHandleA
90cb7;kernel32.GetProcAddress
GetProcAddress:
	Arg[0] = ptr 0x00007ffc88c70000 -> {MZ\x90\x00\x03\x00\x00\x00}
	Arg[1] = ptr 0x00007ff65d2651a9 -> "SetThreadDescription"

90cdc;kernelbase.SetThreadDescription
SetThreadDescription:
	Arg[0] = 0xfffffffffffffffe = 18446744073709551614
	Arg[1] = ptr 0x000002375de09170 -> L"main"

8c96;kernel32.HeapFree
8c1b;ntdll.RtlAllocateHeap
ba8c5;vcruntime140.memmove
8c1b;ntdll.RtlAllocateHeap
8c96;kernel32.HeapFree
8c96;kernel32.HeapFree
8fd6f;kernel32.GetStdHandle

We can see that the shellcodified version, and the version with TLS directory removed failed at the same point of execution. So there is a strong clue that inability to properly execute TLS caused the issue.

Although pe_to_shellcode supports TLS in a way, but it is a very simplified version. The TLS is called only once, before the Entry Point is executed. This may not be enough in some cases. But implementing a proper TLS support is beyond the scope of this small loader, because it would require hooking of functions.

If it is possible, I would recommend you to try compiling it with TLS disabled. Maybe the GNU compiler already did it, and that helped? Please let me know your thoughts.

@Path-17
Copy link
Author

Path-17 commented Jul 9, 2023

As far as I can tell there is no way to fully disable TLS with rust's compiler, I haven't found any flags for it.

I guess it is just a quirk of the implementation between GNU and MSVC that made the difference!

Thank you for your detailed explanation and work on this, I learned a lot from your explanation above :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants