目录

C++逆向

一. 人物基址及相关属性偏移

  1. CE搜索数值,如血量
  2. OD追基址
  3. 龙龙遍历其它偏移

二. 查找人物状态基址及偏移

  1. CE搜索人物状态
  2. OD追基址

三. 人物怪物二叉树

  1. CE搜索NPC名字
  2. OD追基址,追到递归,放弃重来
  3. CE搜索怪物血量
  4. OD追基址,追到二叉树,追出树根
  5. 根据二叉树特性,在汇编中可推测出关键标志位,怪物ID及怪物对象
  6. 在怪物对象下可找到怪物属性(参考人物偏移)

四. DLL显示窗口

  1. 创建MFC_DLL(

    • 创建项目 => MFC动态链接库
  2. 在创建DLL内添加窗口

    • 资源视图 => rc文件右击 => 添加资源 => Dialog
  3. 添加窗口控件类

    • dialog窗口右击 => 添加类(如CMainDialog)
  4. 线程创建并显示窗口

    1. 创建多线程
    2. 创建窗口对象,用new来初始化,用DoModal显示出来
    3. 释放new的内存空间
    4. 释放dll空间并退出dll
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    //唯一的 CMainDllApp 对象
    CMainDllApp theApp;
    CMainDialog *PMainDialog;
    
    DWORD WINAPI _显示窗口(LPARAM lParam)
    {
    	PMainDialog = new CMainDialog;	//用new的方式分配内存空间
    	PMainDialog->DoModal();	//以模态化显示
    	delete PMainDialog;	//释放new分配的内存空间
      FreeLibraryAndExitThread(theApp.m_HInstance,1);	//释放dll空间并退出dll
      return TRUE;
    }
    
    //CMainDllApp 初始化
    BOOL CMainDllApp::InitInstance()
    {
      CWinApp::InitInstance();
      ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)_显示窗口,NULL,0,NULL);
    
      return TRUE;
    }
    

