Jump to content

KryMemory [UDF]


KryziK
 Share

Recommended Posts

A short collection of functions to manipulate and query process memory. This is based off of multiple other libraries I've written for other languages and was created because a friend using AutoIt requested it. It also has increased functionality and efficiency compared to NomadMemory. The handle array idea was also taken from NomadMemory and built onto.

This small library took me a total of a few hours to write, test, and document. However, much testing is left to do. The error checking could also be extended a bit more to account for new users. If you have any suggestions or find any bugs, do not hesitate to reply here. Make sure you include the code that caused the error, your operating system information, and any other relevant information.

Anyways, here it is:

KryMemory Library Download

Documented Functions:

; _Process_Open($sProcessName, $iDesiredAccess = $PROCESS_ALL_ACCESS, $fInheritAccess = False)
; _Process_Close($ahHandle)
; _Process_ReadMemory($ahHandle, $ivAddress, $sType = "dword")
; _Process_ReadMemoryPointer($ahHandle, $ivAddress, $aiOffsets, $sType = "dword")
; _Process_WriteMemory($ahHandle, $ivAddress, $vData, $sType = "dword")
; _Process_WriteMemoryPointer($ahHandle, $ivAddress, $aiOffsets, $vData, $sType = "dword")
; _Process_GetBaseAddress($ahHandle)
; _Process_GetParent($ahHandle)
; _Process_GetModules($ahHandle)
;
; _Address_CalculateStatic($ahHandle, $sModuleName, $ivOffset)
; _Address_CalculatePointer($ahHandle, $ivAddress, $aiOffsets)
;
; _Module_GetBaseAddress($ahHandle, $sModuleName)

Example Usage:

#include "KryMemory.au3"

; Opens a process, enabling the other functions to be used on it.
Local $oProc = _Process_Open("KryziK.exe")

; Makes sure the process was opened.
If @error Then
    ConsoleWriteError("The specified process could not be opened. Error: " & @error & @CRLF)
    Exit(0)
EndIf

; Lists all of the modules in the process and their base address in a nice, pretty table.
ConsoleWrite(StringFormat("%-25s%-25s", "Module Name", "Base Address") & @CRLF)
ConsoleWrite("-------------------------------------" & @CRLF)
For $sModule in _Process_GetModules($oProc)
    ConsoleWrite(StringFormat("%-25s 0x%08X", $sModule, _Module_GetBaseAddress($oProc, $sModule)) & @CRLF)
Next

; Closes the handles created by _ProcessOpen.
_Process_Close($oProc)

Disclaimer: Don't use this for anything that would violate AutoIt Forum rules. Don't be stupid!

Change Log:

- _Process_GetParent added.

1/12/2013 - First release.

Edited by KryziK
Link to comment
Share on other sites

Good job my friend, thank you.

about the WriteProcessMemory and ReadProcessMemory APIs you can get lpNumberOfBytesWritten and lpNumberOfBytesRead in a smarter way, no need to creating the DllStruct. Personally I do them this way:

Func _ProcessWrite($hProcess, $lpAddress, $lpBuffer, $sBufferType = "byte")
Local $tagBuffer = DllStructCreate($sBufferType & "[" & BinaryLen($lpBuffer) & "]")
DllStructSetData($tagBuffer, 1, $lpBuffer)

Local $lpNumberOfBytesWritten = 0
WriteProcessMemory($hProcess, $lpAddress, DllStructGetPtr($tagBuffer, 1), DllStructGetSize($tagBuffer), $lpNumberOfBytesWritten)
If (@error) Then Return SetError(1, 0, 0)

Return SetError(0, $lpNumberOfBytesWritten, 1)
EndFunc

Func WriteProcessMemory($hProcess, $lpBaseAddress, $lpBuffer, $nSize, ByRef $lpNumberOfBytesWritten)
Local $aResult = DllCall("kernel32.dll", "BOOL", "WriteProcessMemory", _
"HANDLE", $hProcess, _
"ptr", $lpBaseAddress, _
"ptr", $lpBuffer, _
"DWORD", $nSize, _
"DWORD*", 0)
If (Not @error) Then $lpNumberOfBytesWritten = $aResult[5]
If (@error Or $aResult[0] == 0) Then Return SetError(1, 0, 0)

Return SetError(0, 0, 1)
EndFunc

I'm sure you can understand them, and you can imagine how ReadProcessMemory can be done using the same method.

Edit: You have done _Address_CalculatePointer in a tricky way, I like how you did it.

Edited by D4RKON3
Link to comment
Share on other sites

Some useful functions:

ProcessGetParent: Gives the parent of a process.

#include 

Func ProcessGetParent(Const $iProcessId)
Local Const $hSnapshot = DllCall('Kernel32.dll', 'HANDLE', 'CreateToolhelp32Snapshot', _
'DWORD', 0x00000002, _ ;TH32CS_SNAPPROCESS
'DWORD', 0)

Local $tagPROCESSENTRY32 = DllStructCreate( _
'DWORD dwSize;' & _
'DWORD cntUsage;' & _
'DWORD th32ProcessID;' & _
'ULONG_PTR th32DefaultHeapID;' & _
'DWORD th32ModuleID;' & _
'DWORD cntThreads;' & _
'DWORD th32ParentProcessID;' & _
'long pcPriClassBase;' & _
'DWORD dwFlags;' & _
'char szExeFile[260]')
DllStructSetData($tagPROCESSENTRY32, 'dwSize', DllStructGetSize($tagPROCESSENTRY32))

Local $avProcess32 = DllCall('Kernel32.dll', 'BOOL', 'Process32First', _
'HANDLE', $hSnapshot[0], _
'ptr', DllStructGetPtr($tagPROCESSENTRY32))

Local $iParentProcessId = 0
While (Not @error) And ($avProcess32[0])
If (DllStructGetData($tagPROCESSENTRY32, 'th32ProcessID') == $iProcessId) Then
$iParentProcessId = DllStructGetData($tagPROCESSENTRY32, 'th32ParentProcessID')
ExitLoop
EndIf

$avProcess32 = DllCall('Kernel32.dll', 'BOOL', 'Process32Next', _
'HANDLE', $hSnapshot[0], _
'ptr', DllStructGetPtr($tagPROCESSENTRY32))
WEnd

_WinAPI_CloseHandle($hSnapshot[0])

Return SetError(0, 0, $iParentProcessId)
EndFunc

SeDebugPrivilege: You will need this privilege before any attempt for opening some processes.

Func SeDebugPrivilege()
Local $iTokenIndex = 1
Local $Struct = DllStructCreate('DWORD;int')
Local $TOKEN_PRIVILEGES = DllStructCreate('DWORD;DWORD[' & (3 * 1) & ']')
DllStructSetData($TOKEN_PRIVILEGES, 1, 1)

While $iTokenIndex <= 1
Local $bPrivilegeValue = DllCall('advapi32.dll', _
'BOOL', 'LookupPrivilegeValue', _
'str', '', _
'str', 'SeDebugPrivilege', _ ;SE_DEBUG_NAME
'ptr', DllStructGetPtr($Struct))

If $bPrivilegeValue[0] Then
DllStructSetData($TOKEN_PRIVILEGES, 2, 0x00000002, (3 * $iTokenIndex)) ;SE_PRIVILEGE_ENABLED
DllStructSetData($TOKEN_PRIVILEGES, 2, DllStructGetData($Struct, 1), (3 * ($iTokenIndex - 1)) + 1)
DllStructSetData($TOKEN_PRIVILEGES, 2, DllStructGetData($Struct, 2), (3 * ($iTokenIndex - 1)) + 2)
DllStructSetData($Struct, 1, 0)
DllStructSetData($Struct, 2, 0)
EndIf

$iTokenIndex += 1
WEnd

