超强回归—菜鸟进阶,c++魔兽争霸全图外挂制作全教程

半年前浅尝制作外挂,初试成功,很是兴奋。发表一贴《菜鸟教程-全图外挂制作全程教学》。地址:https://www.360docs.net/doc/7711061600.html,/thread-2485-1-1.html。

貌似点击量很高。但看贴后的留言,有很多人说难?也有人骂我,说我自己都不会的,是抄袭别人的文章,我还轮不到你个瘪三来指三道四。下面不说这个瘪三了,进入正题。

难在何处?我想:

第一,你不会编程。对于这类人,你们应该去学习,至少掌握一门编程语言。如C++,VB,Delphi等。

第二,你没有弄懂外挂制作原理和思路。首先说原理,思路下面再详细说。其实这个在《菜鸟教程-全图外挂制作全程教学》中有提到。外挂原理一般包括:模拟式,内存式,封包式和指今修改式。比如:大部分改建就是模拟键盘(模拟式)。全图外挂为内存式或指令修改式。

第三,你没有仔细看《菜鸟教程-全图外挂制作全程教学》,对于这类人,我要严重的批判和表示强烈的鄙视。

好了,我们继续正题。如果你已经掌握一门编程语言了,想做外挂,你必须清楚实现整个功能的思路,这个在《菜鸟教程-全图外挂制作全程教学》中也是有的。我们做的全图外挂为内存式,又分DLL注入和程序两种形式,我这里讲的是软件形式,DLL注入的看BR以前的源码。

首先,我们要提升外挂本身程序权限,使其能够有权限修改war3游戏的内存。这个c++可以使用如下代码

1.void EnableDebugPriv()//提升程序自身权限

2.{

3. HANDLE hToken;

4. LUID sedebugnameValue;

5. TOKEN_PRIVILEGES tkp;

6.if (!OpenProcessToken(GetCurrentProcess(),

TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return;

7.if (!LookupPrivilegeValue(NULL,

SE_DEBUG_NAME,&sedebugnameValue))

8. {

9. CloseHandle(hToken);

10. return;

11. }

12. tkp.PrivilegeCount = 1;

13. tkp.Privileges[0].Luid = sedebugnameValue;

14. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

15.if (!AdjustTokenPrivileges(hToken, FALSE, &tkp,

sizeof tkp, NULL, NULL)) CloseHandle(hToken);

16.}

其次,有了权限以后,我们要找到war3.exe进程ID。并打开进程以供编辑修改内存,到达作弊目的。而这个也是重点了。他妈的,都别猴急,哥我打字也很辛苦,先喝杯茶……

啊,下面开始讲重点了,请大家做好笔记,别过后说老子没讲。尼玛,论坛是有记录的,别想坑爹。

获得进程ID:下面这个函数方法就是返回进程的,直接写进程名称,如:GetPIDForProcess(“war3.exe”),还可以用FindWindow的方法,反正能找到进程ID就可以了。

1.//HWND hwar3=::FindWindow(NULL,TEXT("Warcraft III"));

2.//DWORD PID, TID;

3.//TID = ::GetWindowThreadProcessId (hwar3, &PID);

4.DWORD GetPIDForProcess(char* process)//获取进程ID

5.{

6. BOOL working;

7. PROCESSENTRY32 lppe= {0};

8. DWORD targetPid=0;

9.HANDLE

hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS ,0);

10. if (hSnapshot)

11. {

12. lppe.dwSize=sizeof(lppe);

13. working=Process32First(hSnapshot,&lppe)

;

14. while (working)

15. {

16.if(strcmp((const char

*)lppe.szExeFile,process)==0)

17. {

18. targetPid=lppe.

th32ProcessID;

19. break;

20. }working=Process32Next(hSna

pshot,&lppe);

21. }

22. }

23. CloseHandle( hSnapshot );

24. return targetPid;

25.}

注意:有的名称为War3.exe或war3.exe,需要区分大小写。c++有不区分大小写比较的方法,自己去找……我操,这点专研精神都没有,怎么不去死,还学编程做外挂?自己先挂吧。其实我后面有个教你们查看自己的进程和game.dll到底是大写还是小些的方法。

进程ID已经找到,现在是不是直接打开修改内存作弊呢?不,还早呢。我们修改内存也不能乱来,你得先找到Game.dll判断游戏版本,对应修改,要不会把魔兽搞火了,突然跳出来,那你就崩溃了,后悔都来不及。有木有,有木有?开图导致游戏崩溃的老实交代一下。

下面的方法获取game.dll的基址和路径。GetDLLBase(“game.dll”,PID)直接返回的就是game.dll的基址,这个后面是需要用到的。定义一个全局变量TCHAR LastDLLPath[260],LastDLLPath返回的就是game.dll路径,。

1.DWORD GetDLLBase(char* DllName, DWORD tPid)

2.{

3. HANDLE snapMod;

4. MODULEENTRY32 me32;

5. if (tPid == 0) return 0;

6. snapMod = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,

tPid);

7. me32.dwSize = sizeof(MODULEENTRY32);

8. if (Module32First(snapMod, &me32))

9. {

10. do

11. {

12. if (strcmp(DllName,(const

char *)me32.szModule) == 0)

13. {

14. strcpy(LastDLLP

ath ,me32.szExePath);//game.dll路径

15. CloseHandle(sna

pMod);

16. return (DWORD)

me32.modBaseAddr;

17. }

18. }while(Module32Next(snapMod,&me32));

19. }

20. else

21. {

22.Powers=true;

23. }

24. CloseHandle(snapMod);

25. return 0;

26.}

