像偶等之人,雖然平時不太玩游戲,但游戲作為在工作忙碌時的調節也是一個不錯東西。像RPG游戲,通常會玩的是劇情,但很多時候碰到一個怎麼也打不過的BOSS,游戲就卡在那邊,影響了體會劇情的心情。這個時候大家都會想到修改器,把自己的血量維持住,就無敵了。網上搜了一下,發現個《Quick Memory Editor》,共享軟件,有使用次數限制。試用了一下,揣摩了一下原理,然後自己實現了一個簡易的版本,拿出來分享一下。程序中缺少輸入校驗,也沒有特別設計過,只是隨性寫來。至於為什麼要用C#實現,主是基於調用API方便,以及BitConverter這個類,可以很方便的把具體的數值轉換成內存中的字節表示方式,還有是對於C/C++寫界面方面不熟。有了BitConverter這個類,就不用考慮具體的類型在內存是是什麼表示方式了,一切已經為你封裝好了,非常方便。點擊這裡下載
修改器的原理非常簡單,就一句話:把預期的值寫入游戲進程的某段內存中(使用kernel32.dll的WriteProcessMemory函數,見包中的代碼)。那麼要找到需要修改的值的內存地址,該如何處理呢?這裡有個小竅門。
1.我在內存中查找預期值的地址,會得到一組地址,所需要的地址就隱藏的其中。。如圖
我這裡正好是角色的血量是522,在游戲進程的內存中搜索522的值,可以搜索到一大片。
2.經過一番拼殺後,血量降為501了,在結果中查找一下,如圖
呵呵,我這裡只找了一次,就只剩下一條了,運氣不錯。
通常一些人物的屬性,基本上都是一些全局的變量,進程起來後地址是不會變的,有些游戲甚至這個地址是編譯時決定的,只要記住那個地址,不需要查找就可以修改。第一次查找後,目標的地址就會包含在這個列表中。第二次,查找時因為血量變了,目標地址的值是預期的,而非目標地址的值可能變成與血量值相等,也可能變成其他的值,或者是不變,第二次在結果中查詢就過濾掉了一大批。如果沒找到目標地址,那麼再去拼殺一會,再從結果從查找一次,當搜到最後,列表中的數量不再變化時,目標地址就找到了。有些游戲的目標地址不只一個,這個時候,把這些地址一起修改了就行了。根據這個前提,這種方式不是對每個游戲都適合的,特別是針對網游,基本上是不起作用的,是否適用,還需試了才知道啊。
3.做一個定時任務,把目標地址修改成需要的值即可(就是暴力修改,每隔一定時間就修改一次,我的程序裡以100ms間隔)
上圖的LockedValue就是想要修改成的值。
下面看一下具體的代碼是怎麼實現的
首先,要查找游戲進程的內存中的數據,需要用到api函數ReadProcessMemory(kernel32.dll中)
1
[DllImport(
"kernel32.dll"
, SetLastError =
true
)]
2
public
static
extern
bool
ReadProcessMemory(
3
IntPtr hProcess,
4
IntPtr lpBaseAddress,
5
[Out]
byte
[] lpBuffer,
6
int
size,
7
out
int
lpNumberOfBytesRead
8
);
每次從游戲進程中讀取4KB的內存(一頁就是4KB),然後從這4K中查找你要找的值,把匹配的內存地址記下來。如下是查找按鈕的單擊事件,處理了對整個游戲進程內存的搜索過程
01
/// <summary>
02
/// 查找按鍵的單擊事件
03
/// </summary>
04
private
void
btnSearch_Click(
object
sender, EventArgs e)
05
{
06
List<Result> resultList =
new
List<Result>();
07<