Like Share Discussion Bookmark Smile

J.J. Huang   2019-12-17   Game Cheats   瀏覽次數:

遊戲輔助 | 小朋友下樓梯 (C# 血量、階層修改器)

工具準備

  • Cheat Engine
  • Visual Studio

行前準備

輔助構思

  • 透過Cheat Engine抓取血量基址與偏移量
  • 使用C#呼叫Win32API進行記憶體讀寫

找尋基址

  • 開啟down.exe程式

  • 開啟Cheat Engine
  • 選擇down.exe程序 (00000C50-NS-SHAFT)

  • 回到down.exe
  • 並開啟一場新遊戲,並馬上按下暫停
  • 回到Cheat Engine
  • 新的搜尋12 (滿血量為12格)

  • 回到down.exe
  • 讓血量扣血,然後快速再次暫停
  • 其血量格數為7

  • 回至Cheat Engine
  • 再次搜尋7
  • 僅剩下一個地址002BCD48 (每次都會不一樣)

  • 對該地址點擊兩下,新增至下方的作弊表內

  • 002BCD48右鍵選擇Find out what writes to this address (找出是什麼改寫了這個地址)

  • 會開啟The following opcodes write to 002BCD48視窗

  • 回到down.exe
  • 讓血量扣血,或是去踩台階會加血
    • 這邊示範踩台階加血
  • 其血量格數為8
  • 回至Cheat Engine
  • 可見The following opcodes write to 002BCD48視窗內多一筆資料

  • 點擊該筆資料
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
EAX=00000000
EBX=00000000
ECX=002BBBD8
EDX=0008E3C8
ESI=00401C96
EDI=00000000
EBP=0018FD64
ESP=0018FD4C
EIP=00406A42

Probable base pointer =002BBBD8

00406A35 - shl eax,05
00406A38 - mov ecx,[ebp+08]
00406A3B - inc [eax+ecx+00001170]
00406A42 - mov eax,[ebp+08]
00406A45 - push eax
  • 可以發現指針002BBBD8,偏移量00001170

  • 回至Cheat Engine
  • 勾選Hex
  • 新的搜尋,002BBBD8
  • 搜尋出四個地址0018F5640018F9200018FD880018FDA0

  • 針對這四個基址右鍵選擇Find out what accesses to this address (找出是什麼訪問了這個地址)
  • 發現只有0018FD880018FDA0這兩個地址有一直被訪問
  • 點擊Add Address Manually
  • 針對兩個地址手動添加地址,透過基址加上偏移量1170
  • 發現兩個地址對應出來的值都是8

註:即便重新開啟遊戲或是新的一輪都可以透過基址加上偏移量找到血量的地址。


  • 此時針對「階」做搜尋
  • 回到down.exe
  • 重新開啟新一的一局,並馬上暫停,讓其維持在地下0001階
  • 回至Cheat Engine
  • 新的搜尋,1 (記得取消勾選Hex)

  • 回到down.exe

  • 讓階變動,然後快速再次暫停,讓其維持在地下0002階

  • 回至Cheat Engine

  • 再次搜尋2

  • 僅剩下兩個地址002BCED4002BCED8 (每次都會不一樣)

  • 002BCED8地址點擊兩下,新增至下方的作弊表內

  • 002BCED8右鍵選擇Find out what writes to this address (找出是什麼改寫了這個地址)

  • 會開啟The following opcodes write to 002BCED8視窗

  • 回到down.exe

  • 讓階變動,然後快速再次暫停,讓其維持在地下0003階

  • 回至Cheat Engine

  • 可見The following opcodes write to 002BCED8視窗內多一筆資料

  • 點擊該筆資料
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
EAX=002BBBD8
EBX=00000000
ECX=002BBBD8
EDX=00000000
ESI=00401C96
EDI=00000000
EBP=0018FD64
ESP=0018FD4C
EIP=00406212

Probable base pointer =002BBBD8

00406203 - jl 0040621F
00406209 - mov eax,[ebp+08]
0040620C - inc [eax+00001300]
00406212 - mov eax,[ebp+08]
00406215 - sub [eax+000012F4],00000080
  • 可以發現指針002BBBD8,偏移量00001300

註:此時可以發現指針002BBBD8與找血量的時候一摸一樣。

  • 回至Cheat Engine
  • 勾選Hex
  • 新的搜尋,002BBBD8
  • 搜尋出四個地址0018F5640018F9200018FD880018FDA0

註:此時可以四個地址與找血量的時候一摸一樣。

  • 點擊Add Address Manually
  • 針對兩個地址0018FD880018FDA0手動添加地址,透過基址加上偏移量1300
  • 發現兩個地址對應出來的值都是3

註:即便重新開啟遊戲或是新的一輪都可以透過基址加上偏移量找到階層的地址。

編寫輔助

  • 啟動Visual Studio

  • 新增專案 Visual C\# -> Windows 傳統桌面 -> Windows Forms App (.NET Framework)

    • 名稱DownCheat
  • 新增項目

  • Class類別

    • 名稱DownHelper
  • 新增以下代碼

    • 用於Call Win32 API DLL,針對指定程序進行記憶體讀寫
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace DownCheat
{
class DownHelper
{
#region API

//從指定內存中讀取字節集資料
[DllImportAttribute("kernel32.dll", EntryPoint = "ReadProcessMemory")]
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int nSize, IntPtr lpNumberOfBytesRead);

//從指定內存中寫入字節集資料
[DllImportAttribute("kernel32.dll", EntryPoint = "WriteProcessMemory")]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, int[] lpBuffer, int nSize, IntPtr lpNumberOfBytesWritten);

//打開一個已存在的進程對象,並返回進程的句柄
[DllImportAttribute("kernel32.dll", EntryPoint = "OpenProcess")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

//關閉一個內核對象。其中包括文件、文件映射、進程、線程、安全和同步對象等。
[DllImport("kernel32.dll")]
private static extern void CloseHandle(IntPtr hObject);

#endregion

#region 使用方法

//根據進程名獲取PID
public static int GetPidByProcessName(string processName)
{
Process[] arrayProcess = Process.GetProcessesByName(processName);
foreach (Process p in arrayProcess)
{
return p.Id;
}
return 0;
}

//讀取內存中的值
public static int ReadMemoryValue(int baseAddress, string processName)
{
try
{
byte[] buffer = new byte[4];
//獲取緩沖區地址
IntPtr byteAddress = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
//打開一個已存在的進程對象 0x1F0FFF 最高權限
IntPtr hProcess = OpenProcess(0x1F0FFF, false, GetPidByProcessName(processName));
//將制定內存中的值讀入緩沖區
ReadProcessMemory(hProcess, (IntPtr)baseAddress, byteAddress, 4, IntPtr.Zero);
//關閉操作
CloseHandle(hProcess);
//從非托管內存中讀取一個 32 位帶符號整數。
return Marshal.ReadInt32(byteAddress);
}
catch
{
return 0;
}
}

//將值寫入指定內存地址中
public static void WriteMemoryValue(int baseAddress, string processName, int value)
{
try
{
//打開一個已存在的進程對象 0x1F0FFF 最高權限
IntPtr hProcess = OpenProcess(0x1F0FFF, false, GetPidByProcessName(processName));
//從指定內存中寫入字節集資料
WriteProcessMemory(hProcess, (IntPtr)baseAddress, new int[] { value }, 4, IntPtr.Zero);
//關閉操作
CloseHandle(hProcess);
}
catch { }
}

#endregion
}
}
  • 開啟Form1.cs[設計]
  • 新增兩個TextBox、兩個Button

  • 雙擊Button1建立Click事件

  • 雙擊Button2建立Click事件

  • 撰寫程式

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
39
40
41
42
43
44
45
46
47
48
49
50
using System;
using System.Windows.Forms;

