CO2 Memory Addresses and Examples

12/02/2006 09:05 ColdStart#1
Not long ago there was a topic, that died, containing multiple static memory addresses. Some of these addresses were changed or offset by a bit. Some of the ones I found weren't even listed. I have begun to compile a massive list of static and dynamic memory addresses for different variables/properties.

This is really meant for programmers, macro/bot makers, and maybe even the guys at TQ, since these would probably have little to no use or meaning for you otherwise.

Below I will list the currently found Static and Dynamic Memory Addresses in two separate categories/code sections.
The formats for Static and Dynamic Addresses are different only by a little but each format will be listed outside and above the code list containing the addresses.
If there are any exceptions or rules of usage for a particular address a marker of EXCEPTION, UNCONFIRMED, RULE will appear after a C++/C comment mark "//" with a reason for the marker. If unconfirmed, try to confirm it as false or true and it will be eliminated or kept.

The type "Int" may be replaced with "Long" as they are both 4 byte numeric indicators. The type "Char" is of course a string of characters/bytes. Later, examples will show the use of these descriptors, types, and addresses.

STATIC
Static addresses are display in the format of "ADDRESS = DESCRIPTION/PROPERTY (TYPE)"
ADDRESS being the Hexadecimal form (without the 0x indicator) of an address pointer. DESCRIPTION/PROPERTY being the small description of a property or variable. TYPE being the type of variable the pointer relates to, such as a string or an integer.
Code:
Last Checked on 4-December-2006 for Patch 4329

004FF40C = Amount of Items (Int)
004FF1E0 = Gold (Int)
004FE53C = Char Pos X (Int)
004FE540 = Char Pos Y (Int)
004FE484 = Char Name (Char)
00501E00 = Ping (Int)
00502B30 = Map ID (Int)
00502D48 = Map Name (Char)
00502464 = Server Name (Char)
00502568 = Login Name (Char)
004FEFCC = Char Level (Int) 
004FEC84 = Spouse (Char) // UNCONFIRMED: I no longer have a spouse
004FF1C8 = Kill Counter (Int)
004FEFEC = PK Points (Int)
004FEFE8 = EXP (Int)
004FF018 = Virtue Points (Int)
004FEC94 = Strength (Int)
004FECA0 = Vitality (Int)
004FEC9C = Agility (Int)
004FECA4 = Spirit (Int)
004FEFC4 = Stamina (Int)
0051970C = Number of Speedarrowpacks in Inventory (Int) // UNCONFIRMED: I do not own an archer
01540620 = Number of Equipped Arrows (Int) // UNCONFIRMED: I do not own an archer.
DYNAMIC
Dynamic addresses are display in the format of "(0xBASE + OFFSET) = DESCRIPTION/PROPERTY (TYPE)"
BASE is the Hexadecimal form (with the 0x indicator) of a static address pointer that contains a dynamic base pointer address. OFFSET is an optional offset in Decimal form that offsets (by addition) the contained dynamic base pointer within the BASE. The address the BASE contains plus the OFFSET equals the address pointer of the desired variable/property. DESCRIPTION/PROPERTY being the small description of a property or variable. TYPE being the type of variable the pointer relates to, such as a string or an integer.
Code:
Last Checked on 4-December-2006 for Patch 4329

(0x004FF1B8 + 24) = Char HP // UNCONFIRMED: No longer can find HP as dynamic at this pointer or with TSearch
Feel free to contribute to this list!


[Only registered and activated users can see links. Click Here To Register...]

Code Examples
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
12/03/2006 02:09 ColdStart#2
Here is the incredibly simplified and easy method to obtain static address pointers that lead to the dynamic addresses.

This requires TSearch (see Attachment) and [Only registered and activated users can see links. Click Here To Register...].
Once you have both of these tools ready, you can get started with Conquer...

All links/underlined text within the tutorial lead to descriptive images and screenshots to help you.


Note that in this tutorial/example I will be looking for a static pointer for Character HP.

Finding Static Pointers

1. Open up TSearch and click the [Only registered and activated users can see links. Click Here To Register...] and [Only registered and activated users can see links. Click Here To Register...] buttons
Two new panels will show up within the window

2. Open up Conquer 2.0 and (optionally) login.

3. Go back to TSearch and [Only registered and activated users can see links. Click Here To Register...]
"Conquer.exe" will now be the executable TSearch works with

4. Click the [Only registered and activated users can see links. Click Here To Register...]
A dialog titled "Search" will appear

5. [Only registered and activated users can see links. Click Here To Register...]
In this example, this would be your current HP which is a Type of "4 Bytes" or an integer