这里也需要注意的是game.dll的大小写或者名称,如有的平台为game124.dll。然后用下面两个方法获得版本。定义全局变量WC3VER g_War3Ver,enum WC3VER{_UN,_120E,_124B,_124E,_125B,_126B}。

1.void GetWar3Ver()

2.{

3. TCHAR FileVer[64];

4. ODV(TEXT("%s"),LastDLLPath);

5. GetFileVer(LastDLLPath,FileVer,64);

6. ODV(TEXT("%s"),FileVer);

7. if(lstrcmpi(FileVer,TEXT("1, 20, 4, 6074")) ==0)

8. {

9. g_War3Ver=_120E;

10. }

11. else if(lstrcmpi(FileVer,TEXT("1, 24, 1, 6374")) ==0)

12. {

13. g_War3Ver=_124B;

14. }

15. else if(lstrcmpi(FileVer,TEXT("1, 24, 4, 6387")) ==0)

16. {

17. g_War3Ver=_124E;

18. }

19. else if(lstrcmpi(FileVer,TEXT("1, 25, 1, 6397")) ==0)

20. {

21. g_War3Ver=_125B;

22. }

23. else if(lstrcmpi(FileVer,TEXT("1, 26, 0, 6401")) ==0)

24. {

25. g_War3Ver=_126B;

26. }

27. else

28. {

29. g_War3Ver=_UN;

30. }

31.}

32.DWORD GetFileVer(__in LPTSTR FileName, __out LPTSTR lpVersion,

__in DWORD nSize)

