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;
|
![image-20210907000855508 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;
}
|
![image-20210907001044535 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;
}
|
![image-20210907001000176 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;
}
|
![image-20210907001130268 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;
}
|
![image-20210907001216151 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);
}
|
![image-20210907000623174 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;
}
|
![image-20210907000229362 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
}
}
|
![image-20210907000142471 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210907000142471.png]()
![image-20210907000437493 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);
}
|
![image-20210907000007789 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210907000007789.png]()
发送封包
![image-20210907093129601 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210907093129601.png]()
![image-20210907094103352 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
![HexChar转Byte https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210907095955337.png]()
![image-20210907100033189 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210907100033189.png]()
人物攻击call
![image-20210909235021642 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210909235021642.png]()
攻击call
![攻击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
![byte数组转string https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210909234719877.png]()
![image-20210909234803589 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210909234803589.png]()
宝宝攻击call
![image-20210909235211884 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210909235211884.png]()
![image-20210910000032522 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910000032522.png]()
![image-20210909235938870 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210909235938870.png]()
封装主线程调用
设置主线程和卸载主线程
![设置主线程 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910120131190.png]()
![image-20210910145753588 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910145753588.png]()
获得窗口句柄
![获得窗口句柄 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910121228658.png]()
回调函数
![image-20210910150706916 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910150706916.png]()
![image-20210910151510353 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910151510353.png]()
![image-20210910151325787 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910151325787.png]()
主线程选角色消息 主线程HOOK明文包消息 主线程发包消息 寻路消息
![image-20210910153140734 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910153140734.png]()
自动打怪
![image-20210910160108585的副本 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910160108585的副本.png]()
![image-20210910155502637 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;
|
![image-20210910160145145 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910160145145.png]()
结束自动打怪
![image-20210910155653423 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910155653423.png]()
![image-20210910162310999 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910162310999.png]()
StructGame.h声明
![image-20210910155817920 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910155817920.png]()
自动打怪寻路线程
FindwayThread
![image-20210910162049533 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910162049533.png]()
![image-20210910162414707 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910162414707.png]()
循环寻路
![image-20210910162848132 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910162848132.png]()
自动打怪杀怪线程
![image-20210910163655786 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910163655786.png]()
![image-20210910163949316 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910163949316.png]()
![image-20210910164816216 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210910164816216.png]()
任务遍历
void CMainDialogWnd::OnBnClickedButton14()
![image-20210912185239469 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210912185239469.png]()
任务属性
Ttask_PROPERTY
![image-20210912185446307 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210912185446307.png]()
任务列表结构
typedef struct Ttask_List
![image-20210912185836207 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210912185836207.png]()
获得任务列表数据
void Ttask_List::GetData()
![image-20210912193250144 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210912193250144.png]()
任务二叉树遍历
void Ttask_List::taskthree(int threeBase)
![image-20210912194714945 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210912194714945.png]()
![image-20210912194750463 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210912194750463.png]()
检测概论
exe dll 特征码
改写内存或者改写汇编代码
- CRC检测 代码段 下访问断
- 数据检测 数据段 下访问断
- CALL检测
- 堆栈检测
远程注入dll
int _tmain(int argc,_TCHAR* argue[])
![image-20210916202636920 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210916202636920.png]()
InJectDll
![image-20210916230450918 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210916230450918.png]()
![image-20210916225640354 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210916225640354.png]()
劫持注入
劫持工具
![image-20210916231219875 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210916231219875.png]()
收包
发包可以达到功能
收包只能作为判断
收包效率高
recv
WS2_32.recv
收包实例
hook明文包 另一处
![image-20210918111600997 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210918111600997.png]()
还原明文包 另一处
![image-20210918112253926 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210918112253926.png]()
裸体函数 另一处
![image-20210918113148617 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210918113148617.png]()
![image-20210918113816449 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210918113816449.png]()
![image-20210918114739025 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210918114739025.png]()
![image-20210918114915664 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210918114915664.png]()
![image-20210918114948833 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210918114948833.png]()
窗口句柄和帐号
游戏账号
查找到游戏帐号的文本以后
下访问断 退出游戏得到访问代码
发现是一个常量(类似基地址)1670D31C
这个代码在主线程中 主线程入口地址是16670000
那个公式应该是
主线程入口+9C31C
我们用ce搜索主线程入中发现有基地址存放
得到公式
[27AC124]+9D31C
控件遍历
![image-20210919174527143 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210919174527143.png]()
获得控件列表数据 GetData
![image-20210919174552221 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210919174552221.png]()
控件遍历递归 GetData2
![image-20210919175130607 https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/image-20210919175130607.png]()