Local $hCurrentProcess = DllCall('kernel32.dll', _
'HANDLE', 'GetCurrentProcess')

Local $hProcessToken = DllCall('advapi32.dll', _
'BOOL', 'OpenProcessToken', _
'HANDLE', $hCurrentProcess[0], _
'DWORD', 0x00000020 + 0x00000008, _ ;TOKEN_ADJUST_PRIVILEGES + TOKEN_QUERY
'HANDLE*', '')

Local $NEWTOKEN_PRIVILEGES = DllStructCreate('DWORD;DWORD[' & (3 * 1) & ']')

DllCall('advapi32.dll', _
'BOOL', 'AdjustTokenPrivileges', _
'HANDLE', $hProcessToken[3], _
'BOOL', False, _
'ptr', DllStructGetPtr($TOKEN_PRIVILEGES), _
'DWORD', DllStructGetSize($NEWTOKEN_PRIVILEGES), _
'ptr', '', _
'DWORD*', '')

DllCall('kernel32.dll', _
'BOOL', 'CloseHandle', _
'HANDLE', $hProcessToken[3])
EndFunc
Link to comment
Share on other sites

Edit: You have done _Address_CalculatePointer in a tricky way, I like how you did it.

Compared to NomadMemory, this function in particular is very optimized! You also don't need a 0 at the beginning of your offset array!

Link to comment
Share on other sites

I am confused about _Adress_CalculatePointer. Why did you decide to nuke and pave over the one member of $vfinaladdress repeatedly? Could you have just called _Process_ReadMemory on the last element of $aioffsets and then returned that?

Something like this (untested)?

Func _Address_CalculatePointer($ahhandle, $ivaddress, $aioffsets)
    Return _Process_ReadMemory($ahhandle, $ivaddress) + $aioffsets[UBound($aioffsets)]
EndFunc
Edited by jaberwocky6669
Link to comment
Share on other sites

I am confused about _Adress_CalculatePointer. Why did you decide to nuke and pave over the one member of $vfinaladdress repeatedly? Could you have just called _Process_ReadMemory on the last element of $aioffsets and then returned that?

Something like this (untested)?

Func _Address_CalculatePointer($ahhandle, $ivaddress, $aioffsets)
    Return _Process_ReadMemory($ahhandle, $ivaddress) + $aioffsets[UBound($aioffsets)]
EndFunc

When calculating a pointer, you must read the address, add an offset to that read value, and treat that new, combined value as an address. Then, you repeat the process for the rest of the offsets. The result is an address that you then read in your data type to retrieve the data you actually want.
Link to comment
Share on other sites

Let me explain, if it's what you are trying to understand.

For example, there is a variable named X, and there is another variable named Y and of course another one named Z.

When we are dealing with memory, we want a static address for our values (variable).

Let's think about those 3 variables. Imagine that X has a static address, it mean its address always is 0x00100000, but the address of Y and Z are different each time we run the target application.

A pointer, is some kind of variable that holds the address of another variable, simply it points to some where else.

In this example, X holds the address of Y and Y holds the address of Z. The final value that we want to access to is stored in Z and of course address of Z changes each time we run the target app, what to do now?

IT'S SIMPLE...

We read the content of address of X, it will be some address, something like 0x00150000, and then we read the content of 0x00150000, it will be an address again, maybe 0x00170000, and finally we read the content of 0x00170000 which is the actual value of Z.

I'm not sure if this is what you were talking about.

Link to comment
Share on other sites

  • 5 months later...

I'm not as learned as you guys in this and I'm having a lil trouble.

I'm trying to get a char[20] read from a pointer, when I use _Process_ReadMemory it does this:

