C#做遊戲外掛

來源:互聯網
上載者:User
第一課:C#使用WINDOW API和對記憶體的操作。
這一課是些簡單的東西,瞭解的可以直接越過。考慮到大多數使用c#的人都是做網站的,可能沒有機會接觸這些,所以我在這裡做一下粗略的介紹。

step 1:認識WINAPI

windows系統裡提供了很多的函數,我們如果做外掛的話,就需要用到其中的函數(以下簡稱API)。(廢話:這些API被封裝在系統路徑下的DLL檔案裡。事實上,我們不用關心它在哪,我們只要知道怎麼用就可以了,)用起來很簡單,格式如下:
public partial class Form1 : Form
{
[DllImport("kernel32.dll")]          \
public static extern int ReadProcessMemory( |
int hProcess,               |
int lpBaseAddress,             |
int[] lpBuffer,                >程式碼片段1
int nSize,                 |
int lpNumberOfBytesWritten         |
);                      /
...
public Form1()
{
InitializeComponent();
ReadProcessMemory(processhandle,... >代碼2
...
}
...
}
程式碼片段1就是引用api的代碼。我們引用的函數,是做外掛時最常用的函數,從它的名字就可以看的出來它的作用---讀取進程記憶體。(廢話:從代碼裡,我們很容易看的出來,這個函數被封裝在了kernel32.dll這個檔案裡。)引用之後,我們就可以在自己的代碼中使用這個函數了(如代碼2)。
(廢話:WINDOWS還提供很多的API,如果你有興趣瞭解的話,可以到網上搜WINAPI手冊。想深入瞭解的話,可以看MSDN。)
step 2:讀寫記憶體
下面我來說一下,如何使用上一步引用的那個API讀取遊戲的資料。先來看看參數:
public static extern int ReadProcessMemory(
int hProcess, //進程,如果你是做外掛的話,它代表你要掛的那個遊戲。
int lpBaseAddress, //你要讀取的記憶體位址
int[] lpBuffer, //從上面那個參數地址裡讀出來的東西(調用這個函
數的就是為了它) 不管這個參數是什麼類型,它應該是一個數組,否則讀不出東西來
int nSize, //長度,上一個參數,類型是int,那個長度應該用4
int lpNumberOfBytesWritten //用0就行了,想知道它是幹嘛的,自己去MSND吧
關於第一個參數hProcess如何擷取,我過會再說。假設它已經搞定了,那麼這個函數,我們需要關心的只有lpBaseAddress和lpBuffer,既讀的地址,和讀出來的值。(廢話:對了,這個函數貌似還有個傳回值,我們這裡用不到它。如果你有興趣瞭解,MSDN)讀出來的值out int lpBuffer我們在引用API的時候聲明為int型了,但是,我們要從記憶體裡讀的值不一定總是int。我們可以多次引用這個API,第3個參數分別用不同的類型。
下面,我們結合實際,來寫一段讀取誅仙人物HP的代碼。首先,我們需要知道人物HP的地址,(廢話:如何知道這個地址,用CE還是IE,你自己搞定吧。)我是用IE在這裡http://www.ghoffice.com/bbs/read.php?tid-35908-fpage-2.html找到的,它這裡是這樣寫的:
人物基址:[[&H12F830]+&H28]=base
生命:[base+&H254]
(註:&H表示16進位,在C#裡我們用0x表示)
一對[]表示讀一次地址。也就是說123表示值123,而[123]就表示從地址123讀出來的值。幾對[],就要用幾次ReadProcessMemory,我們來寫下代碼:
int[] Base=new int[1];
int[] hp=new int[1];
ReadProcessMemory(process, 0x12F830, Base;, 4, 0);//相當於Base=[&H12F830]
ReadProcessMemory(process, Base+0x28, Base;, 4, 0);//相當於Base=[Base+&H28]
//讀出了人物基址base
ReadProcessMemory(process, Base+0x254, hp;, 4, 0);//相當於hp=[base+&H254]
//讀出了hp
怎麼樣,很簡單吧。
我們讀HP只用了3行ReadProcessMemory。有的時候,讀某個值可能需要很多對[],就要寫N行ReadProcessMemory,這樣寫起來就很麻煩,看起來也很暈。下面我們來寫個函數,讓讀記憶體的過程看起來和[]標記法差不多。
//為了看起來好看,函數的名字最好短些,所以我們用r,表示read
public static int r(int add)
{
int[] r=new int[1];
try
{
ReadProcessMemory(process, add, r, 4, 0);
return r[0];
}

            catch (Exception ex)
{
return -1;
}
}
這個函數很簡單,不用我多說了吧。
有了這個函數,上面的讀取HP的代碼,我們就可以寫成這樣了:
int Base;
int hp;
Base=r(r(0x12F830)+0x28);
//讀出了人物基址base
hp=r(base+&H254);
//讀出了hp
看起來清晰多了吧。

下面我來說下讀取字串,首先引用API:
[DllImport("kernel32.dll")]
public static extern int ReadProcessMemory(
int hProcess,
int lpBaseAddress,
byte[] lpBuffer,
int nSize,
int lpNumberOfBytesRead
);
然後和上面一樣,寫一個讀字串的方法。
public static string rString(IntPtr process, uint add)
{
string[] r;
string temp;
byte[] b = new byte[256];
try
{
API.ReadProcessMemory(process, (IntPtr)add, b, 256, (IntPtr)0);
//讀出的byte[]要按Unicode編碼為字串
temp = System.Text.Encoding.Unicode.GetString(b);
//截取第一段字串
r = temp.Split(''\0'');
return r[0];
}
catch (Exception ex)
{
return "error";
}
}
這個函數和上面那個函數差不多,多的東西注釋裡已經寫了,也很簡單,不必我廢話了。
下面,我們來讀人物的名字。還是剛才那個文章裡得到的,人物名字位移如下:
人物角色名稱:[[base+3a4]+0]
代碼如下:
string name;
name=rString(r(basse + 0x3a4)+0x0);//+0x0可以去掉
讀其他類型的資料和讀INT的雷同,我就不廢話了,大家自己搞定吧。

現在萬事俱備,就差這個process了,下面我來說下,如果獲得遊戲的進程控制代碼(廢話:進程控制代碼:一個用來表示某進程的整形值。推廣到一般,**控制代碼,就是表示某**的整形值)。分兩步,第一步:
System.Diagnostics.Process[] GamesProcess
= System.Diagnostics.Process.GetProcessesByName("elementclient");
這一步用的是.NET本身的方法,System.Diagnostics.Process是.NET裡的進程類,GetProcessesByName靜態方法是通過進程的名字獲得進程數組。這行語句執行之後,所有遊戲進程就放在了GamesProcess裡面。如果你想做多開掛的話,可以通過數組GamesProcess的下標,來確定你要掛的遊戲。
第二步:
int ProcessID=GamesProcess[0].Id;
int process = OpenProcess(0x1F0FFF, 0, ProcessID);
第1行是獲得進程ID,就是工作管理員裡看到的PID。第2行就是獲得進程控制代碼。OpenProcess也是一個系統API,也是在kernel32.dll裡。他的3個參數和傳回值都聲明為INT就OK了。如何引用請看step 1。大家應該可以看出來怎麼用,第3個參數是進程ID,返回的就是進程控制代碼(廢話:1,2參數做何用,想知道的自己看MSDN。懶人直接用樣本裡的參數就行了。以後此類廢話不再多說了)。

看到這裡,大家可以試著寫一個讀取人物資料的小東西試試了。當然,前提是你要知道資料的地址。
寫記憶體:
(廢話:修改遊戲資料,對於寫現在的網遊外掛來說,意義不是很大。因為重要資料的處理都是在服務端進行的,改了也沒用。人們使用寫記憶體,通常是改遊戲的代碼,以實現一些特殊功能,比如誅仙裡的穿牆,無限跳等。要想知道如何改,需要反組譯碼分析經驗。就不是本菜鳥能及的了,呵呵)
WriteProcessMemory(process, (IntPtr)add, bytes, (UInt32)bytes.Length, 0);
寫進程記憶體函數。這個API的各參數和ReadProcessMemory是一一對應的。大家自己聲明,用用看吧。喜歡的話,也可以向上面一樣自己寫個函數,以簡化寫記憶體的代碼。在下一課,我們要用這個函數來向遊戲裡寫代碼。

下一課將是些更有趣的東西。我們要通過外掛讓遊戲執行一些操作。敬請期待吧,呵呵。

第2課 C#注入
這一課其實也很簡單,只不過知道的人不多而已。

step 3:注入

注入沒什麼複雜的,它是一個很簡單的過程。用語言描述就一句話:在別的程式裡寫入你的代碼,並執行。
(廢話:傳說注入分3種,我說的這種屬於哪個呢?我懶的去想,能用就行了,呵呵。)
實現起來也很簡單,就幾行代碼:
byte[] bytes={0xC3};//我們要寫入的代碼
int addr = VirtualAllocEx(process, 0, bytes.Length, 0x1000, 0x40);//一,申請空間
WriteProcessMemory(process, addr, bytes, bytes.Length, 0);//二,把代碼寫進去
int hThread = CreateRemoteThread(process, 0, 0, addr, 0, 0, threadId);//三,執行寫入的代碼
WaitForSingleObject(hThread, 0xFFFFFFFF);//等待線程結束
VirtualFreeEx(process, addr, 0, 0x8000); //四,釋放申請的空間
CloseHandle(hThread);//五,關閉線程句餅

仔細看一下這幾行代碼,你會發現非常簡單,幾乎不需要我多說什麼。這幾個豆耐特裡豆不出來的函數,都是API。根據上面的使用方法,引用一下,就可以用了。你能看懂的那幾個參數和傳回值,就是需要你關心的。不知道的的參數都不用理會,直接用上面的值就行了。還有疑問的話,可以參考WINAPI手冊。值得注意的地方是,第四步釋放申請,如果你看了API手冊,會發現第三個參數是大小,但如果你用bytes.Length的話就錯了,一定要用0。
(廢話:如果你不知道怎麼根據上面的使用方法引用API,我就簡單說兩句。以第二行為例,我們看到VirtualAllocEx的傳回值和5個參數都是int行,那麼這樣聲明就行:
[DllImport("Kernel32.dll")]//沒有特殊說明的話,API一般都是從這個DLL引用的
public static extern int VirtualAllocEx(
int p1,
int p2,
int p3,
int p4,
int p5
);
大家可以看出來,要申明一個API只要知道各參數和傳回值的類型,以及DLL檔案名稱就可以了。喜歡的話,你可以把參數的名字起的有意義些。)

簡簡單單幾行代碼就實現了注入,是不是沒你想像的複雜?呵呵。
現在的一個問題就是,代碼從何而來?
大家可以使用我的工具將你找到的CALL轉換為機器碼。(廢話:這個工具的原理,就是調用MASM編譯,所以任何你在MASM裡能使用的文法和指令(限函數內),都可以在這裡用,當然,文法和MASM裡的文法規則是一樣的。使用的方法在附件裡有詳細的說明,我就不在這裡浪費篇章了。)
工具轉換得到的結果是型如60b8d0305a00ffd08b561c83c40461c3的字串,大家可以用下面的方法把它轉換為byte[]        public static byte[] getBytes(string HEX)
{
byte[] bytes = new byte[HEX.Length / 2];
for (int i = 0; i < bytes.Length; i++)
{
bytes = Convert.ToByte(Int32.Parse(HEX.Substring(i * 2 , 2),

System.Globalization.NumberStyles.AllowHexSpecifier));
}
return bytes;
}
OK,到這裡,大家可以著手試著用外掛調用一下遊戲裡的攻擊CALL了.(如果你不會找CALL,你可以試著在此論壇裡找找)
我已經更正並用紅字標註了,如果有人因為這些錯誤在實踐時受挫,我表示道歉,呵呵。
過些天我可能會寫個簡單的DEMO,大家敬請期待吧.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.