Hướng dẫn viết auto võ lâm 1

AutoPlay nhìn chung được chia làm 2 loại:

  1. - Là các macro thay thế thao tác người chơi, phân tích dữ liệu đồ họa
  2. - Thực thi lệnh game bằng cách thay đổi dữ liệu game [ mem cheat, packet editor ]

Việc phân loại trên chỉ là tương đối do có thể kết hợp 2 loại trên

Loại Macro:

- Chạy dễ dàng với mọi phiên bản, hơi chậm nhưng ổn định, dễ có sai sót do hình ảnh khuất, không chạy được ở chế độ FULL screen và 3D [ 2 chế độ này không bắt được hình ]. Người viết cần kiến thức đồ họa cao

Loại Cheat, hook:

- Chạy riêng từng phiên bản, nhanh nhưng có phần bất ổn, ít khi sai sót khi xử lý, chạy được ở mọi chế độ hình ảnh

Ở đây tôi chỉ nói đến loại 2 do loại này chỉ yêu cầu kiến thức lập trình, không yêu cầu kiến thức đồ họa

Cách Viết AutoPlay loại Hook, mem cheat:

Yêu cầu:

  • - Có các công cụ Game Cheat như Tsearch, MemFinder
  • - Biết assembler
  • - Nắm rõ kỹ thuật hook, packet editor

Các thông tin mà AutoPlay có được là do đọc dữ liệu trong bộ nhớ game, địa chỉ có thể là DMA hay Static nhưng đều có thể tìm ra bằng các tool trên.

Tôi chỉ có thể hướng dẫn các bạn sử dụng Mem Cheat Tool, và hiểu rõ về Hook, các bạn phải tự học ASM

Về Game Hook: Thực chất file hook.dll là dùng để thay đổi dữ liệu trong game

các bạn tham khảo về Hook tại: msdn_hooks32 

Cách thức Hook họat động:

- Khi không có Hook

Windows Message -> Game Windows -> Game Message Patch

- Khi có Hook:

Windows Message -> Game Windows -> Hook.dll -> Game Message Patch

**Lưu ý: Game sẽ thực thi mã trong hook.dll chú không phải AutoPlay thực thi mã trong hook.dll, AutoPlay chỉ gửi các thông điệp đặc biệt để hook.dll biết đó là lệnh của AutoPlay

Hướng dẫn chi tiết:

  1. Bài 1 – Lấy các thông tin cơ bản về nhân vật và tự BUFF máu, mana
  2. Bài 2 – Lấy thông tin về tọa độ nhân vật, tự tìm quái đánh, tự nhặt đồ
  3. Bài 3 – Điều khiển nhân vật chạy

Ở đây không bàn đến việc dùng kỹ thuật đồ họa và chiếm chuột để điều khiển nhân vật. Các phần mềm hiện nay thường dùng chương trình chính Autoplay thực hiện việc đọc bộ nhớ Game lấy thông tin và dùng cơ chế Hook để ghi thông tin cần thay đổi vào bộ nhớ Game. Một điểm lưu ý là khi Hook sẽ chiếm tài nguyên, nên ta có thể dùng một mẹo nhỏ, sau khi Hook ta Unhook ngay lập tức và dùng LoadLibrary để nạp hook.dll vào bộ nhớ game, thay đổi địa chỉ WndProc để thực hiện nhiều ý đồ khác.

