リバースエンジニアリングのためにバイナリにパッチを当てるスクリプトをrubyで作ってみました。
binpatch.rb
#
# binary path for reverse engineering
#
argc = ARGV.size
if argc >= 4 && argc % 2 == 0 then
old = ARGV[0]
new = ARGV[1]
p = 2
bindata = File.binread(old)
while 2 + p <= argc
offset = ARGV[p].hex
inst = ARGV[p+1].hex
bindata[offset] = (inst >> 24).chr
bindata[offset + 1] = ((inst >> 16) & 0xff).chr
bindata[offset + 2] = ((inst >> 8) & 0xff).chr
bindata[offset + 3] = (inst & 0xff).chr
p = p + 2
end
File.binwrite(new, bindata)
else
print "usage: binpatch.rb oldfile newfile offset data\n"
end
使い方は
% ruby binpatch.rb org.bin new.bin 0x100 0xffff0010
0xffff0010は置き換える32bitの値でMIPSELの命令で無限ループになります。
これでオリジナルのバイナリーにパッチを当ててどこまで進んでいるか調べようと思ったのですが、逆アセンブラを自力で流れを追って、書き換える場所を探す必要があり、条件で通らないところもあり、あまり有効な方法ではありませんでした。
パッチ当てて、イメージ作って、Flashに焼いて、実機に実装して実行して確認していたのですが、効率が非常に悪いです。
パッチはcmp -lやobjdump -Dなどで確認できます。
FreeBSDにはbspatchというコマンドがありますが、これはbsdiffで作ったバイナリ形式のdiffでパッチを当てることができて、任意のパッチは当てられないようです。
パッチは無限ループの他に、NOPや不正命令で例外を吐かせる方法なども考えられます。