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