アセンブラを学ぼうと「いまどきのアセンブラプログラミング」という本を読みました。

しかしこの本は2004年のものでとても古く、対応していないものがありました。

そこで今回はこの本に書いてあるアセンブラの内容を今でもできるもので紹介したいと思います。

ゲームの改造の内容がメインですが、これでアセンブラに少しだけ触れることができました。


はじめに

まず今回説明するのは、exe実行ファイルの中の変数を外側からいじる方法です。

そこで今回は苦しんで覚えるC言語の開発環境であるEasyIDECを使ってC言語のプログラムを書き、exeを作ります。

そのexeをうさみみハリケーンというソフトを使って解析し、変数をいじってみます。

うさみみハリケーンはなんかいろいろ解析できるソフトです。

c言語のプログラムの準備

まずEasyIDECで以下のようなプログラムを書いて実行します。
#include <stdio.h>
int main(void)
{
	int a=5;
	char mark[]="a is above here";
	printf("a=%dです。\n",a);
	system("pause");
	printf("aに1を足して%dにしました。\n",++a);
	system("pause");
	if(a==6)
	printf("aは6です。\n");
	else
	printf("aは6ではなく%dとなっています。\n",a);
	system("pause");
	return 0;
}
このプログラムは変数aに5が入っており、
「a=5です。」
と表示し、aに1を足して
「aに1を足して6にしました。」
と表示した後、aが6なら
「aは6です。」
と表示し、aの値が6ではなかったら
「aは6ではなく(aの値)となっています。」
と表示します。

すなわち、このプログラムでは変数aは5から1足して6になりますが、外側から変数aの値が変更されていたら変数aが6ではなくなっているために分かるというものです。

途中にある"a is above here"というのは、exeをいじるときの目印として書いただけです。

これからこのプログラムの変数aを以下の3つの方法で外側からいじってみようと思います。

メモリの書き換え

exeファイルは起動するとメモリに展開されます。

すなわちメモリをいじればexeファイルの動作を書き換えることができるのです。

まず、先ほど作成したexeファイルを実行し、うさみみハリケーンでそのプロセスを選択します。

次に

検索>メモリ範囲を指定して検索

を開き、通常検索の検索に「5」を入力し、通常検索実行をクリックして検索します。


aの初期値が5なので5を検索しましたが、結果が多すぎます。

そこでexeファイル上でなにかキーを押してaの値を6にします。

その後また通常検索で「6」を検索します。


するとアドレスが1つに絞り込めました。

このアドレスをクリックすると、うさみみハリケーンのバイナリエディタの一部が黄色で示されます。


そこがメモリ上の変数aの値です。

ここを書き換えることでexeの動作を変えることができます。

例えばこの「06」の部分を「0F」にしてみましょう。

exeの画面にして何かキーを押すと


のように、aの値が6ではなく15(16進数でF)になっていることが確認できます。

このようにメモリを書き換えることでexeの動作を変化させることができました。


バイナリ解析

今度はメモリではなく、exeファイルそのものを変化させてみようと思います。

まず、うさみみハリケーンを開いて

その他>汎用ファイルアナライザ

から、「青い空を見上げればいつもそこに白い猫」というソフトを起動します。

ここへexeファイルをドロップし、

バイナリエディア起動・編集

をクリックしてバイナリエディタを開きます。

そこには一番左側にアドレス、真ん中に数字が羅列されていて、右側に文字化けした文字が羅列されています。

ここから変数aの値を探します。

今回は”a is above here”という目印を書いたので簡単に探すことができます。

右側の文字化けしている文字列を見てみると、"a is above here"という文字列が一文字ずつばらばらに存在する部分があることが確認できると思います。
今回は変数aの値はその文字の上にあります。


aの初期値は5なので05の部分、すなわちアドレス20Bですね。

これを試しに0Fに書き換えて、exeを実行すれば


変数aの値が初期値5だったのが15になっていることが確認できます。

このようにexeファイルそのものをバイナリファイルとして開いて、書き換えることで中身をいじることができます。


また、バイナリエディタの右側に文字列がそのまま表示されている部分があります。

そこを書き換えれば表示される文字を書き換えることができます。




逆アセンブル

アセンブリを知る

最後にexeファイルを逆アセンブルして解析してみたいと思います。

そもそもexeファイルは、プログラミング言語によって書かれたものがコンパイラで0と1の機械語に変換されてできます。

この機械語は人間が直接読むことはできないので、0と1の2進数を16進数にして人間の分かる記号を付けたものをアセンブリ言語といいます。

