The Cache: Technology Expert's Forum
 
*
Welcome, Guest. Please login or register. September 21, 2019, 05:59:55 AM

Login with username, password and session length


Pages: [1]
  Print  
Author Topic: Memory reading question  (Read 4671 times)
vsloathe
vim ftw!
Global Moderator
Lifer
*****
Offline Offline

Posts: 1669



View Profile
« on: September 09, 2007, 10:05:17 AM »

A little background - I'm writing a bot for a game. Auto-leveling type bot not to use, but because I see a pretty big niche and think I can sell it.

So I have a memory reading library that lets me open up the memory of any process handle (as long as I run it with admin privs obviously). The library lets me read the data from one memory address at a time, so here is my dilemma:

Due to DMA, the memory address of some of the data I want changes with every instance of the game (every time you relog or reopen the game). I can go through the memory and manually get the address each time with a program like CheatEngine or TSearch, but the problem is that this obviously isn't going to work, since I can't have the user manually search for the addresses each time...I was wondering if anyone had any idea how to loop through a memory region and search for a particular "known", and grab the address? If I have the address of one part of the memory region, I have everything, since the structure in memory stays the same, the base address just changes.

Thanks,
-V
Logged

hai
m0nkeymafia
Expert
****
Offline Offline

Posts: 240


Check it!


View Profile
« Reply #1 on: September 09, 2007, 01:16:10 PM »

do you know what to look for as the pattern of the start of the memory you want?

i dont know the start address of memory location, but you could try loop through all memory [starting from the start] and then try match the data there with the pattern your looking for.  you could alternatively allocate a big lump of memory then iterate backwards, but thats nasty.
thats all i can come up with lol, im sure someone else has a better idea Shocked
Logged

I am Tyler Durden
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #2 on: September 09, 2007, 01:32:11 PM »

dunno about a better idea... it is sort of a virus-scanner approach. Don't know how else you could do it, really.
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
nop_90
Global Moderator
Lifer
*****
Offline Offline

Posts: 2203


View Profile
« Reply #3 on: September 09, 2007, 05:31:17 PM »

I have been out of the scene for ages.
i am guessing u are using the MS debug API to read the memory.

but a good place to start is here
http://win32assembly.online.fr/tutorials.html

to allow the segments of the written to you have to change the flags in the PE header,
(you can change segment to read/write/exe etc)

since memory is mapped
virtual memory => physical

the technique i saw was to set index register to address start approx to scan.
wrap in exception handler like show here http://win32assembly.online.fr/Exceptionhandling.html
then scan for bytes, if crashes assembler exception handler catches it, advance set ammount of bytes (2000 lets say) repeat.

a good place to start is here
http://www.woodmann.com/forum/

Investigate the legality of what u are doing Smiley.
Strange that law authorities seem to be more concerned of guys who release cracks etc, then people who make child porn, process the payments for child porn etc.
i guess child porn does not affect buisness intrests
Logged
vsloathe
vim ftw!
Global Moderator
Lifer
*****
Offline Offline

Posts: 1669



View Profile
« Reply #4 on: September 10, 2007, 07:27:12 AM »

As far as I know it's legal, or at least in a legal gray area (they could sue, but you hire a lawyer to write your ToS and make sure that you can legally say "all copyrights owned by so and so, I'm not responsible for what users of the software do, you can't use this if you work for so and so").

Anyway, the library I am using has a function to set the debug level so I would assume that it hooks MS's debug API. The memory read function looks like this:

_MemoryRead($address,$DLLHandle,[$type=dword])

It returns data in the format specified in $type (int, bool, float, char, decimal dword) from $address using the process handle to an opened section of memory $DLLHandle.

