Raised This Month: $51 Target: $400
 12% 

Solved Find Physical Offsets


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Spirit_12
Veteran Member
Join Date: Dec 2012
Location: Toronto, CA
Old 09-01-2018 , 19:37   Find Physical Offsets
Reply With Quote #1

I'm trying to learn how to properly use the StoreToAddress and LoadFromAddress functions. The best usage is in L4D2 Direct package, but there is hardly any tutorial to find physical offsets.

Would anyone be able to help?
__________________

Last edited by Spirit_12; 09-02-2018 at 15:58.
Spirit_12 is offline
hmmmmm
Great Tester of Whatever
Join Date: Mar 2017
Location: ...
Old 09-01-2018 , 20:20   Re: Find Physical Offsets
Reply With Quote #2

What is it you're trying to do? There are lots of different reasons one would need to use offsets.
hmmmmm is offline
Spirit_12
Veteran Member
Join Date: Dec 2012
Location: Toronto, CA
Old 09-01-2018 , 21:09   Re: Find Physical Offsets
Reply With Quote #3

I'm just trying to learn. There is no specific end goal here. Just want to know what are the possibilities with the usage of physical offsets.
__________________
Spirit_12 is offline
hmmmmm
Great Tester of Whatever
Join Date: Mar 2017
Location: ...
Old 09-02-2018 , 04:08   Re: Find Physical Offsets
Reply With Quote #4

Off the top of my head I can think of 2 reasons to use offsets with StoreToAddress/LoadFromAddress



First reason is to read/set member variables. Say for example you have a struct that looks like this:
PHP Code:
struct MyStruct
{
    
float x;
    
float y;
    
float z;
}; 
If you have the address of an object with type MyStruct and you want to read the z value, you'll need to offset from the start of the struct to get that value.

Easiest way to get that offset is to just count the number of bytes before that member. So in this case we have both x and y before z in the struct. Floats are 4 bytes in size so this adds up to 4+4=8 bytes.

In sourcepawn this would look like:
PHP Code:
Address offset view_as<Address>( );
float z view_as<float>( LoadFromAddresspMyObject offsetNumberType_Int32 ) ) // pMyObject is the address of our MyStruct object, NumberType_Int32 means to read 32 bits (or 4 bytes). 


One thing to note is that classes with virtual functions work a bit differently.
Take this class as an example:
PHP Code:
class CSomeClass
{
public:
    
virtual void MyVirtualFunc();
public:
    
float x;
}; 
If you wanted to get the value of x it might look like the offset would be 0 since it's the first member variables, however this would be wrong. Having virtual functions creates a new hidden variable in the class that contains a pointer to an array of all the virtual functions. So a look at how the class memory looks internally would look something like this:
Code:
pVMT - 4 bytes // Pointer to a virtual method table
x - 4 bytes // The x member variable
This means that x has an offset of 4 in the class rather than 0.



Another thing to keep in mind is that inheriting from a class places all of the vfuncs/member vars of the inherited class at the start of the new class.

Another example:
PHP Code:
class CBase
{
public:
    
float x;
    
float y;
};

class 
CChild : public CBase
{
public:
   
float z;
}; 
View of CChild in memory:
Code:
CBase object
    x - 4 bytes
    y - 4 bytes
z - 4 bytes
The offset of z in this example would be sizeof(CBase) which should be 8 bytes.



Dealing with multiple inheritance, lots of nested inheritance or even just lots of member vars can be quite complicated so as a trick you can use the disassembly to get the offset you need. The disassembly also references member variables through offsets, so all you need to do is find a section of disassembly that uses the member variable you're looking to get and copy that offset.

Here's an example of some disassembly (this part) that gets the value of m_nWaterLevel in CS:GO:

"this[351]" is the m_nWaterLevel variable where "this" is a CBasePlayer.

In sourcepawn the equivalent would be this:
PHP Code:
int m_nWaterLevel LoadFromAddressthis view_as<Address>( 351 ) ); 
Therefore it's clear that the offset of m_nWaterLevel is 351.


The second reason I thought of to use offsets in the context of StoreToAddress/LoadFromAddress is to byte-patch functions. All assembly instructions are represented to your computer as raw bytes/numbers, so it is possible to change how code works by replacing certain bytes with different ones. To do this you need to know the offset of those bytes from the start of the function.

Explaining this in lots of detail take too much time and would make this post too long, but if you want an example of this being done look at Peace-Maker's Movement Unlocker plugin. It patches CS:GO game movement code by replacing it with NOP instructions (which do nothing).

Hope this helps.

Last edited by hmmmmm; 09-02-2018 at 04:12.
hmmmmm is offline
Spirit_12
Veteran Member
Join Date: Dec 2012
Location: Toronto, CA
Old 09-02-2018 , 04:44   Re: Find Physical Offsets
Reply With Quote #5

That solidifies a lot of what I grasped on my own. One thing that I’m struggling with is how to find the member variables in IDA disassembly. I’m pretty decent with finding and using signatures. Would you be able to provide some info on how to locate a member variable ?
__________________
Spirit_12 is offline
nosoop
Veteran Member
Join Date: Aug 2014
Old 09-02-2018 , 05:11   Re: Find Physical Offsets
Reply With Quote #6

Quote:
Originally Posted by Spirit_12 View Post
That solidifies a lot of what I grasped on my own. One thing that I’m struggling with is how to find the member variables in IDA disassembly. I’m pretty decent with finding and using signatures. Would you be able to provide some info on how to locate a member variable ?
It mostly takes browsing through and keeping track of what class pointers are in which registers, as well as the context of the retrieved values.

For simple functions like CDirectorVersusMode::InFinaleMap(), it's quick to tell that it takes the implicit CDirectorVersusMode thisptr and returns the value at offset 44h (68 dec), matching what is in the gamedata file as CDirectorVersusMode::m_bInFinaleMap.

One way to get some practice with known class members is to look for functions that modify entity sendprops / dataprops (which are basically named subsets of member variables).
__________________
I do TF2, TF2 servers, and TF2 plugins.
I don't do DMs over Discord -- PM me on the forums regarding inquiries.
AlliedModders Releases / Github / TF2 Server / Donate (BTC / BCH / coffee)
nosoop is offline
asherkin
SourceMod Developer
Join Date: Aug 2009
Location: OnGameFrame()
Old 09-02-2018 , 05:32   Re: Find Physical Offsets
Reply With Quote #7

Quote:
Originally Posted by hmmmmm View Post
PHP Code:
int m_nWaterLevel LoadFromAddressthis view_as<Address>( 351 ) ); 
Just as a note, you should not use LoadFrom/StoreToAddress to read entity member variables, use Get/SetEntData instead.
__________________
asherkin is offline
Spirit_12
Veteran Member
Join Date: Dec 2012
Location: Toronto, CA
Old 09-02-2018 , 15:58   Re: Find Physical Offsets
Reply With Quote #8

Thanks a ton to all of you. I'll be playing with this and see what I can come up with. It has already solved my problems of getting map numbers.
__________________
Spirit_12 is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 07:42.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode