프로그래밍/오토핫키

오토핫키 메모리 읽어오기 메모리 쓰기

포스몬 2016. 11. 20. 04:53




http://assault.cubers.net/

 

http://sourceforge.net/projects/actiongame/files/AssaultCube%20Version%201.2.0.2/AssaultCube_v1.2.0.2.exe/download 


3D FPS 게임 입니다. 


이걸로 메모리 관련 부분을 오토핫키로 제어 하는걸 첫번째로 올릴께요...


아시는 부분들은 다 아시겠지만 모르는 분들은 모르니까요 ;;;



유투브에서 이 게임을 오토핫키로 제어 하도록 만든 예제 동영상도 있습니다.


(외국 어느 사람이 만든겁니다. ^^  동영상을 보고 배우셔도 됩니다..^^)



예제 설명은 다음편에 진행됩니다.


;//실전 예제 입니다. 


startscript:

Gui,+SysMenu +Owner +AlwaysOnTop

Gui, Add, GroupBox, x6 y6 w260 h180 , Assult Cube Viewer

Gui, Add, Text, x16 y22 w200 h12 vNavi, 게임 대기중

;Gui, Add, Text, x140 y27 w120 h12 vNaviA, 프로그램 동작 대기중 

Gui, Add, Text, x16 y42 w100 h12 vNaviHP,

Gui, Add, Text, x16 y62 w100 h12 vNaviSP,

Gui, Add, Text, x16 y82 w240 h12 vNaviAP,

Gui, Add, Text, x16 y102 w200 h12 vNaviX,

Gui, Add, Text, x16 y122 w200 h12 vNaviY,

Gui, Add, Text, x16 y142 w200 h12 vNaviZ,

Gui, Add, Text, x16 y162 w200 h12 vNaviV,

;Gui, Add, Text, x56 y40 w80 h12 vNavi, 

Gui, Add, Button, x220 y160 w40 h20 gExit, 종료

; Generated using SmartGUI Creator for SciTE

XW := A_ScreenWidth - 300

Gui, Show, x%xw% y0, [실전강좌]-포스몬

gosub, game

;startscript:

;gosub, state_show

settimer,GetPostion,10

return


end::

;종료하시겠습니까 확인창 나오게 하기.

Exit:

GuiClose:

ExitApp


game:

guicontrol,,navi,프로그램 대기중

PROGRAM := "ahk_exe ac_client.exe"

gosub, active

sleep, 100

Base := getProcessBaseAddress("ahk_exe ac_client.exe")

;Base := getProcessBaseAddress(PROGRAM)

guicontrol,,navi,GetProcessHandle

return


Active:

WinWait,ahk_exe ac_client.exe , 

IfWinNotActive, ahk_exe ac_client.exe, , WinActivate, ahk_exe ac_client.exe, 

WinWaitActive, ahk_exe ac_client.exe,

;WinMaximize,ahk_exe ac_client.exe

return


GetPostion:

Pointer1 := 0x110

Pointer2 := 0xb0

HPointer := 0xf8

SPointer := 0xfc

APOinter := 0x150

BPOinter := 0x128

GPOinter := 0x158

XPointer := 0x34

YPointer := 0x38

ZPointer := 0x3c

VPointer := 0x40

setformat, integer,HEX

pointerBase := base + 0x000B9990

;msgbox, BASE : %Base%

p1 := ReadMemory(pointerBase, PROGRAM)

;msgbox,P1 : %P1%

p2 := ReadMemory(p1 + Pointer1, PROGRAM)

;msgbox,P2 : %P2%

p3 := ReadMemory(p2 + Pointer2, PROGRAM)

;msgbox,P3 : %P3%

;p3 := ReadMemory(p2 + 0xc, PROGRAM)

;p4 := ReadMemory(p3 + 0x20c, PROGRAM)

setformat, integer,DEC

HP := ReadMemory(P3 + HPointer, PROGRAM)

SP := ReadMemory(P3 + SPointer, PROGRAM)

