目录

灵魂起源及画江山部分代码

C++ 逆向 C++编程原理

软件安全 破解与防破解 外挂与反外挂 病毒分析

灵魂起源

创建DLL并且注入窗口中

实例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
//唯一的一个 C我们的DLLApp 对象

C我们的DLLApp theApp;

CMyDialog *PMainDialog;	//窗口类
DWORD WINAPI ShowDialog(LPARAM lpData)
{
  PMainDialog = new CMyDialog;	//给指针分配空间
  PMainDialog->DoModal();	//阻塞的方式 模态窗口
  delete PMainDialog;	//释放空间 
  FreeLibraryAndExitThread(theApp.m_hInstance,1);	//释放DLL退出线程
  return TRUE;
}

// C我们的DLLApp 初始化
BOOL C我们的DLLApp::InitInstance()
{
  CWinApp::InitInstance();
  ::CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)ShowDialog,NULL,NULL,NULL);	//创建线程
  return TRUE;
}

读写内存修改血量

实例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
void CMyDialog::OnBnClickedButton1()
{
  //	[[[0x00D0DF1C]+1C]+28]+288
  
  //读取内存数据
  DWORD a = *(DWORD*)0x00D0DF1C;
  a = *(DWORD*)(a+0x1C);
  a = *(DWORD*)(a+0x28);
  a = *(DWORD*)(a+0x288);
  
  CString Stemp;
  Stemp.Format(_T("%d"),a);
  MessageBox(Stemp);
  
  //写入内存数据
  a = *(DWORD*)0x00D0DF1C;
  a = *(DWORD*)(a+0x1C);
  a = *(DWORD*)(a+0x28);
  *(DWORD*)(a+0x288) = 999
  
}

函数和call的对应关系

画江山

人物属性结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
typedef struct TROLE_PROPERTY	//人物属性结构
{
  char* szpName;
  DWORD ndHp;
  ...
  ...
  TROLE_PROPERTY* GetData();	//获得人物数据
  void FindWay(int x,int y);
 	DWORD GetMaxJy();	//获得人物当前升级最大经验
  DWORD GetisCombat();	//获得战斗标志位
  DWORD GetComebatNo();	//获得战斗顺序标志位
   
}_TROLE_PROPERTY;

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

获得人物数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
TROLE_PROPERTY*TROLE_PROPERTY::GetData()	//获得人物数据
{
  try
 	{
   	DWORD Base = GetBase(Offset_RoleProperty1);
   	DWORD Offset2 = Offset_RoleProperty2;
   	Base = Base+Offset_RoleProperty2;
    DWORD Temp = *(DWORD*)Base;
    ndLv = *(DWORD*)(Temp+0x12*8);
 	}
 	catch(...)
 	{
    OutputDebugStringA("读取人物信息异常\r\n");
   	return NULL;
 	}
  return this;
}

获得人物基地址+大偏移

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
DWORD GetBase(DWORD offset)	//获得人物基地址+大偏移
{
  DWORD backeax;
  DWORD of = offset;
  __asm
  {
    mov ecx,Base_Role
    mov edx,[ecx]
    mov eax,of
    mov eax,[edx+eax]
    call eax
    mov backeax,eax
  }
  return backeax;
}

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

寻路

 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
void TROLE_PROPERTY::FindWay(int x,int y)	//寻路
{
  try
  {
    DWORD ID = this->GetData()->ndMapId;
    DWORD X=x;
    DWORD Y=y;
    __asm
    {
      mov ecx,Base_Role
      mov eax,[ecx]
      mov edx,[eax+Offset_FindWay]
      call edx
      mov ecx,eax
      push 0
      push Y
      push X
      push ID
      mov edx,[ecx]
     	mov eax,[edx+4]
      call eax  
    }
  }
  catch(...)
  {
   	OutputDebugStringA("寻路异常\r\n");
  }
}

NPC结构

1
2
3
4
5
6
7
8
9
typedef struct TNpc_PROPERTY	//NPC结构
{
  char* szpName;
  DWORD ndID;
  DWORD ndX;
  DWORD ndY;
  DWORD ndOpenNpcID;
  DWORD ndAttackSign;
}_TNpc_PROPERTY;

NPC列表结构

1
2
3
4
5
6
7
typedef struct TNpc_List	//NPC列表结构
{
  DWORD ndNum;
  TNpc_PROPERTY NpcList[1000];
  DWORD ndNo;
  void GetData();
}_TNpc_List;

获得npc列表数据

 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
