2017-11-27 24 views
1

命令が呼び出されるアドレスを見つけるために別の関数を実行する関数をCプログラムに書く方法があるのだろうかと思います。C独自のアセンブリをステップ実行する機能

たとえば、ret関数がメイン関数で使用されているアドレスを探したいとします。

"& main()"で始まるwhileループを作成し、現在のアドレスで命令が "ret"になりアドレスを返すまで、毎回ループして1ずつ増やします。

+2

その仕事をした?... –

+3

異なるx86命令異なる長さを持ち、 'ret'命令と間違える可能性がある_immediate_データ値を含むことがあります。また、関数は複数の 'ret'命令を持つことも、 'ret'命令の変種を持つこともできます。 –

+0

@OliverCharlesworth main()をインクリメントすると、どのような命令が現在のアドレスにあるのか、私はどのように解釈するのか分かりません。 – Ethan

答えて

4

マシンコードを逆アセンブルするプログラムを作成することは可能です。 (明らかに、これはアーキテクチャー固有のものです。このようなプログラムは、それが設計されているアーキテクチャーでのみ動作します)。そして、そのようなプログラムは、mainルーチンのアドレスを取り、それを調べることができます。 (いくつかのC実装では、関数へのポインタは実際には関数のコードのアドレスではありませんが、コードを逆アセンブルするように設計されたプログラムはこれをアカウントに取り込みます)。

これは相当な作業です初心者のための難しさ。

プログラムは命令の間に1バイトずつアドレスをインクリメントしません。多くのアーキテクチャでは、4バイトの固定命令サイズがありますが、他のサイズも可能です。 x86-64アーキテクチャ(様々な名前で知られている)は可変命令サイズを持っています。それを分解することはかなり複雑です。インストラクションを分解するプロセスの一環として、そのインストラクションの大きさを把握して、次のインストラクションがどこにあるかを知る必要があります。

一般的に、実行されたときに返される命令は、mainによって実行されるものであるとは必ずしも判断できません。関数はしばしば簡単な方法で書かれていますが、ジャンプする可能性があります。関数は複数のreturn文を持つことができます。そのコードは連続していない複数の場所にあり、他の機能とコードを共有することさえあります。 (普通のコンパイラではこれが一般的なものかどうかはわかりませんが、それは可能でしょう)。もちろん、mainは戻ってこないかもしれません(コンパイラがこれを検出した場合、

(ちなみに、常にプログラムが終了するか否かを判断するプログラムを書くことは不可能であることを数学的な証明がある。これはHalting Problemと呼ばれている。)

+0

このような詳細な応答をありがとう!私はそれがアーキテクチャ固有のものだと理解しています。しかし、これらの変数が理想的な定数であると仮定できれば(メインは本当にシンプルで、1つの関数を呼び出し、0のステートメントを返します)、プログラムはバイトをリターン命令としてバイトとして認識するまでバイトを読み取ることができますか? – Ethan

+0

いいえ、呼び出し命令がジャンプするアドレスの一部がret命令と同じではないという保証はありません。このように、これは非常に基本的なものであってもかなり複雑な作業です。 – SoronelHaetir

+0

最初に必要なことは、命令の境界を見つけることができることです。つまり、* length *が必要です。次に、x86-32の命令の長さを計算するコードを示します。https://stackoverflow.com/a/23843450/120163これで、opcodeバイトを確実に識別し、命令をデコードできます。それを使って、手続きの中で指示どおりに何かを捜すことができます。 –

関連する問題