学了汇编有一段时间了,不练练手不太好,刚好把之前留下来的坑填完--拳皇13的成就。PS:拳皇13在硬盘里躺了有一两年了(100对战胜利的成就拿到后就没玩了,剩下的都太烦了,需要100超必杀,100真超必杀,哪有这么多气,网络又不好,还有打一半退出的没素质货),最近硬盘快爆了,清下空间。
先举个简单一点的,修改战斗时间:利用Cheat Engine(我的版本是6.8.3,最近翻不出去,下不到最新的)先找到战斗时间的地址。因为时间是60秒,猜测大小是byte,通过几次scan找到该地址,修改该地址数据,观察游戏,战斗时间跟刚才修改的数据一致,确认找打了地址。
再利用Cheat Engine找出是那段代码修改了该数据,得到以下数据:
0041F6F7 - 49 - dec ecx
0041F6F8 - 23 C1 - and eax,ecx
0041F6FA - 89 83 24020000 - mov [ebx+00000224],eax <<
0041F700 - E8 9BF5FFFF - call kofxiii.exe+1ECA0
0041F705 - 3B F8 - cmp edi,eax
EAX=0038F510
EBX=00831DD0
ECX=FFFFFFFF
EDX=FFFFFFFF
ESI=00831DD0
EDI=00000038
ESP=0DCDFE7C
EBP=0DCDFEA0
EIP=0041F700
通过OD调试,找出[ebx+00000224]=0x00831FF4,地址的值:0x0038F510,因为是byte值,因此还得加0x2,所以时间地址:0x00831FF6,时间:56秒的16位是0x38。
经过2天的OD和IDA调试(果然自己很菜,看大佬找基址都是10几分钟),终于找出一个公式,但因为Steam游戏不能用OD和IDA启动,只能附加调试,所以最终的基址不能确定,只好认为现在最终找到的是基址,关机测试,换电脑测试,都没问题,大致就认为OK了。PS:某个词典好屌,占用了F8快捷键调试,害我花了2到3个小时找那个破程序占用了。
追踪到的顺序:
00494DA4 |> \8BCF mov ecx,edi ; kofxiii.0082FB30
004956F8 |. 8BF1 mov esi,ecx ; kofxiii.0082FB30
00495768 |> \8B46 6C mov eax,dword ptr ds:[esi+0x6C] esi:0082FB30
00495778 |. 8D48 F8 lea ecx,dword ptr ds:[eax-0x8] eax:06150094
004942A3 mov ecx, [ecx+10h] ecx:0615008C
eax=461a30跳转
00461A65 |. 83C1 08 add ecx,0x8 ecx:00831D08
004619C1 . 8BF9 mov edi,ecx, ecx:00831D10
先赋值ESI的值和EBX的值
00461A06 . 8B77 0C mov esi,dword ptr ds:[edi+0xC] edi:00831D10
00461A09 . 8D5F 08 lea ebx,dword ptr ds:[edi+0x8]
while(esi != ebx) ebx:00831D18
{
00461A13 > /8B4E 08 mov ecx,dword ptr ds:[esi+0x8]
调用前:第一次ESI:039CBA30 第二次ESI:039CBA48 第三次ESI:03AB1BF0
00461A1B . 8B76 04 mov esi,dword ptr ds:[esi+0x4]
调用后:第一次ESI:039CBA48 第二次ESI:03AB1BF0 第三次ESI:00831D18
}
0041F5F8 |. 8BD9 mov ebx,ecx ecx:00831DD0
0041F6FA |. 8983 24020000 mov dword ptr ds:[ebx+0x224],eax ; 战斗时间赋值 ebx:00831DD0
剩下的就简单了,Copy之前写过工具的代码,快速搭建窗口,MFC没有用过,不太熟悉,Winform倒是最近刚玩过,下面的截图是大部分完成后的结果:时间控制,1P和2P的生命,能量及曝气的控制。
关键代码:
// 获取战斗时间
short Kof13::GetBattleTime()
{
short result = -1;
DWORD dwAddr = GetBattleTimeAddr();
if (dwAddr != NULL && m_handleGame != NULL)
{
unsigned char dwResult = 0;
DWORD dwRead = 0;
ReadProcessMemory(m_handleGame, (LPCVOID)(dwAddr + 2), &dwResult, sizeof(dwResult), &dwRead);
if (dwRead != sizeof(dwResult))
return 0;
unsigned short battleTime = (unsigned short)dwResult;
result = (short)battleTime;
}
return result;
}
// 锁定战斗时间
void Kof13::LockTime()
{
if (m_lockTime <= 0) return;
if (NULL == m_handleGame) return;
DWORD dwAddr = GetBattleTimeAddr();
if (NULL == dwAddr) return;
unsigned char value = (unsigned char)m_lockTime;
DWORD dwWrite = 0;
WriteProcessMemory(m_handleGame, (LPVOID)(dwAddr + 0x2), &value, sizeof(value), &dwWrite);
}
// 获取战斗时间地址
DWORD Kof13::GetBattleTimeAddr()
{
if (!m_handleGame) return 0;
DWORD dwAddr = 0x0082FB30;
DWORD dwResult = 0;
DWORD dwRead = 0;
// [0082FB30 + 0x6C]
dwAddr += 0x6C;
ReadProcessMemory(m_handleGame, (LPCVOID)dwAddr, &dwResult, 4, &dwRead);
if (dwRead != 4)
return 0;
dwAddr = dwResult;
// [[0082FB30+0x6C]-0x8]
dwAddr -= 0x8;
// [[[0082FB30+0x6C]-0x8]+0x10]
dwAddr += 0x10;
ReadProcessMemory(m_handleGame, (LPCVOID)dwAddr, &dwResult, 4, &dwRead);
if (dwRead != 4)
return 0;
dwAddr = dwResult;
dwAddr += 0x8;
DWORD esiValue = 0;
DWORD ebxValue = 0;
ReadProcessMemory(m_handleGame, (LPCVOID)(dwAddr + 0xC), &dwResult, 4, &dwRead);
if (dwRead != 4)
return 0;
esiValue = dwResult;
ebxValue = dwAddr + 0x8;
DWORD ecxValue = 0;
while (esiValue != ebxValue)
{
DWORD dwTempValue = 0;
ReadProcessMemory(m_handleGame, (LPCVOID)(esiValue + 0x8), &dwResult, 4, &dwRead);
if (dwRead != 4)
return 0;
dwTempValue = dwResult;
ReadProcessMemory(m_handleGame, (LPCVOID)(esiValue + 0x4), &dwResult, 4, &dwRead);
if (dwRead != 4)
return 0;
esiValue = dwResult;
if (esiValue != ebxValue)
ecxValue = dwTempValue;
}
return ecxValue + 0x224;
}
Github上私有库竟然免费了,现在才知道,恩,上传上传A_A,上传代码到私有库上,防止外泄。不然怎么会有外挂入门到入狱的说法呢?╮(-_-)╭,修改器写好,刷成就就很快了。PS:想了很久,时间好像不确定是否找到了基址,因为没有找到最开始赋值的地方,而且好像时间的地址一直都是不变的,所以有2天的时间浪费了,像1P和2P的生命,能量及曝气就很确定找到了基址,但代码是不会公布的,๑乛◡乛๑。
再附赠一个能量槽的追踪顺序:
ChearEngine查找调用地址
00486ED8 - 8B C1 - mov eax,ecx
00486EDA - 8B F7 - mov esi,edi
00486EDC - 89 87 DC000000 - mov [edi+000000DC],eax <<
00486EE2 - E8 690A0000 - call kofxiii.exe+87950
00486EE7 - E8 44000000 - call kofxiii.exe+86F30
EAX=00000000
EBX=00000000
ECX=00000000
EDX=024DA4B0
ESI=024DB578
EDI=024DB578
ESP=0D80F748
EBP=0D80F760
EIP=00486EE2
IDA调试找基址
0041E65A mov ecx, dword_8320A0[esi*4]
0041E661 mov [ebp+var_18], ecx
0041E6C6 mov esi, [ebp+var_18] ; var_18= dword ptr -18h ebp:0D80F950 0D80F91C [ebp+var_18]:0D80F938
0041E6F6 mov edi, esi
00486EDC mov [edi+0DCh], eax edi:03872770 024DB578
最终版,可以解锁所有角色的试炼挑战,这个改好,就全成就了,不错不错: