Today we will analyse the shellcode for msfvenom payload “payload/linux/x86/exec” . So lets check the payload options for it.
root@kali:~/slae_analyze# msfvenom -p linux/x86/exec --payload-options
Options for payload/linux/x86/exec:
Name: Linux Execute Command
Module: payload/linux/x86/exec
Platform: Linux
Arch: x86
Needs Admin: No
Total size: 36
Rank: Normal
Provided by:
vlad902 <vlad902@gmail.com>
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
CMD yes The command string to execute
Description:
Execute an arbitrary command
this payload accepts a “CMD” parameter, which is the code to be executed on the system. I will use “whoami” command for analyzing the generated shellcode. Lets pipe the output to ndisasm.
root@kali:~/slae_analyze# msfvenom -p linux/x86/exec CMD=whoami -f raw | ndisasm -u -
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 42 bytes
00000000 6A0B push byte +0xb
00000002 58 pop eax
00000003 99 cdq
00000004 52 push edx
00000005 66682D63 push word 0x632d
00000009 89E7 mov edi,esp
0000000B 682F736800 push dword 0x68732f
00000010 682F62696E push dword 0x6e69622f
00000015 89E3 mov ebx,esp
00000017 52 push edx
00000018 E807000000 call 0x24
0000001D 7768 ja 0x87
0000001F 6F outsd
00000020 61 popa
00000021 6D insd
00000022 6900575389E1 imul eax,[eax],dword 0xe1895357
00000028 CD80 int 0x80
initially we see that, syscall number “11” stored on eax. which implies that its making use of execve to execute our desired command! there are weird call instruction in the middle , we can see edx register getting set with null, along with setting argument 1 (“/bin/sh”) on ebx register. and “push word 0x632d” translates to “-c” in ASCII text, this hints that execve may be called as follows to execute our command.
execve(“/bin/sh”,[*(“/bin/sh”),”-c”,”whoami”],0)
but we note that there is no string “whoami” that is our command in the dissected assembly code. lets analyze the same code in gdb for further inspection.specifically on that call instruction.
root@kali:~/slae_analyze# msfvenom -p linux/x86/exec CMD=whoami -f c
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 42 bytes
Final size of c file: 201 bytes
unsigned char buf[] =
"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x07\x00\x00\x00\x77"
"\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80";
Lets place this in our c template program and run inside gdb.
#include<stdio.h>
#include<string.h>
unsigned char code[] = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x07\x00\x00\x00\x77"
"\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80";
int main()
{
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
we will use GDB extended with Peda for smoother analysis. As Peda has some very cool integrated features which helps us in easier dissection.Lets place a breakpoint at our shellcode.
root@kali:~/slae_analyze/msf_exec# gcc -fno-stack-protector -z execstack -o shellcode shellcode.c
root@kali:~/slae_analyze/msf_exec# ./shellcode
Shellcode Length: 15
root
root@kali:~/slae_analyze/msf_exec# gdb -q ./shellcode
Reading symbols from ./shellcode...(no debugging symbols found)...done.
gdb-peda$ break *&code
Breakpoint 1 at 0x2040
gdb-peda$ run
We dissemble at the start of our shellcode.
[----------------------------------registers-----------------------------------]
EAX: 0x402040 --> 0x99580b6a
EBX: 0x402000 --> 0x1efc
ECX: 0x0
EDX: 0xb7fab890 --> 0x0
ESI: 0xb7faa000 --> 0x1d4d6c
EDI: 0x0
EBP: 0xbffff288 --> 0x0
ESP: 0xbffff26c --> 0x40059d (<main+80>: mov eax,0x0)
EIP: 0x402040 --> 0x99580b6a
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x40203a: add BYTE PTR [eax],al
0x40203c: add BYTE PTR [eax],al
0x40203e: add BYTE PTR [eax],al
=> 0x402040 <code>: push 0xb
0x402042 <code+2>: pop eax
0x402043 <code+3>: cdq
0x402044 <code+4>: push edx
0x402045 <code+5>: pushw 0x632d
[------------------------------------stack-------------------------------------]
0000| 0xbffff26c --> 0x40059d (<main+80>: mov eax,0x0)
0004| 0xbffff270 --> 0x1
0008| 0xbffff274 --> 0xbffff334 --> 0xbffff4df ("/root/slae_analyze/msf_exec/shellcode")
0012| 0xbffff278 --> 0xbffff33c --> 0xbffff505 ("LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc"...)
0016| 0xbffff27c --> 0x402040 --> 0x99580b6a
0020| 0xbffff280 --> 0xbffff2a0 --> 0x1
0024| 0xbffff284 --> 0x0
0028| 0xbffff288 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x00402040 in code ()
gdb-peda$ disassemble
Dump of assembler code for function code:
=> 0x00402040 <+0>: push 0xb
0x00402042 <+2>: pop eax
0x00402043 <+3>: cdq
0x00402044 <+4>: push edx
0x00402045 <+5>: pushw 0x632d
0x00402049 <+9>: mov edi,esp
0x0040204b <+11>: push 0x68732f
0x00402050 <+16>: push 0x6e69622f
0x00402055 <+21>: mov ebx,esp
0x00402057 <+23>: push edx
0x00402058 <+24>: call 0x402064 <code+36>
0x0040205d <+29>: ja 0x4020c7
0x0040205f <+31>: outs dx,DWORD PTR ds:[esi]
0x00402060 <+32>: popa
0x00402061 <+33>: ins DWORD PTR es:[edi],dx
0x00402062 <+34>: imul eax,DWORD PTR [eax],0xe1895357
0x00402068 <+40>: int 0x80
0x0040206a <+42>: add BYTE PTR [eax],al
End of assembler dump.
we see that call instruction again with jump to some memory location. lets analyse by break at that location.
[----------------------------------registers-----------------------------------]
EAX: 0xb ('\x0b')
EBX: 0xbffff25e ("/bin/sh")
ECX: 0x0
EDX: 0x0
ESI: 0xb7faa000 --> 0x1d4d6c
EDI: 0xbffff266 --> 0x632d ('-c')
EBP: 0xbffff288 --> 0x0
ESP: 0xbffff256 --> 0x40205d ("whoami")
EIP: 0x402064 --> 0xe1895357
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
=> 0x402064 <code+36>: push edi
0x402065 <code+37>: push ebx
0x402066 <code+38>: mov ecx,esp
0x402068 <code+40>: int 0x80
[------------------------------------stack-------------------------------------]
0000| 0xbffff256 --> 0x40205d ("whoami")
0004| 0xbffff25a --> 0x0
0008| 0xbffff25e ("/bin/sh")
0012| 0xbffff262 --> 0x68732f ('/sh')
0016| 0xbffff266 --> 0x632d ('-c')
0020| 0xbffff26a --> 0x59d0000
0024| 0xbffff26e --> 0x10040
0028| 0xbffff272 --> 0xf3340000
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x00402064 in code ()
As we see, memory address containing our command string(“whoami”) is pushed onto to the stack . lets verify that what we assume is true.
gdb-peda$ x/s 0x40205d
0x40205d <code+29>: "whoami"
Now lets break before calling interrupt to verify that all the arguments are on the stack setup for execve to execute.
[----------------------------------registers-----------------------------------]
EAX: 0xb ('\x0b')
EBX: 0xbffff25e ("/bin/sh")
ECX: 0xbffff24e --> 0xbffff25e ("/bin/sh")
EDX: 0x0
ESI: 0xb7faa000 --> 0x1d4d6c
EDI: 0xbffff266 --> 0x632d ('-c')
EBP: 0xbffff288 --> 0x0
ESP: 0xbffff24e --> 0xbffff25e ("/bin/sh")
EIP: 0x402068 --> 0x80cd
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x402060 <code+32>: popa
0x402061 <code+33>: ins DWORD PTR es:[edi],dx
0x402062 <code+34>: imul eax,DWORD PTR [eax],0xe1895357
=> 0x402068 <code+40>: int 0x80
0x40206a <code+42>: add BYTE PTR [eax],al
0x40206c: add BYTE PTR [eax],al
0x40206e: add BYTE PTR [eax],al
0x402070: add BYTE PTR [eax],al
[------------------------------------stack-------------------------------------]
0000| 0xbffff24e --> 0xbffff25e ("/bin/sh")
0004| 0xbffff252 --> 0xbffff266 --> 0x632d ('-c')
0008| 0xbffff256 --> 0x40205d ("whoami")
0012| 0xbffff25a --> 0x0
0016| 0xbffff25e ("/bin/sh")
0020| 0xbffff262 --> 0x68732f ('/sh')
0024| 0xbffff266 --> 0x632d ('-c')
0028| 0xbffff26a --> 0x59d0000
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x00402068 in code ()
gdb-peda$ info registers
eax 0xb 0xb
ecx 0xbffff24e 0xbffff24e
edx 0x0 0x0
ebx 0xbffff25e 0xbffff25e
esp 0xbffff24e 0xbffff24e
ebp 0xbffff288 0xbffff288
esi 0xb7faa000 0xb7faa000
edi 0xbffff266 0xbffff266
eip 0x402068 0x402068 <code+40>
eflags 0x282 [ SF IF ]
cs 0x73 0x73
ss 0x7b 0x7b
ds 0x7b 0x7b
es 0x7b 0x7b
fs 0x0 0x0
gs 0x33 0x33
From the above code its clear that all the arguments for execve has been set properly before the interrupt. ebx contains /bin/sh string. and ecx contains address “0xbffff24e” (ESP) which points to memory location “0xbffff25e” which is nothing but address of the /bin/sh followed by other arguments which are present on the stack.
gdb-peda$ x/s 0xbffff25e
0xbffff25e: "/bin/sh"
Finally our code executes successfully ..
gdb-peda$ s
process 9452 is executing new program: /bin/dash
process 9497 is executing new program: /usr/bin/whoami
#output of our command "whoami"
root
[Inferior 2 (process 9497) exited normally]
Warning: not running or target is remote
Thats it for today. I will take up more shellcode analysis in the next few posts. Thank you!
Github Repo link :
https://github.com/strikergoutham/SLAE_assignments
This blog post has been created for the completing the requirements of SecurityTube Linux Assembly Expert certification.
(https://www.pentesteracademy.com/course?id=3)
SLAE student ID : SLAE – 1367
