第一次寫外掛就上手 - 使用Visual C++ 2010(一)

本教學使用的是英文版Visual C++ 2010。
強烈建議有C++基礎再來看。

建立專案

首先啟動Visual C++ 2010,點選File->New->Project
選擇Visual C++Win32 ProjectName輸入專案名稱。

出現Win32 Application WizardNext
點選DLL後將Empty Project打勾,接著點Finish

建立檔案

由於我們建立的是一個空白專案(Empty Project),現在要新增原始碼(Source),以讓我們可以放程式碼(Code)。

在左方的Solution ExplorerSource Files按下右鍵,選擇Add,點New Item
點選C++ File (.cpp),下方Name輸入Main.cpp,接著按下Add

現在我們要新增一個表單(Form,用來設計執行後要出現的視窗),
在左方的Solution ExplorerHeader Files按下右鍵,選擇Add,點New Item
點選Windows Form,下方Name輸入FormMain.h,接著按下Add

按下Add後會出現一個提示,這裡請按Yes

寫程式碼

接著我們就能夠打上程式碼了。
在左方的Solution ExplorerHeader Files中找到剛才建立的FormMain.h,按右鍵,選擇View Code
新增第一行,打上:

FormMain.h
#include <Windows.h>

點兩下FormMain.cpp,即可瀏覽程式碼內容。
在第二行打上:

FormMain.cpp
using namespace 你的名稱;

其中你的名稱請替換成FormMain.hnamespace後面的文字,請參考圖片。

再來加入下方程式碼至FormMain.cpp

FormMain.cpp
void Main(void)
{
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Application::Run(gcnew FormMain);
Application::Exit();
}

點兩下Main.cpp,開啟程式碼編輯畫面。
第一行:

Main.cpp
#include <Windows.h>

第二行:

Main.cpp
extern void Main(void);

往下繼續加入下方程式碼:

Main.cpp
::BOOL WINAPI DllWork ( __in ::HMODULE hModule )
{
Main();
return TRUE;
}

::BOOL WINAPI DllMain ( __in ::HMODULE hModule, __in ::DWORD dwReason, __in __reserved::LPVOID lpvReserved )
{
::HANDLE hThread = NULL;
if ( dwReason == DLL_PROCESS_ATTACH )
{
if (( hThread = ::CreateThread(NULL, 0, (::LPTHREAD_START_ROUTINE)&DllWork, (::HMODULE)hModule, 0, NULL) ) == NULL )
{
return FALSE;
}
if ( ::CloseHandle(hThread) == FALSE )
{ }
}
return TRUE;
}

最後結果如圖。

接著把專案編譯模式設定為Release

然後按下F7,沒有出現錯誤表示編譯成功,再來就能開始設計了。

新增功能

點兩下FormMain.h就能開始設計界面。
從右方的Tool Box中點兩下或者用滑鼠拖曳CheckBox,就會有打勾選項了。
當然還可以從Properties中的Text來修改CheckBoxForm顯示的標題名稱(Caption)。

點兩下剛才新增的checkBox1,把跟在後面的{}刪除,然後加上;,如圖所示。

現在打開FormMain.cpp,新增第一個功能!
我們拿v159.2 CRC 技能連跳來示範,數據如下:

v159.2 CRC 技能連跳
[Enable]
00AE6090:
DB EB 04 90 90 90 90
[Disable]
00AE6090:
DB 0F 8D 2D 01 00 00

你看得懂數據的話,就會知道00AE6090是要寫入的位址。
FormMain.cpp最後方打上:

FormMain.cpp
DWORD UnlimitedJump_Address = 0x00AE6090;

再來就是修改記憶體,要把要修改的內容轉換成bytes(以BYTE陣列來表達)。
如下:

FormMain.cpp
BYTE UnlimitedJump_Enable[] = {0xEB, 0x04, 0x90, 0x90, 0x90, 0x90};
BYTE UnlimitedJump_Disable[] = {0x0F, 0x8D, 0x2D, 0x01, 0x00, 0x00};

不懂數據的只要忽略DB,後面的內容照抄並照上方修改就行了。
現在FormMain.cpp的程式碼應該像這樣:

現在要加上打勾、取消的程式碼。
在 FormMain.cpp 下面加上:

FormMain.cpp
void FormMain::checkBox1_CheckedChanged(System::Object^  sender, System::EventArgs^  e)
{
if (this->checkBox1->Checked)
{
memcpy((void *)UnlimitedJump_Address, UnlimitedJump_Enable, sizeof(UnlimitedJump_Enable));
}
else
{
memcpy((void *)UnlimitedJump_Address, UnlimitedJump_Disable, sizeof(UnlimitedJump_Disable));
}
}

然後按下F7進行編譯,大公告成!
編譯完成的DLL會在專案所在位置的Release資料夾內,注入遊戲中就能看見成品囉!

敬請期待下次的教學。

###警告:由於遊戲有記憶體保護,部分功能可能需在PLAY畫面打勾才有效,在遊戲內打勾可能造成沒有回應且會造成遊戲不正常結束,部分電腦在遊戲不正常結束後會有當機情形;關閉遊戲按鈕亦同,在部分電腦會有當機問題。以上問題均出自於遊戲本身,由於本程式只供學習之用,當機造成的風險請自行承擔,往後的教學會提到如何避免發生上述問題。

#第 1 2 3