Shellcode for windows¶
2010
For our first shellcode, we will create a shellcode in x86-32 to display a “Hello, World!” message. To do this, it is helpful to have some knowledge of the Windows API.
Designing a shellcode¶
We design this basic code on C in shellcode. Afterwards, we re-write in below in assembly, for to do that, we need Windows API to used the primitive function.
#include <stdio.h>
int main() {
printf("Hello, World\n");
retrun 0;
}
We use the printf
which is contained in the library crtdll.dll.
I chose dynamic library not for a question of performance, quite simply to get in touch with dynamic libraries.
The nmdll
command allows you to know the address associated with a function in relation to a library.
The address may change depending on the operating system version.
Here is the result:
> nmdll crtdll.dll | grep printf
6C243255 _cprintf
6C249847 _snprintf
6C24989F _snwprintf
6C24B2D7 _vsnprintf
6C24B32E _vsnwprintf
6C24C06C fprintf
6C24C792 fwprintf
6C24D8F8 printf
6C24E5C5 sprintf
6C24F8FA swprintf
6C250097 vfprintf
6C2500EE vfwprintf
6C250145 vprintf
6C25018F vsprintf
6C2501E7 vswprintf
6C25025D vwprintf
6C250D27 wprintf
We replace retrun 0
by exit
function. Also contained in the library crtdll.dll
.
Use nmdll
to know the address associated with this function:
> nmdll crtdll.dll | grep exit
6C242132 __dllonexit
6C25E004 _aexit_rtn_dll
6C241DB8 _amsg_exit
6C241F91 _c_exit
6C241F82 _cexit
6C241F71 _exit
6C24205F _onexit
6C2420E7 atexit
6C241F60 exit
Construction du shellcode¶
We build the shellcode with the nasm compiler.
global _main
extern _printf
extern _exit
section .data
message db 'Hello, World',12, 0
section .text
_main:
push message
call _printf
xor ebx, ebx
push ebx
call _exit
Deleting all sections
global _main
extern _printf
extern _exit
_main:
jmp one
two:
call _printf
xor ebx, ebx
push ebx
call _exit
one:
call two
db 'Hello, World',12, 0
Removing keyword extern
.
We saw above that he had an address.
So we will replace them with their address:
global _main
_main:
jmp short one
two:
mov eax, 0x6C24D8F8
call eax
xor ebx, ebx
push ebx
mov eax, 0x6C241F60
call ebx
one:
call two
db 'Hello, World',12
Compilation
nasm -f win32 helloworld.asm ld helloworld.obj
After compilation we get the opcodes
> objdump.exe -d .\helloworld.obj
.\helloworld2.obj: file format pe-i386
Disassembly of section .text:
00000000 <_main>:
0: eb 11 jmp 13 <one>
00000002 <two>:
2: b8 f8 d8 24 6c mov $0x6c24d8f8,%eax
7: ff d0 call *%eax
9: bb 60 1f 24 6c mov $0x6c241f60,%ebx
e: 31 c0 xor %eax,%eax
10: 50 push %eax
11: ff d3 call *%ebx
00000013 <one>:
13: e8 ea ff ff ff call 2 <two>
18: 48 dec %eax
19: 65 gs
1a: 6c insb (%dx),%es:(%edi)
1b: 6c insb (%dx),%es:(%edi)
1c: 6f outsl %ds:(%esi),(%dx)
1d: 2c 20 sub $0x20,%al
1f: 77 6f ja 90 <one+0x7d>
21: 72 6c jb 8f <one+0x7c>
23: 64 fs
24: 0a .byte 0xa
This gives us the following opcodes:
\\xeb\\x11\\xb8\\xf8\\xd8\\x24\\x6c\\xff\\xd0\\xbb\\x60\\x1f\\x24
\\x6c\\x31\\xc0\\x50\\xff\\xd3\\xe8\\xea\\xff\\xff\\xff\\x48\\x65
\\x6c\\x6c\\x6f\\x2c\\x20\\x77\\x6f\\x72\\x6c\\x64\\x0a
Let’s test the shellcode:
#include <windows.h>
char shellcode[] = "\\xEB\\x11\\xB8\\xF8\\xD8\\x24\\x6C\\xFF\\xD0\\xBB\\x60\\x1F\\x24\\x6C"
"\\x31\\xC0\\x50\\xFF\\xD3\\xE8\\xEA\\xFF\\xFF\\xFF\\x48\\x65\\x6C\\x6C"
"\\x6F\\x2C\\x20\\x77\\x6F\\x72\\x6C\\x64\\x0A";
int main (int argc, char **argv) {
HMODULE lib = LoadLibrary("crtdll.dll");
int (*ret)(); /* ret is a function pointer */
ret = (int(*)())shellcode; /* ret points to our shellcode */
/* shellcode is type casted as a function */
(int)(*ret)(); /* execute as function shellcode[] */
FreeLibrary(lib);
exit(0); /* exit() */
}
Be careful in this shellcode, it is absolutely necessary to load the library crtdll.dll
otherwise the shellcode will not be able to work because the address of the exit and printf functions cannot be found.