6. TSearch will search for results matching the value and return [Only registered and activated users can see links. Click Here To Register...]
If you get 0 or no results then the value has changed since you last searched, start back at step 4, since we are working with HP, you probably were healed or hit

7. There is generally more than one result, which means you have to filter these results to get the real value and address
In order to filter this you will have to go back into the game and get the value to change, since you are working with HP go get attacked or use an HP potion, then get your new current HP

8. To filter these results you will use the [Only registered and activated users can see links. Click Here To Register...]
When you use the "Search next" feature, a dialog titled "Search Next" will appear

9. Do as you did in step 5 but use your new and changed current HP as the Value
Continue as you did from step 5 to step 6, this time however you should only have [Only registered and activated users can see links. Click Here To Register...]
If you don't only have one result, continue repeating steps 7-9 until you have only one result


10. You now have the [Only registered and activated users can see links. Click Here To Register...] of the property/variable
For later use you should copy down a padded 4 Byte/8 Hex Digit address, so if you had the address 584760 you would need make it 00584760
This address will be different for everyone because it is, after all, dynamic


11. Open up MemHack Pro, but leave TSearch open for later use
A [Only registered and activated users can see links. Click Here To Register...] will appear on MemHack Pro's startup, just close it

12. Under the File menu select [Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...] will appear

13. Scroll until you see "Conquer.exe", click it, and then click the [Only registered and activated users can see links. Click Here To Register...]
"Conquer.exe" will now be the executable MemHack Pro works with

14. Under the Search menu select [Only registered and activated users can see links. Click Here To Register...]
A dialog titled "Pointer Search" will appear

15. Set the Search Type to "Range"
[Only registered and activated users can see links. Click Here To Register...]. Take the padded address you got from step 10,set the last 5 Hex Digits to 0, and place it in the the first field, "Points Between"
[Only registered and activated users can see links. Click Here To Register...]. Take the padded address you got from step 10 and place it in the the second field, "And"
[Only registered and activated users can see links. Click Here To Register...]. Check "Only Find Static Pointers" so that we only find pointers that are static (the same) for everyone
[Only registered and activated users can see links. Click Here To Register...]. Check "Save Offset From" and in the field below it put in the padded address you got from step 10
This will find all static pointers pointing to the address from step 10 within the general range from the "category" address to the address itself and set the results to show the difference/offset from the original address from step 10
A progress bar will run until it is finished searching and a dialog will pop up saying it is finish, just click out of it and go back to the main window


16. Click on the [Only registered and activated users can see links. Click Here To Register...] in the main window's toolbar
A dialog titled "Found Addresses" will appear

17. The most reliable static base pointer generally is the closest one from the dynamic address, to quickly find it click the [Only registered and activated users can see links. Click Here To Register...]
Although generally this is the case, it may not be reliable, later you will test the reliability

18. [Only registered and activated users can see links. Click Here To Register...]

19. In the same row as the "base" you will see a negative Hex and Decimal distance, [Only registered and activated users can see links. Click Here To Register...]

Verifying

20. Go back to TSearch and click the [Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...] will appear

21. Enter the "base" address into the Address field, set the Type to 4 Bytes, and click OK

22. [Only registered and activated users can see links. Click Here To Register...]
This value should be the address of the dynamic pointer without the offset

23. Add the offset as a positive decimal to this value
[Only registered and activated users can see links. Click Here To Register...]. Under the converter set the Data Type to "long"
[Only registered and activated users can see links. Click Here To Register...]. Enter the value from step 23
[Only registered and activated users can see links. Click Here To Register...]. Copy the Hex value
This Hex value should be the address of your HP

24. Add a new cheat as you did in steps 20-21 but [Only registered and activated users can see links. Click Here To Register...]

25. Within the cheat list should be the dynamic address with a value equal to the property/variable you were looking for
In this example, this should be your HP

26. If this is not equal to the property/variable you were looking for, somewhere among these steps you made a mistake, backtrack every step until you find your mistake and start back from there
If you are checking reliability, then it is likely to be unreliable

Reliability

You have a verified static "base" pointer and "offset" to get the address of the dynamic property/variable, but it may not be reliable for everyone now you can post your static "base" pointer and "offset" in this topic for others to check reliabilty and state that it needs to be checked or restart your computer and check the reliability yourself then post your static "base" "pointer" and state that it has been checked

27. To check the reliability do steps 20-26 with the given static "base" pointer and offset

28. If it is not reliable then repeat this entire process and try to find the next closest offset
12/03/2006 02:35 yokoyoko#3
nice B)

