JoyHD

2014年4月3日 星期四

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

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

建立專案

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


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

建立檔案

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

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


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

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

寫程式碼

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

點兩下 FormMain.cpp,即可流覽程式碼內容。
在第二行打上:
using namespace <你的名稱>;
其中<你的名稱>請替換成 FormMain.h 中 namespace 後面的文字,請參考圖片。


再來加入下方程式碼至 FormMain.cpp:
void Main(void)
{
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Application::Run(gcnew FormMain);
Application::Exit();
}

點兩下 Main.cpp,開啟程式碼編輯畫面。
第一行打上:
#include <Windows.h>
第二行
extern void Main(void);
往下繼續加入下方程式碼:
::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 來修改 CheckBox 和 Form 顯示的標題名稱(Caption)。

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

現在打開 FormMain.cpp,新增第一個功能!
我們拿 v159.2 CRC 技能連跳 來示範,數據如下:
 [Enable]
 00AE6090:
 DB EB 04 90 90 90 90
 [Disable]
 00AE6090:
 DB 0F 8D 2D 01 00 00

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

再來就是修改記憶體,要把要修改的內容轉換成bytes(以BYTE陣列來表達)。
如下:
BYTE UnlimitedJump_Enable[] = {0xEB, 0x04, 0x90, 0x90, 0x90, 0x90};
BYTE UnlimitedJump_Disable[] = {0x0F, 0x8D, 0x2D, 0x01, 0x00, 0x00};
不懂數據的只要忽略DB,後面的內容照抄並照上方修改就行了。
現在 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 頁

