Friday 10 April 2020


This blog post has been created for completing the requirements of SecurityTube Linux Assembly Expert Certification:http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/Student ID: SLAE - 1342

Hello Shellcoders,
    It's been a while since I have written any article. So due to the COVID-19 outbreak, I got a chance to relearn assembly and start working on my SLAE assignments again, if you haven’t seen my Assignment 1 blog post on bind shell x86 shellcoding, then you can check it [Here].
Today in this post we will be discussing the Reverse Tcp Shell x86 Shellcode which is the second assignment for the SLAE exam. So the requirement is:
Create a shell_reverse_tcp shellcode
  • Reverse connection to configured IP and port.
  • Execs shell on successful connection 
IP and port should be easily configurable.
So, first let’s see what a reverse shell is and how it works,


So unlike the previously discussed post on bind shell x86 shellcoding, reverse shell is slightly different. If you will pay attention to the above diagram, in reverse shell what an attacker generally do is,  he first initiates a reverse TCP connection from the victim machine that has been compromised and uses it to get back to a host (which the attacker controls). Then after successful connect b/w victim computer and attacker computer it launches a bash or sh shell in case of Linux with which the attacker can interact.

I hope the basic understanding about the reverse shell is clear in your mind now. If you still have any doubt then feel free to ping me on twitter [@Pwsecspirit] Let's start by seeing the C code first for the reverse shell to get the idea of implementation in assembly x86. So I am referring to this C code, which you can find [Here].

It gives us a rough idea about what syscalls we will be needing in our journey.
  • socket()
  • connect()
  • dup2()
  • execve()
Alright so these are the syscalls that we need to use, but how would we be able to call them? Well for that we will need socketcall() Now in my last post I read the value from “unistd_32.h” itself, but now I use sysref tool by one of my friends @berkcgoksel. Go try it if you know which syscall you want to look for.


Okay so " sys_Socketcall " is at 102 number, in hex it's value would be 0x66. Now in assembly we can't write use connect().  A particular value is assigned to each call instead. We need call numbers for the socket and connect calls.


Okay we will need 1 for socket() and 3 for connect() AF_MAX values. Now let's begin with the assembly code.

Your assembly must have _start in the code so it will understand that the code will begin from that point. Now start writing in the _start section:


As discussed in the previous post we are going to use the same XOR operation. If you don’t know about XOR, let me tell you there is a very beautiful property of XOR which we are using here,
The property says , XOR something with itself will always be 0.
So, " xor eax, eax " will be 0 or NULL out the eax register , same with “xor ebx,ebx” ebx register and same with “xor ecx,ecx” ecx register. All of these  instruction takes 2 bytes in our shellcode so in order to save our 1 byte I have used cdq because the CDQ instruction copies the sign (bit 31) of the value in the EAX register into every bit position in the EDX register.


Everything is explained in the comments but let me clear some stuff just in case.. In assembly we use " ; " semicolon to comment something.
  • EAX- System call number
  • EBX- First argument
  • ECX- Second argument
  • EDX- Third argument
  • ESI- Forth argument
  • EDI- Fifth argument
In the end when everything is done we use " int 0x80 " to interrupt the call. In normal language it's like calling the kernel, giving them all register values and using those values the kernel will  get the work done for us. Ez Pz? Moving ahead.


Well, whenever you interrupt the call the return value of the function gets stored in the eax register. So to save it for our future reference we can save it in some other register that we are not using. So I chose the esi register and I am using xchg instruction so it will simply exchange the value between them.
Its like if esi -> 0 
And eax -> 4

Then after (xchg esi, eax) , the values or the data will get exchanged. ESI will now have 4 and EAX will have 0. Now lets have a look at connect().


It will call connect() , also if you want to change the ip address and port number then you can simply change “push dword 0x8198a8c0 ” for ip in hex-> little endian , " mov word dx,0x697a " for port , with your hex value of your port number.

Now we will need dup2() , Read more about from [Here]. First thing first, we need to find the dup2 syscall number.


The syscall number for dup2 is 63 which is 0x3f in hex.


So we are just running the loop and it will run 3 times with the value. Here we are using a loop for duplicating in, out and error with the file descriptor. Now we are left with the final thing.




This is the basic execve() shellcode. It will just pop the " /bin/sh " shell for us xD . Read more about it. [Here]


Here is the result


In the 1st pane I've just assembled the assembly file and linked the object file.
In the 2nd pane , the attacker is listening on port 31337, "nc -nvlp 31337" command is running to start listening on port 31337.
In pane 3 , I am just executing the shellcode.
In pane 4, I have just shown my IP address.

Please let me know if I made any mistakes,

Thanks,
Spirited Wolf

2 comments

Please tell us if we have done anything wrong :) and please share our website if you like.