satumaimoの備忘録

個人的なメモ中心

インラインアセンブラで.textセクション内にデータを挿入する

はじめに

書籍「実践バイナリ解析」第6章の終わりに、以下の練習問題がありました。

objdumpを混乱させるプログラムを記述してみよう。

という訳で、本記事ではobjdumpによる解析を妨げるHello Worldプログラムの作成を試みます。

方針

objdumpのような線形逆アセンブラは、解析対象のセクション内にデータが含まれていた場合、そのデータを誤って命令として認識してしまう可能性があります。

従って本記事では、.textセクションのmainシンボル内にデータを挿入してobjdumpによる解析を妨げられないかを試します。

実装

以下のプログラムを実装しました。

#include <stdio.h>

int main(void){
  char* a;
  __asm__("jmp HOGE \n\t"
          "HELLO: \n\t"
          ".string \"Hello World!\" \n\t"
          "HOGE: \n\t"
          "mov %0, OFFSET FLAT:HELLO \n\t" 
          : "=r" (a)
          );
  printf("%s\n", a);
  return 0;
}

インラインアセンブラを用いて.string \"Hello World!\"をコード内に挿入し、かつ挿入したデータを命令として実行しないようにjmp命令を使用しています。

なお、上記プログラムはintel構文を使ってインラインアセンブリを記述しているので、コンパイル時には-masm=intelオプションを追加する必要があります。

コンパイル&実行

コンパイル

$ gcc -masm=intel -o hello.elf hello.c

実行

$ ./hello.elf
Hello World!

objdumpによる逆アセンブル

objdumpの実行

$ objdump -d -M intel hello.elf

実行結果(抜粋)

0000000000400526 <main>:
  400526:       55                      push   rbp
  400527:       48 89 e5                mov    rbp,rsp
  40052a:       48 83 ec 10             sub    rsp,0x10
  40052e:       eb 0d                   jmp    40053d <HOGE>

0000000000400530 <HELLO>:
  400530:       48                      rex.W
  400531:       65 6c                   gs ins BYTE PTR es:[rdi],dx
  400533:       6c                      ins    BYTE PTR es:[rdi],dx
  400534:       6f                      outs   dx,DWORD PTR ds:[rsi]
  400535:       20 57 6f                and    BYTE PTR [rdi+0x6f],dl
  400538:       72 6c                   jb     4005a6 <__libc_csu_init+0x46>
  40053a:       64 21 00                and    DWORD PTR fs:[rax],eax

000000000040053d <HOGE>:
  40053d:       48 c7 c0 30 05 40 00    mov    rax,0x400530
  400544:       48 89 45 f8             mov    QWORD PTR [rbp-0x8],rax
  400548:       48 8b 45 f8             mov    rax,QWORD PTR [rbp-0x8]
  40054c:       48 89 c7                mov    rdi,rax
  40054f:       e8 ac fe ff ff          call   400400 <puts@plt>
  400554:       b8 00 00 00 00          mov    eax,0x0
  400559:       c9                      leave  
  40055a:       c3                      ret    
  40055b:       0f 1f 44 00 00          nop    DWORD PTR [rax+rax*1+0x0]

HELLOシンボル内に格納されているはずの"Hello World!"文字列が、誤って命令として解釈されました。

一方、HELLOシンボル以外の部分は、コード内に.string \"Hellow World!\"を挿入した影響を受けませんでした。

感想

objdumpによる逆アセンブルを妨げるのが元々の目的でしたが、結果としては.textセクション内にデータを挿入するだけで終わってしまいました。

「objdumpを混乱させる」ことに成功したかは微妙ですが、意外と簡単に.textセクション内にデータを挿入できたのは面白かったです。

参考サイト

GCCのインラインアセンブラの書き方 for x86 - OSのようなもの

gcc - Intel assembly syntax OFFSET - Stack Overflow

gccでアセンブラを出力しそれを実行ファイルにする

gdbをデフォルトでintel記法にする | 初期化処理の仕組み - BioErrorLog Tech Blog

X86アセンブラ/x86アセンブラ - Wikibooks