Wednesday, October 18, 2017

SLAE64 Exam - Assignment 5 of 7 (Analysis of Shellcode)

This post is the fifth of 7 exam assignments of the Pentester Academy's x86/64 Assembly and Shellcoding on Linux.

SLAE64 - 1501

Success in these 7 assignments results in the Pentester Academy's SLAE64 certification.

http://www.securitytube-training.com/online-courses/x8664-assembly-and-shellcoding-on-linux/index.html


  •  Take up at least 3 shellcode samples created using Msfpayload for linux/x86_64
  •  Use GDB to dissect the funcSonality of the shellcode
  •  Document your analysis 
All 3 shellcode.c's used in this assignment are here:

I chose 3 msfvenom shell to analyze and disect with GDB:

  • linux/x64/shell_bind_tcp
  • linux/x64/shell_reverse_tcp
  • linux/x64/exec

linux/x64/shell_bind_tcp

I reviewed this shell code's basic options:


The only required option for this shellcode is the LPORT which defaults to 4444

I generated shellcode in c format:

I noticed a few null bytes ("\x00") in the shellcode, so I re-ran the command with the -b (bad character removal) option:


I noted that the shellcode size was 127 bytes.

I pasted the shellcode into the shellcode.c template:


I compiled it with the following command:


 gcc -fno-stack-protector -z execstack shellcode.c -o shellcode

I loaded the shellcode binary into GDB with the following command:

$ gdb -q ./shellcode -tui

I set up the GDB interface as follows:


Note: I defined the intel syntax via the .gdbinit file.

I "stepi'd" until the decoding loop finished:


I noticed that the code at <code+39> had decoded into something resembling a syssocket syscall (0x29).  I advanced the execution to the first syscall and examined the registers:

Note also used the "x/6xg $rsp" command to show the first six positions on the stack.


I noticed that prior to the execution of the syscall command, that rax had the syssocket value of 41, the rdi had 2, the rsi had 1 and rdx had 0.  I executed the first system call and noted the return value of 3 in rax.  



I stepi'd to the next system call and examined the registers and stack:


This time the rax had 49 (bind), the rdi had 3, the rsi had the value of the default port 4444 (0x5c11) and the rdx had a value of 16.  I executed the system call and noted the return value of 0.

I stepi'd to the next system call.


The rax had 50 (listen).  The rdi had 3 (int fd) and the rsi had memory location of port 4444.

I steps'd to the next system call.



The rax had 33 (dup).  The rdi had 4 (oldfd) and the rsi has 2 (newfd).  The syscall was followed by a jne command which repeated the syscall until the rsi decremented to 0.  Then the syscall executed with a return value of 0 in rax.

I stepi'd to the last system call.



The rax had 59 (execve).  The rdi had the memory location that holds the /bin//sh string (in hex) and the rsi had a pointer which pointed to the memloc of the /bin//sh string.

I executed the syscall, and in another terminal connected to the bind via netcat.



It worked.  Yay.

inux/x64/shell_reverse_tcp


I reviewed this shell code's basic options:


I noticed that it had two basic options; the LHOST and the LPORT(which defaults to port 4444).

I generated the shellcode in c format:

I noticed a null byte ("\x00"), so I reran it adding msfvenom's -b (bad character removal) switch:



Next, I  pasted the shellcode in the shellcode.c template:


I compiled it with the following gcc command:


$   gcc -fno-stack-protector -z execstack shellcode.c -o shellcode

I put the resulting binary (shellcode) in gdb and examined the state of the registers and stack at the start of the code section of the binary.

$ gdb -q ./shellcode -tui


I noticed that the decoding stub ended at <code+37> (after the loop finishes) and that the rest was gibberish that would decode when the loop finished.  I advanced to when the loop finishes and examined the decoded shellcode (starting at <code+39>).



After the decoding loop finished, I examined the first 8 assembly instructions and notice that now the opcode resembled a syssocket system call set up (0x29; 41).  I advanced the the first system call and examined the state of the registers and stack.



Prior to the first system call the rax contained 41 (syssocket).  The rdi contained 0; rsi was 1, rdx was 0.
I executed the syscall and noted a return value of 3 in the rax.

I advanced to the next syscall and examined the state of the registers and stack.



This time the rax held 42 (connect).  The rdi had 3; rsi held the memory location of the IP (0x0100007f; which is 127.0.0.1) and the port (0x5c11; which is 4444).  The rdx held 16 (length of string in rsi).  I executed the syscall.


Next was the dup section (33).  I stepi'd through the jne loop and watched as the rsi decremented to 0.   I executed the syscall and noted the return value of 0 in the rax.

I advanced to the next syscall.



The rax held 59 (execve). The rdi had the stack pointer to the /bin//sh string.  The rsi had the stack pointer that pointed to the memloc of the /bin//sh string.  The rdx held 0.

I executed the syscall.



It worked. Yay.

linux/x64/exec

I reviewed this shell code's basic options:


I noted that the only argument was the CMD.  I planned to the use the string "cat /etc//passwd" (added an extra "/" to the string to make it an even 16 bytes).

I generated and examined the shellcode in c format.


I noticed some null bytes, so I reran the command with the -b switch.


I pasted the shellcode into the shellcode.c template as before and compiled it with a modified gcc command as before.

Then, I put the shellcode binary in gdb.

gdb -q ./shellcode -tui



I set up gdb by setting a breakpoint for the beginning of the shellcode ("code") section of the c-based binary.  I also set up the tui interface to display the assembly and registers.

I saw that the decoder stub ended at the loop command (<code+37>).  Noticed that after the loop were commands that were unrecognized by gdb or unusual in shellcode.  I stepi'd through the loop function and noticed that the code from <code+39> changed to recognizable syscall preparation commands.



Seeing indications that the code after the stub had decoded properly, I advanced to the first syscall and inspected the state of the registers and stack.



The rax held 59 (execve).  The rdi held memloc of the "/bin/sh" string.  The rsi held memloc pointer to the "/bin/sh" string.  I executed the syscall.



The "cat /etc/passwd" command successfully executed.

It worked. Yay.


1 comment:

  1. Situs Judi Slot Online dan Judi Bola Online Terpercaya
    Kumpulan 8 keuntungan 인천광역 출장샵 bermain 청주 출장샵 situs judi slot online 광주광역 출장안마 terpercaya, daftar agen judi 김포 출장마사지 online seperti judi 청주 출장안마 slot online, judi bola, slot joker123 terbaik.

    ReplyDelete