AP := ReadMemory(P3 + APointer, PROGRAM)

AB := ReadMemory(P3 + BPointer, PROGRAM)

GP := ReadMemory(P3 + GPointer, PROGRAM)

Coordx := HexToFloat(ReadMemory(P3 + XPointer, PROGRAM))

Coordy := HexToFloat(ReadMemory(P3 + YPointer, PROGRAM))

Coordz := HexToFloat(ReadMemory(P3 + ZPointer, PROGRAM))

View := HexToFloat(ReadMemory(P3 + VPointer, PROGRAM))

;msgbox,HP : %HP%

guicontrol,,NaviHP,HP 피값 : %HP% 

guicontrol,,NaviSP,SP 실드 : %SP% 

guicontrol,,NaviAP,AP 총알 : %AP% / 탄띠 : %AB% / 수류탄 : %GP%

guicontrol,,NaviX,X 좌표 : %Coordx%

guicontrol,,NaviY,Y 좌표 : %Coordy%

guicontrol,,NaviZ,Z 좌표 : %Coordz% - 높이

guicontrol,,NaviV,View 각도 : %View%

return



HexToFloat(x) 

{

   Return (1-2*(x>>31)) * (2**((x>>23 & 255)-150)) * (0x800000 | x & 0x7FFFFF)

}



getProcessBaseAddress(windowTitle, windowMatchMode := "3")   

{

        if (windowMatchMode && A_TitleMatchMode != windowMatchMode)

        {

            mode := A_TitleMatchMode ; This is a string and will not contain the 0x prefix

            StringReplace, windowMatchMode, windowMatchMode, 0x ; remove hex prefix as SetTitleMatchMode will throw a run time error. This will occur if integer mode is set to hex and matchmode param is passed as an number not a string.

            SetTitleMatchMode, %windowMatchMode%    ;mode 3 is an exact match

        }

        WinGet, hWnd, ID, %WindowTitle%

        if mode

            SetTitleMatchMode, %mode%    ; In case executed in autoexec

        if !hWnd

            return ; return blank failed to find window

       ; GetWindowLong returns a Long (Int) and GetWindowLongPtr return a Long_Ptr

        return DllCall(A_PtrSize = 4     ; If DLL call fails, returned value will = 0

            ? "GetWindowLong"

            : "GetWindowLongPtr"

            , "Ptr", hWnd, "Int", -6, A_Is64bitOS ? "Int64" : "UInt")  

            ; For the returned value when the OS is 64 bit use Int64 to prevent negative overflow when AHK is 32 bit and target process is 64bit 

            ; however if the OS is 32 bit, must use UInt, otherwise the number will be huge (however it will still work as the lower 4 bytes are correct)      

            ; Note - it's the OS bitness which matters here, not the scripts/AHKs

}   


