构造假堆栈
本帖最后由 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 12:12
能说说是什么代码吗。
C++的,你不是技术人员么? 都是底层的东西 基础教学~ 看不懂..... 青春染指悲伤ヽ 发表于 2013-6-17 12:12
能说说是什么代码吗。
我都告诉你这是C++的你还告诉我你不懂VB是什么意思? 还是Hook。。。
Win7下运行出错
原因是Use_Stdcall_Bypass_Call_Func里面的
jmpeax //跳入MessageBox()函数执行
改成call eax则正常。