防止Visual C ++内联函数

时间:2013-07-30 23:22:14

标签: c++ assembly compiler-optimization dll-injection ollydbg

我用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_password已被内联,因为我看不到任何CALL指令。

所以我的问题是,如何防止这种情况发生?有没有办法告诉编译器我希望函数出现在可执行文件中?

我问的原因是因为我正在尝试执行DLL注入,我的主要目标是将调用重定向到check_password到另一个函数。

1 个答案:

答案 0 :(得分:5)

在asm中没有宏这样的东西(它只是文本替换你的代码并在代码编译之前发生)。你所指的是函数已被内联,通常在编译器决定这样做时它是一件好事,没有c ++广泛的方法来做到这一点,但你可以做这样的事情

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

代码取自this answer
这将阻止内联函数。请记住,大多数时间内联是一件好事,因为它摆脱了函数调用的开销,除了代码膨胀和调试之外,它也没有真正的负面影响。编译器非常聪明,通常可以做出关于内联的良好决策。您可能已经知道,您可以使用c ++中的inline说明符来 建议 到编译器中,该函数应该被内联。

我最初还认为防止函数内联的一种更便携的方法是从函数指针中调用它,但是这个post说不然。

对于使用 gcc 查看此答案的人,您可以阻止内联,例如此void __attribute__ ((noinline)) myfunc()这似乎也适用于clang(我正在使用Apple clang 4.0版),所以应该涵盖人们将使用的大多数c ++编译器。