qemu monitorを使ってメモリ上にロードされている実行中のアプリケーションの機械語をダンプ
qemu monitorを使う記事の続きです。
前回記事はこちらになります。
本記事ではwalkアプリケーションを起動した状態でqemu monitorを使ってメモリ上にマッピングされたwalkの実行ファイルを探し当てるところまでをやります。
qemu monitorを使ってアプリケーションの実行コードがロードされている場所をのぞいて見ましょう。hariboteOSではGDTの格納内容は以下のようになっています。
index | content |
---|---|
1003 | taska用(アプリはないので使っていない) |
1004 | idle用(アプリはないので使っていない) |
1005 | 1個目に確保されるアプリのLDTへの参照 |
1006 | 2個目に確保されるプリのLDTへの参照 |
... | 省略 |
1エントリの登録内容はこんな感じ。
struct SEGMENT_DESCRIPTOR { short limit_low, base_low; char base_mid, access_right; char limit_high, base_high; };
構造体上での表現 63 55 47 39 31 23 15 7 0 +--------+--------+--------+--------+--------+--------+--------+--------+ |base_hi |limit_hi| ar |base_mid| base_low | limit_low | +--------+--------+--------+--------+--------+--------+--------+--------+ CPUの仕様上のデスクリプタ ※limit_highの上位4bitはアクセス属性の続きになります。だから実際はCPUは上の構造体を以下の形式で扱います。 63 55 47 39 31 23 15 7 0 +--------+----+----+--------+--------+--------+--------+--------+--------+ |base_hi |ar |l_hi| ar |base_mid| base_low | limit_low | +--------+----+----+--------+--------+--------+--------+--------+--------+ ※入りきらない変数名は省略しています
GDTは前回記事のinfo registersコマンドの出力にある通り、
GDT= 00270000 0000ffff
この場所に格納されています。
アプリケーションのLDTが登録されている場所に近い1000×8(0x1F40
)以降のエントリをダンプして見ます
GDTのindexが8倍されているこが腑に落ちない人は以下の記事にまとめてあるので参考にしてください。
(qemu) xp /10xg 0x271F40 0000000000271f40: 0x000089032c500067 0x000089032d0c0067 0000000000271f50: 0x000089032dc80067 0x00008200508c000f 0000000000271f60: 0x000082005148000f 0x000082005204000f 0000000000271f70: 0x0000820052c0000f 0x00008200537c000f 0000000000271f80: 0x000082005438000f 0x0000820054f4000f
これを表に起こして見ます。
idx | description | base_hi | ar | l_hi | ar | base_mid | base_low | limit_low | base | limi | ar |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0x000089032c500067 | 00 | 0 | 0 | 89 | 03 | 2c50 | 0067 | 00032c50 | 00067 | 089 |
1 | 0x000089032d0c0067 | 00 | 0 | 0 | 89 | 03 | 2d0c | 0067 | 00032d0c | 00067 | 089 |
2 | 0x000089032dc80067 | 00 | 0 | 0 | 89 | 03 | 2dc8 | 0067 | 00032dc8 | 00067 | 089 |
3 | 0x00008200508c000f | 00 | 0 | 0 | 82 | 00 | 508c | 000f | 0000508c | 0000f | 082 |
4 | 0x000082005148000f | 00 | 0 | 0 | 82 | 00 | 5148 | 000f | 00005148 | 0000f | 082 |
5 | 0x000082005204000f | 00 | 0 | 0 | 82 | 00 | 5204 | 000f | 00005204 | 0000f | 082 |
6 | 0x0000820052c0000f | 00 | 0 | 0 | 82 | 00 | 52c0 | 000f | 000052c0 | 0000f | 082 |
7 | 0x00008200537c000f | 00 | 0 | 0 | 82 | 00 | 537c | 000f | 0000537c | 0000f | 082 |
8 | 0x000082005438000f | 00 | 0 | 0 | 82 | 00 | 5438 | 000f | 00005438 | 0000f | 082 |
9 | 0x0000820054f4000f | 00 | 0 | 0 | 82 | 00 | 54f4 | 000f | 000054f4 | 0000f | 082 |
5番目のエントリのLDT00005204
を表示。なおこれはコンソール1で実行したアプリケーションのLDTになります。
(qemu) xp /2xg 0x00005204 0000000000005204: 0x0040fa06200001e6 0x0040f3063000cfff
idx | description | base | lim | ar |
---|---|---|---|---|
1 | 0x0040fa06200001e6 | 00062000 | 001e6 | 4fa |
2 | 0x0040f3063000cfff | 00063000 | 0cfff | 4f3 |
とりあえずコードセグメント00062000
をダンプ
(qemu) xp /486bc 0x00062000 0000000000062000: '\x00' '\xd0' '\x00' '\x00' 'H' 'a' 'r' 'i' 0000000000062008: '\x00' '\x00' '\x00' '\x00' '\x00' '\x04' '\x00' '\x00' 0000000000062010: '\x07' '\x00' '\x00' '\x00' '\xe0' '\x01' '\x00' '\x00' 0000000000062018: '\x00' '\x00' '\x00' '\xe9' '\xb7' '\x01' '\x00' '\x00' 0000000000062020: '\x10' '\x04' '\x00' '\x00' 'U' '\x89' '\xe5' 'W' 0000000000062028: 'V' '\xbf' 'L' '\x00' '\x00' '\x00' 'S' '\xbe' 0000000000062030: '8' '\x00' '\x00' '\x00' 'R' '\xe8' 'M' '\x01' 0000000000062038: '\x00' '\x00' 'h' '\x80' '>' '\x00' '\x00' '\xe8' 0000000000062040: 'd' '\x01' '\x00' '\x00' 'h' '\x00' '\x04' '\x00' 0000000000062048: '\x00' 'j' '\xff' 'j' 'd' 'h' '\xa0' '\x00' 0000000000062050: '\x00' '\x00' 'P' '\xe8' '\xbd' '\x00' '\x00' '\x00' 0000000000062058: '\x89' 'E' '\xf0' 'j' '\x00' 'j' '_' 'h' 0000000000062060: '\x9b' '\x00' '\x00' '\x00' 'j' '\x18' 'j' '\x04' 0000000000062068: 'P' '\xe8' '\xf1' '\x00' '\x00' '\x00' '\x83' '\xc4' 0000000000062070: '0' 'h' '\x05' '\x04' '\x00' '\x00' 'j' '\x01' 0000000000062078: 'j' '\x03' 'j' '8' 'j' 'L' '\xff' 'u' 0000000000062080: '\xf0' '\xe8' '\xb1' '\x00' '\x00' '\x00' '\x83' '\xc4' 0000000000062088: '\x18' 'j' '\x01' '\xe8' ';' '\x01' '\x00' '\x00' 0000000000062090: 'h' '\x05' '\x04' '\x00' '\x00' 'j' '\x01' '\x89' 0000000000062098: '\xc3' 'j' '\x00' 'V' 'W' '\xff' 'u' '\xf0' 00000000000620a0: '\xe8' '\x92' '\x00' '\x00' '\x00' '\x83' '\xc4' '\x1c' 00000000000620a8: '\x83' '\xfb' '4' 't' 'W' '\x83' '\xfb' '6' 00000000000620b0: 't' 'E' '\x83' '\xfb' '8' 't' '6' '\x83' 00000000000620b8: '\xfb' '2' 't' '\'' '\x83' '\xfb' '\n' 't' 00000000000620c0: '\r' 'h' '\x05' '\x04' '\x00' '\x00' 'j' '\x01' 00000000000620c8: 'j' '\x03' 'V' 'W' '\xeb' '\xb0' '\xff' 'u' 00000000000620d0: '\xf0' '\xe8' '\xe7' '\x00' '\x00' '\x00' 'X' '\x8d' 00000000000620d8: 'e' '\xf4' '[' '^' '_' ']' '\xe9' '+' 00000000000620e0: '\x00' '\x00' '\x00' '\x83' '\xfe' 'O' '\x7f' '\xd4' 00000000000620e8: '\x83' '\xc6' '\x08' '\xeb' '\xcf' '\x83' '\xfe' '\x18' 00000000000620f0: '~' '\xc5' '\x83' '\xee' '\x08' '\xeb' '\xc0' '\x81' 00000000000620f8: '\xff' '\x93' '\x00' '\x00' '\x00' '\x7f' '\xb3' '\x83' 0000000000062100: '\xc7' '\x08' '\xeb' '\xae' '\x83' '\xff' '\x04' '~' 0000000000062108: '\xa4' '\x83' '\xef' '\x08' '\xeb' '\x9f' '\xba' '\x04' 0000000000062110: '\x00' '\x00' '\x00' '\xcd' '@' 'W' 'V' 'S' 0000000000062118: '\xba' '\x05' '\x00' '\x00' '\x00' '\x8b' '\\' '$' 0000000000062120: '\x10' '\x8b' 't' '$' '\x14' '\x8b' '|' '$' 0000000000062128: '\x18' '\x8b' 'D' '$' '\x1c' '\x8b' 'L' '$' 0000000000062130: ' ' '\xcd' '@' '[' '^' '_' '\xc3' 'W' 0000000000062138: 'V' 'U' 'S' '\xba' '\x06' '\x00' '\x00' '\x00' 0000000000062140: '\x8b' '\\' '$' '\x14' '\x8b' 't' '$' '\x18' 0000000000062148: '\x8b' '|' '$' '\x1c' '\x8b' 'D' '$' ' ' 0000000000062150: '\x8b' 'L' '$' '$' '\x8b' 'l' '$' '(' 0000000000062158: '\xcd' '@' '[' ']' '^' '_' '\xc3' 'W' 0000000000062160: 'V' 'U' 'S' '\xba' '\x07' '\x00' '\x00' '\x00' 0000000000062168: '\x8b' '\\' '$' '\x14' '\x8b' 'D' '$' '\x18' 0000000000062170: '\x8b' 'L' '$' '\x1c' '\x8b' 't' '$' ' ' 0000000000062178: '\x8b' '|' '$' '$' '\x8b' 'l' '$' '(' 0000000000062180: '\xcd' '@' '[' ']' '^' '_' '\xc3' 'S' 0000000000062188: '\xba' '\x08' '\x00' '\x00' '\x00' '.' '\x8b' '\x1d' 0000000000062190: ' ' '\x00' '\x00' '\x00' '\x89' '\xd8' '\x05' '\x00' 0000000000062198: '\x80' '\x00' '\x00' '.' '\x8b' '\r' '\x00' '\x00' 00000000000621a0: '\x00' '\x00' ')' '\xc1' '\xcd' '@' '[' '\xc3' 00000000000621a8: 'S' '\xba' '\x09' '\x00' '\x00' '\x00' '.' '\x8b' 00000000000621b0: '\x1d' ' ' '\x00' '\x00' '\x00' '\x8b' 'L' '$' 00000000000621b8: '\x08' '\xcd' '@' '[' '\xc3' 'S' '\xba' '\x0e' 00000000000621c0: '\x00' '\x00' '\x00' '\x8b' '\\' '$' '\x08' '\xcd' 00000000000621c8: '@' '[' '\xc3' '\xba' '\x0f' '\x00' '\x00' '\x00' 00000000000621d0: '\x8b' 'D' '$' '\x04' '\xcd' '@' '\xc3' 'U' 00000000000621d8: '\x89' '\xe5' ']' '\xe9' 'D' '\xfe' '\xff' '\xff' 00000000000621e0: 'w' 'a' 'l' 'k' '\x00' '*'
ダンプ内容がwalk.hrbの実行バイナリと一致
$ hexdump -C walk.hrb 00000000 00 d0 00 00 48 61 72 69 00 00 00 00 00 04 00 00 |....Hari........| 00000010 07 00 00 00 e0 01 00 00 00 00 00 e9 b7 01 00 00 |................| 00000020 10 04 00 00 55 89 e5 57 56 bf 4c 00 00 00 53 be |....U..WV.L...S.| 00000030 38 00 00 00 52 e8 4d 01 00 00 68 80 3e 00 00 e8 |8...R.M...h.>...| 00000040 64 01 00 00 68 00 04 00 00 6a ff 6a 64 68 a0 00 |d...h....j.jdh..| 00000050 00 00 50 e8 bd 00 00 00 89 45 f0 6a 00 6a 5f 68 |..P......E.j.j_h| 00000060 9b 00 00 00 6a 18 6a 04 50 e8 f1 00 00 00 83 c4 |....j.j.P.......| 00000070 30 68 05 04 00 00 6a 01 6a 03 6a 38 6a 4c ff 75 |0h....j.j.j8jL.u| 00000080 f0 e8 b1 00 00 00 83 c4 18 6a 01 e8 3b 01 00 00 |.........j..;...| 00000090 68 05 04 00 00 6a 01 89 c3 6a 00 56 57 ff 75 f0 |h....j...j.VW.u.| 000000a0 e8 92 00 00 00 83 c4 1c 83 fb 34 74 57 83 fb 36 |..........4tW..6| 000000b0 74 45 83 fb 38 74 36 83 fb 32 74 27 83 fb 0a 74 |tE..8t6..2t'...t| 000000c0 0d 68 05 04 00 00 6a 01 6a 03 56 57 eb b0 ff 75 |.h....j.j.VW...u| 000000d0 f0 e8 e7 00 00 00 58 8d 65 f4 5b 5e 5f 5d e9 2b |......X.e.[^_].+| 000000e0 00 00 00 83 fe 4f 7f d4 83 c6 08 eb cf 83 fe 18 |.....O..........| 000000f0 7e c5 83 ee 08 eb c0 81 ff 93 00 00 00 7f b3 83 |~...............| 00000100 c7 08 eb ae 83 ff 04 7e a4 83 ef 08 eb 9f ba 04 |.......~........| 00000110 00 00 00 cd 40 57 56 53 ba 05 00 00 00 8b 5c 24 |....@WVS......\$| 00000120 10 8b 74 24 14 8b 7c 24 18 8b 44 24 1c 8b 4c 24 |..t$..|$..D$..L$| 00000130 20 cd 40 5b 5e 5f c3 57 56 55 53 ba 06 00 00 00 | .@[^_.WVUS.....| 00000140 8b 5c 24 14 8b 74 24 18 8b 7c 24 1c 8b 44 24 20 |.\$..t$..|$..D$ | 00000150 8b 4c 24 24 8b 6c 24 28 cd 40 5b 5d 5e 5f c3 57 |.L$$.l$(.@[]^_.W| 00000160 56 55 53 ba 07 00 00 00 8b 5c 24 14 8b 44 24 18 |VUS......\$..D$.| 00000170 8b 4c 24 1c 8b 74 24 20 8b 7c 24 24 8b 6c 24 28 |.L$..t$ .|$$.l$(| 00000180 cd 40 5b 5d 5e 5f c3 53 ba 08 00 00 00 2e 8b 1d |.@[]^_.S........| 00000190 20 00 00 00 89 d8 05 00 80 00 00 2e 8b 0d 00 00 | ...............| 000001a0 00 00 29 c1 cd 40 5b c3 53 ba 09 00 00 00 2e 8b |..)..@[.S.......| 000001b0 1d 20 00 00 00 8b 4c 24 08 cd 40 5b c3 53 ba 0e |. ....L$..@[.S..| 000001c0 00 00 00 8b 5c 24 08 cd 40 5b c3 ba 0f 00 00 00 |....\$..@[......| 000001d0 8b 44 24 04 cd 40 c3 55 89 e5 5d e9 44 fe ff ff |.D$..@.U..].D...| 000001e0 77 61 6c 6b 00 2a 00 |walk.*.|
hrbファイルの構造と照らし合わせて逆アセンブル
(qemu) xp /486bi 0x00062000 0x00062000: 00 d0 addb %dl, %al 0x00062002: 00 00 addb %al, (%eax) 0x00062004: 48 decl %eax 0x00062005: 61 popal 0x00062006: 72 69 jb 0x62071 0x00062008: 00 00 addb %al, (%eax) 0x0006200a: 00 00 addb %al, (%eax) 0x0006200c: 00 04 00 addb %al, (%eax, %eax) 0x0006200f: 00 07 addb %al, (%edi) 0x00062011: 00 00 addb %al, (%eax) 0x00062013: 00 e0 addb %ah, %al 0x00062015: 01 00 addl %eax, (%eax) 0x00062017: 00 00 addb %al, (%eax) 0x00062019: 00 00 addb %al, (%eax) 0x0006201b: e9 b7 01 00 00 jmp 0x621d7;!!!!! このジャンプ命令でアプリの実行開始番地に飛ぶ ・・・長すぎるので略・・・ 0x000621d7: 53 pushl %ebx;!!!!ここにジャンプ!!!!! 0x000621d8: ba 00 00 00 8b movl $0x8b000000, %edx 0x000621dd: 5c popl %esp 0x000621de: 24 08 andb $8, %al 0x000621e0: 00 8b 24 08 cd 08 addb %cl, 0x8cd0824(%ebx) 0x000621e6: 40 incl %eax 0x000621e7: 5b popl %ebx 0x000621e8: c3 retl 0x000621e9: ba 0f 00 00 8b movl $0x8b00000f, %edx 0x000621ee: 44 incl %esp 0x000621ef: 04 cd addb $0xcd, %al 0x000621f1: 40 incl %eax 0x000621f2: c3 retl 0x000621f3: 40 incl %eax 0x000621f4: c3 retl 0x000621f5: c3 retl 0x000621f6: 55 pushl %ebp 0x000621f7: 89 fe movl %edi, %esi 0x000621f9: ff .byte 0xff 0x000621fa: ff 77 61 pushl 0x61(%edi) 0x000621fd: ff 77 61 pushl 0x61(%edi) 0x00062200: 00 00 addb %al, (%eax) ・・・ずっと00なので省略 0x00062420: 00 00 addb %al, (%eax)
walkは多分処理がリバースエンジニアリングできるほど簡単ではないのでとりあえず今日はこのくらいにしておきます。(hello worldあたりを題材にしておいたほうがよかったなぁ)
わからないこと
このセグメント内容をメモリにロードし終わった後、EIPの初期値を何にするかよくわかりません。0x0006201b
までのバイナリは実行コードではなさそうですし、jumpした番地以外の場所も実行できるプログラムなのか怪しいです。
おまけ
セグメントディスクリプタのエントリは分解された状態で格納されていますが、 これを人間にとって読みやすい形に整形する正規表現でも貼っておきます。
置換前 (0x(.{2})(.{1})(.{1})(.{2})(.{2})(.{4})(.{4}).*) 置換後 $1,$2$6$7,$4$8,$3$5 置換前:0x0040fa06200001e6 置換後:0x0040fa06200001e6,00062000,001e6,4fa original,base,limit,access_right の順のcsvになります。
参考
- qemu monitor自体はosdev-jpのslackで知りました。
- http://www15.big.or.jp/~yamamori/sun/qemu/usage.html
- https://en.wikibooks.org/wiki/QEMU/Monitor#info