namespace DownCheat
{
public partial class Form1 : Form
{
//遊戲基址
private int baseAddress = 0x0018FDA0;
//遊戲名字
private string processName = "down";
//遊戲血量地址
private int bloodAddress;
//遊戲階層地址
private int stageAddress;

public Form1()
{
InitializeComponent();
//讀取 基址
baseAddress = DownHelper.ReadMemoryValue(baseAddress, processName);
//計算 血量的地址 = 基址中的值 + 偏移量
bloodAddress = baseAddress + 0x1170;
//計算 階層的地址 = 基址中的值 + 偏移量
stageAddress = baseAddress + 0x1300;
}

private void button1_Click(object sender, EventArgs e)
{
if (DownHelper.GetPidByProcessName(processName) == 0)
{
MessageBox.Show("遊戲沒有運行!");
return;
}
//給血量地址中寫入數值,TextBox裡面的值
DownHelper.WriteMemoryValue(bloodAddress, processName, int.Parse(this.textBox1.Text));
}

private void button2_Click(object sender, EventArgs e)
{
if (DownHelper.GetPidByProcessName(processName) == 0)
{
MessageBox.Show("遊戲沒有運行!");
return;
}
//給階層地址中寫入數值,TextBox裡面的值
DownHelper.WriteMemoryValue(stageAddress, processName, int.Parse(this.textBox2.Text));
}
}
}
  • 運行測試

  • 持續點擊Button1可以一直將血量拉滿

  • 點擊Button2可以發現階層快速爬升到你設定的階層

註:如要分享.exe檔案,請到專案目錄下的Debug資料夾內,將其全部複製給別人即可。注意因為使用C#撰寫,對方的電腦要有安裝.NET Framework才可執行。


註:以上參考了
小朋友下樓梯輔助程式
Download Games