ichirin2501's diary

いっちりーん。

セクションヘッダテーブルのサイズを変更してみた

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の解析を妨害することができます。
あくまで小手先の小手先って感じですが