Usually I am looking for a known number, like for instance mana (I can actually OCR the points of mana or HP from the screen but it's slow) - so I scan for that number, record addresses that have it in an array, cast a spell, and then loop through the array to see which addresses contain data that changed...so on and so forth until I have the address for mana. The address for health is then [mana address] - 0x4 (4 hex bytes).

The problem with looping through and scanning the memory is that it takes SO LONG so I was wondering if anyone knew a way to do it faster.
Logged

hai
vsloathe
vim ftw!
Global Moderator
Lifer
*****
Offline Offline

Posts: 1669



View Profile
« Reply #5 on: September 10, 2007, 06:03:40 PM »

I have part of my solution worked out so I'll post it here. The code might look a little convoluted to some of you because it's written in AutoItScript. I've been using AutoItScript for bot development because it's so well suited to that purpose (lots of really finite control over windows and objects without having to get my hands too dirty, and good ability to plug in COM objects too).

Here goes:
Code:
Const $uniquePatternOffset=0x374
Const $uniquePatternValue=0x007D0A7C
Const $uniquePatternOffset2=4
Const $uniquePatternValue2=3

Const $CurrentHealthOffset=0x4c0
Const $MaxHealthOffset=0x4D8
Const $CurrentManaOffset=0x4c4
Const $MaxManaOffset=0x4Dc
Const $OffsetSearchStep=0x1000
Const $maxSearchableMemory=0x70000000
Const $startSearchableMemory=0x400000

HotKeySet("^+!{ESC}","Abort") ; Ctrl Shift Alt {Esc}

SetPrivilege("SeDebugPrivilege", 1)
$handle = _MemOpen()

$offsets=findplayerdataoffset($handle)

Func findplayerdataoffset($handle)
$baseOffset=$startSearchableMemory
$baseOffset+=$uniquePatternOffset

$timerStart=TimerInit()

TrayTip("Begin Search. ","Looking for base offset.",2,1)
While $baseOffset<$maxSearchableMemory
$value=_WoWMemRead($baseOffset,$handle,'dword')
If $value=$uniquePatternValue  Then
If _WoWMemRead($baseOffset-$uniquePatternOffset2,$handle,'dword')=$uniquePatternValue2 Then
$baseOffset-=$uniquePatternOffset      ; Found our offset.  Put offset back to xxxxx000
TrayTip("Found Location. ",Hex($baseOffset)&" "&Floor(TimerDiff($timerStart)/1000)&" seconds.",2,1)
Dim $dataarray
$dataarray=_ArrayCreate($baseOffset+$CurrentHealthOffset,$baseOffset+$MaxHealthOffset,$baseOffset+$CurrentManaOffset,$baseOffset+$MaxManaOffset)
Return $dataarray
ExitLoop
EndIf
EndIf
$baseOffset+=$OffsetSearchStep
WEnd
EndFunc


_MemClose($handle)

A couple of the functions like _MemClose() and _MemOpen() are just reusable pieces I wrote so I wouldn't have to go through the headache of changing the text by which the process handle is gotten should the game developer ever decide to change it (which they frequently do), but merely change the value of one global variable.

Anyway, it might seem unintelligible to you, and I myself have trouble understanding memory addressing and pointers at times still, but that's what I've come up with so far. That returns the player's health, max health, mana, and max mana. I'm now working on returning all objects near the player (monsters to kill) in an array, because I already can rotate the player towards a location using some math functions and the data on each monster contains its XYZ coords.

EDIT: forgot to make it actually do something.
« Last Edit: September 11, 2007, 06:22:55 AM by vsloathe » Logged

hai
vsloathe
vim ftw!
Global Moderator
Lifer
*****
Offline Offline

Posts: 1669



View Profile
« Reply #6 on: September 11, 2007, 01:43:56 PM »

Cool, I figured out that the base array pointer that contains the PlayerID is 0x468 hex bytes up from the location of the "known" that my scanner locates.

I've roughly identified the location of some components of the memory struct that contains player data like so (add each offset to the location of the base pointer, 0x468 bytes up from the known that I locate):

+0x00 player ID - 8 bytes integer
+0x10 - x - float
+0x14 - y - float
+0x18 - z - float
+0x1C - horizontal direction - float (0 ... 2*PI)
+0x20 - vertical direction - float (-PI/2 ... PI/2)
+0x30 ->(4 bytes address, pointer to another structure) +0x58 health - 4 bytes integer
+0x30 -> +0x5C mana - 4 bytes integer
+0x40 target ID - 8 bytes integer
+0x58 health - 4 bytes integer
+0x5C mana - 4 bytes integer

In case anyone is interested.

I think I can do a decent job of finding monsters to kill using the target ID.
Logged

hai
m0nkeymafia
Expert
****
Offline Offline

Posts: 240


Check it!


View Profile
« Reply #7 on: September 11, 2007, 02:09:20 PM »

nice one dude good find!
Logged

I am Tyler Durden
vsloathe
vim ftw!
Global Moderator
Lifer
*****
Offline Offline

Posts: 1669



View Profile
« Reply #8 on: September 12, 2007, 06:35:59 AM »

Yeah by the time I'm done this I'm going to be the resident expert on game memory reading. lol
Logged

hai
Pages: [1]
  Print  
 
Jump to:  

Perkiset's Place Home   Best of The Cache   phpMyIDE: MySQL Stored Procedures, Functions & Triggers
Politics @ Perkiset's   Pinkhat's Perspective   
cache
mart
coder
programmers
ajax
php
javascript
Powered by MySQL Powered by PHP Powered by SMF 1.1.2 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks


Valid XHTML 1.0! Valid CSS!