33.{

34. TCHAR SubBlock[64];

35. DWORD InfoSize;

https://www.360docs.net/doc/7711061600.html,Size =

GetFileVersionInfoSize(FileName,NULL); if(InfoSize==0) return 0;

37. TCHAR *InfoBuf = new TCHAR[InfoSize];

38. GetFileVersionInfo(FileName,0,InfoSize,InfoBuf);

39. unsigned int cbTranslate = 0;

40. struct LANGANDCODEPAGE

41. {

42. WORD wLanguage;

43. WORD wCodePage;

44. }

45. *lpTranslate;

46.VerQueryValue(InfoBuf,

TEXT("\\VarFileInfo\\Translation"),

47. (LPVOID*)&lpTranslate,&cbTranslate);

48. // Read the file description for each language and code

page.

49. wsprintf( SubBlock,

50. TEXT("\\StringFileInfo\\%04x%04x\\FileV

ersion"),

51. lpTranslate[0].wLanguage,

52. lpTranslate[0].wCodePage);

53. void *lpBuffer=NULL;

54. unsigned int dwBytes=0;

55.VerQueryValue(InfoBuf, SubBlock, &lpBuffer,

&dwBytes);

56. lstrcpyn(lpVersion,(LPTSTR)lpBuffer,nSize);

57. delete[] InfoBuf;

58. return dwBytes;

59.}

获得版本后我们就可以打开进程了。

1.HANDLE hopen=OpenProcess( PROCESS_ALL_ACCESS|PROCESS_TERMINA

TE|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE,FALSE,P ID);

2.//打开war进程以供编辑

再用switch语句判断。如

1.switch(g_War3Ver)

2.{

3.case _120E:

4.//修改内存代码自己去找吧//大地图去除迷雾

5.PATCH(0x406B53,"\x90\x8B\x09");

6.PATCH(0x2A0930,"\xD2");

7.//野外显血

8.PATCH(0x166E5E,"\x90\x90\x90\x90\x90\x90\x90\x90");

9.PATCH(0x16FE0A,"\x33\xC0\x90\x90");

10.//视野外点选

11.PATCH(0x1BD5A7,"\x90\x90");

12.PATCH(0x1BD5BB,"\xEB");

13.//小地图显示单位

14.PATCH(0x1491A8, "\x00");

15.break;

16.case _124B:

17.//小地图显示单位

18.PATCH(0x361EAB,"\x90\x90\x39\x5E\x10\x90\x90\xB8\x00\

x00\x00\x00\xEB\x07");

19.break;

20.case _124E:

21.//至于作弊代码你们是直接写,还是写成一个方法调用,随你们自己。

22.break;

23. case _UN:

24. default:

25.break;

26.}

这里还有个特别重要的:PATCH,这是定义的一个宏,不懂的百度。

#define PATCH(i,w) WriteProcessMemory(hopen,(LPVOID)(g_dwGameAd dr+i),w,sizeof(w)-1,0);

hopen就是先打开war进程以供编辑时返回的句柄的,g_dwGameAddr就是GetDLLBase(char* DllName, DWORD tPid)返回的基址。

回想:在《菜鸟教程-全图外挂制作全程教学》里面,有人在那“教训”我,我只想说:“你装B装的可以了,爷我法眼一开就知道你是个瘪三”。

记得有人问过为什么这个宏在这里使用WriteProcessMemory,和BR的不同,什么意思?是因为这个是在自己的程序里面,如果DLL注入的话就要用

#define PATCH(i,w) memcpy((LPVOID)(g_dwGameAddr+i),w,sizeof(w)-1)。

这个教程难免还有疏漏的地方,如有留言,看到必回。谢谢大家支持!

补充一下,在前面,两处说道大小写不一致的问题,这里教你们一个方法,怎么知道具体的名称.

首先,我们打开魔兽,找到War3.exe进程,直接就可以看出他的大小写是什么。然后可以根据上面的DWORD GetDLLBase(char* DllName, DWORD tPid)和DWORD GetPIDForProcess(char* process)获得War3.exe进程加载的所有模块,如果单机启动,是加载本地的game.dll。如果在平台上启动游戏,你会发现加载的是平台自带的game.dll。

如建一个控制台程序,源码如下:

1.#include "StdAfx.h"

2.#include

3.#include

4.#include

5.TCHAR LastDLLPath[260];

6.DWORD GetDLLBase(char* DllName, DWORD tPid)

7.{

8. HANDLE snapMod;

9. MODULEENTRY32 me32;

10. if (tPid == 0) return 0;

11. snapMod = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,

tPid);

12. me32.dwSize = sizeof(MODULEENTRY32);

13. if (Module32First(snapMod, &me32))

14. {

15.

16. do

17. {

18. /*if (strcmp(DllName,(const

char *)me32.szModule) == 0)

19. { */

20. printf( "%s\n

",me32.szExePath);

21.

22. /*}*/

23. }

24. while(Module32Next(snapMod,&me32));

25. }

26. CloseHandle(snapMod);

27. return 0;

28.}

29.DWORD GetPIDForProcess(char* process)

30.{

31. BOOL working;

32. PROCESSENTRY32 lppe= {0};

33. DWORD targetPid=0;

34.HANDLE

hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS ,0);

35. if (hSnapshot){

36. lppe.dwSize=sizeof(lppe);

37. working=Process32First(hSnapshot,&lppe)

;

38. while (working){

39.if(strcmp((const char

*)lppe.szExeFile,process)==0)

40. {

41. targetPid=lppe.

th32ProcessID;

42. break;

43. }working=Process32Next(hSna

pshot,&lppe);

44. }

45. }

46. CloseHandle( hSnapshot );

47. return targetPid;

48.}

49.

50.

51.int main(int argc, char* argv[])

52.{

53. HANDLE hToken;

54. LUID sedebugnameValue;

55. TOKEN_PRIVILEGES tkp;

56.OpenProcessToken(GetCurrentProcess(),

TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);

57.LookupPrivilegeValue(NULL,

SE_DEBUG_NAME,&sedebugnameValue);

58. tkp.PrivilegeCount = 1;

59. tkp.Privileges[0].Luid = sedebugnameValue;

60. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

61. AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp,

NULL, NULL);

62. CloseHandle(hToken);

63.

64.//HWND hwar3=::FindWindow(NULL,TEXT("Warcraft

III"));

65. //DWORD PID,TD;

66. //TD = GetWindowThreadProcessId (hwar3, &PID);

67. //和下面一样的效果。

68. DWORD PID=GetPIDForProcess("war3.exe");

69. GetDLLBase("war3.exe",PID);

70. getchar();

71. return 0;

72.}

相关文档
最新文档