发表回复 
使用ahk读取内存判断魔兽争霸是否处于聊天状态
2009-12-16, 23 : 21
使用ahk读取内存判断魔兽争霸是否处于聊天状态
[i=s] 本帖最后由 dule2859 于 2009-12-16 23:37 编辑 [/i]

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

#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 , 金山游侠什么的都行.建议看下别的教程,学会怎么分析内存,找地址,然后就可以用本文中的例子,做出内存挂了:)
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2009-12-17, 18 : 24
 
你好。
请问一下有没有办法判断现在是否在游戏还是在等待玩家进去?
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2009-12-17, 22 : 49
 
IsWaitting()
{
Process, Exist ; sets ErrorLevel to the PID of this running script
h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
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
h := DllCall("OpenProcess", "UInt", 24, "Int", false, "UInt", pid) ;DllCall("OpenProcess", "Int", 0x0010 | 0x0400, "Int", false, "UInt", pid, "UInt")
VarSetCapacity(value,4,0)
DllCall("ReadProcessMemory","UInt",h,"UInt",0x6FAE8450,"Str",value,"UInt",4,"UIntP",0)
Return,value
}

以上函数可以判断是否在等待玩家.当等待玩家时,函数将返回非0,否则返回0.
跟上面那个函数一样的,说明一下,以上这个函数只对1.24c版本有效,1.20e的地址我懒得测试了 ^_^
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2010-02-01, 23 : 06
 
非常感谢能共享经验~~感激啊
访问这个用户的网站 查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2010-02-05, 22 : 24
 
这才是根本上解决问题啊:handshake
感谢共享
访问这个用户的网站 查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2010-05-05, 01 : 58
 
[i=s] 本帖最后由 arliang 于 2010-5-5 02:00 编辑 [/i]

谢谢,正想找这个,找着了。
再请教一下,这是怎么找到的的?

原来有说了,没仔细看,不好意思

<strong>不积跬步,无以至千里;<br />
不积小流,无以成江海。</strong>
访问这个用户的网站 查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2012-12-28, 10 : 13
 
代码: (全选)
提供以下各版本的聊天地址:
;1.20e 0045CB8C
;1.23  6FAD6E30
;1.24b 6FAE8450
;1.24c 6FAE8450
;1.24e 6FAE8450
;1.25b 6FAD15F0
;1.26a 6FAD15F0
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2012-12-28, 20 : 09
 
2# airey
判断是否正在游戏局中:
IsPlaying := R(Adr.Game + Adr.Playing)
4:游戏中,2:房间外,1:房间内等待中
ce中这么表示:Game.dll+ACC590
对于XP,直接就是0x6FACC590
版本1.24E

AutoHotKey Ansi x86 v1.1.24.01
Win10.0.14388 x64
访问这个用户的网站 查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2013-03-23, 14 : 50
 
你好呀朋友
h := DllCall("OpenProcess", "UInt", 24, "Int", false, "UInt", pid)
这个数字24是什么意思呀?哪里有参数的资料。我网上都找不到。
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
发表回复 


论坛跳转:


联系我们 | Autohotkey 中文站 | 回到顶部 | 回到正文区 | 精简(归档)模式 | RSS 聚合