2013-07-30 20 views
1

我写在C++一个简单的程序:预防的Visual 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编译它表示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到另一个函数。

+3

在asm中没有这样的宏,你指的是函数已经被内联,通常当编译器决定去做它是一件好事,检查了这一点http://stackoverflow.com/questions/3329214/is-it-it-it-force-a-function-not-in-inline如果你仍然想阻止 – aaronman

+0

添加“__declspec(noinline)”行为解决了这个问题。谢谢! – hcf

+0

@yzt sure thing – aaronman

回答

5

在asm中没有这样的宏(它只是文本替换你的代码,发生在代码编译之前)。什么你指的是该功能已被内联,通常当编译器决定做它,它是一件好事,没有C++宽的方式来做到这一点,但你可以做这样的事情采取了这种

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

代码从this answer
这会阻止函数被内联。请记住,大多数时间内联是一件好事,因为它消除了函数调用的开销,除代码膨胀和调试外,它也没有真正的负面影响。编译器非常聪明,通常会对内联做出很好的决定。正如你可能已经知道你可以使用C++中的inline说明符到建议给编译器该函数应该被内联。

我原本也认为一个更便携的方法来防止函数内联将从函数指针调用它,但这post否则说。

为人们寻找这个答案使用GCC可以防止内联这样的无效void __attribute__ ((noinline)) myfunc()这看起来像它适用于铛太(我用苹果铛版本4.0),所以应该涵盖大多数++编译器的人会作为C正在使用。