Register for your free account! | Forgot your password?

You last visited: Today at 12:19

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Memory Confusion

Discussion on Memory Confusion within the CO2 Programming forum part of the Conquer Online 2 category.

Reply
 
Old   #1
 
elite*gold: 0
Join Date: Sep 2007
Posts: 580
Received Thanks: 112
Memory Confusion

Hey there, I am running in to some problems on a little project that I have been working on. Basically I'm trying to go through a conquer client and hook and call as many different functions so I can get some exposure to that kind of thing.

Basically I have two functions: One function displays a message on the screen, the other returns the address of an inventory item by index.
Display Message:
Code:
MOV EBX, Properties::Inventory_Base_address
PUSH EBX
MOV ECX, Properties::Inventory_Sub_address
CALL Properties::Inventory_Count_Function_address
MOV _TReturn, EAX
Inventory Item Address:
Code:
MOV ESI, Properties::Inventory_Base_address
LEA EDI,DWORD PTR SS:[EBP-0x1C]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
PUSH TIndex
LEA ECX, DWORD PTR SS:[EBP-0x1C]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
CALL Properties::Inventory_Deque_Function_address
MOV _TTReturn, EAX
Both of these functions work when they are called not in series with one another. But as soon as I try to display anything before or after calling the inventory item function the client crashes. When I call either of these functions by themselves they seems to use memory in the realm of 0x25AAXXX. When I call them in series with one another the memory space it uses jumps to like 0x6XXXXXX which causes the client to crash as soon as it is accessed. This applies to the string I pass to the DisplayMessage function as well as the pointer returned for the item information. I've tried to google around but just don't seem to know what I should be looking at.

Any ideas? I appreciate your help.



StarBucks is offline  
Old 02/20/2017, 13:30   #2
 
elite*gold: 0
Join Date: Aug 2010
Posts: 988
Received Thanks: 1,076
Quote:
Originally Posted by StarBucks View Post
...
From what you have posted it is clear that you are not paying attention to the value of all the general registers.

I am going to try to explain this to you as fast as I can because I need to sleep :P

Say we have 3 functions Foo, Bar & FooBar, all 3 functions make use of EBP and expect EBP to to always point somewhere on the stack.

Code:
FooBar()
{
    MOV EBP, 100000;
    CALL Foo;
    CALL Bar;
}
Foo()
{
     //EBP is 100000 here because FooBar made sure of that before it called Foo. 
     MOV EBP, 1;//No foo is not playing nice and it decided to change the value of EBP.
}
Bar()
{
    //EBP here is 1 because Foo made sure of it when it was called before bar.
    MOV EAX, EBP;
    CALL [EAX + 4];//This is where shit hits the fan. [EAX + 4] was supposed to point to 100004 now instead it point to 5 which will instantly cause memory access violations and crash the app. 
}
When a callee returns, The caller function expects that the callee cleaned up after itself and didn't trash the registers or the stack.

Typically you would do something like this to avoid this issue.

Code:
__declspec(naked) DWORD Foo()
{
__asm
{
    PUSHAD;

    //Do stuff.

    POPAD;
    

    //Or store the registers you know you are going to change on the stack and restore them when you are done. 
    PUSH ECX;
    PUSH EBP;
    etc
    
    //Do stuff with exc and ebp. 

    POP EBP;
    POP ECX;
    etc
}
}



Also you need to make sure that the function you are calling cleans up after itself so something like this:

Code:
__declspec(naked) DWORD Foo()
{
__asm
{
    PUSH EAX;
    CALL xyz;//xyz never pops the value of EAX that we pushed on the stack and that will mess up things if the calling function expects Foo to clean up after itself  
    RET;//This here points to an invalid return address.
}
}
Plenty of other problems in the bits of asm you posted but I really don't have time to go over them all, However very quickly.

Code:
MOV ESI, Properties::Inventory_Base_address//ESI needs to be saved somewhere, Same with EDI below.
LEA EDI,DWORD PTR SS:[EBP-0x1C]//Does EBP really point to where you think it points?
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]//What does ESI point to an array?
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]//This is doing exactly what the instruction above it already did so whats the point?
PUSH TIndex//Are you sure Inventory_Deque_Function_address actually pops this before it returns?
LEA ECX, DWORD PTR SS:[EBP-0x1C]//Does Inventory_Deque_Function_address use EDI or ECX?
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]//useless duplicate 
CALL Properties::Inventory_Deque_Function_address
MOV _TTReturn, EAX
//Where is the RET instruction? This function needs to return somewhere.


{ Angelius } is offline  
Old 02/20/2017, 23:54   #3
 