C:Program Files (x86)AutoIt3IncludeKryMemory.au3 (158) : ==> Subscript used with non-Array variable.:
Local $ahCall = DllCall($ahHandle[0], "bool", "ReadProcessMemory", "handle", $ahHandle[1], "dword_ptr", $ivAddress, "ptr", DllStructGetPtr($vReadData), "ulong_ptr", DllStructGetSize($vReadData), "ptr", DllStructGetPtr($vNumberOfBytesRead))
Local $ahCall = DllCall($ahHandle^ ERROR
 
^ was a single read so I don't know why I would need an array.
 
I would use _Process_ReadMemoryPointer but I can't seem figure how the array should be laid out. Is it just [0] = 1st offset and so on? If it is then I musta done something else wrong.
 
Just a simple example would do me a world of good because I'm one of gods jokes a dyslexic person who likes to program.
Link to comment
Share on other sites

  • 3 weeks later...

 

I'm not as learned as you guys in this and I'm having a lil trouble.

I'm trying to get a char[20] read from a pointer, when I use _Process_ReadMemory it does this:

C:Program Files (x86)AutoIt3IncludeKryMemory.au3 (158) : ==> Subscript used with non-Array variable.:
Local $ahCall = DllCall($ahHandle[0], "bool", "ReadProcessMemory", "handle", $ahHandle[1], "dword_ptr", $ivAddress, "ptr", DllStructGetPtr($vReadData), "ulong_ptr", DllStructGetSize($vReadData), "ptr", DllStructGetPtr($vNumberOfBytesRead))
Local $ahCall = DllCall($ahHandle^ ERROR
 
^ was a single read so I don't know why I would need an array.
 
I would use _Process_ReadMemoryPointer but I can't seem figure how the array should be laid out. Is it just [0] = 1st offset and so on? If it is then I musta done something else wrong.
 
Just a simple example would do me a world of good because I'm one of gods jokes a dyslexic person who likes to program.

 

Make sure you have your function variables in the right place: 

_Process_ReadMemory($ahHandle, $ivAddress(, $sType))

reversed to nomad's:

_MemoryRead($iv_Address, $ah_Handle(, $sv_Type))

You'll get the error if any function call is set up incorrectly, so check your entire script.

It might just be me, but _Process_ReadMemoryPointer doesn't seem to work anyway.

Edited by neosporin
Link to comment
Share on other sites

  • 4 weeks later...

Thanks for the help.

I ended up using a mix of nomad and krymem to get it to work, but I am knee deep in it again and glad to got a reply. When ever possible I prefer using non-ethnic stereotype engineering in my programs so I hope this will take care of it.

P.S. For all those people out there that are gritting their teeth thinking "He's making a bot!" maybe you could say it is.. It's to read game chat to me because I miss out on so much in a game because I can't keep up wit the chat.

Nope same message maybe I got a bad copy of kry.

Edited by blaqmail
Link to comment
Share on other sites

Edit: manipulating notepad.exe memory violates forum rules.

Edited by crashdemons

My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

Link to comment
Share on other sites

so actually I mean when something is in plain text like hello world it seems to be in memory encoded with 16 bits and as such I have to search for h e l l o  w o r l d where the spaces in between are the 0x00 character. Are there any memorysearch function or do I have to code them myself based on reading chunks of memory

Link to comment
Share on other sites

  • 6 years later...

If the code runs under 64bit, then _Address_CalculatePointer returns only 32bit back. Here is my fix for this problem.

Func _Address_CalculatePointer($ahHandle, $ivAddress, $aiOffsets)
    Local $vFinalAddress = DllStructCreate("dword_ptr")
    DllStructSetData($vFinalAddress, 1, $ivAddress)
    For $iOffset In $aiOffsets
        ;DllStructSetData($vFinalAddress, 1, _Process_ReadMemory($ahHandle, DllStructGetData($vFinalAddress, 1)) + $iOffset)
        DllStructSetData($vFinalAddress, 1, _Process_ReadMemory($ahHandle, DllStructGetData($vFinalAddress, 1),"ptr") + $iOffset)
    Next
    Return DllStructGetData($vFinalAddress, 1)
EndFunc   ;==>_Address_CalculatePointer

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...