wow 发表于 2013-6-17 10:28:28

构造假堆栈

本帖最后由 wow 于 2013-6-17 10:29 编辑

#include <windows.h>

/////////////////////////////////////////////////////////////////////////////////
//   __stdcall 与 _cdecl 两个函数最后只会影响edi跟esi的值,函数都不会出什么问题
/////////////////////////////////////////////////////////////////////////////////

// __stdcall 方式的函数
void WINAPI Use_Stdcall_Bypass_Call_Func(DWORDdwFakeStackFrameArray ,
                                                                                 DWORD FunctionName,
                                                                                 DWORD *dwArgv,
                                                                                 DWORD dwcount,
                                                                                 DWORD dwXAddr);
// _cdecl方式的函数
void WINAPI Use_cdecl_Bypass_Call_Func(DWORDdwFakeStackFrameArray ,
                                                                           DWORD FunctionName,
                                                                           DWORD *dwArgv,
                                                                           DWORD dwcount,
                                                                           DWORD dwXAddr);

void BypassCallStackCheck(LPTSTR szDllName);
void FuncG(void);



void FuncG(void)
{
    BypassCallStackCheck(TEXT("kernel32.dll"));
      MessageBox(NULL, "Test Bypass Call Stack Check", "winsun: Bypass", 0);
}

void BypassCallStackCheck(LPTSTR szDllName)
{
      DWORD dwFakeStackFrame = {0};

      DWORD   dwFakeRetAddr = 0xFEFEFEFE;
    PDWORDpdwEbp = NULL;
      PCHAR   pszTitle = "ByPass Call Stack Check \0";
      PCHAR   pszCaption = "winsun \0";
      DWORD   dwMsgBoxAddr = 0;
      DWORD   dwRealAddr = 0;
    PBYTE   pbSearchRet = NULL;
      dwMsgBoxAddr = (DWORD)GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxA");
      
    for ( int iLoop = 0; iLoop < 100; )
    {
      dwFakeStackFrame   = (DWORD)&dwFakeStackFrame;
                dwFakeStackFrame = dwFakeRetAddr;
                iLoop += 2;
    }


      HMODULE hmodle = GetModuleHandle(szDllName);
      if (hmodle == NULL)
      {
                // can't find the module
                return ;
      }
      DWORD RetAddress = NULL;
      try
      {
                // 找代码段里面的ret指令
                PIMAGE_DOS_HEADERmzhead = (PIMAGE_DOS_HEADER) hmodle;
                PIMAGE_NT_HEADERS peheader =
                        (PIMAGE_NT_HEADERS)((DWORD)mzhead + mzhead->e_lfanew);
                LPBYTE pbuf = (LPBYTE)( (DWORD)mzhead + peheader->OptionalHeader.BaseOfCode );
                DWORD dwsize = peheader->OptionalHeader.SizeOfCode;
                for (DWORD i=0; i<dwsize; i++, pbuf++)
                {
                        if (*pbuf == 0x0C3)
                        {
                              RetAddress = (DWORD)pbuf;
                              break;
                        }
                }
      }
      catch (...)
      {
                // 不可读异常
                return ;
      }
      if (RetAddress == NULL)
      {
                // no ret code in module
                return ;
      }

      //函数参数,最后一个参数,倒数第二个参数...
      DWORD argv = {0};
      argv = MB_OK;
      argv = (DWORD)pszCaption ;
      argv = (DWORD)pszTitle;
      argv = NULL;

    Use_Stdcall_Bypass_Call_Func(dwFakeStackFrame, dwMsgBoxAddr, argv, 4, RetAddress); // 0x7c921224);
}

_declspec (naked) void WINAPI Use_Stdcall_Bypass_Call_Func(DWORD dwFakeStackFrameArray ,
                                                                                                                   DWORD FunctionName,
                                                                                                                   DWORD *dwArgv,
                                                                                                                   DWORD dwcount,
                                                                                                                   DWORD dwXAddr)
{
      _asm
      {
                //function prologue(函数前导指令)
                mov edi, edi
                push ebp
                mov ebp, esp
               
                //function body
                push esi
                mov esi,ebp
               
                push REAL_RET_ADDR
                moveax,dwArgv
                movecx,dwcount

                // 函数使用的参数入当前栈
push_argv:
                movebx,
                push ebx
                addeax,4
                dececx
                jnzpush_argv

                push dwXAddr
                moveax, FunctionName
                movebp, dwFakeStackFrameArray //把假栈帧基地址赋值给EBP
                jmpeax //跳入MessageBox()函数执行
                              
REAL_RET_ADDR:
                movebp,esi
                popesi
                //function epilogue(函数后继指令),for stack balance
                movesp, ebp
                popebp
                ret20
      }
}

_declspec (naked) void WINAPI Use_cdecl_Bypass_Call_Func(DWORD dwFakeStackFrameArray ,
                                                                                                                   DWORD FunctionName,
                                                                                                                   DWORD *dwArgv,
                                                                                                                   DWORD dwcount,
                                                                                                                   DWORD dwXAddr)
{
      _asm
      {
                //function prologue(函数前导指令)
                        mov edi, edi
                        push ebp
                        mov ebp, esp

                        //function body
                        push esi
                        mov esi,ebp
                        push edi
                        mov edi,dwcount

                        push REAL_RET_ADDR
                        moveax,dwArgv
                        movecx,dwcount
push_argv:
                        movebx,
                        push ebx
                        addeax,4
                        dececx
                        jnzpush_argv

                        push dwXAddr
                        moveax, FunctionName
                        movebp, dwFakeStackFrameArray //把假栈帧基地址赋值给EBP
                        jmpeax //跳入MessageBox()函数执行

REAL_RET_ADDR:
                        rol edi,2
                        add esp,edi
                        pop edi
                        movebp,esi
                        popesi
                        //function epilogue(函数后继指令),for stack balance
                        movesp, ebp
                        popebp
                        ret20
      }
}


int main()
{
      FuncG();
      return 0;
}你懂的。

狸猫 发表于 2013-6-17 11:30:31

在我眼里就是天书哎。。

青春手卷 发表于 2013-6-17 11:44:40

表示我也看不懂的

姬霸腾 发表于 2013-6-17 11:57:09

注释太少了吧,看的真艰难,还看不懂

青春染指悲伤ヽ 发表于 2013-6-17 12:12:37

能说说是什么代码吗。

夜尽天明 发表于 2013-6-17 12:31:25

青春染指悲伤ヽ 发表于 2013-6-17 12:12
能说说是什么代码吗。

C++的,你不是技术人员么?

mar1321 发表于 2013-6-17 17:16:57

都是底层的东西 基础教学~

icksky 发表于 2013-6-18 13:26:05

看不懂.....

夜尽天明 发表于 2013-6-18 15:18:30

青春染指悲伤ヽ 发表于 2013-6-17 12:12
能说说是什么代码吗。

我都告诉你这是C++的你还告诉我你不懂VB是什么意思?

qqlinhai 发表于 2013-6-19 09:47:52

还是Hook。。。
Win7下运行出错
原因是Use_Stdcall_Bypass_Call_Func里面的
jmpeax //跳入MessageBox()函数执行
改成call eax则正常。
页: [1] 2 3
查看完整版本: 构造假堆栈