callach 发表于 2018-3-6 22:27:00

Ring3反作弊篇(基于EBP遍历调用栈及模块名)

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

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

源码如下:


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

#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);

fnMessageBoxA    pMessageBoxA = NULL;

DWORD Functiion(DWORD x, DWORD y);


//
// 提取函数
//
BOOL TiQuan()
{
    HANDLE    hToken;
    BOOL    fOk = 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;

    DWORD    nPEB = nEBP;
    BOOL    bFound = FALSE;
    HMODULE hMods = {0};
    DWORD    cbNeeded = 0;
    char    szModName;

    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)
{
    char    szDllPath = {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;
}



// 暴力搜索R3断链隐藏模块
BOOL WINAPI GetCheatModuleByEBP(const DWORD nEBP,const char *pszPath,const int nLen,DWORD & nCRC,DWORD & nFileSize);
{
DWORD ModuleBase = 0;
DWORD ModuleSize = 0;
WCHAR szModuleName = {0};
WCHAR szPathName = {0};
HANDLE hProcess = INVALID_HANDLE_VALUE;

memset(pszPath,0x00,nLen);
nCRC = nFileSize = 0;
if(nProcessID == 0)
return FALSE;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId());
if(!hProcess)
return FALSE;
for(int i=-1, BaseAddress=0; BaseAddress<0x80000000; BaseAddress+=0x1000)
{
MEMORY_BASIC_INFORMATION mbi;
if(NT_SUCCESS(ZwQueryVirtualMemory(hProcess, (PVOID)BaseAddress, MemoryBasicInformation, &mbi, sizeof(mbi), 0)))
{
   if(ModuleBase && ModuleBase != (DWORD)mbi.AllocationBase && ModuleSize)
    ModuleBase = ModuleSize = 0;
    if(mbi.Type != MEM_IMAGE)
    continue;
    ModuleBase = (DWORD)mbi.AllocationBase;
   if(ModuleBase && mbi.BaseAddress == (PVOID)BaseAddress)
    ModuleSize = (DWORD)mbi.BaseAddress + mbi.RegionSize - (DWORD)mbi.AllocationBase;
    if(mbi.AllocationBase != (PVOID)BaseAddress)
    continue;
   
   if(ModuleBase == 0 || ModuleSize == 0)
    continue;
    if((ModuleBase <= nEBP) && (ModuleBase + ModuleSize) >= nEBP)
   {
    ULONGNameSize = 0x100;
    LPVOIDpBuffer = malloc(NameSize);
    if(!pBuffer)
    {
   ASSERT(FALSE);
   continue;
    }
   
    NTSTATUS status = ZwQueryVirtualMemory(hProcess, (PVOID)mbi.AllocationBase, MemorySectionName, pBuffer, NameSize, &NameSize);
    if(status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_BUFFER_OVERFLOW)
    {
   free(pBuffer);
   pBuffer = malloc(NameSize);
   status = ZwQueryVirtualMemory(hProcess, (PVOID)mbi.AllocationBase, MemorySectionName, pBuffer, NameSize, 0);
    }
   
    if(!pBuffer) continue;
   if(!NT_SUCCESS(status))
    {
   free(pBuffer);
   continue;
    }
   POBJECT_NAME_INFORMATION SectionName = (POBJECT_NAME_INFORMATION)pBuffer;
    ANSI_STRINGtmpAS;
   PUNICODE_STRING usSectionName;
    char   *pTemp = NULL;
   usSectionName = (PUNICODE_STRING)pBuffer;
    _wcsnicmp(szModuleName, usSectionName->Buffer, usSectionName->Length / sizeof(WCHAR));
    wcsncpy(szModuleName, usSectionName->Buffer, usSectionName->Length / sizeof(WCHAR) );
    szModuleName = UNICODE_NULL;
    DeviceName2PathName(szPathName, szModuleName);
    pTemp = (char *)malloc(sizeof(char)*(2*wcslen(szPathName)+1));
    memset(pTemp , 0 , 2 * wcslen(szPathName)+1);
    W2C(pTemp,szPathName,2 * wcslen(szPathName)+1) ;
   memcpy(pszPath,pTemp,strlen(pTemp));
    delete [] pTemp;
    pTemp = NULL;
   nFileSize = mbi.RegionSize;
    nCRC   = GetFileCRC(pszPath);
   free(pBuffer);
    pBuffer = NULL;
    CloseHandle(hProcess);
    return TRUE;
   }
} else if(ModuleBase && ModuleSize)
{
   ModuleBase = ModuleSize = 0;
}
}
CloseHandle(hProcess);
return FALSE;
}
页: [1]
查看完整版本: Ring3反作弊篇(基于EBP遍历调用栈及模块名)