1

これは私にとって初めてのことであり、今ではアイデアが不足しているため、皆さんが私を助けてくれることを本当に願っています.

私は数時間答えを探しましたが、実際に機能する答えを見つけることができませんでした.

実行中のプロセスにコードを直接挿入したいと考えています。はい、あなたはそれを正しく読みました。別のアプリケーションにコードを挿入しようとしていますが、信じられないかもしれませんが、これはその機能を拡張するためだけのものです。

Windows で Visual Studio 2012 Express Edition を使用しています。

次のコードがあります。

__declspec(naked) void Foo()
{
    __asm
    {
        // Inline assembly code here
    }
}
__declspec(naked) void FooEnd() {}

int main()
{
    cout << HEX(Foo) << endl;
    cout << HEX(FooEnd) <<  endl;
    cout << (int)FooEnd - (int)Foo << endl;

    // Inject code here using WriteProcessMemory

    return 0;
}

読みやすさを維持するためにほとんどのコードは削除されていますが、リクエストに応じて他の部分を投稿できます。

出力は次のとおりです。

0x010B1000
0x010B1010
16

結果のサイズは実際には正しくありません。関数は正しい順序でコンパイルされます (/ORDER を使用して確認してください) が、コンパイラはサイズを拡張する各メソッドの後に 0xCC (int 3) バイトの束を追加するため、実際の (有用な) 数値を取得できません。実際の実行可能コードを含むバイト数。

別のスタックオーバーフローの質問では、「エディット コンティニュ」を無効にするとこれらの余分なバイトがなくなると言われていますが、何があってもうまくいきませんでした。

また、デバッグの代わりにリリース セットアップを使用してみました。一連の最適化設定を変更しましたが、どれも効果がありませんでした。何が解決策になると思いますか?明らかな何かが欠けている可能性があります。

とにかく、これは(あなたの意見では)関数の長さ(読みやすさ、信頼性、使いやすさ)を取得するための最良の方法ですか?

あなたが助けられるようにするために、私がしなければならなかったすべてを説明したことを願っています. さらに質問がある場合は、お気軽にコメントを残してください。

あなたの時間と努力に感謝します。

4

3 に答える 3

5

Devolus が指摘しているように、コンパイラは次の関数を妥当な (通常は 16 で割り切れる) 開始アドレスに揃えるために、コードの後に​​これらの余分なバイトを挿入しています。

0xCC はブレークポイント命令であるため、コンパイラは実際にあなたを助けようとしています。実行中の任意の時点で命令ポインターが誤って関数の外を指している場合、コードはデバッガー (接続されている場合) に侵入します。

これはあなたの目的のために心配する必要はありません。0xCC パディングは関数の一部と見なすことができます。

于 2013-08-06T21:28:03.890 に答える
4

コードを挿入するときは余分なパディングは必要ないので、破棄しても問題ありません。それらをコピーしても問題ないはずです。コピーの数バイトが余分に発生するだけです。いずれにせよ、注入しているメモリはページ整列ブロックによって意志される可能性があるため、それを取り除いても実際には何も得られません。

しかし、本当に削除したい場合、問題の簡単な解決策は、次の関数の前の最後のバイトから 0xcc バイトがなくなるまで逆方向に反復することです。

すなわち:

__declspec(naked) void Foo()
{
   __asm
   {
      _emit 0x4A
      _emit 0x4B
   }
}
__declspec(naked) void FooEnd() {}


int main(int argc, char** argv)
{
   //start at the last byte of the memory-aligned code instead of the first byte of FooEnd
   unsigned char* fooLast = (unsigned char*)FooEnd-1;

   //keep going backwards until we don't have a 0xcc
   while(*fooLast == 0xCC)
      fooLast--;

   //fooLast will now point at the last byte of your function, so you need to add 1
   int length = ((int)fooLast - (int)Foo) + 1;

   //should output 2 for the length of Foo
   std::cout << length;
}
于 2013-08-06T21:27:13.517 に答える
2

次の関数をマーカーとして使用しているため、追加のバイトはコンパイラによって挿入されてメモリ アラインメントが作成されるため、破棄することはできません。

一方、挿入されたコードはアセンブリで記述しているため、コードを記述してコンパイルし、バイナリ形式をバイト配列に配置することもできます。それが私がこれを行う方法です。なぜなら、あなたは正確な長さを持っているからです。

于 2013-08-06T21:01:05.327 に答える