Art of ShellCoding: Metasploit Add User Payload Analysis
In the previous post, we saw how we can encode the shellcode with our customized encoding schemes. In this post, we will see how some of the famous shellcodes from the metasploit framework work. We will analyze three different shellcodes using different techniques and tools in this mini shellcode analysis series. In this post, we will examine linux/x86/adduser shellcode with ndisasm and will see how the stuff works behind the scene.
The adduser shellcode adds a specified user to the linux system. Let's see how we can create this shellcode using msfvenom:
Let's copy the shellcode from the 'shellcode' file and analyze it using ndisasm as follows:
We have the complete disassembly of the code here:
Having a look at the disassembly, we will see that we have four primary system calls here which are setreuid, open, write and exit system call. I know things may not be clear here and you might be wondering how exactly i can say this? Let's break the code down and see it ourselves:
mov ebx,ecx
push byte +0x46
pop eax
int 0x80
Clearing out ECX, we move the obtained 0 to EBX. Next, we put 0x46 in EAX using a PUSH-POP operation. The 0x46 in hexadecimal corresponds to 70 in decimal and denotes setreuid() syscall. The setreuid syscall takes two parameters, i.e., int setreuid(uid_t ruid, uid_t euid); The parameters ruid and euid are real and effective user ids. The setreuid set the real and effective user ids of the current process to the values provided in setreuid. Since we have 0 in EBX and 0 in ECX, this means that setreuid will be called as setreuid(0,0) and 0 corresponds to the user id root.
pop eax
xor ecx,ecx
push ecx
push dword 0x64777373
push dword 0x61702f2f
push dword 0x6374652f
mov ebx,esp
inc ecx
mov ch,0x4
int 0x80
The above piece of code puts 0x5 in EAX which is nothing but sys_open(int open(const char *pathname, int flags);) system call. Next, we clear out ECX and push it to the stack. The value to be pushed into the stack is 0 since we cleared out ECX using XOR operation. The next three instructions put the string /etc//passwd on the stack, and since they are at the top of the stack, we move ESP to EBX. Next, we increment ECX to 1 and then move 0x4 to CH register which is HIGH bytes of CX register. We already have a value in CL which is 1. Therefore, this operation will make the value in ECX as 0x401 which is nothing but a bitmask representing a combination of O_WRONLY | O_APPEND flags. Using this combination of registers, we will be opening /etc/passwd file in write-only append mode. Upon successful execution, it will return the descriptor for the file. The next two lines exchange the descriptor with EBX register and call
xchg eax,ebx
call dword 0x4e
Here is the trick of this shellcode. Since we issue a call instruction, the data after the call instruction is pushed onto the stack. Confused? After the call instruction we have:
0000002B 6E outsb 0000002C 6970756E3A417A imul esi,[eax+0x75],dword 0x7a413a6e 00000033 627242 bound esi,[edx+0x42] 00000036 334B30 xor ecx,[ebx+0x30] 00000039 7072 jo 0xad 0000003B 52 push edx 0000003C 41 inc ecx 0000003D 59 pop ecx 0000003E 3A30 cmp dh,[eax] 00000040 3A30 cmp dh,[eax] 00000042 3A3A cmp bh,[edx] 00000044 2F das 00000045 3A2F cmp ch,[edi] 00000047 62696E bound ebp,[ecx+0x6e] 0000004A 2F das 0000004B 7368 jnc 0xb5 0000004D 0A598B or bl,[ecx-0x75]
These may look like instructions, but they are not. In fact, this is the data. Let's analyze it as follows:
From 6E to 68(Second Last Line, 0A is line feed):
6e 69 70 75 6e 3a 41 7a 62 72 42 33 4b 30 70 72 52 41 59 3a 30 3a 30 3a 3a 2f 3a 2f 62 69 6e 2f 73 68
Transforms to:
nipun:AzbrB3K0prRAY:0:0::/:/bin/sh
nipun:AzbrB3K0prRAY:0:0::/:/bin/sh
The above string is the data to be written into the file we opened using SYS_OPEN call. Coming back to the call instruction it will land us at the at the byte 59 (Last line) after 0A:
We can see the value in EIP which points to byte 59. Let's reconfirm it:
Now, the POP ECX command will put the data to be written into the ECX register, and the next instruction puts the length of this data onto the EDX register. Rest of the code is straightforward it pushes the value 0x4 on the stack and pops it to EAX register. This is nothing but the WRITE system call. This means we have the following arrangement of registers:
EAX: 0x4 Write System CallEBX: File Descriptor (From the XCHG Operation)
ECX: The data itself
EDX: Length of data
We simply issue the interrupt, and the data gets written to the /etc/passwd file. Next, we just issue an exit system call by putting 0x1 to EAX using a PUSH-POP operation
Analysis:
The shellcode appends the specified user credentials to /etc/passwd file and exits.
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
Student-ID: SLAE-1080
No comments: