欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

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

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

申请转正贴:【原创】ring3反作弊篇——基于EBP遍历调用栈及模块名
之前自己做的一款老游戏的基于R3入门级的反作弊代码中的片段,仅供学习参考~~
通杀Win XP/7/8,哪位兄弟装了WIN10麻烦测试一下谢谢!
感谢NV、漏网之鱼~~

//
// 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);
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[0].Luid))
            Sleep(1);
        tp.Privileges[0].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[pImgDos->e_lfanew];
        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[1024] = {0};
    DWORD    cbNeeded = 0;
    char    szModName[MAX_PATH];
    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[i], szModName, _countof(szModName));
        if(hMods[i])
        {
            if(nPEB >= (DWORD)hMods[i] && (nPEB <= ((DWORD)hMods[i] + GetPEImageSize(hMods[i]))))
            {
                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[MAX_PATH] = {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[ebp + 0x8];
    //
    // 设置堆栈指针
    __asm mov edi, dword ptr[ebp];
__Loop:
    //
    // 保存当前堆栈的返回地址 也就是呼叫这个函数的上一层函数的内存空间
    __asm mov eax, dword ptr[edi + 0x4];
    //
    // 调用匹配规则函数
    __asm push eax;
    __asm call dword ptr[ebp + 0xc];
    __asm add esp, 0x4;
    //
    // 获取上一个堆栈的指针
    __asm mov edi, dword ptr[edi];
    __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[BackCall];
    __asm push edx;
    //
    // 设置最大检测深度
    __asm push 0x50;
    __asm call dword ptr[Check];
    __asm add esp, 0x8;
    return x + y;
}
// 这里是测试函数
DWORD Function(DWORD x,DWORD y)
{
    //x += y;
    __asm mov edx,dword ptr[x];
    __asm add edx,0x10;                // 深度检测10个
    __asm mov dword ptr[x],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[MAX_PATH] = {0};
 WCHAR szPathName[MAX_PATH] = {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)
   {
    ULONG  NameSize = 0x100;
    LPVOID  pBuffer = 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_STRING  tmpAS;
     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[usSectionName->Length / sizeof(WCHAR)] = 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;
}
 

vs2010工程源码下载
http://www.rayfile.com/zh-cn/files/a1dcbf4c-d15e-11e4-ac13-0015c55db73d/
博客地址:
http://blog.csdn.net/wangningyu/article/details/44569803

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功