ddを使用したバイナリパッチ

ddを使用したバイナリパッチ

私はこの文章(下)を何度も読みました。最近ではここdd、パッチの使い方について混乱しました。何もないコンパイラは言うまでもありません。

30年前、私が学校で使用していたUnixシステムは、RAMとディスク容量が非常に限られていました。特に、/usr/tmpファイルシステムが非常に小さいため、誰かが大きなプログラムをコンパイルしようとすると問題が発生する可能性があります。もちろん、学生はとにかく「大きなプログラム」を書いてはいけません。大規模なプログラムは通常、「どこか」からコピーされたソースコードです。私たちの多く/usr/bin/cc/home/<myname>/ccdd置き換えるバイナリ/tmpパッチ用/usr/tmp、どれがより大きいか。もちろん、これは問題をさらに悪化させるだけです。当時、これらのコピーが占めるディスク容量は非常に重要でしたが、今/tmpはいっぱいで、他のユーザーがファイルを編集できないようにすることがよくあります。何が起こっているのかを発見した後、システム管理者はchmod go-r /bin/* /usr/bin/*「修正」を実行し、Cコンパイラのすべてのコピーを削除しました。

(強調は私のもの)

マニュアルページにはddパッチへの言及はなく、とにかく用途の変更ができないとします。

バイナリは実際にパッチできますかdd?これは歴史的意味がありますか?

答え1

やってみようこれは単純なCプログラムです:

#include <stdio.h>
int main(int argc, char **argv) {
    puts("/usr/tmp");
}

私たちはそれを次のように構築しますtest

$ cc -o test test.c

実行すると、「/usr/tmp」が印刷されます。

/usr/tmpバイナリで「」がどこにあるかを見てみましょう。

$ strings -t d test | grep /usr/tmp
1460 /usr/tmp

-t d 10進数で印刷オフセット見つかった文字列ごとにファイルに追加します。

/tmp\0それでは、 ""だけを含む一時ファイルを作成しましょう。

$ printf "/tmp\x00" > tmp

これでバイナリがあるので、変更したい文字列がどこにあるかを知っていて、代替文字列を含むファイルがあります。

これで次のことができますdd

$ dd if=tmp of=test obs=1 seek=1460 conv=notrunc

tmp(" "ファイル)からデータを読み込み/tmp\0、1バイトの出力ブロックサイズを使用してバイナリファイルに書き込み、何も書き込み前に以前に見つかったオフセットにジャンプし、完了すると消去します。ファイルは切り捨てられません。

パッチ付き実行ファイルを実行できます。

$ ./test
/tmp

プログラムによって印刷された文字列リテラルは変更され、今度は " /tmp\0tmp\0"が含まれますが、文字列関数は最初のヌルバイトを見るとすぐに停止します。このパッチを使用すると、文字列を短くしたり、同じ長さにすることができますが、これ以上作成することはできませんが、この目的には十分です。

だから私たちは物をパッチするのに使うことができるだけでなく、ddすでにやってきました。

答え2

「パッチされたバイナリ」の意味によって異なります。

dd時々変更バイナリを使用します。もちろん、そのような機能はありませんが、ddファイルを開いて特定のオフセットで内容を読み書きできるので、内容を書き込む場所を知っていればチャジャン、それがパッチです。

たとえば、一部のPNGデータを含むバイナリファイルがあります。binwalkオフセット検索を使用してdd抽出し(通常はbinwalkからもアイテムを抽出しますが、コピーに問題がある)、編集を使用して編集されたgimpファイルのサイズが元のサイズ以下であることを確認します(オフセットの変更は実行できません) 。簡単に))をdd使用して、変更された画像を元の位置に戻します。

$ binwalk thebinary
[…]
4194643    0x400153     PNG image, 800 x 160, 8-bit/color RGB, non-interlaced
[…]
$ dd if=nickel bs=1 skip=4194641 count=2 conv=swab | od -i
21869 # file size in this case - depends on the binary format
$ dd if=thebinary bs=1 skip=4194643 count=21869 of=theimage.png
$ gimp theimage.png
$ pngcrush myimage.png myimage.crush.png
# make sure myimage.crush.png is smaller than the original
$ dd if=myimage.crush.png of=thebinary bs=1 seek=4194643 conv=notrunc

場合によっては、バイナリファイルの文字列(パスや変数名など)を変更したい場合があります。を使用してこれを行うこともできますが、dd使用する方が簡単ですsed。置き換えられた文字列が元の文字列と同じ長さであることを確認しても、オフセットは変更されません。

sed -e s@/the/old/save/path@/the/new/save/path@ -i thebinary

または、ゼロバイトを追加する@MichaelHomerの例を選択してください。

sed -e 's@/usr/tmp@/tmp\x00tmp@' -i test

もちろん、実際に動作していることを後で確認する必要があります。

答え3

はい、ddを使用してバイナリをパッチすることができます。

stdinのデータでファイルをパッチするには:

dd of=file.bin bs=1 count=2 conv=notrunc

次に、パッチする(テキスト)データを入力します。上記は、2文字以上を入力するように求められた場合でも、ファイルの先頭から2バイトのみをパッチします。
ファイルの中央部分にパッチを適用するには、seekファイルデータの場所(アドレス)を指定してパッチを開始します。例えば。

dd of=file.out bs=1 count=2 seek=2 conv=notrunc

または

echo "<address: data>" | xxd -r - file.out

印刷できない文字にパッチを適用する場合は、パッチするデータを含むバイナリ一時ファイルを作成します。例えば。

dd if=file.in of=file.out bs=1 count=2 seek=2 conv=notrunc

または

xxd -r hexoffsets.in file.out

または、標準入力にオフセットを持つ16進データを提供してください。

echo "<address: hex-data>" | xxd -r - file.out

定義:
パッチは、hexdumpをバイナリに変換することを意味します(xxdマンページから)。

Ubuntu 16.04.7でテストされました。

関連情報