[Các bạn có thể tham khảo bài viêt sau để biết cách dùng Hook và mẹo này://www.codeproject.com/threads/winspy.asp]. Ngoài ra, để chương trình có thêm nhiều chức năng, có thể ta sẽ phải gọi các hàm trong game_y.exe và khi đó ta phải mở rộng cái Hook.dll để có thể hook + inject code vào Game process [sẽ nói trong bài 3].

Bài 1 - Lấy các thông tin cơ bản về nhân vật và tự BUFF máu, mana

Tất cả các nhân vật [người chơi, quái, Npc...] được lưu thông tin trong mảng gồm 256 đối tượng, mỗi đối tượng kích thước 0x7E4C, địa chỉ lưu địa chỉ của mảng trên là 0x00D3A570. Đối tượng 0 để trống, đối tượng 1 là người chơi, còn lại là quái & Npc.

Khi chưa dùng cơ chế inject code nói trên ta có thể đọc bộ nhớ của Game bằng hàm ReadProcessMemory. Dưới đây là minh họa lớp đối tượng Npc và một số biến thành viên cần dùng [phần ... là phần dữ liệu chưa dùng tới, các bạn phải đặt một mảng BYTE với kích thước tương ứng vào đó để các địa chỉ OFFSET của các biến được chính xác]

Code:

#define NPC_BASE_ADD 0x00D3A570 #define NPC_DATA_SIZE 0x00007E4C #define MAX_NPC 256 #define PLAYER_INDEX 1 class CNpc { ... DWORD m_NpcKind; //0x0020 1=mod, 1=player,... ... DWORD m_Doing; //0x00EC 1=stand, 2=walk, 3=run... ... int m_CurLife; //0x0B44 int m_CurLifeMax; int m_CurLifeRep; int m_CurMana; int m_CurManaMax; ... BOOL m_bRideHorse; //0x0D58 char Name[32]; //0x0D5C Ten nhan vat int m_n***; ... BOOL m_FightMode; //0x0EAC }; // Tim cua so va xac dinh Game Process Handle o day ... CNpc Npc; LPBYTE lpBaseAdd, lpCurAdd; //Read start Address of Npc Array ReadProcessMemory[m_hVLProcess, [LPBYTE]NPC_BASE_ADD, [LPVOID]&lpBaseAdd, 4, NULL]; //Start Address of PLAYER lpCurAdd = lpBaseAdd + PLAYER_INDEX*NPC_DATA_SIZE; //Read PLAYER ìnormation ReadProcessMemory[m_hVLProcess, lpCurAdd, [LPVOID]&Npc, sizeof[CNpc], NULL]; ...

Khi đọc được các thông số máu và mana rồi ta có thể dùng hàm PostMessage[hWnd, WM_KEYDOWN...] để gửi phím 1, 2, 3. Các bạn thấy ở trên có 1 biến m_FightMode dùng để xác định nhân vật đang ở chế độ đánh [ở bản đồ có quái] hoặc đang ở trong thành [không dùng chiêu được]. Căn cứ vào đó ta có thể gửi phím 1, 2, 3 khi cần thiết [m_FightMode=TRUE]. Nếu nhân vật về thành rồi khỏi bơm máu nữa [nhiều khi dính độc về cả phút mà cứ đứng trong thành bơm máu thì phí quá].

Linh tinh khác: Game VLTK có định nghĩa một số hàm macro có thể dùng ở dòng gõ CHAT, ví dụ:

“/Switch Horse”, “/Switch Sit”, “/SayPhrase 0”, , “/SayPhrase 1” các bạn thử mà xem, cũng thũ vị lắm. Các bạn mở file UIconfig.ini sẽ thấy nhiều hàm hơn. Dưới đây là đoạn code mà có thể thêm vào chương trình của mình dùng để chat hoặc chạy một hàm macro trong Game. Bạn có thể lập trình lên xuống ngựa hay ngồi xuống, đứng lên, ... mà ko phải dùng WM_KEYDOWN gửi phím tắt V, M [vì ở chế độ phím Mặc định, nhấn V sẽ ko ngồi đâu].

Code:

void PostChatMessage[LPCTSTR szChatMsg] { //Set focus to CHAT edit control ::PostMessage[m_hVLWin, WM_KEYDOWN, VK_RETURN, 0x001C0001]; //Clear CHAT edit control ::PostMessage[m_hVLWin, WM_KEYDOWN, VK_DOWN, 0x00500001]; while [szChatMsg[0]] { ::PostMessage[m_hVLWin, WM_CHAR, LOBYTE[szChatMsg[0]], 0]; szChatMsg++; } //Set focus to Game Window ::PostMessage[m_hVLWin, WM_KEYDOWN, VK_RETURN, 0x001C0001]; }

Đến đây các bạn có thể lập được một chương trình tự buff mana, ngồi rao bán hàng rồi đấy. Ở bài 2 tôi sẽ nói về cách xác định tọa độ nhân vật [cũng giống như của các Npc khác] và đồ. Địa chỉ OFFSET tọa độ của nhân vật & Npc không phải là 0x10F8 như các bạn tưởng đâu, đó là địa chỉ đích Npc sẽ chạy tới, sẽ đánh tới... nếu nhân vật ngồi xuống, giá trị này sẽ bằng 0.

Bài 2 – Lấy thông tin về tọa độ nhân vật, tự tìm quái đánh, tự nhặt đồ

Hix, được các bác admin quan tâm, em lại viết tiếp.

Bây giờ đến phần toạ độ của nhân vật. Bổ sung thêm các biến thành viên vào lớp CNpc, chúng ta có các thông tin về toạ độ và thông tin đối tượng cần đánh/ theo sau/ đồ cần nhặt:

Code:

class CNpc { public: ... int m_NextAdd; //0x000C – xac dinh Npc ton tai hay ko ... int m_ActiveSkill; //0x0114 – ky nang dang su dung ... int m_MapX, m_MapY, m_MapZ; //0x0D0C – toa do Cell int m_OffX, m_OffY; //0x0D18 – toa do Npc trong Cell [*1024] ... int m_nPeopleIdx; //0x0DE0 Npc can tan cong, hoac theo sau ... int m_nObjectIdx; //0x0DEC Obj can nhat ... WORD m_RegX; //0x0EC4 – toa do Region WORD m_RegY; public: void GetMapPos[int *nX, int *nY]; };

Toàn bàn đồ được chia thành nhiều vùng, có kích thước 512x1024, mỗi vùng lại chia thành nhiều cell, có kích thước là 32x32. Hai biến WORD RegX, RegY lưu giá trị vùng [Region], các biến MapX, MapY lưu giá trị của cell; OffX,OffY là toạ độ Npc trong ô đó [giá trị = 1024/pixel].

Toạ độ của nhân vật được tính như sau:

Code:

#define REGION_WIDTH 512 #define REGION_HEIGHT 1024 #define CELL_WIDTH 32 #define CELL_HEIGHT 32 void CNpc::GetMapPos[int *nX, int *nY] { *nX = m_RegX*REGION_WIDTH + m_MapX*CELL_WIDTH + [m_OffX>>10]; *nY = m_RegY*REGION_HEIGHT + m_MapY*CELL_HEIGHT + [m_OffY>>10]; }

Hàm sẽ trả về nX, nY giá trị toạ độ tuyệt đối của nhân vật/ Npc trên bản đồ, tính theo pixel [không phải toạ độ vẫn thường nói trong GAME đâu]. Còn toạ độ trong Game [thể hiện trên bản đồ nhỏ] sẽ được tính bằng:

Code:

nOrgX = nX>>8; // dich phai 8 bit, chia cho 256

nOrgY = nY>>9; // dich phai 9 bit, chia cho 512

Đến đây các bạn có thể xác định được toạ độ của nhân vật cũng như của Npc bất kỳ trong mảng 256 Npc rồi, và do đó sẽ xác định được khoảng các giữa chúng. Vấn đề là khi quái bị chết, không phải tất cả dữ liệu trong đối tượng bị xoá, trừ khi có quái hoặc player khác được nạp vào vùng nhớ đó. Tôi có thấy 1 địa chỉ ở OFFSET 0x000C, tạm đặt tên biến là m_NextAdd vì thấy nó lưu các địa chỉ quanh quanh trong mảng 256 Npc, khi quái chết, hoặc ra khỏi vùng nhớ [đi ra xa], giá trị m_NextAdd được đặt về 0.

Vậy thuật toán đơn giản để tìm quái để tấn công sẽ như sau:

Code:

CNpc Player; Npc; int nX, nY; int nMinIndex, nMinDistance=2000; //Read PLAYER information lpCurAdd = lpBaseAdd + NPC_DATA_SIZE; ReadProcessMemory[m_hVLProcess, lpCurAdd, [LPVOID]&Player, sizeof[CNpc], NULL]; for [int i=2; i< MAX_NPC; i++] { //Read NPC information lpCurAdd = lpBaseAdd + i*NPC_DATA_SIZE; ReadProcessMemory[m_hVLProcess, lpCurAdd, [LPVOID]&Npc, sizeof[CNpc], NULL]; if [!Npc.m_NextAdd] continue; // Npc does not exist if [Npc.m_CurLifelParam; int *pX, *pY; switch [nAdd] { case 2: // DO WALK pX = [int*][PlayerBaseAdd + 0x108C]; pY = [int*][PlayerBaseAdd + 0x1090]; SendCmdWalkToServer[*pX, *pY]; break; case 3: // DO RUN pX = [int*][PlayerBaseAdd + 0x108C]; pY = [int*][PlayerBaseAdd + 0x1090]; SendCmdRunToServer[*pX, *pY]; break; default: // ASSIGN OTHER VALUES pX = [int*]nAdd; *pX = nVal; } }

Kết thúc loạt bài về viết chương trình AutoPlay. Từ đây các bạn có thể cải tiến chương trình theo ý thích của mình, làm bao nhiêu chức năng tùy ý. Và từ sau bài này các bạn vào trao đổi và có cao kiến hay thắc mắc gì cứ nêu ra chúng ta cùng bàn luận nhé. Các đoạn code trên có nhiều chỗ tôi gõ trực tiếp lên đây [ko phải copy từ chương trình ra vì chỉ cần lấy phần cơ bản cho dễ hiểu] nên đôi khi gõ tắt hoặc gõ lỗi tí xíu, các bạn tự sửa lấy nhé.

Theo dõi Chung Nguyễn Blog

Các bài viết trên website thường xuyên được đăng tải và cập nhật trên trang Facebook Chung Nguyễn Blog nếu thường xuyên đọc bài trên website hay chỉ đơn giản là mến mộ sự đẹp trai thanh lịch của chàng trai coder tuổi trăng tròn đôi mươi thì hãy tặng cho Chung một LIKE trên trang Facebook Chung Nguyễn Blog nhé! Mãi yêu các bạn!

813 👍

Đánh giá bài viết

[Archive] Hướng dẫn viết auto cho game Võ Lâm 1 [VLTK]

5/5 1 votes

Chủ Đề