web-dev-qa-db-ja.com

Linux実行可能ファイルで使用されるコード変換のタイプ

Linux実行可能ファイルを作成するために、どのタイプのエンコーディングが使用されているのかを尋ねたいと思います。十六進法、二進法、その他。どのように変換されますか?この実行可能ファイルから元のコードを取得する方法はありますか?

ここに私が持っている少しのコードがあります:

ELF���������>�����%|�����@�������������������@�8��@���������������������@�������@�����7<�����7<������� ������������������f�����f���������������������� ������[�UPX!L
h�h�8����������?�E�h=��ڊ̓�N�    4���9ISloB�q�w�]ȉ.��,ς��Q䝦����#e��-�N����/�b,���d<��'��-E��6E�s�/�U���ly�V�Y2]"a��S�.�hU�|�S�J�I�2���X}
�G0�;���5d�$���.)

それはどういう意味ですか?

13
redchief

バイナリです。ソースコードがコンパイルされました。エディターで表示できます(blessのような16進エディターは、より洗練された変更を加えることができます)が、何をしているのかを本当に知る必要があります。文字列を変更する場合にのみ有効です。

よりハードコアなものについては、バイナリをAssemblyコードにリバースエンジニアリングすることができます。これは多くの場合、人間が解析可能な最低レベルのコンピューター言語と見なされます。

objdump -d helloworld | less

しかし、それは多くのコンパイラのナンセンスも含みます。たとえば、G ++で 最も単純なhelloworld.cpp をコンパイルし、その後objdump itをコンパイルすると、最終的に226行(208ストリップ)になります。 「hello world」をアセンブリの15行だけで書く 、コンパイルしてobjdump itできますが、それでも166行になります(削除)。

Assemblyで十分なら、これは何が起こっているのかを理解するのに十分なアクセス権を与え、さらにそれを変更させさえするかもしれません...しかし、元の質問に答えるには:

コンパイルされたコードをoriginalソースコードに戻すことはできません。

ごめんなさい。これは、情報(コメント、フォーマット、読み取り可能なアルゴリズムの概念など)を失い、静的に他のものにリンクされ、一般的に最適化されており、最高で最も熟練したプログラマー以外には理解できないようにする一方向の変換です。

問題の規模を把握するために、リバースエンジニアリングソフトウェアのアイデア全体に 独自のStack Exchangeサイト があります。

29
Oli

コメントに対する評判ポイントが足りないので、答えです。

いいえ、「バック」に変換することはできません。 upx packerについて言及しましたが、upxのマニュアルを読んだことはありますか?

あなたがソースを失った場合、または他の誰かのコードにアクセスできない場合は、ここでは重要ではありませんが、それは単に不可能です。

バイナリ実行可能ファイルはコンパイラで作成されました。このサイトに記載されていることを信じないでください。正確にそのコンパイラのマニュアルを読んでください。次に、ここで、元のコードが書かれた言語、使用されたコンパイラーを追加できます。そして、このステップ(前処理、コンパイル、リンク、多分パッキング)が全体として逆ではなく、原作者が意図したものを分析し、記述します。

7
justabot

これはおそらく、ここで詳しく説明されているバイナリファイル(ELFファイル)です。

https://en.wikipedia.org/wiki/Executable_and_Linkable_Format

通常のテキストエディターで変更し、変更を保存した場合、これは良い考えではなく、破棄した可能性があります。

3
Bruni

オリがすでに彼の答えで指摘したように、実行可能ファイルの非常に元のソースコードを取得することはできません。

ソースコードのコンパイル中(通常より広く受け入れられるため、ソースコードを実行可能ファイルに「変換」するプロセス全体としてのコンパイル)、多くの情報が失われます。

Cプリプロセッサは、たとえば、次のことを(とりわけ)行います。

  • プリプロセッサディレクティブ(#ステートメント)の解釈、実行、削除
  • コメントを削除
  • 不要な空白を削除する

一方、ソースコードのコンパイル中に失われないものは、機能的に同等のソースコードに技術的に戻すことができます。

それの訳は:

  • バイナリ命令は、アセンブリ命令と1対1で対応しています。アセンブリソースコードのアセンブルは、対応表に基づいてアセンブリ命令をバイナリ命令に変換するだけです。 単一のバイナリ命令は常に識別可能であり、単一のアセンブリ命令に復帰可能です;
  • アセンブリ命令do n'tは、C命令と1:1で対応しています。 Cソースコードのコンパイルは通常はそうではありません単なる対応表に基づいたC命令のアセンブリ命令への単なる変換、実際にはしばしば反対。通常、C命令は複数の(コンパイラに基づいて異なることが多い)アセンブリ命令に変換されます。ただし、複数のアセンブリ命令のパターンは通常、単一のC命令に識別および復帰できます

実行可能ファイルを機能的に同等のソースコードに戻すことを目的とするデコンパイラと呼ばれるツールがあります。ただし、結果は通常、非常に元のソースコードから(および通常はコンパイル不可能でも)何かfarです。

このプログラムを検討してください。

#include <stdio.h>

#define MESSAGE "Literal strings will be recovered" // This preprocessor directive won't be recovered

/*

This comment and the comment above won't be recovered

*/

int main(int argc, char* argv[]) {
    printf(MESSAGE);
    return 0;
}

それを実行可能ファイルにコンパイルし、再びソースコードに逆コンパイルすることにより、これは通常あなたが戻すものです(この特定のケースではgcc/ Boomerang )を使用しました:

// address: 0x80483fb
int main(int argc, char **argv, char **envp) {
    printf("Literal strings will be recovered");
    return 0;
}

予測どおり:

  • プリプロセッサディレクティブがありません
  • コメントがありません(デコンパイラーによって追加された// address: 0x80483fbを除く)
  • 不要な空白がありません(逆コンパイラーによって追加された改行と表は別として)

これもかなり良い結果です。コードにインラインアセンブリ命令を含めることは珍しくありません。

asm("Assembly_instruction");
__asm__("Assembly_instruction");

一番下の行は(他の回答で既に指摘したように):実行可能ファイルの非常に元のソースを取得することはできません*。

*ただし、実行可能ファイルと運に応じて、mightデコンパイラを使用して何かを取得できます。

3
kos

コンパイル済みプログラムについて話している場合、実行可能ファイルは通常バイナリです。 file path/to/executableを使用して詳細情報を検索できます。バイナリ実行可能ファイルを16進数で表示するには、たとえばhexdump -C path/to/executable | less(それが何であれあなたに役立つでしょう)。 「元の形式に戻す」場合は、適切な逆コンパイラを使用する必要があります たとえば、この投稿を参照してください 。コンパイルされたバイナリでない場合、それは何らかの種類の実行可能スクリプトになり、任意のテキストエディターで簡単に読み取れるはずです。ここで示したのは、おそらくコンパイルされた実行可能ファイルです。 ELFは「実行可能およびリンク形式」を意味し、Linux/Unixシステムで一般的なバイナリ形式です。必要な場合は、strings path/to/executableを使用して、バイナリファイルから読み取り可能な文字列部分を抽出する可能性があります。

2
Hinz