AHK通过读取内存实现魔兽争霸改键

现在网上流传的魔兽争霸ahk改键脚本都存在一个问题,就是无法区分游戏是否处在聊天状态.因为都是基于按键的模拟,没有对游戏的内存进行分析. 而且发现最近许多人问关于ahk读取内存的问题. 其实只要能够调用windows的api,任何编程语言读取内存都是没有问题的.下面展示一下一个简单的魔兽改键脚本(针对1.20e和1.24c),其中的IsChatting()函数就是对内存读取,来判断魔兽是否处于聊天状态.

FN_GetMem(MADDRESS,PROGRAM)
{
WinGet, pid, PID, %PROGRAM%
VarSetCapacity(MVALUE,4,0)
ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "UInt")
DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)
Return, *(&MVALUE+3)<<24 | *(&MVALUE+2)<<16 | *(&MVALUE+1)<<8 | *(&MVALUE)
}

FN_SetMem(WVALUE,MADDRESS,PROGRAM)
{
WinGet, pid, PID, %PROGRAM%
ProcessHandle := DllCall("OpenProcess", "int", 2035711, "char", 0, "UInt", PID, "UInt")
DllCall("WriteProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS, "Uint*", WVALUE, "Uint", 4, "Uint *", 0)
DllCall("CloseHandle", "int", ProcessHandle)
}

现在网上流传的魔兽争霸ahk改键脚本都存在一个问题,就是无法区分游戏是否处在聊天状态.因为都是基于按键的模拟,没有对游戏的内存进行分析.  而且发现最近许多人问关于ahk读取内存的问题.  其实只要能够调用windows的api,任何编程语言读取内存都是没有问题的.下面展示一下一个简单的魔兽改键脚本(针对1.20e和1.24c),其中的IsChatting()函数就是对内存读取,来判断魔兽是否处于聊天状态.

#ifWinActive, Warcraft III
;;;;; 改键 ;;;;;
$q::
KeyIsOn := GetKeyState("ScrollLock" ,"T")  ;;得到scrollLock的状态
if(KeyIsOn && !IsChatting())    ;如果scrollLock灯亮并且不是聊天状态
{
   Send,{Numpad8}    ;发送numpad8
}
Else
{
   Send,q    ;还是发q
}
return
#ifWinActive

IsChatting()
{
   Process, Exist  ; 获取脚本进程的PID到ErrorLevel 变量中
    h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)       ;得到进程的句柄
   DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
   VarSetCapacity(ti, 16, 0)  ; structure of privileges
   NumPut(1, ti, 0)  ; one entry in the privileges array...
   ; Retrieves the locally unique identifier of the debug privilege:
   DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege", "Int64P", luid)
   NumPut(luid, ti, 4, "int64")
   NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
   ; Update the privileges of this process with the new access token:
   DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false, "UInt", &ti, "UInt", 0, "UInt", 0, "UInt", 0)    ;从上面到这里,都是为了使提升脚本的进程权限
   DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory      ;关闭进程句柄
   WinGet,pid,PID,A    ;得到当前激活窗口的进程pid,因为热键q只有当魔兽激活时候才生效,所以得到的总是魔兽的pid
   h := DllCall("OpenProcess", "UInt", 24, "Int", false, "UInt", pid) ;打开魔兽进程   
VarSetCapacity(value,4,0)
   DllCall("ReadProcessMemory","UInt",h,"UInt",0x47AFD0,"Str",value,"UInt",4,"UIntP",0)     ;读取地址,判断魔兽的版本
   addr := (NumGet(value)==0x6989787A) ? 0x6FAE8450:0x0045cb8c ;不同版本的war3判断是否聊天的地址是不一样的,这里兼容1.20e和1.24c
   DllCall("ReadProcessMemory","UInt",h,"UInt",addr,"Str",value,"UInt",4,"UIntP",0)
   ; 读取内存的值判断是否在聊天  1.20e 0x0045cb8c   1.24c 0x6FAE8450
   Return,value    ;返回读取的值,如果不在聊天,返回的应该是0
}

以上的例子主要介绍了使用api读取游戏进程内存的过程.里面用到的地址需要自己去用别的工具分析,cheat engine   , 金山游侠什么的都行.建议看下别的教程,学会怎么分析内存,找地址,然后就可以用本文中的例子,做出内存挂


 

给TA捐赠
共{{data.count}}人
人已捐赠
其他

Autohotkey实现Socket通信

2018-1-17 21:29:09

其他应用

AHK实现游戏多开

2018-1-17 22:09:50

4 条回复 A文章作者 M管理员
  1. 蝉

    虽然看不懂,但功能感觉很高超!?

  2. 懒⃢?ܫ?⃢猫

    666666别的不知道了

  3. —━═☆飾de璦

    感谢大佬分享,有没有魔兽钓鱼得哈,我超喜欢钓鱼

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索