14 則留言:

  1. 請問偷比大大 <(_ _)>
    小的已經照著文中的步驟一步一步的做
    也用了文中舉例的超級定怪來當作第一個數據
    不過小的注入打勾後遊戲與程式都關閉了
    求偷比大大的解 <(_ _)>

    回覆刪除
    回覆
    1. 因為數據不是最新的,
      你可以到永恆血色找找新數據,

      刪除
    2. 以經將數據更新並且測試過!

      刪除
    3. 所以是可以還是不行?

      刪除
    4. 回復偷比大大,可以 !
      但必須要在Play處開啟功能

      刪除
  2. 作者已經移除這則留言。

    回覆刪除
  3. 大大您好 小弟我最金在學習大大發著這篇 可是注入後這個功能一打勾整個程式就關掉了 大大可以幫忙看一下嗎?
    ----------------------------------------------------------------------------------
    //TwMS v169.3_ICS_CS端吸怪 + 物落腳下 + 攻擊不停
    //更新:tsuan2000

    [Enable]
    Alloc(CSMobVac,512)

    CSMobVac:
    Push Ebp
    Mov Ebp,Esp
    Push Ebx
    Push Esi
    Mov Esi,[Ebp+08]
    Xor Ebx,Ebx
    Push Edi
    cmp [esi+70],ebx
    JNE 00D855CC

    mov ecx,[015487D0]
    call 00D85554
    Mov [Ebp+08],Eax
    Fild Dword Ptr [Ebp+08]
    Mov Edi,[Ebp+0C]
    fdiv qword ptr [011C6BD0]
    Fstp Qword Ptr [Ebp+34]
    Cmp Edi,Ebx
    je 00D8560A
    fld qword ptr [esi+00000094]
    Push Ecx
    fsub qword ptr [esi+74]
    Push Ecx
    Fmul Qword Ptr [Ebp+34]
    Fadd Qword Ptr [Esi+74]
    Fstp Qword Ptr [Esp]
    call 005AFAAA
    Pop Ecx
    Pop Ecx

    mov eax,[01543DF4]
    Mov [Eax+A0A4],0
    Mov [Eax+A0B4],0
    mov eax,[01543DF4]
    mov eax,[eax+0000B2DC]
    mov [edi],eax
    mov edi,[ebp+10]
    cmp edi,ebx
    je 00D8562E

    fld qword ptr [esi+0000009C]
    push ecx
    fsub qword ptr [esi+7C]
    push ecx
    fmul qword ptr [ebp+34]
    fadd qword ptr [esi+7C]
    fstp qword ptr [esp]
    call 005AFAAA
    pop ecx
    pop ecx

    mov eax,[01543DF4]
    mov eax,[eax+0000B2E0]
    Jmp 00D8562C

    012B8908:
    DD CSMobVac
    [Disable]
    012B8908:
    DD 00D85579
    DeAlloc(CSMobVac)
    ------------------------------------------------------------------------
    DWORD allhit_place_nostopAddress = 0x012B8908;
    DWORD allhit_place_nostop_desable = 0x00D85579;
    DWORD allhit_place_nostop_jj1 = 0x00D855CC;
    DWORD allhit_place_nostop_jj2 = 0x00D8562E;
    DWORD allhit_place_nostop_jj3 = 0x00D8562C;
    DWORD allhit_place_nostop_call1=0x005AFAAA;
    DWORD allhit_place_nostop_call2 = 0x00D85554;
    DWORD allhit_place_nostop_call3 = 0x00D8560A;
    DWORD allhit_place_nostop_FDV1 = 0x011C6BD0;

    void __declspec(naked) allhit_place_nostop()
    {
    __asm
    {
    Push Ebp
    Mov Ebp, Esp
    Push Ebx
    Push Esi
    Mov Esi, dword ptr[Ebp + 0x08]
    Xor Ebx, Ebx
    Push Edi
    cmp dword ptr[esi + 0x70], ebx
    JNE jjjne1

    mov ecx, dword ptr[0x015487D0] ///////////////////////
    call allhit_place_nostop_call2
    Mov dword ptr[Ebp + 0x08], Eax
    Fild Dword Ptr[Ebp + 0x08]
    Mov Edi, dword ptr[Ebp + 0x0C]
    fdiv qword ptr[allhit_place_nostop_FDV1]
    Fstp Qword Ptr[Ebp + 0x34]
    Cmp Edi, Ebx
    je JJJe2
    fld qword ptr[esi + 0x00000094]
    Push Ecx
    fsub qword ptr[esi + 0x74]
    Push Ecx
    Fmul Qword Ptr[Ebp + 0x34]
    Fadd Qword Ptr[Esi + 0x74]
    Fstp Qword Ptr[Esp]
    call allhit_place_nostop_call1
    Pop Ecx
    Pop Ecx

    mov eax, dword ptr[0x01543DF4]
    Mov dword ptr[Eax + 0xA0A4], 0
    Mov dword ptr[Eax + 0xA0B4], 0
    mov eax, dword ptr[0x01543DF4]
    mov eax, dword ptr[eax + 0x0000B2DC]
    mov dword ptr[edi], eax
    mov edi, dword ptr[ebp + 0x10]
    cmp edi, ebx
    je JJJe1

    fld qword ptr[esi + 0x0000009C]
    push ecx
    fsub qword ptr[esi + 0x7C]
    push ecx
    fmul qword ptr[ebp + 0x34]
    fadd qword ptr[esi + 0x7C]
    fstp qword ptr[esp]
    call allhit_place_nostop_call1
    pop ecx
    pop ecx

    mov eax, dword ptr[0x01543DF4]
    mov eax, dword ptr[eax + 0x0000B2E0]
    Jmp allhit_place_nostop_jj3

    jjjne1:
    jmp allhit_place_nostop_jj1
    JJJe1:
    jmp allhit_place_nostop_jj2

    JJJe2:
    jmp allhit_place_nostop_call3

    }
    }
    DWORD allhit_place_nostop_Enable = (DWORD)allhit_place_nostop;

    void FormMain::checkBox2_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
    {
    if (this->checkBox2->Checked)
    {
    memcpy((void *)allhit_place_nostopAddress, &allhit_place_nostop_Enable, sizeof(allhit_place_nostop_Enable));
    }
    else
    {
    memcpy((void *)allhit_place_nostopAddress, &allhit_place_nostop_desable, sizeof(allhit_place_nostop_desable));
    }
    }

    回覆刪除
    回覆
    1. 寫開關,原因在文末有說明。

      刪除
    2. 可是我在play的地方打勾浸遊戲後不動沒事一放招一樣關閉耶 我是影舞者連普通物理攻擊都一樣關閉
      還有就是小弟我對組合語言沒太多的研究 就像有些地方要改用push跟pop還有一些地方該注意的請問大大有沒有相關的參考網頁之類的可以推薦一下 還有就是小弟我也是vb6的愛用者好不容易下定決心....藥學看看c++ 所以可以請大大將c++餵饃哪個檔案要放飆頭檔哪個藥方資源檔還有餵甚饃{和}刪除,加上;這些解釋一下嗎? 順帶一途小弟用的是vs2013有些地方無太一樣但是大致上看得懂

      刪除
  4. 偷比大大好久不見
    想不到現在還有外掛教學
    崇拜m(_ _)m

    回覆刪除
  5. 那請問一下該如何更新外掛 ?

    回覆刪除
  6. 請問我都照著步驟做 按偵錯怎麼沒辦法啟動dll omo?
    https://drive.google.com/file/d/0Bw6LTvG2v9u_MUxpdWZDLVd3MlU/edit?usp=sharing

    回覆刪除

注意:只有此網誌的成員可以留言。