五. 编写注入器

  1. 新建MFC应用

  2. 提升扠限

    1. 获取进程钥匙: OpenProcessToken()

    2. 获取当前进程句柄: GetCurrentProcess()

    3. 查看权限: LookupPrivilegeValue(

    4. 设置新权限: AdjustTokenPrivileges()

    5. 关闭进程句柄: CloseHandle()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    
     void _提权()
     {
      //1. 获取进程钥匙
      HANDLE 进程_钥匙;
      if(FALSE == OpenProcessToken(GetCurrentProcess(),//进程句柄=>当前进程
                                    TOKEN_ALL_ACCESS,	//所有权限
                                    &进程_钥匙));	//存放钥匙
       {
         MessaseBox(NULL,_T("打开进程访问令牌失败!"),_T("错误提示"),MB_OK);
         return;
       }
    
       //2.查看进程里面的特权信息
       LUID 进程_权限;
       if(FALSE == LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&进程_权限))
       {
         MessaseBox(NULL,_T("查看进程权限信息失败!"),_T("错误提示"),MB_OK);
         return;
       }
    
       //3. 调节进程权限
       TOKEN_PRIVILEGES 进程_新特权;
       进程_新特权.PrivilegCount = 1;	//特权个数
       进程_新特权.Privileg[0].Attributes = SE_PRIVILEGE_ENABLED;	//启用特权
       进程_新特权.Privileg[0].Luid = 进程_权限;	//将查到的luid存放到luid里面
       if(FALSE == AdjustTokenPrivileges(进程_钥匙,FALSE,&进程_新特权,sizeof(进程_新特权),NULL,NULL))
       {
         MessaseBox(NULL,_T("打开进程权限失败!"),_T("错误提示"),MB_OK);
        return;
       }
    
       //4. 关闭进程句柄
       CloseHandle(进程_钥匙);
     }
    
  3. 开始注入

    1. 获取窗口句柄: FindWindow()
    2. 根据窗口句柄获取进程ID PID: GetWindowThreadProcessId()
    3. 根据PID获取进程句柄: OpenProcess()
    4. 在远程进程中申请内存空间: VirtualAllocEx()
    5. 在远程进程中写入咱们的DLL地址: WriteProcessMemory()
    6. 获取LoadLibraryA()函数地址: GetProcAddress()
    7. 在远程进程中创建一个线程: CreateRemoteThread()
    8. 清理战场
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    
    void _注入辅助()
    {
    	//1. 查找窗口
    	HWND 游戏窗口句柄;
      游戏窗口句柄 = FindWindow(游戏窗口类名,NULL);
      if(游戏窗口句柄 == NULL)
      {         
        MessaseBox(NULL,_T("游戏未启动"),_T("错误提示"),MB_OK);
        return;
      }
    
      //2. 获取进程ID PID
      DWORD 进程_PID = 0;
      GetWindowThreadProcessId(游戏窗口句柄,&进程_PID);
      if(进程_PID == 0)
      {
        MessaseBox(NULL,_T("获取进程PID失败"),_T("错误提示"),MB_OK);
        return;
      }
    
      //进程: 一个进程中的程序
      //一个进程可以有多个窗口
      //3. 获取进程句柄
      HANDLE 进程_进程句柄 = NULL;
      进程_进程句柄 = OpenProcess(PROCESS_ALL_ACCESS,FALSE,进程_PID);
      if(进程_进程句柄 == NULL)
      {       
        MessaseBox(NULL,_T("获取进程PID失败"),_T("错误提示"),MB_OK);
        return;
      }
    
      //4. 在远程进程中申请内存空间
      LPVOID 申请空间地址 = NULL;
      DWORD 申请空间 =256;
      申请空间地址 = VirtualAllocEx(进程_进程句柄,NULL,申请空间,MEM_COMMIT,PAGE_READWRITE);
      if(申请空间地址 == NULL)
      {
        MessaseBox(NULL,_T("获取进程PID失败"),_T("错误提示"),MB_OK);
        return;
      }
    
      //5. 将DLL的路径写入到远程进程中
      /*
      CHAR 当前路径[256];
      CHAR DLL路径[256];
      GetCurrentDirectoryA(sizeof(当前路径),当前路径);	//获取运行目录
      strcpy_s(DLL路径,当前路径);
      strcpy_s(DLL路径,"\\");
      strcpy_s(DLL路径,DLL名);
      */
    	SIZE_T 实际写入大小 = 0;
      CHAR DLL路径[256] = "C:\\Users\\Admin\\Desktop\\MyDll.dll "
      if(FALSE == WriteProcessMemory(进程_进程句柄,申请空间地址,DLL路径,strlen(DLL路径)+1,&实际写入大小))
      {
        MessaseBox(NULL,_T("DLL写入失败"),_T("错误提示"),MB_OK);    
        return;
      }
      LPTHREAD_START_ROUTINE 函数地址 = NULL;
      函数地址 = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("kernel32.dll"),"LoadLibraryA");
    
      //6. 在远程进程中创建一个线程
      HANDLE 进程_远程线程句柄 = NULL;
      进程_远程线程句柄 = CreateRemoteThread(进程_进程句柄,NULL,0,函数地址,申请空间地址,0,NULL);
      if(进程_远程线程句柄 == NULL)
      {        
        MessaseBox(NULL,_T("创建远程线程失败"),_T("错误提示"),MB_OK);    
        return;
      }
      WaitForSingleObject(进程_远程线程句柄,0xFFFFFFFF);
      CloseHandle(进程_远程线程句柄);
      VirtualFreeEx(进程_进程句柄,申请空间地址,申请空间,MEM_DECOMMIT);
      CloseHandle(进程_进程句柄);
    }
    

六. 实现读取游戏数据

  1. 实现读取人物信息
  2. 用指针的方式读取内存
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
//基址管理
#define _人物基址 (DWORD)GetModuleHandleA("Game. exe”) +0x3B3E78
#define _背包基址 (DWORD)GetModuleHandleA("Game. exe”) +0x3B40F4

//结构管理
struct R_人物屬性
{
  DWORD 状态;
  DWORD 最大血值;
  DWORD 当前蓝值;
  DWORD 最大藍值;
  PCHAR 人物名 = "";
  FLOAT X坐标;
  FLOAT Y坐标;
  DWORD dw对象;
  DWORD 类型;
  FLOAT 距离;
  DWORD ID;
  
  void _初始化();   
}

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20220228170413062.png

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20220302123201384.png

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20220302123234809.png