void TNpc_List::GetData	//获得npc列表数据
{
  try
  {
    DWORD Base = Base_NPC;
    DWORD Offset = Offset_RoleProperty2;
    ndNum = *(DWORD*)(Base+0xC);	//ID数组成员数
    DWORD Base1 = *(DWORD*)(Base+0x4);	//ID数组根
    DWORD Id= 0;
    int j = 0;
    DbgPrint_Mint("NPCID数组大小:%x\r\n",ndNum);
    for(int i=0;i<ndNum;i++)
    {
      Id = *(DWORD*)(Base1+i*0x4);
      if(Id>0x100000)
      {
        Id = Id&0x0FFFFF;
        DWORD Temp=*(DWORD*)Base;
				Temp=*(DWORD*)(Temp+Id*0x8);
        Temp=*(DWORD*)(Temp+Offset);
				NpcList[j].ndId=*(DWORD*)(Temp+0x0*0x8); 
        NpcList[j].ndX=*(DWORD*)(Temp+0x5*0x8); 
        NpcList[j].ndY=*(DWORD*)(Temp+0x6*0x8);
				NpcList[j].ndOpenNpcID=*(DWORD*)(Temp+0x96*0x8); 
        NpcList[j].ndAttackSign=*(DWORD*)(Temp+0x3*0x8);
        DWORD NameAddr=*(DWORD*)(Temp+Ox1*0x8);
				NpcList[j].szpName=(char*)(NameAddr+0x4);
                                   
        j=j+1;
      }
    }
    ndNo=j;
  }
  catch(...)
  {
    OutputDebugStringA("获得npc列表数据异常\r\n");
  }
}

获得战斗标志位

1
2
3
4
5
6
7
DWORD TROLE_PROPERTY::GetisCombat()	//获得战斗标志位
{
  DWORD Back=GetBase(Offset_isCombat1); 
  Back=Back+Offset_isCombat2;
	DWORD n=*(DWORD*)Back;
	return n;
}

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

获得战斗顺序标志位

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
DWORD TROLE_PROPERTY::GetComebatNo()	//获得战斗顺序标志位
{
  DWORD Back = GetBase(Offset_CombatNo1)
  __asm 
  {
    mov ecx ,Back 
    mov eax ,[ecx]
    mov edx ,[eax+Offset_CombatNo2]
    call edx 
    mov Back,eax
  }
  Back =*(DWORD*)(Back+4):
  return Back;
}

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

获得人物当前升级最大经验

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
DWORD TROLE_PROPERTY::GetMaxJy()	//获得人物当前升级最大经验
{
  DWORD Back1=GetBase (Offset_MaxJingYan); 
  DWORD* pLv = new DWORD;
  DWORD* pBack = new DWORD;
  *pLv = this->GetData()->ndLv; 
	__asm 
  { 
		push pLv 
    push pBack 
    mov ecx, Back1 
    add ecx, 4 
    mov eax, Call_LvtoJy 
    call eax 
	} 
  DWORD Temp=*pBack;  
  Temp=*(DWORD*)(Temp+Ox10); 
  return Temp; 

}

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

Hook明文包

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
void HookGameClearE()	//Hook明文包
{
  DWORD dwHookAddr = HookClearEAddr;	//HOOK地址
  DWORD dwTargetAddr = (DWORD)HookGameClearECall;	//跳转到的子程序
  DbgPrint_Mine("Hook明文包地址%x HookCall地址%x\r\n",dwHookAddr ,dwTargetAddr);
  EnableDebugPrivilege(TRUE); //提升权限 
  
  DWORD pid =NULL;
  DWORD WriteSize =NULL;
  GetWindowThreadProcessId(GetGameWndHandle(), &pid); //获得进程ID 
  hProcess =OpenProcess(PROCESS_ALL_ACCESS,FALSE ,pid ); //打开进程
  DbgPrint_Mine("pid:%x\r\n",pid );
  DbgPrint_Mine("hProcess:%x\r\n",hProcess );
  
  byte Temp =OxE9;	//jmp
  WriteProcessMemory(hProcess,(LPDWORD)(dwHookAddr + 0x00),&Temp,1 ,&WriteSize);
  DWORD Temp1= dwTargetAddr - dwHookAddr - 5;	//跳转的差值
  WriteProcessMemory(hProcess,(LDDWORD)(dwHookAddr + 0x01),&Temp1,4 ,&WriteSize);
  byte Temp2=0x90;	//用nop填充
  WriteProcessMemory(hProcess,(LPDWORD)(dwHookAddr + 0x05),&Temp2,1 ,&WriteSize);
}

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

