2016-09-13 5 views
5

生徒にOllyDbgを逆に使って実行方法を変更させるという目的で、簡単なCプログラムを作成しました。コンパイルされた実行可能ファイルは、追跡が難しいスタートアップ呼び出しで満たされているため、初心者がOllyでそれを元に戻すための努力を妨げることになります。私はコンパイラにそのすべて/ほとんどを削除するように伝えたいと思います。逆コンパイルするための簡単な逆実行ファイルを作成するためのCコンパイラオプションが必要

私はVisual Studio 2015 Proを使用していますが、私はVSの仲間ではありません。どこから起動するのか分かりません。

+1

まあ、これらの「スタートアップコール」は、プログラムを実行させるために非常に重要であると仮定しています。たぶん、それらを取り除くのではなく、単純なターゲットのためにコンパイルすることを考えるべきでしょうか?小さな組み込み機器(AVRのような)用のツールチェーンは、少し簡単なアセンブリを生成するかもしれません。また、GCCを使用している場合は、最適化をオフ(-O0)にすることもできます。 –

答えて

3

限り、あなたの主な機能は、標準Cライブラリにアクセスしていない、あなたは、Windows API呼び出しを使用すると、あなたは、次の2つのリンカースイッチでCランタイムスタートアップコードを削除することができますで

/entry:<your_main_function> /nodefaultlib 

、コンパイルし、次のようになしCランタイム・ライブラリを、あなたのコードをリンクすることができ、簡単なコンソールアプリケーション(私はあなたが使用していると仮定しました)と「メイン」の主な機能を使用して完全な例:

cl /c main.c 
link /entry:main /nodefaultlib /libpath:<path_to_libs> /subsystem:console main.obj kernel32.lib user32.lib 

Visコマンドラインツールを手動で実行したくない場合は、Studioのプロジェクトダイアログに相当するオプションが埋め込まれています。

これは、小さくても単純なEXEを生成するはずです。デバッグセッションが始まると、メイン関数のすぐ内側から開始する必要があります。

注:標準のIOがないと、文字列の長さを取得するなど、いくつかのルーチンを自分で書く必要があるため、数値の出力が難しくなることがあります。しかし、カーネル32のGetStdHandle()とWriteConsole()関数だけがコンソールに出力する必要がある唯一のAPI呼び出しはありません。 user32.libでアクセス可能なwsprintf()APIもあります。これは、サンプルベアボーンを保持するために使用することをお勧めしますが、Cスタイルの書式設定された文字列を作成することを可能にします。 wsprintf()を使用して番号を出力プロンプト/文字列に変換し、WriteConsoleを使用してコンソールに送信します。

更新:以下は、標準CライブラリとCRTスタートアップコードを必要とせずに2つの数値を加算した結果を出力するサンプルCプログラムです。これは、リバースエンジニアリングのサンプルで、数値の1つを変更してコマンドラインで別の結果を得るのに適しています。

免責事項:私は原因バッファサイズをチェックし、誤使用は、バッファオーバーフローに貢献することができたときの欠如に()実際に危険な関数であるwsprintfに同意するものとします。ここでは、Win32 API(user32.lib)に組み込まれているためにのみ使用されています。この例では、数値を文字列に変換する簡単な方法です。

私が知る限り、ウィンドウに組み込まれている唯一のCスタイルの書式設定関数は、この関数のANSI/WIDEバージョンです。 strsafe.lib関数は標準ライブラリに依存しているようですが、そうでなければそれらを使用していました。あなたが違うことを知っているなら、私に知らせてください!そのため、標準Cライブラリ関数を使用しない場合は、独自の数値を文字列変換関数に記述するか、他の人が使用することをお勧めします。

#include <Windows.h> 

//quick-and-dirty string-length function 
DWORD getStringLen(const char* pszStr) 
{ 
    const char* p = pszStr; 
    while(*p) ++p; 
    return(p - pszStr); 
} 

//program entry point - note that int return value does propagate back to 
// ExitProcess() despite main() being the program's actual entry point; 
// the ret at the end of this function returns back to the loader, which 
// in turn calls ExitThread() with EAX; the return value can be 
// checked on the comamnd-line via: echo %ERRORLEVEL% 
int main(void) 
{ 
    DWORD dwNum1 = 5; 
    DWORD dwNum2 = 3; 
    DWORD dwResult = dwNum1+dwNum2; 

    //build formatted output string 
    // 
    // NOTE: wsprintfA() is an unsafe function and is only used as an example 
    //  DO NOT USE in production code! 
    // 
    #pragma warning(disable : 4995) //wsprintf is a depreciated function 
    char szTemp[100]; 
    int iRet = wsprintfA(szTemp,"%u + %u = %u\n",dwNum1,dwNum2,dwResult); 

    //get console stdandard output handle 
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 
    if (INVALID_HANDLE_VALUE == hConsole) 
    { 
     iRet = -1; 
    } 
    else 
    { 
     //output the string 
     WriteConsoleA(hConsole,szTemp,getStringLen(szTemp),&dwNum1,NULL); 
    } 

    return(iRet); 
} 
+0

Thanks @bytepointer、kernel32のGetStdHandle()とWriteConsole()関数を使用して、あなたが与えたコンパイラ/リンカオプションを使うのは、私が必要としていたものでした。実行可能な実行ファイルは、生徒がOllyで逆にするのが簡単です。後で追加した**非常に素晴らしいコード例もありがとうございます。私はあなたの答えとして答えています。 – mvwhyatt

関連する問題