;  AHK读写游戏内存的函数  By FeiYue
;
; 中途读取(或写入)N级指针地址时不应该设置“字节”参数,
; 但是最后读取的数值需要准确指明“字节”参数,读取1、2、4、8字节的正整数值。
; 如果最后读取的是负数或小数或字符串,还需要指明“类型”或“编码”参数。
; 类型参数可以使用Char(1字节)、Short(2字节)、Int(4字节)
; 、Float(4字节)、Double(8字节)、Str(N字节,可以加编码)。
;
; 读值(进程ID或进程名, 目标地址, 字节="", 类型="", 编码="")
; 写值(进程ID或进程名, 目标地址, 写入值, 字节="", 类型="", 编码="")

F1::

程序名 := "Loginp.exe"
基址   := 0x01c4c5a8
血偏移 := 0x15c
写入值 := 15000

读取值:=读值(程序名, 读值(程序名,基址)+血偏移, 4)
MsgBox, 4096, 提示, % "写入前读取值为:" 读取值

写值(程序名, 读值(程序名,基址)+血偏移, 写入值, 4)

读取值:=读值(程序名, 读值(程序名,基址)+血偏移, 4)
MsgBox, 4096, 提示, % "写入后读取值为:" 读取值

return


;======== 下面是函数 ========

; 中途读取(或写入)N级指针地址时不应该设置“字节”参数,
; 但是最后读取的数值需要准确指明“字节”参数,读取1、2、4、8字节的正整数值。
; 如果最后读取的是负数或小数或字符串,还需要指明“类型”或“编码”参数。
; 类型参数可以使用Char(1字节)、Short(2字节)、Int(4字节)
; 、Float(4字节)、Double(8字节)、Str(N字节,可以加编码)。

读值(进程ID或进程名, 目标地址, 字节="", 类型="", 编码="")
{
    static buf, type:={1:"uchar", 2:"ushort", 4:"uint", 8:"int64"}
    ;------------------
    Process, Exist, %进程ID或进程名%
    if !(PID:=ErrorLevel)
        Throw "获取进程ID失败"
    ;------------------
    if !进程句柄:=DllCall("OpenProcess"
    , "UInt",0x001F0FFF, "UInt",0, "UInt",PID, "Ptr")
        Throw "获取进程句柄失败"
    ;------------------
    字节:=字节 ? 字节 : (!A_Is64bitOS) ? 4 : DllCall("IsWow64Process"
        , "Ptr",进程句柄, "IntP",IsWow64)*0+IsWow64 ? 4 : 8
    类型:=类型 ? 类型 : type[字节]
    VarSetCapacity(buf, (字节<8?8:字节), 0)
    ;------------------
    if !DllCall("ReadProcessMemory", "Ptr",进程句柄
    , "Ptr",目标地址, "Ptr",&buf, "UInt",字节, "UInt",0)
        Throw "读取内存值失败" DllCall("CloseHandle","Ptr",进程句柄)
    ;------------------
    if !DllCall("CloseHandle", "Ptr",进程句柄)
        Throw "关闭进程句柄失败"
    ;------------------
    return (类型!="Str") ? NumGet(buf, 类型)
        : (编码="") ? StrGet(&buf, 字节)
        : StrGet(&buf, 字节, 编码)
}

写值(进程ID或进程名, 目标地址, 写入值, 字节="", 类型="", 编码="")
{
    static buf, type:={1:"uchar", 2:"ushort", 4:"uint", 8:"int64"}
    ;------------------
    Process, Exist, %进程ID或进程名%
    if !(PID:=ErrorLevel)
        Throw "获取进程ID失败"
    ;------------------
    if !进程句柄:=DllCall("OpenProcess"
    , "UInt",0x001F0FFF, "UInt",0, "UInt",PID, "Ptr")
        Throw "获取进程句柄失败"
    ;------------------
    字节:=字节 ? 字节 : (!A_Is64bitOS) ? 4 : DllCall("IsWow64Process"
        , "Ptr",进程句柄, "IntP",IsWow64)*0+IsWow64 ? 4 : 8
    类型:=类型 ? 类型 : type[字节]
    VarSetCapacity(buf, (字节<8?8:字节), 0)
    ;------------------
    (类型!="Str") ? NumPut(写入值, buf, 类型)
        : (编码="") ? StrPut(写入值, &buf, 字节)
        : StrPut(写入值, &buf, 字节, 编码)
    ;------------------
    if !DllCall("VirtualProtectEx", "Ptr",进程句柄
    , "Ptr",目标地址, "UInt",字节, "UInt",0x04, "UInt*",0)
        Throw "修改权限失败" DllCall("CloseHandle","Ptr",进程句柄)
    ;------------------
    if !DllCall("WriteProcessMemory", "Ptr",进程句柄
    , "Ptr",目标地址, "Ptr",&buf, "UInt",字节, "UInt",0)
        Throw "写入内存值失败" DllCall("CloseHandle","Ptr",进程句柄)
    ;------------------
    if !DllCall("CloseHandle", "Ptr",进程句柄)
        Throw "关闭进程句柄失败"
    ;------------------
    return 目标地址+字节
}

提权()  ; 有可能需要
{
   static PROCESS_QUERY_INFORMATION := 0x400
   , TOKEN_ADJUST_PRIVILEGES := 0x20
   , SE_PRIVILEGE_ENABLED := 0x2

   hProc := DllCall("OpenProcess", "UInt",PROCESS_QUERY_INFORMATION
   , "Int",0, "UInt",DllCall("GetCurrentProcessId"), "Ptr")
   DllCall("Advapi32\OpenProcessToken", "Ptr",hProc
   , "UInt",TOKEN_ADJUST_PRIVILEGES, "PtrP", token)

   DllCall("Advapi32\LookupPrivilegeValue"
   , "Ptr",0, "Str","SeDebugPrivilege", "Int64P",luid)
   VarSetCapacity(TOKEN_PRIVILEGES, 16, 0)
   NumPut(1, TOKEN_PRIVILEGES, "UInt")
   NumPut(luid, TOKEN_PRIVILEGES, 4, "Int64")
   NumPut(SE_PRIVILEGE_ENABLED, TOKEN_PRIVILEGES, 12, "UInt")
   DllCall("Advapi32\AdjustTokenPrivileges", "Ptr",token
   , "Int",0, "Ptr",&TOKEN_PRIVILEGES, "Int",0, "Ptr",0, "Ptr",0)
   res := A_LastError
   DllCall("CloseHandle", "Ptr",token)
   DllCall("CloseHandle", "Ptr",hProc)
   Return res
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。