would you show me how to check memory values in autohotkey? i.e i'll use dllcall(). I'll get the PID, use openprocessmemory, readprocessmemory? then what?
12/03/2006 02:44 ColdStart#4
Quote:
Originally posted by yokoyoko@Dec 2 2006, 20:35
nice B)

would you show me how to check memory values in autohotkey? i.e i'll use dllcall(). I'll get the PID, use openprocessmemory, readprocessmemory? then what?
I personally do not know AutoHotKey, but I will try to whip up a quick script based on their Help files. I should have it done within an hour or two.
12/03/2006 02:51 yokoyoko#5
ok thank you so much i'll check back an hour or two :) and obviously +k for you when u'r done ^^

autohotkey can only work with dllcalls for memory processing...

also i'm planning on learning a programming languague to make bots (instead of macros. ) What do you recommend? I already know javascript and php, little bit of perl and sql stuff. and i want to learn whatever is the quickest possible.

basically what I need to do is to capture/read/send packets, and perhaps get an understanding of the game structure and perform in game functions such as jumping (w/o window activated. )

WOW, just realized I needed everything, lol i'm such a noob
12/03/2006 03:28 ColdStart#6
Quote:
Originally posted by yokoyoko@Dec 2 2006, 20:51
ok thank you so much i'll check back an hour or two :) and obviously +k for you when u'r done ^^

autohotkey can only work with dllcalls for memory processing...

also i'm planning on learning a programming languague to make bots (instead of macros. ) What do you recommend? I already know javascript and php, little bit of perl and sql stuff. and i want to learn whatever is the quickest possible.

basically what I need to do is to capture/read/send packets, and perhaps get an understanding of the game structure and perform in game functions such as jumping (w/o window activated. )

WOW, just realized I needed everything, lol i'm such a noob
Since you already know JavaScript and PHP, I would think your best choice for bots would be C++ or C#. Generally most bots don't actually handle packets, they generally monitor memory and use DLL injecting/codecaving to execute in-game functions. To figure out codecaving and DLL injection methods, you need a pretty solid knowledge of ASM (aka x86 assembly language), a good disassembler, and a good debugger.

C++ is better for inline assembly code, but C# makes it a bit of a hassle. C# also lacks many interfaces to DLLs that C++ already has written for.

Creating a bot is much harder since you really need to work with the core components of the executable and application memory.
12/03/2006 03:43 yokoyoko#7
So i should learn C++? i heard it's way harder than C#, because of the inheritance and stuff, but oh well

ASM doesn't seem too hard, just hardcore

Will HLA (high level assembly) work in this case? they're easier to learn.
12/03/2006 04:08 ColdStart#8
Quote:
Originally posted by yokoyoko@Dec 2 2006, 21:43
So i should learn C++? i heard it's way harder than C#, because of the inheritance and stuff, but oh well

ASM doesn't seem too hard, just hardcore

Will HLA (high level assembly) work in this case? they're easier to learn.
C++ isn't as hard as people say. It is just bad hype.

Nope, because output of disassemblers and debuggers are in machine level assembly (LLA).
12/03/2006 04:28 yokoyoko#9
Still waiting for the memory reading thing ^^ I don't need to much, like a whole function set or anything, just an example, say, how i would read player experiance.

you are very helpful indeed xD
12/03/2006 04:57 ColdStart#10
Quote:
Originally posted by yokoyoko@Dec 2 2006, 22:28
Still waiting for the memory reading thing ^^ I don't need to much, like a whole function set or anything, just an example, say, how i would read player experiance.

you are very helpful indeed xD
Sorry about the delayed response, AutoHotKey's syntax structure and variable usage confused me.

Here is an example that gets the user's Gold (static) and Current HP (dynamic) in AutoHotKey:
Code:
ExtInt(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4); From AutoHotKey Help
{
Loop %pSize%
result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result
return -(0xFFFFFFFF - result + 1)
}

;Get PID
Process, Exist,Conquer.exe

;Store PID
pid = %ErrorLevel%

;Check if Process Available
if pid
{
;Create 4 Byte (Int) Structure for Gold
VarSetCapacity(gold,4,0)

;Create 4 Byte (Int) Structure for Char HP Base Address
VarSetCapacity(hpa,4,0)
;Create 4 Byte (Int) Structure for Char HP
VarSetCapacity(hp,4,0)

;Open the Process for Handling
ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "UInt")

