免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
本次游戏没法给
内容参考于:微尘网络安全
上一个内容:35.x64汇编写法(二)
效果图:
首先打开之前的项目,然后添加一个类
名字叫Hook
然后把它俩拖到通用里面
然后Hook.h文件写下图红框的内容
然后StartData.h文件里面下图红框里的代码
然后StartData.cpp文件添加下图红框的代码,这样就可以全局使用Hook了
要Hook的位置地址
ws2_32.dll的基址
偏移0x00007FFE95F0740F - 0x00007FFE95F00000 = 0x740F
然后在 InitInstance 函数中获取
然后g_HookAddress的初始化
然后g_HookAddress的声明
然后Hook.cpp里
然后添加一个asm
然后 ASMCall.asm
然后添加 ASMCall.asm 后设置依赖项
然后勾选
然后设置 ASMCall.asm 属性
然后属性选择下图红框
HookCall函数
ASMCall.asm文件的内容
extern g_Calladdr:far
extern g_mingwenaddr:far
extern g_size:far
.code
HookCall proc
mov qword ptr[g_mingwenaddr],rdx ;明文包数据
mov qword ptr[g_size],r8 ; 明文包大小
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov r15,qword ptr[g_Calladdr];用来调试输出的call,也就是执行 Hook.cpp 里的OutPutcall函数
call r15
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
; 跳转回去
mov rax,qword ptr [rsp]
add rsp,8
; 执行被劫持位置的原本代码
push rdi
push r14
push r15
sub rsp,80h
jmp rax
HookCall endp
end
然后添加一个按钮
按钮名字
然后双击按钮创建 鼠标左键单击时执行的函数
劫持后(Hook后)使用x64dbg查看代码情况,注意x64dbg代码不是实时的,就是修改之后在x64dbg看到的还是原来的代码,需要设置一下断点,触发断点才可以显示最新的代码,有时候只设置一下断点它就会更新
![]()
![]()
获取明文包和把明文放到 vector 里(g_Calladdr)
![]()
代码逻辑说明
首先点击 hook明文包按钮
![]()
触发下图红框的函数
![]()
然后又触发,劫持数据包函数和打印数据包函数
![]()
然后劫持数据包函数触发 HookCall函数(汇编代码)
![]()
HookCall汇编代码,又触发把数据包放到 vector 里逻辑
![]()
OutPutcall 把数据包放到 vector 里逻辑,到这数据包的获取就结束了,然后在看定时器
![]()
下图红框位置设置每500毫秒触发定时器
![]()
定时器代码,读取 pData->m_Pack.p_data
![]()
MyDialog.cpp文件的修改:修改 OnTimer函数,新加 OnBnClickedButton5函数(hook明文包按钮)
void MyDialog::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (nIDEvent == 1) {
Role_Stu Role = pData->Updata_Role(0);//更新角色
CString str;
str.Format("角色对象:%p\n角色名字:%s\n角色等级:%d\n角色状态:%d\n角色的ID:%d\n角色血量:%d/%d\n角色蓝量:%d/%d\n角色活力:%d/%d\n角色精力:%d/%d\n角色经验:%d/%d\n角色坐标 x:%f z:%f y:%f\n角色体力:%d\n角色定力:%d\n角色身法:%d\n角色潜能:%d\n角色力量:%d\n角色灵气:%d\n外功攻击:%d\n内功攻击:%d\n外功防御:%d\n内功防御:%d\n角色命中:%d\n角色闪避:%d\n会心攻击:%d\n会心防御:%d", Role.m_Objadr, Role.m_Name.c_str(), Role.m_Lv, Role.m_State, Role.m_ID, Role.m_HP.min, Role.m_HP.max, Role.m_MP.min, Role.m_MP.max, Role.m_Vitality.min, Role.m_Vitality.max, Role.m_Energy.min, Role.m_Energy.max, Role.m_Exp.min, Role.m_Exp.max, Role.fPos.x, Role.fPos.z, Role.fPos.y, Role.m_PStrength, Role.m_CStrength, Role.m_Footwork, Role.m_Potential, Role.m_power, Role.m_Reiki, Role.m_Out_attack, Role.m_In_attack, Role.m_Out_Defense, Role.m_In_Defense, Role.m_hit, Role.m_dodge, Role.m_HeartAttack, Role.m_HeartDefense);
SetDlgItemText(IDC_STATIC, str);
}
if (nIDEvent == 2)
{
VDataStu vt = pData->Updata_Around();//更新数据
CString str;
for (size_t i = 0; i < 1000; i++)
{
if (vt.m_data.size() <= i) {
m_list.SetItemText(i, 0, "");
m_list.SetItemText(i, 1, "");
m_list.SetItemText(i, 2, "");
m_list.SetItemText(i, 3, "");
m_list.SetItemText(i, 4, "");
m_list.SetItemText(i, 5, "");
}
else {
str.Format("%p", vt.m_data[i].m_Objadr);
m_list.SetItemText(i, 0, str);
str.Format("%p", vt.m_data[i].m_ID);
m_list.SetItemText(i, 1, str);
str.Format("%s", vt.m_data[i].m_Name.c_str());
m_list.SetItemText(i, 2, str);
str.Format("%d", vt.m_data[i].m_HP.ptr);
m_list.SetItemText(i, 3, str);
str.Format("%f %f %f", vt.m_data[i].fPos.x, vt.m_data[i].fPos.z, vt.m_data[i].fPos.y);
m_list.SetItemText(i, 4, str);
str.Format("%s", vt.m_data[i].type_name.c_str());
m_list.SetItemText(i, 5, str);
}
}
}
if (nIDEvent == 3)
{
VDataStu* vt = pData->Updata_Backpack();//更新数据
CString str;
int m_size = vt[0].m_data.size() + vt[1].m_data.size() + vt[2].m_data.size();
int j = 0;
int k = 0;
for (size_t i = 0; i < 1000; i++)
{
if (m_size <= i) {
m_list.SetItemText(i, 0, "");
m_list.SetItemText(i, 1, "");
m_list.SetItemText(i, 2, "");
m_list.SetItemText(i, 3, "");
m_list.SetItemText(i, 4, "");
}
else {
if (i >= vt[0].m_data.size() && i < vt[0].m_data.size() + vt[1].m_data.size()) {
j = 1;
k = i - vt[0].m_data.size();
}
else
{
if (i >= vt[0].m_data.size() + vt[1].m_data.size()) {
j = 2;
k = i - vt[0].m_data.size() - vt[1].m_data.size();
break;
}
k = i;
}
str.Format("%p", vt[j].m_data[k].m_Objadr);
m_list.SetItemText(i, 0, str);
str.Format("%x", vt[j].m_data[k].m_ID);
m_list.SetItemText(i, 1, str);
str.Format("%s", vt[j].m_data[k].m_Name.c_str());
m_list.SetItemText(i, 2, str);
str.Format("%d", vt[j].m_data[k].m_Lv);
m_list.SetItemText(i, 3, str);
str.Format("%s", vt[j].m_data[k].type_name.c_str());
m_list.SetItemText(i, 4, str);
}
}
}
if (nIDEvent == 4)
{
VDataStu vt = pData->Updata_Skill();//更新数据
QWORD addrs = 0;
CString str;
for (size_t i = 0; i < 1000; i++)
{
if (vt.m_data.size() <= i) {
m_list.SetItemText(i, 0, "");
m_list.SetItemText(i, 1, "");
m_list.SetItemText(i, 2, "");
m_list.SetItemText(i, 3, "");
m_list.SetItemText(i, 4, "");
}
else {
str.Format("%p", vt.m_data[i].m_Objadr);
m_list.SetItemText(i, 0, str);
str.Format("%p", vt.m_data[i].m_ID);
m_list.SetItemText(i, 1, str);
str.Format("%s", vt.m_data[i].m_Name.c_str());
m_list.SetItemText(i, 2, str);
str.Format("%d", vt.m_data[i].m_Lv);
m_list.SetItemText(i, 3, str);
str.Format("%d", vt.m_data[i].Countdown);
m_list.SetItemText(i, 4, str);
}
}
}
if (nIDEvent == 5)
{
CStringA str;
int m_size = pData->m_Pack.p_data.size();
str.Format("调试--m_size %d p_size %d", m_size, p_size);
if (m_size > p_size) {
//m_list.DeleteAllItems();
for (size_t i = 0; i < (m_size - p_size); i++)
{
LogA(str.GetBuffer());
m_list.InsertItem(i, "");
str.Format("%x", pData->m_Pack.p_data[i + p_size].Pack_long);
m_list.SetItemText(i, 0, str);
str.Format("%s", pData->m_Pack.p_data[i + p_size].Pack.c_str());
m_list.SetItemText(i, 1, str);
int nItemCount = m_list.GetItemCount();
int nLastIndex = nItemCount - 1;
m_list.EnsureVisible(nLastIndex, FALSE);
}
p_size = m_size;
}
}
CDialogEx::OnTimer(nIDEvent);
}
void MyDialog::OnBnClickedButton5()// hook明文包按钮
{
CString str;
CString str1;
GetDlgItemText(IDC_BUTTON5, str);
str1 = "Hook明文包";
if (str == str1) {
str = "还原明文包";
SetDlgItemText(IDC_BUTTON5, str);
for (size_t i = 0; i < 6; i++)
{
m_list.DeleteColumn(0);//清空标题
}
m_list.DeleteAllItems();//清空所有行
/*插入标题列*/
CString head[] = { TEXT("包长"),TEXT("包内容") };
m_list.InsertColumn(0, head[0], LVCFMT_CENTER, 50, NULL);
m_list.InsertColumn(1, head[1], LVCFMT_LEFT, 800, NULL);
pMsg->HookBegin();
SetTimer(5, 500, NULL);
}
else {
KillTimer(5);
pMsg->HookEnd();
SetDlgItemText(IDC_BUTTON5, str1);
}
}
Hook.cpp文件的内容
#include "pch.h"
extern "C" UINT64 HookCall;
extern "C" UINT64 g_mingwenaddr = 0; // 明文包数据
extern "C" UINT64 g_size = 0; // 明文包大小
extern "C" UINT64 g_Calladdr = (UINT64)&OutPutcall;
void CMessage::HookBegin()// hook代码
{
/**
0x48 0xB8的汇编代码是 mov rax,0
0xFF, 0xD0的汇编代码是 call rax
ff d0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 这些是要跳转的内存地址,也就是之前说的send位置
*/
char HookText[0xc] = { 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xD0 };// 把游戏代码修改成为跳转到 asm
QWORD a = (QWORD)&HookCall; // HookCall 是劫持之后执行的函数地址
memcpy_s(&HookText[2], 8, &a, 8);// 把 HookCall 地址写到跳转里
DWORD old = 0;
MessageBeep(1);
// 修改内存属性为可读可写可执行
VirtualProtect((LPVOID)g_HookAddress, 0x100, PAGE_EXECUTE_READWRITE, &old);
// g_HookAddress这个是 (QWORD)GetModuleHandle("ws2_32.dll") + 0x740F; 被劫持的位置
// 通过 memcpy_s 把被劫持位置的代码写成 HookText,也就是
// mov rax, &HookCall
// push rax
memcpy_s((LPVOID)g_HookAddress, 0xc, HookText, 0xc);
// 还原内存属性
VirtualProtect((LPVOID)g_HookAddress, 0x100, old, &old);
}
void CMessage::HookEnd() // 恢复代码
{
/*
{ 0x57, 0x41, 0x56, 0x41, 0x57, 0x48, 0x81, 0xEC, 0x80, 0x00, 0x00, 0x00 }的代码
57 | push rdi
41:56 | push r14
41:57 | push r15
48:81EC 80000000 | sub rsp,80
也就是劫持之前的代码,原本的代码
*/
BYTE old_CallCode[0xc] = { 0x57, 0x41, 0x56, 0x41, 0x57, 0x48, 0x81, 0xEC, 0x80, 0x00, 0x00, 0x00 };
DWORD old = 0; //{0x57, 0x41, 0x56, 0x41, 0x57, 0x48, 0x81, 0xEC, 0x80, 0x00, 0x00, 0x00};
VirtualProtect((LPVOID)g_HookAddress, 0x100, PAGE_EXECUTE_READWRITE, &old);
memcpy_s((LPVOID)g_HookAddress, 0xc, &old_CallCode, 0xc);
VirtualProtect((LPVOID)g_HookAddress, 0x100, old, &old);
}
void OutPutcall() { // 把数据包放到 vector 里,然后就能显示到界面上了
/**
g_mingwenaddr 和 g_size 是从 ASMCall.asm 里的 HookCall 函数得到的
g_mingwenaddr数据包内容
g_size数据包大小
ReadByte(g_mingwenaddr) 读取1字节明文内容
0x9a有点频繁,心跳
0x53是激活窗口就断的
*/
if (ReadByte(g_mingwenaddr) != 0x9a && ReadByte(g_mingwenaddr) != 0x53 && g_size < 0x100) {
pData->pstu.Pack_long = g_size;
pData->pstu.char_pack = (char*)g_mingwenaddr;
// 通用_Byte数组转十六进制字串 显示十六进制的内容
pData->pstu.Pack = 通用_Byte数组转十六进制字串((unsigned char*)g_mingwenaddr, g_size);
pData->m_Pack.p_data.push_back(pData->pstu);
LogA("----------%x----------", g_size);
// 十六进制打印
R_memory(g_mingwenaddr, g_size);
LogA("%s", (char*)pData->pstu.Pack.c_str());
}
}
Hook.h文件的内容
#pragma once
extern "C" void OutPutcall();
class CMessage
{
public:
public:
void HookBegin();
void HookEnd();
};