提升权限

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
BOOL EnableDebugPrivilege (BOOL bEnable) //提升权限OpenProcess 
{
  BOO fOK =FALSE; 
  HANDLE hToken;
  if(OpenProcessToken(GetCurrentProcess()), TOKEN_ADTUSI_PRIVILEGES, &hToken)) //打开进程访问令牌
  {
    TOKEN_PRIVILEGES tp; 
    tp.PrivilegeCount = 1;
    LookupPrivilegelalue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); 
    tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED:0;
    AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof (tp), NULL, NULL);
    fOK = (GetlastError() == ERROR_SUCCESS);
    CloseHandle(hToken);
  }
  return fOK;
}

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

HOOK明文包子程序

 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
__declspec(naked) void HookGameCIearECa11()//裸体函数 HOOK明文包子程序
{
  __asm
  {
    //eax包长 ecx包内容 edx socket flags 0
    pushad
    mov BaoChang, eax
    mov ecx, [esi+4]
    mov BaoNeiRongAddr, ecx
  }
  p =new byte[BaoChang];
  ReadProcessMemory(hProcess, (LPCVOID)BaoNeiRongAddr, p, BaoChang, O);
  DbgPrint_Mine("包长:%x",BaoChang);
  for (int i=0;i<(int)BaoChang; i++)
  {
    sprintf(s, "%02X",p[i]);
    strcat_s(a, s);
  }
  DbgPrint_Mine("%s", a);
  sprintf(a, "%s","包内容:");
  delete p;
  
  __asm
  {
    popd
    mov ecx,dword ptr [esi+4]
    mov edx,dword ptr [edi+0xC]
    jmp HookGameClearBackAdrr
  }
          
}

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

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

还原明文包

1
2
3
4
5
6
7
8
void UnHookGameClearE()	//还原明文包
{
  //8B 4E 04 8B 57 0C 还原代码
  DWORD dwHookAddr = HookClearEAddr;
  DWORD WriteSize = NULL;
  byte Temp[] = {0x8B,0x4E,0x04,0x8b,0x57,0x0C};
  WriteProcessMemory(hProcess,(LPDWORD)(dwHookAddr + 0x00),&Temp,6 ,&WriteSize);
}

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

发送封包

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

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

发送封包

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

HexChar转Byte

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

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

人物攻击call

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

攻击call

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

自动打怪相关

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

byte数组转string

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

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

宝宝攻击call

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

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

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

封装主线程调用

设置主线程和卸载主线程

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

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

获得窗口句柄

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

回调函数

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

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

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

主线程选角色消息 主线程HOOK明文包消息 主线程发包消息 寻路消息

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

自动打怪

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910160108585的副本.png

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

自动打怪参数结构体

1
2
3
4
5
6
7
typedef struct TAutomaticKill	//自动打怪参数结构体
{
  int ndx1;
  int ndy1;
  int ndx2;
  int ndy2;
}_TAutomaticKill;

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

结束自动打怪

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

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

StructGame.h声明

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

自动打怪寻路线程

FindwayThread

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

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

循环寻路

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

自动打怪杀怪线程

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

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

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

任务遍历

void CMainDialogWnd::OnBnClickedButton14()

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

任务属性

Ttask_PROPERTY

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

任务列表结构

typedef struct Ttask_List

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

获得任务列表数据

void Ttask_List::GetData()

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

任务二叉树遍历

void Ttask_List::taskthree(int threeBase)

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

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

检测概论

exe dll 特征码

改写内存或者改写汇编代码

  • CRC检测 代码段 下访问断
  • 数据检测 数据段 下访问断
  • CALL检测
  • 堆栈检测

远程注入dll

int _tmain(int argc,_TCHAR* argue[])

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

InJectDll

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

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

劫持注入

劫持工具

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

收包

发包可以达到功能

收包只能作为判断

收包效率高

recv

WS2_32.recv

收包实例

hook明文包 另一处

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

还原明文包 另一处

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

裸体函数 另一处

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

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

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

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

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

窗口句柄和帐号

游戏账号

查找到游戏帐号的文本以后

下访问断 退出游戏得到访问代码

发现是一个常量(类似基地址)1670D31C

这个代码在主线程中 主线程入口地址是16670000

那个公式应该是

主线程入口+9C31C

我们用ce搜索主线程入中发现有基地址存放

得到公式

[27AC124]+9D31C

控件遍历

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

获得控件列表数据 GetData

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

控件遍历递归 GetData2

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