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


32

私はこの引用を(以下)数回読んでいますが、最近ここにありますが、コンパイラだけでなくあらゆるものddにパッチを適用する方法に絶えず困惑しています:

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

(エンファシス鉱山)

ddマン・ページには、パッチを適用し、このとにかくを行うために再目的とすることができないと思うについては何も言いません。

バイナリには本当にパッチを適用できddますか?これに歴史的な意義はありますか?


3
確かに-ちょうどodバイトの16進コードのファイル、あなたの編集を決定し、必要なオフセットを検索し、bs=$patchsize count=1 seek=$((offset/bs)) conv=notrunc中にあなたのパッチの右側。
mikeserv

3
誰かがブートセクタを上書きしたことはありません。;)
パルティアショット

@ParthianShot実際、ブートドライブの最初の〜260MB(+ルート)をDebian LiveCDの一部で1回上書きしました。O_oしかし、私はそれが本当にパッチを当てているとは思わない、
へへへ...-Amziraro

1
むしろ、それはディスクデストロイヤーの予想される完全に正常な動作です:D
Amziraro

回答:


73

試してみよう。簡単な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、を使用してパッチを適用できるだけでなく、たった今それを実行しました。


1
これは素晴らしいことです...そして、私は本番環境では決して遭遇しないことを強く望みます!過去に同様の方法を使用してシリアル番号をマイクロコントローラーの16進数イメージに入れましたが、自分で足を撃ちすぎるのは簡単すぎます。
マイケルショー

特定のバイナリにパッチを適用する方法を誰かに書面で指示したい場合は、「16進エディタでファイルを開き、/usr/tmp文字列を見つけて、それを/tmpに置き換えて、ドン「末尾の\0バイトを忘れずに、ファイルを保存して、指を交差させてください」。または、さらに良いことに、最初にいくつかの健全性チェックを実行してからを呼び出すシェルスクリプトdd。今は亡きベンダーによってソフトウェアの古い作品はちょうどその時残念ながら、このようなものの必要性が頻繁に発生している新システムに移行します。
Guntram Blohmはモニカをサポートします

ええ、sedはこの種のものにとってはより良いです。ただし、「このパッチを適用することで、文字列を短くしたり、同じ長さにしたり、長くしたりすることはできません」という全体については完全には正しくありません。変更する文字列の直後のデータを気にするか、次の文字列を元の文字列のサブ文字列にすることはできないと仮定しています。言い換えると、メモリの.stringsセクションにいて、「/ usr \ 0 / bin / bash \ 0」を取得している場合、最初にそれを変更するだけで/ usr / bin / bashに変更できます。 nullバイトで「/ usr // bin / bash」にする(たとえば)。
パルティアショット

2
@ParthianShot - sed'S ではないこの種のもののために、より良い-あなたがすることができないので、expliciltlyかつ正確に制限sedの読み取り/あなたがかもしれない方法で、書き込みバッファdd-それは今までに最初の場所で、このために使用された全体の理由です。を使用ddすると、任意のバイトの任意のカウントを任意に配置できます。これについても言えませんsed。場合はdd、ここでメスのように使用され、あなたが適用されるsed台無しボールのよう。
mikeserv

これは公平な(かなりまれですが!)ポイントです。結果または別の任意ではあるが特定のデータを気にせずに文字列を長くすることができる場合があります。ただし、一般的な声明には賛成です。
マイケル・ホーマー

9

「バイナリのパッチ」の意味に依存します。

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

または、0バイトが追加された@MichaelHomerの例をピックアップするには:

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

もちろん、後で実際に機能するかどうかを確認する必要があります。


... sedバイナリファイルを適切に処理するを持っていると仮定します。これはgnuの場合のようですが、asciiファイルのみsedで動作する古いsedsの多くではなく、他のもの(特に\0入力のs)と混同されます。そして最大の行の長さに制限がありました。
Guntram Blohmはモニカをサポートします

1
busybox sedはバイナリファイルを正常に変更できるように思われますが\x00、GNUのように置換文字列では理解しませんsed。それはテストを必要としますが、それでもdd、いくつかの場合よりもはるかに単純なので、言及する価値があると思います。バイナリにパッチを当てることは、いずれにせよひどいビジネスです。
-frostschutz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.