コンテンツにスキップ

Cache Me Outside

tl;dr

tcache poisoning

プログラム

  • FLAG 付きの malloc を 7 回 (A と呼ぶ)
  • FLAG なしの malloc を 1 回 (B と呼ぶ)
  • A を free
  • B を free
  • 任意のアドレス(入力)に任意の 1 バイト(入力)を代入
  • malloc して、出力

malloc は全て 0x80 バイトです。

解法

さて、malloc というのは最後に free をしたものを返すため、何もしないと最後の malloc で返ってくるのは B です。

また、今回の場合は malloc サイズが小さいため tcache という仕組みの 双方向連結リスト (free list) に繋がれます。free list の様子を見てみましょう。

  • 最初
bin -> 無
  • free(A)
bin -> A
  • free(B)
bin -> B -> A

ここで、任意の 1 バイトを変えられる

  • malloc
bin -> A

tcache bin も他の malloc chunk 同様に FD, BK で管理されている訳なので、その FD を書き換えて malloc をする時にこんな状態にすれば FLAG が出力されそうな気がしますね。

bin -> A
B -> A (関係ない)

B のアドレスの下位 1 バイトを 0 にすると FLAG が出るっぽいので、tcache bin の FD の下位 1 バイトまでの offset を探しましょう。

入力は最初に malloc したアドレスからの offset なので、tcache bin からそう遠くはないはずです。ローカルとリモートでは libc が違うので、offset は検討をつけてから全探索します。

結果、-5144 でした。

from pwn import *

#p=process("./heapedit")
p=remote("mercury.picoctf.net",17612)
p.sendline(b"-5144")
p.sendline(b"\x00")
p.recvuntil(b"Value:")
print(p.recvall())
p.close()

最終更新日: 2021年4月8日