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


## 環境
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;
}
```
こうして

``` Terminal
gcc -g main.c -o bin
```
ズドン。
一応動作チェック。

``` Terminal
./bin
```
> :(

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

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

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

# 待って！あきらめるのはまだ早いよ！
(略)


## 実際にどのHexを修正するか確認する。
``` Terminal
gobjdump -d bin
```
> (略)
0000000100000f70 <_superduperUltimateCheckMethod>:
(略)
   100000f74:	c6 45 ff 00          	movb   $0x0,-0x1(%rbp) //　これだ！

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

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

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

``` Terminal
vi bin
```
``` vi
:%!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......

~~**なるほど！！**~~

``` vi
:%s/00/&/gn
```
> 8803 matches on 551 lines

**なるほど、わからん！**

## 何処のオフセットに位置しているか調べる
``` Terminal
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を弄る。

``` Terminal
vi bin
```
``` vi
:%!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.$....

``` vi
:%!xxd -r
```

## 弄くったものを確認してみる。
``` Terminal
gobjdump -d bin
```
> (略)
0000000100000f70 <_superduperUltimateCheckMethod>:
(略)
   100000f74:	c6 45 ff 01          	movb   $0x1,-0x1(%rbp) // ちゃんと **$0x1** に変わってる！！

ズドン

``` Terminal
./bin
```
> ;D

**笑顔あったけぇ・・・**

![congratulation.jpg](https://qiita-image-store.s3.amazonaws.com/0/102952/208bc212-2b25-fc8a-a1dc-912e7407f7e3.jpeg "congratulation.jpg")

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