有三到 发表于 2024-3-4 09:30:41

ring3反作弊篇——基于EBP遍历调用栈及模块名

之前自己做的一款老游戏的基于R3入门级的反作弊代码中的片段,仅供学习参考~~

通杀Win XP/7/8,哪位兄弟装了WIN10麻烦测试一下谢谢!

//
// CallStackList.cpp : 定义控制台应用程序的入口点。
//
// thanks for NV.
//

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>

#include "EasyDetour.h"

#include <TlHelp32.h>
#include <;Psapi.h>
#pragma comment(lib,"psapi.lib")

typedef int (WINAPI *fnMessageBoxA)(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType);

fnMessageBoxApMessageBoxA = NULL;

DWORD Functiion(DWORD x, DWORD y);


//
// 提取函数
//
BOOL TiQuan()
{
HANDLEhToken;
BOOLfOk = FALSE;

if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken))
{
    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount=1;
    if(!LookupPrivilegeValueA(NULL,"SeDebugPrivilege",&tp.Privileges.Luid))
      Sleep(1);

    tp.Privileges.Attributes=SE_PRIVILEGE_ENABLED;
    if(!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL))
      Sleep(1);

    fOk = (GetLastError() == ERROR_SUCCESS);
    CloseHandle(hToken);
}

return fOk;
}

//
// 获取PE文件大小
//
DWORD GetPEImageSize(HMODULE hModule)
{
PBYTE pInfo = (PBYTE)hModule;
PIMAGE_DOS_HEADER pImgDos = (PIMAGE_DOS_HEADER)pInfo;
PIMAGE_NT_HEADERS pImgNt;
if(pImgDos->e_magic==IMAGE_DOS_SIGNATURE)
{
    pImgNt = (PIMAGE_NT_HEADERS)&pInfo;
    if(pImgNt)
    {
      if(pImgNt->Signature==IMAGE_NT_SIGNATURE)
      {
      return pImgNt->OptionalHeader.SizeOfImage;
      }
    }
}
return NULL;
}

//
// Hook MessageBox for test
//
BOOL WINAPI GetCheatModuleByEBP(DWORD nEBP,char *pszPath,int nLen)
{
TiQuan();
if(nEBP == 0)
    return FALSE;

DWORDnPEB = nEBP;
BOOLbFound = FALSE;
HMODULE hMods = {0};
DWORDcbNeeded = 0;
charszModName;

HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentProcessId());
//IsWow64Process(hProcess, &Wow64Process); //判断是32位还是64位进程
EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded);

nPEB = nEBP;
for (UINT i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
{
    GetModuleFileNameExA(hProcess, hMods, szModName, _countof(szModName));
    if(hMods)
    {
      if(nPEB >= (DWORD)hMods && (nPEB <= ((DWORD)hMods + GetPEImageSize(hMods))))
      {
      memset(pszPath,0x00,nLen);
      wsprintfA(pszPath,"%s",szModName);
      bFound = TRUE;
      break;
      }
    }
}

CloseHandle(hProcess);
return bFound;
}

//
// Hook MessageBox for test
//
int WINAPI newMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType)
{
Functiion(0,0);
return pMessageBoxA(hWnd,lpText,lpCaption,uType);
}

//
// 回调函数
//
DWORD BackCall(DWORD Address)
{
charszDllPath = {0x00};
if(GetCheatModuleByEBP(Address,szDllPath,MAX_PATH))
    printf("检测地址:0x%08x%s\n", Address, szDllPath);
else
    printf("检测地址:0x%08x未知模块\n", Address, szDllPath);

//
// 在这里添加白名单 黑名单匹配的代码 (黑名单返回1 白名单返回0)
//

return 0;
}

//
// 检测呼叫者调用连
//
BOOL __declspec(naked)Check(void)
{
__asm push ebp;
__asm mov ebp, esp;
__asm sub esp, 0x8;

__asm push edi;
__asm push ecx;

//
// 查询次数
__asm mov ecx, dword ptr;

//
// 设置堆栈指针
__asm mov edi, dword ptr;

__Loop:

//
// 保存当前堆栈的返回地址 也就是呼叫这个函数的上一层函数的内存空间
__asm mov eax, dword ptr;

//
// 调用匹配规则函数
__asm push eax;
__asm call dword ptr;
__asm add esp, 0x4;

//
// 获取上一个堆栈的指针
__asm mov edi, dword ptr;

__asm cmp eax, 0x1;
__asm je __Out;

//
// 如果已经为空了 则直接退出

__asm cmp edi, 0x0;
__asm je __Out;

__asm loop __Loop;

__Out:

__asm pop ecx;
__asm pop edi;
__asm add esp, 0x8;
__asm pop ebp;
__asm ret;
}



//
// 测试函数
//
DWORD Functiion(DWORD x, DWORD y)
{

//
// 设置回调函数
__asm mov edx, dword ptr;
__asm push edx;

//
// 设置最大检测深度
__asm push 0x50;
__asm call dword ptr;
__asm add esp, 0x8;

return x + y;
}

// 这里是测试函数
DWORD Function(DWORD x,DWORD y)
{
//x += y;
__asm mov edx,dword ptr;
__asm add edx,0x10;      // 深度检测10个
__asm mov dword ptr,edx;
return x;
}

int MsgBox()
{
return MessageBoxA(NULL,"Hello World by Koma !","Test",MB_OK);
}

int _tmain(int argc, _TCHAR* argv[])
{
pMessageBoxA = MessageBoxA;
DetourHook((void**)&pMessageBoxA,newMessageBoxA);
MsgBox();
while(getchar() != 'a')
    Sleep(0);
DetourUnHook((void**)&pMessageBoxA,newMessageBoxA);
return 0;
}

页: [1]
查看完整版本: ring3反作弊篇——基于EBP遍历调用栈及模块名