Nomad Posted July 5, 2006 Author Share Posted July 5, 2006 Thanks, Ill do just that ^^, And once again, keep up the good work ^^Here, I was searching the net for some tutorials on stuff and decided to do a little work for you too:Cheat Engine Pointer Help #1Cheat Engine Pointer Help #2There's a lot to read in those topics (especially #2 ), and you might have to read it all to understand, but these should help you.Nomad Link to comment Share on other sites More sharing options...
AzKay Posted July 5, 2006 Share Posted July 5, 2006 Thanks ill read them ^^, Or try anyway. (( Are you saying we are you error-guineapigs ?! xD )) # MY LOVE FOR YOU... IS LIKE A TRUCK- # Link to comment Share on other sites More sharing options...
AzKay Posted July 5, 2006 Share Posted July 5, 2006 I have adapted these new memory functions in order to create a memory editor in AutoIt. Can anyone test this out with the Diablo II cheats to see if this works? CODE#include <GUIConstants.au3> $gui = GUICreate("AutoIt Memory Editor", 360, 280) Global $combo = GUICtrlCreateCombo("", 10, 10, 230, 20) _RefreshList() $open = GUICtrlCreateButton("Open", 250, 10, 45, 20) $refresh = GUICtrlCreateButton("Refresh", 305, 10, 45, 20) GUICtrlCreateGroup("Read", 5, 40, 350, 118) GUICtrlCreateLabel("Data Type", 10, 58, 60, 15) $rtype = GUICtrlCreateCombo("byte", 70, 55, 100, 20) GUICtrlSetData(-1, "ubyte|char|short|ushort|int|uint|dword|udword|ptr|float|double|int64|uint64") GUICtrlCreateLabel("Address", 10, 88, 60, 15) $raddress = GUICtrlCreateInput("0x00000000", 70, 85, 100, 20) $read = GUICtrlCreateButton("Read", 15, 120, 70, 20) $rclose = GUICtrlCreateButton("Close", 95, 120, 70, 20) $rdata = GUICtrlCreateEdit("", 180, 55, 170, 95) GUICtrlCreateGroup("Write", 5, 158, 350, 117) GUICtrlCreateLabel("Data Type", 10, 176, 60, 15) $wtype = GUICtrlCreateCombo("byte", 70, 173, 100, 20) GUICtrlSetData(-1, "ubyte|char|short|ushort|int|uint|dword|udword|ptr|float|double|int64|uint64") GUICtrlCreateLabel("Address", 10, 206, 60, 15) $waddress = GUICtrlCreateInput("0x00000000", 70, 203, 100, 20) $write = GUICtrlCreateButton("Write", 15, 238, 70, 20) $wclose = GUICtrlCreateButton("Close", 95, 238, 70, 20) $wdata = GUICtrlCreateEdit("", 180, 173, 170, 95) GUICtrlSetState($combo, $GUI_FOCUS) _Disable() GUISetState() $proc = 0 $mem = 0 While 1 $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE Exit Case $combo $proc = ProcessExists(GUICtrlRead($combo)) Case $refresh _RefreshList() Case $open $mem = _MemOpen($proc) If @error or $mem = 0 or $proc = 0 Then mError("Can't open process memory!") Else _Enable() EndIf Case $read _SizeOf(GUICtrlRead($rtype)) If @error Then mError("Wrong data type!") Else GUICtrlSetData($rdata, _MemRead($mem, GUICtrlRead($raddress), GUICtrlRead($rtype))) EndIf Case $rclose, $wclose _MemClose($mem) _Disable() Case $write _SizeOf(GUICtrlRead($wtype)) If @error Then mError("Wrong data type!") Else _MemWrite($mem, GUICtrlRead($waddress), GUICtrlRead($wdata), GUICtrlRead($wtype)) EndIf EndSwitch Sleep(0) WEnd Func mError($sText, $iFatal = 0, $sTitle = "Error", $iOpt = 0) Local $ret = MsgBox(48 + 4096 + 262144 + $iOpt, $sTitle, $sText) If $iFatal Then Exit Return $ret EndFunc Func _RefreshList() Local $ps = ProcessList(), $list = "" For $i = 1 to $ps[0][0] $list &= "|" & $ps[$i][0] Next GUICtrlSetData($combo, $list) GUISetState() EndFunc Func _Disable() GUICtrlSetState($rtype, $GUI_DISABLE) GUICtrlSetState($raddress, $GUI_DISABLE) GUICtrlSetState($read, $GUI_DISABLE) GUICtrlSetState($rclose, $GUI_DISABLE) GUICtrlSetState($rdata, $GUI_DISABLE) GUICtrlSetState($wtype, $GUI_DISABLE) GUICtrlSetState($waddress, $GUI_DISABLE) GUICtrlSetState($write, $GUI_DISABLE) GUICtrlSetState($wclose, $GUI_DISABLE) GUICtrlSetState($wdata, $GUI_DISABLE) GUISetState() EndFunc Func _Enable() GUICtrlSetState($rtype, $GUI_ENABLE) GUICtrlSetState($raddress, $GUI_ENABLE) GUICtrlSetState($read, $GUI_ENABLE) GUICtrlSetState($rclose, $GUI_ENABLE) GUICtrlSetState($rdata, $GUI_ENABLE) GUICtrlSetState($wtype, $GUI_ENABLE) GUICtrlSetState($waddress, $GUI_ENABLE) GUICtrlSetState($write, $GUI_ENABLE) GUICtrlSetState($wclose, $GUI_ENABLE) GUICtrlSetState($wdata, $GUI_ENABLE) GUISetState() EndFunc Func _MemOpen( $i_Pid, $i_Access = 0x1F0FFF, $i_Inherit = 0 ) Local $av_Return[2] = [DllOpen('kernel32.dll')] Local $ai_Handle = DllCall($av_Return[0], 'int', 'OpenProcess', 'int', $i_Access, 'int', $i_Inherit, 'int', $i_Pid) If @error Then DllClose($av_Return[0]) SetError(1) Return 0 EndIf $av_Return[1] = $ai_Handle[0] Return $av_Return EndFunc Func _MemRead( $ah_Mem, $i_Address, $s_Type = 'dword' ) If not IsArray($ah_Mem) Then SetError(1) Return '' EndIf Local $v_Struct = DllStructCreate($s_Type) DllCall($ah_Mem[0], 'int', 'ReadProcessMemory', 'int', $ah_Mem[1], 'int', $i_Address, 'ptr', DllStructGetPtr($v_Struct), 'int', DllStructGetSize($v_Struct), 'int', '') If @error Then SetError(1) Return '' EndIf Return DllStructGetData($v_Struct, 1, 1) EndFunc Func _MemWrite( $ah_Mem, $i_Address, $v_Data, $s_Type = 'dword' ) If not IsArray($ah_Mem) Then SetError(1) Return 0 EndIf Local $v_Struct = DllStructCreate($s_Type) DllStructSetData($v_Struct, 1, $v_Data, 1) DllCall($ah_Mem[0], 'int', 'WriteProcessMemory', 'int', $ah_Mem[1], 'int', $i_Address, 'ptr', DllStructGetPtr($v_Struct), 'int', DllStructGetSize($v_Struct), 'int', '') If not @error Then Return 1 Else SetError(1) Return 0 EndIf EndFunc Func _MemClose( $ah_Mem ) If not IsArray($ah_Mem) Then SetError(1) Return 0 EndIf DllCall($ah_Mem[0], 'int', 'CloseHandle', 'int', $ah_Mem[1]) If not @error Then DllClose($ah_Mem[0]) Return 1 Else DllClose($ah_Mem[0]) SetError(1) Return 0 EndIf EndFunc Func _SizeOf( $s_Type ) Local $v_Struct = DllStructCreate($s_Type), $i_Size = DllStructGetSize($v_Struct) $v_Struct = 0 Return $i_Size EndFuncVery kewl. Works, I tryed it on spider solitaire xD Now you gotta step it up a notch, and make a search function for it xD, Liek cheatengine. ( first scan you search 4byte and search the value 500, you move the card, your score is 499, you go and search 4byte 499, and it narrows down the addresses, then you can choose the one you want) That would be reall kewl ^^ # MY LOVE FOR YOU... IS LIKE A TRUCK- # Link to comment Share on other sites More sharing options...
Nomad Posted July 5, 2006 Author Share Posted July 5, 2006 Thanks ill read them ^^, Or try anyway.(( Are you saying we are you error-guineapigs ?! xD )) Of course, nothing better than a wide variety of users on a wide variety of platforms with a wide variety of uses for these functions to test out their functionality in all circumstances. Nomad Link to comment Share on other sites More sharing options...
AzKay Posted July 5, 2006 Share Posted July 5, 2006 /sob, wait, yay, im a guinea pig !~ # MY LOVE FOR YOU... IS LIKE A TRUCK- # Link to comment Share on other sites More sharing options...
erifash Posted July 6, 2006 Share Posted July 6, 2006 @erifash: Attach the source.Okay, isn't the codebox working?Memory_GUI.au3 My UDFs:_FilePrint() | _ProcessGetName() | _Degree() and _Radian()My Scripts:Drive Lock - Computer Lock Using a Flash DriveAU3Chat - Simple Multiuser TCP ChatroomStringChunk - Split a String Into Equal PartsAutoProxy - Custom Webserver Link to comment Share on other sites More sharing options...
Nomad Posted July 6, 2006 Author Share Posted July 6, 2006 (edited) Okay, isn't the codebox working? No, a copy and paste made the entire script 1 line for me, and I didn't want to spend an hour separating it all. Good work on this. I have a few suggestions though. 1) You should implement some kind of pointer support. For a lot of games you need to read a series of pointers to get to the desired address. I had to read an address, then add the offset to the value at that address, then convert it to hex and read it again, and again... 2) When I tried my Diablo II character name, I could only read 1 'char' and it was in decimal, not ASCII. I got 78 instead of 'N'. I tried putting [16] at the end of 'char' in the combo box, but it didn't work. 3) I assume you are using Windows 2000+. I can tell because the combo box drop down size is automatically adjusted for those OS. I'm on Windows 98 though, and it doesn't auto-size. So, with a setting of 20, the combo box will not drop down at all. I had to change it to 100. I prefer to use Windows 98 for AutoIt because if it works on Windows 98, it'll work on any Windows OS (usually). Once again, nice job on this. I've considered doing something like this, but I'm not sure if I will. Oh, and I didn't mess with the writing aspect of your script, but if I have time later I will. Nomad Edited July 6, 2006 by Nomad Link to comment Share on other sites More sharing options...
Nomad Posted July 6, 2006 Author Share Posted July 6, 2006 Ok, I just spent the last 4 hours testing out _MemoryPointerRead and _MemoryPointerWrite. After a few small adjustments, I'm confident that they are completely debugged. I have updated the first post with the latest functions. If you have any problems, or are unsure how to use them, post a reply here. Nomad Link to comment Share on other sites More sharing options...
Snarg Posted July 6, 2006 Share Posted July 6, 2006 In the Diablo II examples you named the funcitons incorrectly. Example: Local $DllInformation = _MemOpen($ProcessID)oÝ÷ Ù(hºW[y«¢+Ù1½°ÀÌØí±±%¹½ÉµÑ¥½¸ô}5µ½Éå=Á¸ ÀÌØíAɽÍÍ% It's a small thing but it could generate a lot of useless questions. A little reading goes a long way. Post count means nothing. Link to comment Share on other sites More sharing options...
Nomad Posted July 6, 2006 Author Share Posted July 6, 2006 (edited) In the Diablo II examples you named the funcitons incorrectly. Example: Local $DllInformation = _MemOpen($ProcessID)oÝ÷ Ù(hºW[y«¢+Ù1½°ÀÌØí±±%¹½ÉµÑ¥½¸ô}5µ½Éå=Á¸ ÀÌØíAɽÍÍ% It's a small thing but it could generate a lot of useless questions. Thanks. I renamed the functions but didn't update the D2 examples, forgot. Edited July 6, 2006 by Nomad Link to comment Share on other sites More sharing options...
AzKay Posted July 6, 2006 Share Posted July 6, 2006 Nice, Ill be back when I test out the pointer read & write =P # MY LOVE FOR YOU... IS LIKE A TRUCK- # Link to comment Share on other sites More sharing options...
AzKay Posted July 6, 2006 Share Posted July 6, 2006 Nice, Ill be back when I test out the pointer read & write =PHmm, If by the time im completly familiar with your memory udf, and you havnt made one, I should make a help file well, *try* # MY LOVE FOR YOU... IS LIKE A TRUCK- # Link to comment Share on other sites More sharing options...
Nomad Posted July 6, 2006 Author Share Posted July 6, 2006 Hmm, If by the time im completly familiar with your memory udf, and you havnt made one, I should make a help file well, *try* I already have, so I can submit these for inclusion in the beta. I'm just wanting to make sure the functions are completely debugged first. I suppose I could attach them to the first post if necessary.Nomad Link to comment Share on other sites More sharing options...
AzKay Posted July 6, 2006 Share Posted July 6, 2006 Ah, well, good work =D # MY LOVE FOR YOU... IS LIKE A TRUCK- # Link to comment Share on other sites More sharing options...
Styler001 Posted July 7, 2006 Share Posted July 7, 2006 I'm not sure if this is the right place to post this, or if there's a better forum to do it in, but here goes.... I'm trying to use a slightly modified version of JoshDB's example from another thread to read the values in a couple of memory addresses in Knight Online. As of this moment, I know the addresses I'll give are correct since I just checked them again and I get the expected results using TSearch. The problem I'm having is that I'm expecting to receive values of 1211 for MaxHealth and 1109 for CurrentHealth. But, I get 0 for both. I'm extremely nooby at this part of AutoIt, so I'm pretty sure I'm doing something extremely stupid. I've tried w0uter's and Nomad's functions and get the same results with both, and the last time I tried, I was using Nomad's latest versions. Anyway, here is JoshDB's original code: Func Health() $h_open = _MemOpen($pid) $currentHealth = Int(_MemRead($h_open,IniRead("SLB.ini","memory","currentHealth",0),4)) $maxHealth = Int(_MemRead($h_open,IniRead("SLB.ini","memory","maxHealth",0),4)) $Healthpercent = $currentHealth/$maxHealth*100 _MemClose($h_open) Return $Healthpercent EndFuncoÝ÷ Ù(§q涬¦§´ýz-æx®H~)^#ozjøv¬r^¶ayú%"§v·¦¢÷¶´ß¡Þj[a=êÜz{lw#f¢yr¶¼¢h±ç¢|§-¹©eÉø§vØ^½©nzÂ7öih¢H§ú+"¯zÚâyÛاØ^½©nzÊÞqè¯yÛh6^¥§ZÛajÝý²0"IèÀý¶)àÒ)ìµæ¡ýv×V§w]tô Ý"¯zfzË«zØZ¶+b²z-ën®x§FÞq«¬zæyתâazf¬Ðý½ç^rV«yÛazf趽©nzÊ-êí©ôjwl¶)eç÷´ßÛ¢»az·¬º[l#f²êÞÊ·öYZÊ'¢ØzØZ¶Ø^謮¢Ø§r[z«¨µú+6wl~éܶ*'±8Z·lmçºÇ¢ºâg£7ö÷¢Énuçmé¢Øb±Êy«¢+ØÀÌØíÁ¥ô]¥¹ÑAɽÍÌ ÅÕ½Ðí-¹¥¡Ñ=¹±¥¹¹áÅÕ½Ðì¤(ÀÌØí5á!±Ñ ôÀ(ÀÌØí ÕÉɹÑ!±Ñ ôÀ() ±° ÅÕ½Ðí!±Ñ ÅÕ½Ðì¤)]¥¹Ñ¥ÙÑ ÅÕ½ÐíU¹Ñ¥Ñ±´9½ÑÁÅÕ½Ðì¤)M¹ ÅÕ½ÐìÀÌØí5á!±Ñ ôÅÕ½ÐìµÀìÀÌØí5á!±Ñ µÀì I1¤$)M¹ ÅÕ½ÐìÀÌØí ÕÉɹÑ!±Ñ ôÅÕ½ÐìµÀìÀÌØí ÕÉɹÑ!±Ñ µÀì I1¤()Õ¹!±Ñ ¤(ÀÌØí¡}½Á¸ô}5µ½Éå=Á¸ ÀÌØíÁ¥¤(ÀÌØí ÕÉɹÑ!±Ñ ô%¹Ð¡}5µ½ÉåI ÀÌØí¡}½Á¸°ÁàÁÁÕÀ°Ð¤¤(ÀÌØí5á!±Ñ ô%¹Ð¡}5µ½ÉåI ÀÌØí¡}½Á¸°ÁàÁÁÔå°Ð¤¤(}5µ½Éå ±½Í ÀÌØí¡}½Á¸¤((%IÑÕɸÀÌØí ÕÉɹÑ!±Ñ (%IÑÕɸÀÌØí5á!±Ñ )¹Õ¹ I've been agonizing over this for a few days and can't seem to see where my problem lies. But, like I said, it's probably a stupid error on my part. I don't know if the problem is because AutoIt has problems reading addresses from Knight Online. Others using ACTool have been able to get this to work, but ACTool is way to primitive when compared to AutoIt to even consider using anymore. If you guys can help, I'd really appreciate it. Link to comment Share on other sites More sharing options...
Nomad Posted July 7, 2006 Author Share Posted July 7, 2006 (edited) I'm not sure if this is the right place to post this, or if there's a better forum to do it in, but here goes.... I'm trying to use a slightly modified version of JoshDB's example from another thread to read the values in a couple of memory addresses in Knight Online. As of this moment, I know the addresses I'll give are correct since I just checked them again and I get the expected results using TSearch. $pid = WinGetProcess ("KnightOnline.exe") $MaxHealth = 0 $CurrentHealth = 0 Call ("Health") WinActivate ("Untitled - Notepad") Send ("$MaxHealth = " & $MaxHealth & @CRLF) Send ("$CurrentHealth = " & $CurrentHealth & @CRLF) Func Health() $h_open = _MemoryOpen($pid) $CurrentHealth = Int (_MemoryRead ($h_open, 0x0A0EC5A0, 4)) $MaxHealth = Int (_MemoryRead ($h_open, 0x0A0EC59C, 4)) _MemoryClose ($h_open) Return $CurrentHealth Return $MaxHealth EndFunc Next time don't spend days with a problem like this. If it's a problem caused by your syntax, I can help. If it's a problem caused by improper addresses, I can't help. But if it's a problem caused by me, I want to know about it. Also, the reason you were getting 0 is because that is what any of my functions return if they have an error, which they did because you were sending the $ah_Handle returned from _MemoryOpen as the address for _MemoryRead, and sending the address as $ah_Handle. The _MemoryRead functions were throwing an error right from the get go. @Error checked at 1 which as stated in the header is: Invalid $ah_Handle. Don't take this the wrong way, I'm just pointing out what you could've done to help solve this. Always check the error messages when things aren't working correctly. Nomad Edit: hmm, having problems posting... Edited July 7, 2006 by Nomad Link to comment Share on other sites More sharing options...
Nomad Posted July 7, 2006 Author Share Posted July 7, 2006 (edited) Updated the first post with the newest version of the include file, examples, and help files. The help files are in the format for UDF submission, I think, which is why there is a lot of extra 'stuff' in them. I added the 2 new pointer functions to the include file and also added another return value to them. Now they both return the destination address ($Array[0] for _MemoryPointerRead) and _MemoryPointerRead returns the value stored there, $Array[1]. This was done for obvious reasons. Also note that the $av_Offset structure has changed. $av_Offset[0] is no longer used, you may need to update any scripts using this function. Hopefully this will be the last time I need to update. But I'm sure I'll find another reason at some point to make another update. I'm already having thoughts for another improvement... Enjoy, Nomad Edited July 7, 2006 by Nomad Link to comment Share on other sites More sharing options...
Styler001 Posted July 7, 2006 Share Posted July 7, 2006 Sorry I didn't post this earlier, but the board was having brainfarts last night and wouldn't let me reply. Sorry for not saying something about this sooner. It's just that the last time I asked for help here (not from you) I got reemed because the guy assumed I wasn't willing to do any of the work myself. He asked questions and I answered them, and he assumed. So I was a little leary of asking this time because I'm using your memory functions (which, while I don't understand them fully, I do understand the concept of what they are supposed to be doing), and I'm using JoshDB's[\u] snippet that I modified (incorrectly, as I had a feeling). So, neither of these are anything that I've personally put alot of time into like you and Josh have. I guess I'm just a little gunshy now. Anyway, I tried your corrections, but still got the same results of 0. I'm attaching a screenshot of the TSearch screen showing the process at the top that it's using, as well as the memory addresses and their values. The little graphic below the TSearch screenshot is the health bar (red) with the 1109/1211 showing what I'm looking for. After the first wrong results, I looked at your modifications and noticed that you hadn't included the Call ("Health"), so I included that, but still got the same results anyway. I also removed the "include" command since I am still just including the _MemoryOpen, _MemoryRead, and _MemoryClose functions directly in the script at this time. Other than those two changes, I haven't made any other modifications to it. But, like I said, I still got the same results with or without the Call ("Health"). I was wondering if the $pid would have anything to do with the problem? I've seen different values for that, but couldn't really tell if there would be a benefit to using ProcessExists instead of WinGetProcess, since they both just seem to return the PID. One more question...Doesn't declaring $Health as a local variable in the Health function limit its use outside of the function? I had thought that you couldn't pass a local variable outside of its function. I guess I'm a little confused since it was declared globally at the beginning, then locally in the function. Link to comment Share on other sites More sharing options...
Nomad Posted July 7, 2006 Author Share Posted July 7, 2006 Don't worry about asking me for help, I don't mind as long as it pertains to something directly related to my scripts. I don't have the time, or patience, to try and help anyone find the addresses to use these functions, but that also doesn't directly apply to my functions. Your questions so far are directly related to the use of my functions and I want to be sure everyone knows how to use them properly. Getting the information needed to use them is your responsibility though. After the first wrong results, I looked at your modifications and noticed that you hadn't included the Call ("Health"), so I included that, but still got the same results anyway. I also removed the "include" command since I am still just including the _MemoryOpen, _MemoryRead, and _MemoryClose functions directly in the script at this time. Other than those two changes, I haven't made any other modifications to it. But, like I said, I still got the same results with or without the Call ("Health").That shouldn't effect any of your readings anyway. Also, I don't use the Call function to call my functions, in AutoIt you don't need it. But you can use it if you prefer. I was wondering if the $pid would have anything to do with the problem? I've seen different values for that, but couldn't really tell if there would be a benefit to using ProcessExists instead of WinGetProcess, since they both just seem to return the PID.Yes, if the process ID is incorrect then you are going to get a return value of 0 since the _MemoryOpen function is not finding the process. Try this to see if you are finding the process correctly, sometimes the name you see in the task manager is not the correct process name to enter:$pid = WinGetProcess ("windowname") If $pid = -1 Then MsgBox(4096, "ERROR", "The process doesn't exist") EndIfoÝ÷ Øí«ç$²¢Kazw!yÉ-á+®ß¢·rîËb¢{-j»b"¶ò:§bjwh¶)¶¬jëh×6$h_open = _MemoryOpen($pid) If @Error Then MsgBox(4096, "_MemoryOpen", "_MemoryOpen @Error = " & @Error) EndIf $CurrentHealth = _MemoryRead (0xA0EC5A0, $h_open) If @Error Then MsgBox(4096, "_MemoryRead", "_MemoryRead @Error = " & @Error) EndIfoÝ÷ Ù8^È^rKaz{¦mêâØ^æz·è®Ø^~éܶ*'Ö©¦X²ÚÛ{Z¶Ø^zºè®Z ±¬¬Ì+¢x*º^© So $Health = the return value of the function, which was the local value for $Health within the function. I hope that's clear, hehe. Nomad Link to comment Share on other sites More sharing options...
Styler001 Posted July 7, 2006 Share Posted July 7, 2006 (edited) Thanks, Nomad. I'll get those checks put in place and give this another shot later this evening (Pacific time zone). And, yes, your explanations all made sense. I'm just a little confused about not having to use Call. Is the $Health=Health() how the Health function is called? Edited July 7, 2006 by Styler001 Link to comment Share on other sites More sharing options...
Recommended Posts