第四章:安全的交互通道
消息钩子,Hook游戏消息处理过程,GetKeyState(),GetAsyncKeyState()和GetKeyBoardState()函数,进程间通信。
消息钩子:SetWindowsHookEx(),UnhookWindowsHookEx()
Hook游戏消息处理过程:GetWindowLong(),SetWindowLong()
GetKeyState(),GetAsyncKeyState()和GetKeyBoardState()函数:容易Hook检测到。
按键->键盘驱动捕捉这个中断转为Virtual Key Code -> I/O管理器装成IRP(中断请求包)->OS组装VK_XX为WM_CHAR.
GetKeyState,GetKeyBoardState两个在消息过程(此时状态才会变)中使用前者取一个,后者取所有的。
GetAsyncKeyState其返回值内容,最高位表示是否按下,最低位表示上次调用此函数后,这个按键是否按下。
栈回塑检查就是检查返回地址是否合法,伪造就是push一个伪造的栈帧进去。
game.exe 游戏映像
normal.dll 游戏功能模块
invader.dll 非法模块
//game.exe
#include "normaldll\normaldll.h"
#include "invader\invader.h"
#include <vector>
#include <Windows.h>
using namespace std;
vector<int> vecAddr;
int ebpret[6][2] = { 0 };
void fun1()
{
__asm{
push eax
push ebx
push ecx
lea eax, [ebpret]
mov [eax], ebp
mov ecx, ebp
add ecx, 4
mov ebx, [ecx]
add eax, 4
mov [eax], ebx
pop ecx
pop ebx
pop eax
}
for(int i = 0; i < 6; ++i)
{
printf("ebp:%08x retaddr:%08x \n",ebpret[i][0],ebpret[i][1]);
}
fnnormaldll();
}
void fun2()
{
__asm{
push eax
push ebx
push ecx
lea eax, [ebpret]
add eax, 8
mov [eax], ebp
mov ecx, ebp
add ecx, 4
mov ebx, [ecx]
add eax, 4
mov [eax], ebx
pop ecx
pop ebx
pop eax
}
fun1();
}
void fun3()
{
__asm{
push eax
push ebx
push ecx
lea eax, [ebpret]
add eax, 0x10
mov [eax], ebp
mov ecx, ebp
add ecx, 4
mov ebx, [ecx]
add eax, 4
mov [eax], ebx
pop ecx
pop ebx
pop eax
}
fun2();
}
void fun4()
{
__asm{
push eax
push ebx
push ecx
lea eax, [ebpret]
add eax, 0x18
mov [eax], ebp
mov ecx, ebp
add ecx, 4
mov ebx, [ecx]
add eax, 4
mov [eax], ebx
pop ecx
pop ebx
pop eax
}
fun3();
}
void main()
{
HMODULE baseAddr = GetModuleHandle(L"testFakeStackFrames.exe");
nnormaldll = (int)baseAddr;
ninvader = (int)baseAddr;
ninvader = (int)baseAddr;
fninvader();
__asm{
push eax
push ebx
push ecx
lea eax, [ebpret]
add eax, 0x20
mov [eax], ebp
mov ecx, ebp
add ecx, 4
mov ebx, [ecx]
add eax, 4
mov [eax], ebx
pop ecx
pop ebx
pop eax
}
fun4();
while(true)
{
Sleep(1000);
}
}
//normal.dll
// normaldll.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "normaldll.h"
#include <string>
// This is an example of an exported variable
NORMALDLL_API int nnormaldll=0;
int ebpretdll[6][2] = { 0 };
bool CheckStackFrame()
{
int bRet = 0;
__asm
{
push eax
push ebx
push ecx
push edx
push edi
push ebp
lea edx, [ebpretdll]
mov ebx, nnormaldll
mov ecx, 5
label:
mov [edx], ebp
add edx, 4
mov ebx, ebp
add ebx, 4
mov edi, [ebx]
mov [edx],edi
add edx, 4
mov edi, [ebp]
mov ebp, edi
dec ecx
jge label
pop ebp
pop edi
pop edx
pop ecx
pop ebx
pop eax
}
printf("EXE Baseaddr:%08x\n follow is check statck info:\n",nnormaldll);
for(int i = 0; i < 6; ++i)
{
printf("ebp:%08x retaddr:%08x \n",ebpretdll[i][0],ebpretdll[i][1]);
}
return bRet;
}
// This is an example of an exported function.
NORMALDLL_API int fnnormaldll(void)
{
CheckStackFrame();
wchar_t buf[100] = { 0 };
wsprintfW(buf,L"EXE address:%08x, current dll address:%08x",nnormaldll,GetModuleHandle(L"normaldll.dll"));
MessageBoxW(NULL,buf, L"normal dll caption", MB_OK);
return 42;
}
// This is the constructor of a class that has been exported.
// see normaldll.h for the class definition
Cnormaldll::Cnormaldll()
{
return;
}
//invader.dll
// invader.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "invader.h"
#include <windows.h>
#include <stdio.h>
#include <process.h>
#include "..\normaldll\normaldll.h"
// This is an example of an exported variable
INVADER_API int ninvader=0;
HANDLE g_event = NULL;
typedef int (*PFUN)(void);
DWORD fakestack[20] = { 0 };
DWORD addr = 0;
_declspec (naked) void fakeframe(DWORD funaddr,DWORD fakestack)
{
__asm{
mov edi, edi
push ebp
mov ebp, esp
push eax
push ebx
//push ebp
mov eax, addr
add eax,18*4
mov ebx, [ebp]
mov [eax], ebx
add eax,4
mov [eax], esp
jmp PUSH_REAL_RET_ADDR
FUN:
push 0x771f000a ;//ret
mov eax, ebp
mov ebx, addr
mov [eax],ebx
mov eax, funaddr
jmp eax
PUSH_REAL_RET_ADDR:
call FUN
mov eax, addr
add eax,19*4
mov esp, [eax]
sub eax, 4
mov ebx, [eax]
mov [ebp], ebx
pop ebx
pop eax
mov esp, ebp
pop ebp
ret 8
}
}
void hah1()
{
for(int i = 0; i< 20; )
{
fakestack[i] = (DWORD)&fakestack[i+2];
fakestack[i+1] = 0x00000021;
i += 2;
}
HMODULE hnormaldll = GetModuleHandleW(L"C:\\test\\testFakeStackFrames\\Debug\\normaldll.dll");
PFUN p = (PFUN)GetProcAddress(hnormaldll,"?fnnormaldll@@YAHXZ");
//nnormaldll = (int)GetModuleHandle(L"invader.dll");
addr = (DWORD)&fakestack;
fakeframe((DWORD)p,addr);
}
void hah2()
{
hah1();
}
void hah3()
{
hah2();
}
void hah4()
{
hah3();
}
unsigned __stdcall start_address( void * pa )
{
g_event = CreateEventW(NULL,FALSE,FALSE,L"SNOWMAN");
printf("11111\n");
WaitForSingleObject( g_event, INFINITE );
hah4();
while(true)
{
printf("dddddddddddddd\n");
Sleep(1000);
}
_endthreadex( 0 );
return 0;
}
// This is an example of an exported function.
INVADER_API int fninvader(void)
{
HANDLE hthread = (HANDLE)_beginthreadex(NULL,0,&start_address,NULL,0,NULL);
//Sleep(3000);
//hah4();
return 42;
}
// This is the constructor of a class that has been exported.
// see invader.h for the class definition
Cinvader::Cinvader()
{
return;
}
//trigeror
#include <windows.h>
#include <stdio.h>
#include <process.h>
void main()
{
HANDLE g_event = CreateEventW(NULL,FALSE,FALSE,L"SNOWMAN");
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
printf(" OK is exist, only triger\n");
SetEvent(g_event);
}
}
测试结果:
normal.dll调用时栈如下:
非法调用时的栈: