1

私はC++で簡単なプログラムを書きました:

#include <stdio.h>

const signed char pass[] = "\x70\x61\x73\x73\x77\x6F\x72\x64";

bool __stdcall check_password(const signed char * str)
{
    unsigned int i;
    for(i=0;i<8;++i)
        if(str[i]!=pass[i])
            return false;
    return true;
}

int main(int argc, char * argv[])
{
    signed char buf[20];
    printf("please enter the password: ");
    scanf("%s",buf);
    printf((check_password(buf)) ? "correct!\n" : "incorrect.\nPress any key to exit..\n");
    getchar();
    return 0;
} 


それをVisual Studio Express 2010でコンパイルしました。
結果をOllyDbgで開いたところ、次のようになりました。

Address   Hex dump            Command                                          Comments
00FF1011  ³.  8B35 A020FF00   MOV ESI,DWORD PTR DS:[<&MSVCR100.printf>]
00FF1017  ³.  68 0021FF00     PUSH OFFSET pass2.00FF2100                       ; ASCII "please enter the password: "
00FF101C  ³.  FFD6            CALL ESI
00FF101E  ³.  8D45 E8         LEA EAX,[LOCAL.6]
00FF1021  ³.  50              PUSH EAX
00FF1022  ³.  68 1C21FF00     PUSH OFFSET pass2.00FF211C                       ; ASCII "%s"
00FF1027  ³.  FF15 A820FF00   CALL DWORD PTR DS:[<&MSVCR100.scanf>]
00FF102D  ³.  83C4 0C         ADD ESP,0C
00FF1030  ³.  33C0            XOR EAX,EAX
00FF1032  ³>  8A4C05 E8       MOV CL,BYTE PTR SS:[EAX+EBP-18]
00FF1036  ³.  3A88 F420FF00   CMP CL,BYTE PTR DS:[EAX+pass2.pass]             ; ASCII "password"
00FF103C  ³. 75 0D           JNE SHORT pass2.00FF104B
00FF103E  ³.  40              INC EAX
00FF103F  ³.  83F8 08         CMP EAX,8
00FF1042  ³. 72 EE           JB SHORT pass2.00FF1032
00FF1044  ³.  B8 2021FF00     MOV EAX,OFFSET pass2.00FF2120                    ; ASCII "correct!\n"
00FF1049  ³. EB 05           JMP SHORT pass2.00FF1050
00FF104B  ³>  B8 2C21FF00     MOV EAX,OFFSET pass2.00FF212C                    ; ASCII "incorrect.\nPress any key to exit..\n"
00FF1050  ³>  50              PUSH EAX
00FF1051  ³.  FFD6            CALL ESI
00FF1053  ³.  83C4 04         ADD ESP,4
00FF1056  ³.  FF15 9C20FF00   CALL DWORD PTR DS:[<&MSVCR100.getchar>]

check_passwordCALL 命令が表示されないため、関数がインライン化されているように見えます。

だから私の質問は、どうすればこれが起こらないようにすることができますか? 関数を実行可能ファイルに表示することをコンパイラに伝える方法はありますか?

私が尋ねている理由は、DLL インジェクションを実行しようとしているからです。私の主な目標は、呼び出しをcheck_password別の関数にリダイレクトすることです。

4

1 に答える 1

5

asm にはマクロのようなものはありません (コードをテキストで置き換えるだけで、コードがコンパイルされる前に実行されます)。あなたが参照しているのは、関数がインライン化されていることです。通常、コンパイラーがそれを行うことを決定した場合、それは良いことです。これを行うC ++全体の方法はありませんが、このようなことを行うことができます

class X {
     __declspec(noinline) int member_func() {
          return 0; 
     }
};

この回答から取得したコード。
これにより、関数がインライン化されなくなります。ほとんどの場合、インライン化は関数呼び出しのオーバーヘッドを取り除くため良いことであり、コードの肥大化とデバッグ以外に実際の悪影響はないことを覚えておいてください。コンパイラは非常に賢く、一般的にインライン化について適切な決定を下します。既にご存知かもしれませんがinline、c++ で指定子を使用して、関数をインライン化する必要があることをコンパイラ に提案できます。

また、関数のインライン化を防ぐためのより移植性の高い方法は、関数ポインターから呼び出すことだと当初考えていましたが、この投稿ではそうではありません。

gccを使用してこの回答を見ている人は、この void のようなインラインを防ぐことができます。void __attribute__ ((noinline)) myfunc()これは、clang でも機能するように見えます (私は Apple clang バージョン 4.0 を使用しています)。

于 2013-07-30T23:50:20.617 に答える