elite*gold: 0
Join Date: Sep 2007
Posts: 580
Received Thanks: 112
Quote:
Originally Posted by { Angelius } View Post
Plenty of other problems in the bits of asm you posted but I really don't have time to go over them all, However very quickly.

Code:
MOV ESI, Properties::Inventory_Base_address// PUSHAD?
LEA EDI,DWORD PTR SS:[EBP-0x1C]//Does EBP really point to where you think it points? I think this is where my problem lies.
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]//What does ESI point to an array? ESI pointing to the array that contains Inventory Item pointer information. This location is correct as I'm getting the correct values.
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]//This is doing exactly what the instruction above it already did so whats the point? Each time this is called EDI and ESI are increased by 0x4. Essentially increasing the index of the array
PUSH TIndex//Are you sure Inventory_Deque_Function_address actually pops this before it returns? Doesn't look like it POPs it but it copies the value using a MOV and the stack pointer + offset.
LEA ECX, DWORD PTR SS:[EBP-0x1C]//Does Inventory_Deque_Function_address use EDI or ECX? Looks like it uses ECX.
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]//useless duplicate, same as above.
CALL Properties::Inventory_Deque_Function_address
MOV _TTReturn, EAX
//Where is the RET instruction? This function needs to return somewhere. Do I need a return when the function isn't naked?
You are totally right. Though at one point I was pushing and popping all the data and it was still crashing. I think my real issues lies in me not knowing what I am doing with managing the stack. All of the other functions that I have used I've never needed to allocate space and de-allocate space as its all handled with the PUSH and POPing (right? thought I had noticed this). The part that is throwing me for a loop is why does it only become a problem when I call two of my functions one after the other? If I repeatedly called my "display message" function that calls the ItemCount function I have zero issues. I can also call both of the functions separately and they work just fine.

Here are the functions that I am using.
Code:
void Client::DisplayMessage(int TChatType, string _TTMessage)
{
	__asm{
		PUSHAD
		PUSHFD
		PUSH 0
		PUSH 0
		PUSH 0xFFFF00
		PUSH TChatType
		PUSH DWORD PTR DS:[_TTMessage]
		MOV ECX, 0x508D10
		CALL Properties::ScreenMessage_Function_address
		POPFD
		POPAD
	}
}
Code:
int Client::GetInvetoryItemCount(){
	int _TReturn = 0;
	__asm {
		PUSHAD
		PUSHFD
		MOV EBX, Properties::Inventory_Base_address
		PUSH EBX
		MOV ECX, Properties::Inventory_Sub_address
		CALL Properties::Inventory_Count_Function_address
		MOV _TReturn, EAX
		POPFD
		POPAD
	}
	return _TReturn;
}
Code:
int Client::GetInventoryItemAddress(int TIndex){
	int _TTReturn = 0;
	__asm{
		PUSHAD
		PUSHFD
		MOV ESI, Properties::Inventory_Base_address
		LEA EDI,DWORD PTR SS:[EBP-0x1C]
		MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
		MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
		PUSH TIndex
		LEA ECX, DWORD PTR SS:[EBP-0x1C]
		MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
		MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
		CALL Properties::Inventory_Deque_Function_address
		MOV _TTReturn, EAX
		POPFD
		POPAD
	}
	return _TTReturn;
}
I'm calling the function kinda of like this:
Code:
void HandleCommand(int Cmd)
{
       switch(Cmd)
              Case 1:
                 DisplayMessage(2006, "Testing message");
       switch(Cmd)
              Case 2:
                 DisplayMessage(2006, "Item Count:" + GetInventoryItemCount());
       switch(Cmd)
              Case 3:
                 cout << hex << "Address: " << GetInventoryItemAddress(3) << endl;
       switch(Cmd)
              Case 4:
                 DisplayMessage(2006, "Testing message");
                 GetInventoryItemAddress(3);
}
I can use commands 1 through 3 but when I call 4 it causes a crash. And it does appear to crash when it uses anything EBP. You asked above, "Is this where you think EBP points?" And, honestly, I'm not even sure how to answer that question. I think my issue is stack management in my GetInventoryItemAddress.

I appreciate you taking the time to look this over.