そのためアセンブリ言語はCPUの動作に1:1で対応した言語となります。

まず、うさみみハリケーンを開いて

その他>汎用ファイルアナライザ

から、「青い空を見上げればいつもそこに白い猫」というソフトを起動します。

そこへexeファイルをドロップして、

x86/x64逆アセンブル

をクリックし、

逆アセンブル実行

をクリックすることで逆アセンブルできます。


しかし、逆アセンブルしたものを変更することはできません。

そのため「青い空を見上げればいつもそこに白い猫」からバイナリエディタを起動し、

逆アセンブルしたものを見ながらバイナリデータを見てみようと思います。


先ほどバイナリエディタからaの値を変更しましたが、そのアドレスは20Bでした。

アドレス20Bのところを逆アセンブルしたデータで見てみると


と書いてあります。

すなわち、アセンブラでは変数aに5を代入するのは

mov eax, 00000005h

と書くことがわかります。

「mov」とは代入する命令で、ここではeaxに00000005hを代入しています。

このような命令のことをオペコードと言い、オペコードを「mov」などの記号として表したものをニーモニックと言います。


「eax」とはCPUの中にあるメモリを表しており、レジスタと言います。

レジスタの中にはデータを入れることができます。

レジスタにも種類があり、eaxは32ビット(4バイト)のサイズです。

eaxはaxを拡張したものです。

axは16ビット(2バイト)のサイズのレジスタで、アキュームレータと呼ばれます。

さらにaxはahとalから構成されており、ahとalは8ビット(1バイト)のサイズのレジスタです。

このようにアセンブラでは変数の代わりにレジスタを使っていることがわかります。


「00000005h」は16進数の5で、16進数であることを明示するために「h」が語尾についています。

アセンブラを参考にバイナリをいじる

逆アセンブルすることでアセンブラの仕組みを少し理解できました。

またニーモニックから、変数の値を書き換える以外にexeファイルをいじることができます。

今回のexeファイルではIF文でaが6かどうか判断している部分があります。

このIF文はアセンブラで「cmp」に対応します。

逆アセンブルしたものから「cmp」を検索すると


eaxが06hと同じか比較している部分があります。

このアドレス2DBの部分の「83F806」を書き換えればIF文を書き換えることができます。

例えば「83F806」の「06」を「0F」にすれば、aが15かどうか判断するIF文に書き換えられます。

また「83F806」の部分を何もしない命令である「90」(ニーモニックでNOP)に書き換えればIF文の判定式をつぶせます。


これでexeを実行してみると

aが6なのにelse以降が実行されていることが確認できます。


他にも、今回のexeでは「++a」と変数aに1を足している部分があります。

アセンブラで足す計算は「add」であるため、「add」を検索すると

が見つかります。

eaxに01hを足していることがわかります。

この「83C001」の部分を「909090」にすれば1が足されなくなりますし、「01」の部分を「0F」にしてみれば15が足されるようになります。


exeを実行してみると

1ではなく15が足されていることが確認できます。


まとめ

「いまどきのアセンブラプログラミング」という本は私のアセンブラへ興味を掻き立ててくれました。

しかしこの本が2004年のものと古いため、本の中で紹介されている「OllyDbg」「PeRdr」「Tsearch」「BZ」などのツールはリンクが切れていたり、64ビットに対応していなかったりしていました。

そこで2020年(もう2021年になるけど)の現代風にまた「うさみみハリケーン」というソフトを使ってアセンブラ・バイナリ解析をしてみました。

今私が愛用しているのは64bitにも対応しているアセンブラデバッガであるx64dbgです。

おすすめです。

しかし、実はこのEasyIDECで生成したexeファイルではこのような解析ができたのですが、他の言語やコンパイラだとできませんでした。

例えばVisualStudioでコンパイルしたexeでは、バイナリエディタで開いてもある程度の文字列は表示されるのですが、無駄に数字が多く、さらに今回用いた”a is above here”作戦も変数の位置が全然異なる位置にあり、変数の場所を特定することができませんでした。

またプログラミング言語であるKuinを用いてGUI,CUIの両方のプログラムを作ってバイナリで開いても同様に無駄に数字が多く、変数の位置も異なっていたためできませんでした。

またKuinで特徴的だったのは、バイナリエディタのビットイメージ表示でくいなちゃんが表示されたことです。


まあこのように単純なコンパイラで単純なコードでないと私には解析できませんでした。

この本にあるようにゲームを改造するにはもっとバイナリやアセンブラに詳しくないといけなく、また気合や根気など精神的な粘り強さも必要なのかなと思いました。