ELF format のセクションヘッダテーブルのセクションサイズを
変更することで、アンチデバッグに応用できないかと考え、
IDA Pro demo 6.2(Linux), GDB(7.2-51.fc14),
objdump(2.20.51.0.7-8.fc14)の各3種の動作を確かめて見ました。
実験環境
Fedora14, カーネル2.6.35.14-103.fc14.i686
メモリ 2GB
もちろん32bit環境です
実験に使ったテストプログラム
#include <stdio.h> const char *s = "abcdefg"; int data[100]; int main(){ int i; puts(s); for(i=0; i<100; i++) data[i] = i; for(i=0; i<10; i++) printf("%d\n",i); return 0; }
上記のプログラムを、
gcc (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4) で、コンパイル。
その実行ファイルのセクション情報
[@ichirin c]$ readelf -S a.out There are 30 section headers, starting at offset 0x80c: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .interp PROGBITS 08048134 000134 000013 00 A 0 0 1 [ 2] .note.ABI-tag NOTE 08048148 000148 000020 00 A 0 0 4 [ 3] .note.gnu.build-i NOTE 08048168 000168 000024 00 A 0 0 4 [ 4] .gnu.hash GNU_HASH 0804818c 00018c 000020 04 A 5 0 4 [ 5] .dynsym DYNSYM 080481ac 0001ac 000060 10 A 6 1 4 [ 6] .dynstr STRTAB 0804820c 00020c 000051 00 A 0 0 1 [ 7] .gnu.version VERSYM 0804825e 00025e 00000c 02 A 5 0 2 [ 8] .gnu.version_r VERNEED 0804826c 00026c 000020 00 A 6 1 4 [ 9] .rel.dyn REL 0804828c 00028c 000008 08 A 5 0 4 [10] .rel.plt REL 08048294 000294 000020 08 A 5 12 4 [11] .init PROGBITS 080482b4 0002b4 000030 00 AX 0 0 4 [12] .plt PROGBITS 080482e4 0002e4 000050 04 AX 0 0 4 [13] .text PROGBITS 08048340 000340 0001cc 00 AX 0 0 16 [14] .fini PROGBITS 0804850c 00050c 00001c 00 AX 0 0 4 [15] .rodata PROGBITS 08048528 000528 000018 00 A 0 0 4 [16] .eh_frame_hdr PROGBITS 08048540 000540 000024 00 A 0 0 4 [17] .eh_frame PROGBITS 08048564 000564 00007c 00 A 0 0 4 [18] .ctors PROGBITS 080495e0 0005e0 000008 00 WA 0 0 4 [19] .dtors PROGBITS 080495e8 0005e8 000008 00 WA 0 0 4 [20] .jcr PROGBITS 080495f0 0005f0 000004 00 WA 0 0 4 [21] .dynamic DYNAMIC 080495f4 0005f4 0000c8 08 WA 6 0 4 [22] .got PROGBITS 080496bc 0006bc 000004 04 WA 0 0 4 [23] .got.plt PROGBITS 080496c0 0006c0 00001c 04 WA 0 0 4 [24] .data PROGBITS 080496dc 0006dc 000008 00 WA 0 0 4 [25] .bss NOBITS 08049700 0006e4 0001b0 00 WA 0 0 32 [26] .comment PROGBITS 00000000 0006e4 00002c 01 MS 0 0 1 [27] .shstrtab STRTAB 00000000 000710 0000fc 00 0 0 1 [28] .symtab SYMTAB 00000000 000cbc 000440 10 29 45 4 [29] .strtab STRTAB 00000000 0010fc 000214 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific)
セクションヘッダテーブルのサイズは上記だと Size の列の値になります。
このSizeの値を、2140000000(0x7f8dcf00)を書き換えて実験してみました。
符号あり32bit整数の最大に近い値です。メモリ確保のエラーを狙いました。
当然ですが、通常に動作させた場合は走ることを前提としています。
そのため、通常なら動作するけど、解析には失敗するみたいな形になります。
まずは IDA の結果から。
セクション | IDAの影響 | 詳細 |
---|---|---|
[ 0] | no | |
[ 1] .interp | no | |
[ 2] .note.ABI-tag | no | |
[ 3] .note.gnu.build-i | no | |
[ 4] .gnu.hash | no | |
[ 5] .dynsym | yes | 落ちはしないが、解析できない |
[ 6] .dynstr | no | |
[ 7] .gnu.version | no | |
[ 8] .gnu.version_r | no | |
[ 9] .rel.dyn | yes? | メモリ確保でPCがフリーズ、確保後に解析結果が出るかも? |
[10] .rel.plt | ? | 上と同じと思われる(未確認、二度はやりたくないw) |
[11] .init | yes | 警告が出て落ちる |
[12] .plt | yes | 警告が出て落ちる |
[13] .text | yes | 警告が出て落ちる |
[14] .fini | yes | 警告が出て落ちる |
[15] .rodata | yes | 警告が出て落ちる |
[16] .eh_frame_hdr | yes | 警告が出て落ちる |
[17] .eh_frame | yes | 警告が出て落ちる |
[18] .ctors | yes | 警告が出て落ちる |
[19] .dtors | yes | 警告が出て落ちる |
[20] .jcr | yes | 警告が出て落ちる |
[21] .dynamic | no | |
[22] .got | yes | 警告が出て落ちる |
[23] .got.plt | yes | 警告が出て落ちる |
[24] .data | yes | 警告が出て落ちる |
[25] .bss | no? | 同様の警告が出る、でも落ちない |
[26] .comment | no | |
[27] .shstrtab | no | |
[28] .symtab | yes | 落ちはしないが、解析できない |
[29] .strtab | no |
このような結果になりました。ちなみに、警告が出て落ちるときのエラーは、
その後、そのままIDAが落ちます。
次に、GDB の結果です。
セクション | GDBの影響 | 詳細 |
---|---|---|
[ 0] | no | |
[ 1] .interp | no | |
[ 2] .note.ABI-tag | yes | ファイル形式の認識不可 |
[ 3] .note.gnu.build-i | yes | ファイル形式の認識不可 |
[ 4] .gnu.hash | no | |
[ 5] .dynsym | no | |
[ 6] .dynstr | no | |
[ 7] .gnu.version | no | |
[ 8] .gnu.version_r | no | |
[ 9] .rel.dyn | no | |
[10] .rel.plt | no | |
[11] .init | no | |
[12] .plt | no | |
[13] .text | no | |
[14] .fini | no | |
[15] .rodata | no | |
[16] .eh_frame_hdr | no | |
[17] .eh_frame | no | |
[18] .ctors | no | |
[19] .dtors | no | |
[20] .jcr | no | |
[21] .dynamic | yes | runするとコアダンプ、gdbが落ちる |
[22] .got | no | |
[23] .got.plt | no | |
[24] .data | no | |
[25] .bss | no | |
[26] .comment | no | |
[27] .shstrtab | yes | ファイル形式の認識不可 |
[28] .symtab | no | |
[29] .strtab | no |
.dynamicセクションだけコアダンプなのが気になります。
通常なら動作、GDBで動作させると落ちるってどういうことw
最後に objdump の結果です。
セクション | objdumpの影響 | 詳細 |
---|---|---|
[ 0] | no | |
[ 1] .interp | no | |
[ 2] .note.ABI-tag | no? | メモリ確保でフリーズ。その後、解析は可 |
[ 3] .note.gnu.build-i | no? | メモリ確保でフリーズ。その後、解析は可 |
[ 4] .gnu.hash | no | |
[ 5] .dynsym | yes | 解析できない |
[ 6] .dynstr | yes | 解析できない |
[ 7] .gnu.version | no | |
[ 8] .gnu.version_r | yes | 解析できない |
[ 9] .rel.dyn | no | |
[10] .rel.plt | no | |
[11] .init | no | |
[12] .plt | no | |
[13] .text | no | |
[14] .fini | no | |
[15] .rodata | no | |
[16] .eh_frame_hdr | no | |
[17] .eh_frame | no | |
[18] .ctors | no | |
[19] .dtors | no | |
[20] .jcr | no | |
[21] .dynamic | no | |
[22] .got | no | |
[23] .got.plt | no | |
[24] .data | no | |
[25] .bss | no? | メモリ確保でフリーズ。その後、解析は可 |
[26] .comment | no | |
[27] .shstrtab | yes | 解析できない |
[28] .symtab | yes | 解析できない |
[29] .strtab | no |
以上のような結果になりました。
気になるのは、書き換えた値と実験環境のメモリとの関連性です…。
結論としては、
動作環境が制限されてしまいますが、今回のアンチデバッグ手法は
小手先としては十分有効かと思われます。
修正するのがめんどくさいw
追記 11/27 15:25
テストプログラムを実際に書き換えたファイル
(.dynamic, .data, .symtab セクションの書き換えを行った)
http://dl.dropbox.com/u/18954202/anti.out
余談
セクションのフラグを書き換えることで、
IDAの解析を妨害することができます。
あくまで小手先の小手先って感じですが