2016-11-06 22 views
0

これは、最近のこれらの方法(私が推測する)はもはや動作しないので、訓練の一種です。Cプログラムでフックを修正する方法(スタックの修復)

Win XPとMinGWコンパイラが使用されています。特別なコンパイラオプションは関係ありません(1つのソースファイルを記述するだけでgccです)。すべての

まず、プログラムを終了するアドレスを保存し、いくつかのフック関数にジャンプする:

// Our system uses 4 bytes for addresses. 
typedef unsigned long int DWORD; 

// To save an address of the exit from the program. 
DWORD addr_ret; 

// An entry point. 
int main() 
{ 
    // To make a direct access to next instructions. 
    DWORD m[1]; 

    // Saving an address of the exit from the program. 
    addr_ret = (DWORD) m[4]; 

    // Replacing the exit from the program with a jump to some Hook function. 
    m[4] = (DWORD) Hook; 

    // Status code of the program's execution. 
    return 0; 
}  

ので、我々、このコードの目的は、システムの特権レベルへのアクセスを得ることですシステムに返す(返すべきである)ので、プログラムをいくつかのメソッドにリダイレクトするだけです。このメソッドのコード:

// Label's declaration to make a jump. 
jmp_buf label; 

void Hook() 
{ 
    printf ("Test\n"); 

    // Trying to restore the stack using direct launch (without stack's preparation) of the function (we'll wee it later). 
    longjmp(label, 1); 

    // Just to make sure that we won't return here after jump's (from above) finish, because we are not getting stuck in the infinite loop. 
    while(1) {} 
} 

そして最後に、私は、スタックポインタを修正する必要があります(私の意見では)機能状態だろう - ESP登録:我々はこれらが含まれて使用する必要があります。もちろん、

void FixStack() 
{ 
    // A label to make a jump to here. 
    setjmp(label); 

    // A replacement of the exit from this function with an exit from the whole program. 
    DWORD m[1]; 
    m[2] = addr_ret; 
} 

を規定のプログラムのために:

#include <stdio.h> 
#include <setjmp.h> 

プログラムの全体の論理は、私のシステムで正常に動作しますが、私は私のスタック(ESP)を復元することはできませんので、プログラムが不正のリターンコードを返します。

上記のソリューションの前に、私はジャンプとFixStack関数を使用しませんでした。私はこれらの行は、フック関数ではなく、ジャンプやサイクルながらだったことを意味する:

DWORD m[1]; 
m[2] = addr_ret; 

しかし、このバリアントで、私は(それが大きな8バイトにあったプログラムを終了する前にESPレジスタに誤った値を得ていましたこのプログラムの入力前のこのレジスタの値)。だから私は何とかこれらの8バイトを追加することに決めました(Cプログラムの内部にASMコードを避ける)。これはFixStack関数への適切な出口(スタックからいくつかの値を取り除く)を使ってジャンプする目的です。 (Iユーティリティをデバッグの使用にいくつかの勧告を求めてから始まる:

echo %ErrorLevel% 

は、だから私の質問は非常に広いです。しかし、私が述べたように、それは、このコマンドを使用して、プログラムの実行の正しいステータスを返しません。 OllyDbgのみを使用していました)、記述されたHookの実装に可能な解決策で終わりました。

+0

@ryykerは、それがエラーなしでコンパイル、および)の回答に記載された最終版は、(もちろん、 –

+0

@ryykerが、それはおそらくいくつかの他のコンパイラを使用して、いくつかの他のシステムでコンパイルしていない正常に動作します。どこからでも実行可能なソリューションを作るのは難しいです(異なるコンパイラは最終的に異なるコードを生成し、プログラムの実行フローをリダイレクトするためにハックを使います)。しかし、これについては、私はエラーや警告を得ることはありません。 –

答えて

0

私は自分のプログラムを意図したとおりに動作させることができました。これで、Win XPでMinGWを使用したコンパイル済みのプログラムを、エラーや正しい戻りコードなしで起動することができます。

はたぶん誰かのために役に立ちます。もちろん

#include <stdio.h> 
#include <setjmp.h> 

typedef unsigned long int DWORD; 

DWORD addr_ret; 


int FixStack() 
{ 
    DWORD m[1]; 
    m[2] = addr_ret; 

    // This line is very necessary for correct running! 
    return 0; 
} 


void Hook() 
{ 
    printf("Test\n"); 

    FixStack(); 
} 


int main() 
{ 
    DWORD m[1]; 

    addr_ret = (DWORD) m[4]; 

    m[4] = (DWORD) Hook; 
} 
0

あなたが、これが唯一の非常に特定のビルド環境で動作することを実現しましたようです。アドレスがDWORD-ishではないため、64ビットターゲットでは動作しません。

これを行うためにC標準ライブラリが提供する機能を使用したくない理由はありますか? (またはこれに非常に類似した何か。)

#include <stdlib.h> 

void Hook() 
{ 
    printf("Test\n"); 
} 

int main() 
{ 
    atexit(Hook); 
} 
関連する問題