LoginSignup
7
6

More than 5 years have passed since last update.

C言語でビルド済みの実行ファイルを書き換えてみた。

Last updated at Posted at 2016-09-07

環境

Mac / gcc / gdb / binutils

対象になるコードをビルド

main.c
#include <stdio.h>
#include <stdbool.h>

static bool superduperUltimateCheckMethod() {
    bool response = false; // ミス、本当はtrueを返すのが正しかった。。。
    return response;
}

int main() {
    printf("%s", superduperUltimateCheckMethod() ? ";D" : ":(");
    return 0;
}

こうして

gcc -g main.c -o bin

ズドン。
一応動作チェック。

./bin

:(

当然 superduperUltimateCheckMethod は常に false を返してくる実装になっているので、渋い顔文字が出力されます。

求める正しい挙動は ;D が出力される事です。
本来ならばコードを修正する所ですが、今回はこのバイナリ自体を弄って正しい挙動を実現してみます。

「コード・・・バグっちゃったね・・・///」

待って!あきらめるのはまだ早いよ!

(略)

実際にどのHexを修正するか確認する。

gobjdump -d bin

(略)
0000000100000f70 <_superduperUltimateCheckMethod>:
(略)
100000f74: c6 45 ff 00 movb $0x0,-0x1(%rbp) // これだ!

正しくは $0x1 となって居ないとちゃんと動作しない部分が、上記のコードのミスで $0x0 となっていますね。

目的は、Hex上の「00」を「01」に治すだけ!

では修正に向けて、早速viでバイナリの中身を見てみましょう。

vi bin
:%!xxd

42 0000290: 626f 6c5f 7074 7200 5f5f 4441 5441 0000 bol_ptr.DATA..
43 00002a0: 0000 0000 0000 0000 0010 0000 0100 0000 ................
44 00002b0: 1000 0000 0000 0000 0010 0000 0300 0000 ................
45 00002c0: 0000 0000 0000 0000 0600 0000 0100 0000 ................
46 00002d0: 0000 0000 0000 0000 5f5f 6c61 5f73 796d ........
la_sym
47 00002e0: 626f 6c5f 7074 7200 5f5f 4441 5441 0000 bol_ptr.__DATA..
48 00002f0: 0000 0000 0000 0000 1010 0000 0100 0000 ................
49 0000300: 0800 0000 0000 0000 1010 0000 0300 0000 ................
50 0000310: 0000 0000 0000 0000 0700 0000 0300 0000 ................
51 0000320: 0000 0000 0000 0000 1900 0000 4800 0000 ............H...
52 0000330: 5f5f 4c49 4e4b 4544 4954 0000 0000 0000 __LINKEDIT......

なるほど!!

:%s/00/&/gn

8803 matches on 551 lines

なるほど、わからん!

何処のオフセットに位置しているか調べる

gobjdump -x bin

(略)
索引名 サイズ VMA LMA File off Algn
0 .text 00000062 0000000100000f20 0000000100000f20 00000f20 2*4
(略)
SYMBOL TABLE:
(略)
**0000000100000f70
* d 24 FUN 01 0000 _superduperUltimateCheckMethod

太字になっている所が大事な所です。

私の環境での結果を見やすく纏めると

VMA = 0000000100000f20
fileOff = 00000f20
targetSymbol = 0000000100000f70

となります。

targetOffset = fileOff + (targetSymbol - VMA)

の公式を元に計算すると、私の環境では
f70 との結果が出ました。

つまり、 「00 を 01 に変更する必要があるオフセット位置は "f70"」 という事まで分かりました。

実際にHexを弄る。

vi bin
:%!xxd
:/f70

248 0000f70: 5548 89e5 c645 ff 00 8a45 ff24 010f b6c0 UH...E...E.$....

やったぜ。

今回修正対象になるのは 「00」 なので、一目瞭然です。

viでここを 「01」 に変更して保存します。

248 0000f70: 5548 89e5 c645 ff 01 8a45 ff24 010f b6c0 UH...E...E.$....

:%!xxd -r

弄くったものを確認してみる。

gobjdump -d bin

(略)
0000000100000f70 <_superduperUltimateCheckMethod>:
(略)
100000f74: c6 45 ff 01 movb $0x1,-0x1(%rbp) // ちゃんと $0x1 に変わってる!!

ズドン

./bin

;D

笑顔あったけぇ・・・

congratulation.jpg

参考:http://dev.ariel-networks.com/wp/archives/1107

7
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6