ProcessWriteMemory(data, address, processIDorName, type := "Int", numBytes := 4) {

    VarSetCapacity(buf, numBytes, 0)

    (type = "Str")

        ? StrPut(data, &buf, numBytes)

        : NumPut(data, buf, type)


    Process Exist, %processIDorName%

    if !processID := ErrorLevel

        throw Exception("Invalid process name or process ID:`n`n""" . processIDorName . """")


    if !processHandle := DllCall("OpenProcess", "Int", 40, "UInt", 0, "UInt", processID, "Ptr")

        throw Exception("Failed to open process.`n`nError code:`t" . A_LastError)


    result := DllCall("WriteProcessMemory", "Ptr", processHandle, "Ptr", address, "Ptr", &buf, "Ptr", numBytes, "UInt", 0, "UInt")


    if !DllCall("CloseHandle", "Ptr", processHandle, "UInt") && !result

        throw Exception("Failed to close process handle.`n`nError code:`t" . A_LastError)


    if !result

        throw Exception("Failed to write process memory.`n`nError code:`t" . A_LastError)


    return result

}

WriteMemory(WriteAddress = "", PROGRAM="", Data="", TypeOrLength = "")

{

  

   Static OLDPROC, hProcess, pid


   If (PROGRAM != OLDPROC)

   {

        if hProcess

          closed := DllCall("CloseHandle", "UInt", hProcess), hProcess := 0, OLDPROC := ""

        if PROGRAM

        {

            WinGet, pid, pid, % OLDPROC := PROGRAM

            if !pid 

               return "Process Doesn't Exist", OLDPROC := "" ;blank OLDPROC so subsequent calls will work if process does exist

            hProcess := DllCall("OpenProcess", "Int", 0x8 | 0x20, "Int", 0, "UInt", pid)   

        }

   }


    If Data is Number   ; Either a numeric value or a memory address.

    {

        If TypeOrLength is Integer  ; Address of a buffer was passed.

        {

            DataAddress := Data

            DataSize := TypeOrLength    ; Length in bytes of the data in the buffer.

        }

        Else    ; A numeric value was passed.

        {

            If (TypeOrLength = "Double" or TypeOrLength = "Int64")

                DataSize = 8

            Else If (TypeOrLength = "Int" or TypeOrLength = "UInt"

                                          or TypeOrLength = "Float")

                DataSize = 4

            Else If (TypeOrLength = "Short" or TypeOrLength = "UShort")

                DataSize = 2

            Else If (TypeOrLength = "Char" or TypeOrLength = "UChar")

       DataSize = 1

            Else {

              ;  MsgBox, Invalid type of number.

                Return False 

            }

            VarSetCapacity(Buf, DataSize, 0)

            NumPut(Data, Buf, 0, TypeOrLength)

            DataAddress := &Buf

        }

    }

    Else    ; Data is a string.

    {

        DataAddress := &Data

        If TypeOrLength is Integer  ; Length (in characters) was specified.

        {

            If A_IsUnicode

                DataSize := TypeOrLength * 2    ; 1 character = 2 bytes.

            Else

                DataSize := TypeOrLength

        }

        Else

        {

            If A_IsUnicode

                DataSize := (StrLen(Data) + 1) * 2  ; Take the whole string

            Else                                    ; with the null terminator.

                DataSize := StrLen(Data) + 1

        }

    }                                               

    ; will return null if write works

    if (hProcess && DllCall("WriteProcessMemory", "UInt", hProcess 

                                         , "UInt", WriteAddress

                                         , "UInt", DataAddress

                                         , "UInt", DataSize

                                         , "UInt", 0))

        return                               

    else  return !hProcess ? "Handle Closed:" closed : "Fail"

}


ReadMemory(MADDRESS=0,PROGRAM="",BYTES=4)

{

   Static OLDPROC, ProcessHandle

   

   ; keep buffer a local variable, rather than static so that it is 

   ; quasi thread safe. 

   VarSetCapacity(buffer, BYTES) 

   If (PROGRAM != OLDPROC)

   {

        if ProcessHandle

          closed := DllCall("CloseHandle", "UInt", ProcessHandle), ProcessHandle := 0, OLDPROC := ""

        if PROGRAM

        {

            WinGet, pid, pid, % OLDPROC := PROGRAM

            if !pid 

               return "Process Doesn't Exist", OLDPROC := "" ;blank OLDPROC so subsequent calls will work if process does exist

            ProcessHandle := DllCall("OpenProcess", "Int", 16, "Int", 0, "UInt", pid)   

        }

   }

   

   If !(ProcessHandle && DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS, "Ptr", &buffer, "UInt", BYTES, "Ptr", 0))

      return !ProcessHandle ? "Handle Closed: " closed : "Fail"

   else if (BYTES = 1)

      Type := "UChar"

   else if (BYTES = 2)

      Type := "UShort"

   else if (BYTES = 4)

      Type := "UInt"

   else 

      Type := "Int64"

   return numget(buffer, 0, Type)

}


;=============== 여기 까지가 예제 끝 입니다.  ======================