在逆向cs零点行动的时候发现了一个问题,并不能像cs1.6那样直接找到坐标基址(不知道是不是因为是steam上的原因),下面提供逆向思路
总共分为三步
1.找到敌人血量地址
2.通过敌人血量地址找到坐标地址
3.算法分析
4.代码实现绘制
1.我们走到人机身旁搜单浮点型的100,打一下搜减小的数值,多试几次
找到了血量地址
2.浏览此地址相关内存区域发现了三个连续的浮点数
经锁定这三个值,敌人会走不动,由此确定这正是我们要找到坐标地址,把这三个数的地址添加到地址列表中
3.找出是什么访问了这个地址
找到第一行汇编代码
54DDE47B | 8B35 C883BD55 | mov esi,dword ptr ds:[55BD83C8] | esi:"€枠"
54DDE481 | 83FE 01 | cmp esi,1 | esi:"€枠"
54DDE484 | 0F8E 15030000 | jle hw.54DDE79F |
54DDE48A | 833F 00 | cmp dword ptr ds:[edi],0 | edi:"€枠"
54DDE48D | 0F84 0C030000 | je hw.54DDE79F |
54DDE493 | C705 A07E0F55 00000000 | mov dword ptr ds:[550F7EA0],0 |
54DDE49D | 85F6 | test esi,esi | esi:"€枠"
54DDE49F | 0F8E 9F000000 | jle hw.54DDE544 |
54DDE4A5 | 8B0D C483BD55 | mov ecx,dword ptr ds:[55BD83C4] |
54DDE4AB | BA C07E0F55 | mov edx,hw.550F7EC0 |
54DDE4B0 | 81C1 0C630000 | add ecx,630C |
54DDE4B6 | 8D81 F49CFFFF | lea eax,dword ptr ds:[ecx-630C] |
54DDE4BC | 3BC7 | cmp eax,edi | edi:"€枠"
54DDE4BE | 74 72 | je hw.54DDE532 |
54DDE4C0 | 83B9 F49CFFFF 00 | cmp dword ptr ds:[ecx-630C],0 |
54DDE4C7 | 74 69 | je hw.54DDE532 |
54DDE4C9 | 8B01 | mov eax,dword ptr ds:[ecx] |
54DDE4CB | 8B80 88000000 | mov eax,dword ptr ds:[eax+88] |
54DDE4D1 | 8942 FC | mov dword ptr ds:[edx-4],eax |
54DDE4D4 | 8B01 | mov eax,dword ptr ds:[ecx] |
54DDE4D6 | 8B80 8C000000 | mov eax,dword ptr ds:[eax+8C] |
54DDE4DC | 8902 | mov dword ptr ds:[edx],eax |
54DDE4DE | 8B01 | mov eax,dword ptr ds:[ecx] |
54DDE4E0 | 8B80 90000000 | mov eax,dword ptr ds:[eax+90] |
54DDE4E6 | 8942 04 | mov dword ptr ds:[edx+4],eax |
54DDE4E9 | 8B01 | mov eax,dword ptr ds:[ecx] |
54DDE4EB | 8B80 44010000 | mov eax,dword ptr ds:[eax+144] |
54DDE4F1 | 8942 14 | mov dword ptr ds:[edx+14],eax |
54DDE4F4 | 8B01 | mov eax,dword ptr ds:[ecx] |
54DDE4F6 | 8B80 48010000 | mov eax,dword ptr ds:[eax+148] |
54DDE4FC | 8942 18 | mov dword ptr ds:[edx+18],eax |
54DDE4FF | 8B01 | mov eax,dword ptr ds:[ecx] |
54DDE501 | 8B80 4C010000 | mov eax,dword ptr ds:[eax+14C] |
54DDE507 | 8942 1C | mov dword ptr ds:[edx+1C],eax |
54DDE50A | 8B01 | mov eax,dword ptr ds:[ecx] |
54DDE50C | 8B80 50010000 | mov eax,dword ptr ds:[eax+150] |
54DDE512 | 8942 20 | mov dword ptr ds:[edx+20],eax |
54DDE515 | 8B01 | mov eax,dword ptr ds:[ecx] |
54DDE517 | 8B80 54010000 | mov eax,dword ptr ds:[eax+154] |
54DDE51D | 8942 24 | mov dword ptr ds:[edx+24],eax |
54DDE520 | 8B01 | mov eax,dword ptr ds:[ecx] |
54DDE522 | 8B80 58010000 | mov eax,dword ptr ds:[eax+158] |
54DDE528 | 8942 28 | mov dword ptr ds:[edx+28],eax |
54DDE52B | C742 E8 01000000 | mov dword ptr ds:[edx-18],1 |
54DDE532 | 81C1 88670000 | add ecx,6788 |
54DDE538 | 83C2 58 | add edx,58 |
54DDE53B | 83EE 01 | sub esi,1 | esi:"€枠"
54DDE53E | 0F85 72FFFFFF | jne hw.54DDE4B6 |
可以看到esi是0x14,这是需要遍历的次数,edi是外部传过来的可以定为eax = edi,ecx = edi,在比较eax和edi的时候相等则跳,第一次一定是跳过去的,后面ecx加了一个0x6788进入下次循环, 0x54DDE4C0处比较ecx-0x630C处的值是否为0,是则跳,让ecx累加0x6788进入下次循环,不是则不跳由于上文ecx+0x630C,所以要读的是ecx+0x630C的值把它给eax,eax+0x88处的值给自己,看[ecx]的内存区域,可以发现我们要找的坐标并且每个坐标地址都相差0x324
由此可以确定eax+0x88处存的正是我们的X坐标,以此类推往下分别是Y和Z
4.首先是算法代码
void GetGameBaseAddr(HANDLE hProcess) {
DWORD 遍历次数 = (GetHLModuleAddrClasscE.GetModuleAddress(L"hw.dll") ) + 0x10183C8; //自己写的获取模块地址
DWORD 内存地址 = (GetHLModuleAddrClasscE.GetModuleAddress(L"hw.dll")) + 0x10183C4;
DWORD edi寄存器,esi寄存器;
SIZE_T SRet;
ReadProcessMemory(hProcess,(LPVOID)内存地址,&edi寄存器,4,&SRet);
ReadProcessMemory(hProcess,(LPVOID)遍历次数,&esi寄存器,4,&SRet);
DWORD ecx寄存器 = edi寄存器;
DWORD eax寄存器 = edi寄存器;
float eax接收;
for (int i = 0; i < 遍历次数; i++) {
if (eax寄存器 == edi寄存器) {
ecx寄存器 += 0x6788;
ReadProcessMemory(hProcess,(LPVOID)(ecx寄存器 - 0x630C),&eax寄存器,4,&SRet);
continue;
}
else {
ReadProcessMemory(hProcess,(LPVOID)(ecx寄存器 - 0x630C),&eax寄存器,4,&SRet);
if (eax寄存器 != 0) {
ReadProcessMemory(hProcess,(LPVOID)(ecx寄存器 + 0x630C),&eax寄存器,4,&SRet); //Read X Addr
GameAddr.EaxValueX = eax寄存器;
ReadProcessMemory(hProcess, (LPVOID)(eax寄存器 + 0x88), &(GameCoord.X), 4, &SRet);
ReadProcessMemory(hProcess, (LPVOID)(eax寄存器 + 0x8C), &(GameCoord.Y), 4, &SRet);
ReadProcessMemory(hProcess, (LPVOID)(eax寄存器 + 0x90), &(GameCoord.Z), 4, &SRet);
//printf("%f %f %f", GameCoord.X , GameCoord.Y, GameCoord.Z);
return;
}
else {
ecx寄存器 += 0x6788;
continue;
}
}
}
}
然后是绘制代码(我用的ImGui)
ImGui::Checkbox(u8"绘制方框",&CheckBoxaa);
if (CheckBoxaa) {
float x, y, z;
SIZE_T Sret;
//GetGameBaseAddr(hProcess);
DWORD CoorBase = GameAddr.EaxValueX;
float RectArry[4][4] = { 0 };
float Rx, Ry,Ry2, Rz, sf;
float Wx,Wy, Wz,Wzh;
DWORD32 hModule = GetHLModuleAddrClasscE.GetModuleAddress(L"hw.dll") - 0xF779D8;
for (int player = 0; player < 12; player++) {
ReadProcessMemory(hProcess, (LPVOID)(CoorBase+ 0x88 + player * 0x324), &x, sizeof(x), &Sret);
ReadProcessMemory(hProcess, (LPVOID)(CoorBase +0x8C+ player * 0x324), &y, sizeof(y), &Sret);
ReadProcessMemory(hProcess, (LPVOID)(CoorBase + 0x90+player * 0x324), &z, sizeof(z), &Sret);
ReadProcessMemory(hProcess, (LPVOID)(hModule + 0xDC6260), &RectArry, 64, &Sret);
//printf("%d",GetLastError());
Rz = RectArry[0][3] * x + RectArry[1][3] * y + RectArry[2][3] * z + RectArry[3][3];
sf = 1 / Rz;
Rx = (float)GameRect.right / 2 + (RectArry[0][0] * x + RectArry[1][0] * y + RectArry[2][0] * z + RectArry[3][0]) * sf * (float)GameRect.right / 2;
Ry = (float)GameRect.bottom / 2 - (RectArry[0][1] * x + RectArry[1][1] * y + RectArry[2][1] * z + RectArry[3][1]) * sf * (float)GameRect.bottom / 2;
Ry2 = (float)GameRect.bottom / 2 - (RectArry[0][1] * x + RectArry[1][1] * y + RectArry[2][1] * (z + 70) + RectArry[3][1]) * sf * (float)GameRect.bottom / 2;
Wx = Rx - (Ry2 - Ry) / 4;
Wy = Ry - (Ry2 - Ry) / 2;
Wz = Ry2 - Ry;
Wzh = (Ry2 - Ry) / 2;
ImGui::GetForegroundDrawList()->AddLine(ImVec2(Wx, Wy), ImVec2(Wx + Wzh, Wy), ImColor(0, 255, 255, 255));
ImGui::GetForegroundDrawList()->AddLine(ImVec2(Wx + Wzh, Wy), ImVec2(Wx + Wzh, Wy + Wz), ImColor(0, 255, 255, 255));
ImGui::GetForegroundDrawList()->AddLine(ImVec2(Wx + Wzh, Wy + Wz), ImVec2(Wx, Wy + Wz), ImColor(0, 255, 255, 255));
ImGui::GetForegroundDrawList()->AddLine(ImVec2(Wx, Wy + Wz), ImVec2(Wx, Wy), ImColor(0, 255, 255, 255));
}
//DWORD ModuleAddr = 0x78CA0000;
//HANDLE hProcess = GetHLModuleAddrClasscE.GetProcessHandle();
//printf("%f %f %f\n",x,y,z);
}
//绘制区
ImGui::End();
}
效果展示