Edit:
So I have been messing around with this more throughout the day and I have made some changes. I really tried to make the functions something that I understand a little better and I feel like I did a decent job in that.
My deque function now looks like this:
Code:
int Client::GetInventoryItemAddress(int TIndex){
	int _TTReturn = 0;
	int adr1 = *reinterpret_cast<int*>(0x050BDF8);
	int adr2 = *reinterpret_cast<int*>(0x050BDFC);
	int adr3 = *reinterpret_cast<int*>(0x050BE00);
	int adr4 = *reinterpret_cast<int*>(0x050BE04);
	__asm{
		PUSHAD
		PUSHFD
		PUSH adr4
		PUSH adr3
		PUSH adr2
		PUSH adr1
		PUSH TIndex
		MOV ECX, ESP  //ECX need to the the address of the first Address on the stack.
		ADD ECX, 0x4
		CALL Properties::Inventory_Deque_Function_address;
		ADD ESP, 0x10 //Because the values are not popped off the stack need to 'reset' the stack pointer
		MOV _TTReturn, EAX
		POPFD
		POPAD // After this the stack and registers looked like they did before it started.
	}
	return _TTReturn;
}
When I was rewriting the function I took extra care to make sure that the registers and the stack looked exactly like they did before the ASM portion of the code was executed. With this new function I am still having troubles when I try to call my displaymessage function right after this one. Even Ollydbg seems to be acting strange (Actually i don't know what I'm doing )

When I look at the registers I see that:
Code:
EAX 02A5FAF8 ASCII "Testing Message"
And when I "follow in stack" I see:
Code:
02A5FAF8 74736554 MSVCRT.74736554
And if I instead "follow in dump" I see:
Code:
02A5FAF8  54 65 73 74 69 6E 67 20 4D 65 73 73 61 67 65     Testing Message
StarBucks is offline  
Old 02/27/2017, 01:49   #4
 
elite*gold: 0
Join Date: Sep 2007
Posts: 580
Received Thanks: 112
Looks like my post didn't quite make it though.

Sorry for the double post here but its a different question from the last post. Figured it was better than creating a thread. I sold my issue, I was passing a string that was shorter than the expected string so it would crash.

My new problem has to do with reading a memory location that is no longer allocated to the client. I'm able to load all inventory items, entities, and ground items but every once in a while the client crashes is one of those things disappears while its, say, half way through reading. My first thought was that the pointer I was using was 0 (and the client immediately checks for a null pointer) but that was not my issue. It seems its trying to read an address that was once the location for the entity but is no longer allocated to the client.

I have tried to google around but thought I might ask if any of you guys have had any experience with this or possibly know a way I can check if a pointer is pointing to a location in the clients memory space. Thanks!


StarBucks is offline  
Old 02/27/2017, 09:30   #5
 
elite*gold: 0
Join Date: Aug 2010
Posts: 988
Received Thanks: 1,076
Quote:
Originally Posted by StarBucks View Post
Looks like my post didn't quite make it though.

Sorry for the double post here but its a different question from the last post. Figured it was better than creating a thread. I sold my issue, I was passing a string that was shorter than the expected string so it would crash.

My new problem has to do with reading a memory location that is no longer allocated to the client. I'm able to load all inventory items, entities, and ground items but every once in a while the client crashes is one of those things disappears while its, say, half way through reading. My first thought was that the pointer I was using was 0 (and the client immediately checks for a null pointer) but that was not my issue. It seems its trying to read an address that was once the location for the entity but is no longer allocated to the client.

I have tried to google around but thought I might ask if any of you guys have had any experience with this or possibly know a way I can check if a pointer is pointing to a location in the clients memory space. Thanks!
No there isn't, And because you don't solely own that object you are queering you never store the returned results you instead query the map/vector values whenever you need access to them (A snapshot of the collection).

Assuming what you are reading the values of off is a collection of some sort map/vector/etc it's values will constantly change because the client is making use of it.

So 2 things come to mind:
1- (potentially dangerous), would be to get a pointer to whatever collection you want to query and cast it to it's known type, So if you know it's an std::map you static_cast<xyz> it to an std::map then access it as you would normally do in C++ using find/foreach etc. This would make it easier to access the collection values and will to a degree, Insure that you wont be accessing a value that doesn't exist in the collection anymore. However, This would only work if you have direct access to the process memory.

2- Is to look for a mutex or a lock of some sort that is being utilized by the client before accessing the collection (if any) and then lock it yourself before queering the collection.

Both approaches are a bit advanced and will require some effort on your end but I am sure you will eventually figure it out.

Good luck.
{ Angelius } is offline  
Old 02/27/2017, 12:23   #6
 
elite*gold: 0
Join Date: Jul 2014
Posts: 402
Received Thanks: 540
Quote:
Originally Posted by { Angelius } View Post
No there isn't, And because you don't solely own that object you are queering you never store the returned results you instead query the map/vector values whenever you need access to them (A snapshot of the collection).