;Check if Handle Created
if ProcessHandle
{
;Get the raw 4 Bytes for Gold in Variable
DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",0x004FF1E0,"Str",gold,"UInt",4,"UInt *",0)

;Get the raw 4 Bytes for Char HP Base Address
DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",0x004FF1B8,"Str",hpa,"UInt",4,"UInt *",0)
;Get the raw 4 Bytes for Char HP
DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",ExtInt(hpa)+24,"Str",hp,"UInt",4,"UInt *",0)

;Close the Process Handler
DllCall("CloseHandle","int",ProcessHandle)

;Display the Gold and Char HP
MsgBox % "Gold: " . ExtInt(gold) . Chr(13) . Chr(10) . "HP: " . ExtInt(hp)
}
}
[Only registered and activated users can see links. Click Here To Register...]
12/03/2006 05:22 yokoyoko#11
ty very much!!! i can't run the script right now, but i think it'll work out very well. The only 2 parts that I didn't understand is the first loop, and the hp part.

also, what if I have multiple conquer.exe running? will the script run into an error? and what do I do to get a value from a specific conquer process (i.e. how would I get the PID of the process that have the right character)

other than those all seems perfect. +karma
12/03/2006 06:08 ColdStart#12
Quote:
Originally posted by yokoyoko@Dec 2 2006, 23:22
ty very much!!! i can't run the script right now, but i think it'll work out very well. The only 2 parts that I didn't understand is the first loop, and the hp part.

also, what if I have multiple conquer.exe running? will the script run into an error? and what do I do to get a value from a specific conquer process (i.e. how would I get the PID of the process that have the right character)

other than those all seems perfect. +karma
The first loop (the only loop) with in the function ExtInt is actually pretty simple. It takes any raw byte structure and turns it into a proper integer by adding each byte in proper place.

Code:
Loop %pSize%
Since pSize defaults to 4, the loop will run the following command 4 times (unless changed of course)

Code:
result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
result starts at 0
A_Index starts at 1 on the first run of the loop and it will end at 4
The *() expects the content between the parentheses to be an address and turns it into a byte
So &pSource gets the address in memory of the variable pSource (which was referenced)
The optional argument of the function called pOffset just allows you to offset the address of the byte by an integer (this isn't used in my example)
A_Index-1 is the index -1 so that it has a 0 base
Now if we have 0x00F1AE24 for &pSource, plus 0 for pOffset, plus the 0-based index we would get the address plus an increasing number
This allows us to get 4 bytes from the address, so from the example the bytes would be the value of 0x00F1AE24, 0x00F1AE25, 0x00F1AE26, and 0x00F1AE27
The only problem that when you add these bytes as such, they are on incorrect shifts (they are exponentially off, so 10 wouldn't be 10, but 0.1 etc)
We then have to shift the value of the bytes on an 8-bit axis (8 bits*0-base index=correct shift)
So now that we know what each part does, we simply add the value of the address of a byte in an address "array" at the correct corresponding shift to result
This in effect adds each byte together at the correct shift to get a usable AutoHotKey integer
Sadly only AutoHotKey has this byte conversion issue, every language I know does not have such problems

The HP part, as explained in the first post with the Dynamic address definitions, first gets the value of the static "base" pointer address. This value is an offset away from Dynamic variable address. The offset for HP from the listed "base" pointer address is 24, so we add 24 to the value returned by the static "base" pointer address to get the Dynamic variable's address. We then get the value of this Dynamic address, which happens to be the actual HP.

I am not sure about anything if more than one instance of Conquer.exe is running. I doubt it would get an error, but instead just get the numerically first PID, which should be the first instance launched. You could simply make a system like COPartner where you check the process name of the active window and if it is Conquer.exe then you get the PID.

To utilize this within a language such as AutoHotKey, you would need to make psuedo function threading for each instance/PID and hotkey switching. I may some time show an example of such a thing, but it doesn't directly deal with this topic.
12/03/2006 06:14 smoothjonny#13
for once i don't mind the double posts =P


...this kid seems like the real deal... watch out prog4mer (cuz i see you're here too atm)

he's a noob after our hearts :)
12/03/2006 06:27 yokoyoko#14
thx, i gotta go to sleep right now, will try it tomorrow. I figured out a different way to get a specific PID. :)

Quote:
he's a noob after our hearts
what's that suppose to mean lol?
12/03/2006 17:06 ColdStart#15
Quote:
Originally posted by smoothjonny@Dec 3 2006, 00:14
for once i don't mind the double posts =P


...this kid seems like the real deal... watch out prog4mer (cuz i see you're here too atm)

he's a noob after our hearts :)
The only reasons why I double posted are that the editing function is extremely screwed up for the first post, so it is harder to manage and the guide to find static "base" address pointers from dynamic pointers is incredibly long.

I am only here to help. Capturing the hearts of thousands is just a perk.

Glad you think of me positively :)