KryziK Posted January 12, 2013 Share Posted January 12, 2013 (edited) 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 DownloadDocumented 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 January 12, 2013 by KryziK mLipok, DungDajHjep and FireFox 2 1 Link to comment Share on other sites More sharing options...
FaridAgl Posted January 12, 2013 Share Posted January 12, 2013 (edited) 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 January 12, 2013 by D4RKON3 http://faridaghili.ir Link to comment Share on other sites More sharing options...
FaridAgl Posted January 12, 2013 Share Posted January 12, 2013 Some useful functions:ProcessGetParent: Gives the parent of a process.expandcollapse popup#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) EndFuncSeDebugPrivilege: You will need this privilege before any attempt for opening some processes.expandcollapse popupFunc 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 http://faridaghili.ir Link to comment Share on other sites More sharing options...
KryziK Posted January 12, 2013 Author Share Posted January 12, 2013 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 More sharing options...
jaberwacky Posted January 13, 2013 Share Posted January 13, 2013 (edited) 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 January 13, 2013 by jaberwocky6669 Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
KryziK Posted January 13, 2013 Author Share Posted January 13, 2013 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 More sharing options...
FaridAgl Posted January 13, 2013 Share Posted January 13, 2013 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. http://faridaghili.ir Link to comment Share on other sites More sharing options...
jaberwacky Posted January 14, 2013 Share Posted January 14, 2013 Oh, I see it now. Sheesh, Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
blaqmail Posted July 4, 2013 Share Posted July 4, 2013 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 More sharing options...
neosporin Posted July 22, 2013 Share Posted July 22, 2013 (edited) 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 July 22, 2013 by neosporin Link to comment Share on other sites More sharing options...
blaqmail Posted August 20, 2013 Share Posted August 20, 2013 (edited) 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 August 20, 2013 by blaqmail Link to comment Share on other sites More sharing options...
junkew Posted August 20, 2013 Share Posted August 20, 2013 (edited) interesting. Can someone share an example how to use this for example on notepad.exe 1. start notepad 2. type hello world 3. find the text hello world with readprocessmemory Edited August 20, 2013 by junkew FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
crashdemons Posted August 20, 2013 Share Posted August 20, 2013 (edited) Edit: manipulating notepad.exe memory violates forum rules. Edited August 20, 2013 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 More sharing options...
junkew Posted August 20, 2013 Share Posted August 20, 2013 From scite I added on first line #AutoIt3Wrapper_UseX64=Y and it works How did you know to look on address 0x000100E8? I assume this can be done on any process (as long as you have enough priveleges) to read the content. FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
junkew Posted August 20, 2013 Share Posted August 20, 2013 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 FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
Beonn Posted May 18, 2020 Share Posted May 18, 2020 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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now