Assuming what you are reading the values of off is a collection of some sort map/vector/etc it's values will constantly change because the client is making use of it.

So 2 things come to mind:
1- (potentially dangerous), would be to get a pointer to whatever collection you want to query and cast it to it's known type, So if you know it's an std::map you static_cast<xyz> it to an std::map then access it as you would normally do in C++ using find/foreach etc. This would make it easier to access the collection values and will to a degree, Insure that you wont be accessing a value that doesn't exist in the collection anymore. However, This would only work if you have direct access to the process memory.

2- Is to look for a mutex or a lock of some sort that is being utilized by the client before accessing the collection (if any) and then lock it yourself before queering the collection.

Both approaches are a bit advanced and will require some effort on your end but I am sure you will eventually figure it out.

Good luck.
Or just do it the right way: Hook "EndScene" and only access the collection from inside that hook.
Best Coder 2014 is offline  
Old 02/27/2017, 16:39   #7
 
elite*gold: 0
Join Date: Aug 2010
Posts: 988
Received Thanks: 1,076
Quote:
Originally Posted by Best Coder 2014 View Post
Or just do it the right way: Hook "EndScene" and only access the collection from inside that hook.
Yes, That's one way and it could actually work if you have direct access to the process memory since you would be waiting on the client to do all of it's dirty work, However I wouldn't call it "The right way", as the right way will always depend on 2 things, Single vs Multi-threaded and how you plan to access and use the data.

You could hook the GameMap.Process(), GameShow() or even the OnTimer() and still **** up if you are storing the returned results and plan to use them later instead of accessing the data on demand and in real time.
{ Angelius } is offline  
Old 02/27/2017, 17:32   #8
 
elite*gold: 0
Join Date: Jul 2014
Posts: 402
Received Thanks: 540
Quote:
Originally Posted by { Angelius } View Post
You could hook the GameMap.Process(), GameShow() or even the OnTimer() and still **** up if you are storing the returned results and plan to use them later instead of accessing the data on demand and in real time.
Then don't do that. Or, if you for some weird reason really want to access the collection from a separate thread (which is a useless and stupid idea, but whatever), you can just clone the values into your own thread-safe collection.
Best Coder 2014 is offline  
Old 02/28/2017, 16:46   #9
 
elite*gold: 0
Join Date: Aug 2010
Posts: 988
Received Thanks: 1,076
Quote:
Originally Posted by Best Coder 2014 View Post
Then don't do that. Or, if you for some weird reason really want to access the collection from a separate thread (which is a useless and stupid idea, but whatever), you can just clone the values into your own thread-safe collection.
That's what I said since the beginning, But thanks for reiterating


{ Angelius } is offline  
Reply



« About PlayCo Bots | Proxy hunt loot idea? »

Similar Threads
confusion
05/25/2014 - Rohan - 1 Replies
how to make my own rohan offline for??? please let me know :confused:
confusion about cFlyFF!
09/04/2010 - Flyff - 7 Replies
Hello, everybody.. I have been reading about cFlyFF a lot, and as far as i'm concerned,some timeago it was possible to register but now..??? is it? So, yea, the question is - Is it possible to register in cFlyFF and actually play it? Thanks in advance! P.S English please!
confusion..take a look
02/24/2010 - Silkroad Online - 9 Replies
i saw the heroes of alexandria update on isro and there they say this set will not be de 11D of chinese: http://img.joymax.com/property/silkroad/silkroado nline_3/us/ter_img/leg5_img/sub/items/items02_pic2 .jpg and this set will be universal for chinese and european too: http://img.joymax.com/property/silkroad/silkroado nline_3/us/ter_img/leg5_img/sub/items/items01_pic2 .jpg but im confused because i'd known the frist image is D11 for chinese and the second is for european.what is the...
Clear the SV Confusion
03/24/2007 - Conquer Online 2 - 4 Replies
Okay, I&#39;m getting kind of lost, and confused with the 10,000 different threads of SV, and the 9 million ways of cracking it. Can anyone just clear up a few things. 1. Which exactly is the version that works right now? 2. How can we tell we have that version (screens would help)? 3. What we need to do to make that version work. I&#39;m sorry this may seem noob, but after trying to search for a way to fix it, I&#39;ve only found myself confused for the past 3 days. There are many different SV...



All times are GMT +1. The time now is 12:19.


Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.

BTC: 33E6kMtxYa7dApCFzrS3Jb7U3NrVvo8nsK
ETH: 0xc6ec801B7563A4376751F33b0573308aDa611E05

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2019 elitepvpers All Rights Reserved.