[彙編]彙編練習(1):寫個拳皇13修改器

        學了彙編有一段時間了,不練練手不太好,剛好把之前留下來的坑填完--拳皇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  

        最終版,可以解鎖所有角色的試煉挑戰,這個改好,就全成就了,不錯不錯:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章