Getting/Setting offsets

Official Announcements about Source.Python.
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Getting/Setting offsets

Postby satoon101 » Mon Dec 17, 2012 8:59 am

You can now get and set bool, integer, and float offsets!!! If you know the offset, you can use the following to get/set the value:
  • Binutils.GetLocBool(<addr>)
  • Binutils.GetLocInt(<addr>)
  • Binutils.GetLocFloat(<addr>)
  • Binutils.SetLocBool(<addr>, <bool value>)
  • Binutils.SetLocInt(<addr>, <integer value>)
  • Binutils.SetLocFloat(<addr>, <float value>)
I used the following as my test script on Windows for CS:GO:

Syntax: Select all

from Source import Binutils
from events import Event
from players.helpers import pointer_from_userid


offsets = {
'kills': {'offset': 3760, 'value': 10},
'assists': {'offset': 3764, 'value': 3},
'deaths': {'offset': 3768, 'value': 5},
}


@Event
def player_say(GameEvent):
userid = GameEvent.GetInt('userid')
pointer = pointer_from_userid(userid)
text = GameEvent.GetString('text')
if text == 'get':
for offset in offsets:
print('=====================================')
print(pointer)
print(offset)
value = Binutils.GetLocInt(pointer + offsets[offset]['offset'])
print(value)
print('=====================================')
elif text == 'set':
for offset in offsets:
Binutils.SetLocInt(
pointer + offsets[offset]['offset'], offsets[offset]['value'])
Unfortunately, we are still having issues with Linux. Once we get those fixed, we will release a new build with these new functions. If you already know how to build yourself, you are certainly welcome to build for Windows and test this out yourself.


* Edit: Another update!! Just added basic offset functionality to BaseEntity classes. The above script can now look like:

Syntax: Select all

from events import Event
from players.entity import PlayerEntity
from players.helpers import index_from_userid


offsets = {
'kills': 10,
'assists': 3,
'deaths': 5,
}


@Event
def player_say(GameEvent):
userid = GameEvent.GetInt('userid')
index = index_from_userid(userid)
player = PlayerEntity(index)
text = GameEvent.GetString('text')
if text == 'get':
for offset in offsets:
print('=====================================')
print(player.__getattr__(offset))
print('=====================================')
elif text == 'set':
for offset in offsets:
player.__setattr__(offset, offsets[offset])


Satoon
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Dec 17, 2012 7:42 pm

For the built-in offsets for BaseEntity classes, we will only use non-networked values. So, for instance, while the offset to get/set an player's render value is 176 (196 on Linux), instead of using the offset, which could change in future updates, we still want to use CBaseEntity.m_clrRender, which is almost certainly not going to change.

Having said that, if anyone finds any interesting offsets, please post them here, so that we can consider whether or not to add them as built-in offsets. The same goes for keyvalues, networked properties, and dynamic functions as well. Keyvalues and networked properties should never need updating. Dynamic functions and offsets could change, so we still fully intend to get a full team together at some point to help keep them up-to-date.

Also, another tidbit about the code in the previous post. I have noticed that there are quite a few script requests on the ES forums for "reset score". To use the above to reset a player's score, you would simply use:

Syntax: Select all

from events import Event
from players.entity import PlayerEntity
from players.helpers import index_from_userid

@Event
def player_say(GameEvent):
if GameEvent.GetString('text') != '!reset':
return

userid = GameEvent.GetInt('userid')
index = index_from_userid(userid)
player = PlayerEntity(index)
player.kills = 0
player.assists = 0
player.deaths = 0


Satoon
Tuck
Global Moderator
Posts: 205
Joined: Sat Jul 14, 2012 9:35 pm
Location: Copenhagen

Postby Tuck » Mon Dec 17, 2012 8:54 pm

does this mean you now have a way of setting transparency of player models ?
-Tuck
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Dec 17, 2012 10:33 pm

No, and again, that is not an issue with the plugin, but with the specific game "CS:GO" (or the version of the engine it is running on). Using the same method on CS:S with Source.Python works perfectly fine. I'm still uncertain as to how to do this in CS:GO, but hopefully someone can figure it out. These offsets will almost assuredly not have anything to do with it, though.

Satoon
User avatar
La Muerte
Administrator
Posts: 180
Joined: Sun Jul 15, 2012 1:48 pm
Location: Belgium
Contact:

Postby La Muerte » Mon Dec 17, 2012 11:30 pm

I wouldn't reply with this because it doesn't rly contribute much to this thread (as most of my posts), but fuck it: This is amazing, love it ;)
(We'd be given "like" buttons or something :p )
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Mon Dec 17, 2012 11:37 pm

:) We enjoy all feedback!!! It would be nice to have a like button, or something of the like. We will look into that possibility for the future.

Satoon
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Tue Dec 18, 2012 9:38 am

Nice! Definitely m_nButtons! :D

Do booleans work for you?
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Tue Dec 18, 2012 4:50 pm

Ayuto wrote:Nice! Definitely m_nButtons! :D

Do booleans work for you?
I'll add m_nButtons when I get the chance. I have not tested booleans or floats as of yet, but I will shortly.

Satoon
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Fri Dec 21, 2012 2:01 pm

Hey guys,

I've just added more Get/SetLoc<X> functions. Here are all the types currently supported:
  • Bool
  • Char
  • Double
  • Float
  • Int
  • Long
  • LongLong
  • Pointer
  • Short

I've also added 3 functions to let you restructure your own objects:
  • AllocateMemory
  • DeallocatePointer
  • ReallocatePointer

See the following examples using SPE:


I will try to post tutorials about that someday but for now, they can be a good reference. Also, if you have questions, feel free to ask!

L'In20Cible
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Fri Dec 21, 2012 4:49 pm

Vote for GetLocString() and SetLocString()! :D
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Fri Dec 21, 2012 6:03 pm

Hey Ayuto,

I thought about adding those as well. But the problem is that the way to handle them can differ from one to the other. In example, does that the given pointer need to hold a pointer of the string or the string itself? How the server will react if we reallocate a string and its pointer/size change? How can we be sure it was not a pooled string referenced somewhere else? etc...

For now, you have all the tools needed to get/set strings. In example, you could use the following functions:

Syntax: Select all

# ============================================================================
# >> IMPORTS
# ============================================================================
# Source.Python Imports
# Binutils
from Binutils import GetLocChar
from Binutils import SetLocChar
from Binutils import ReallocatePointer


# ============================================================================
# >> FUNCTIONS
# ============================================================================
def GetLocString(ptr):
'''Returns the string at the given memory location'''

# Get a return variable...
return_value = str()

# Get the first character...
current_character = GetLocChar(ptr)

# Loop as long as we find valid character...
while ord(current_character):

# Add the current character to the return variable...
return_value += current_character

# Increase the current memory location...
ptr += 1

# Get the next character...
current_character = GetLocChar(ptr)

# Finally, return the retrieved string...
return return_value

def SetLocString(ptr, string):
'''Sets the given memory location to the given string'''

# Get the length of the given string...
length = len(string) + 1

# Reallocate the given pointer to the length of the given string...
ptr = ReallocatePointer(ptr, length)

# Set a variable to the current memory location...
current_location = ptr

# Loop through all characters...
for current_character in string:

# Set the current location to the current character...
SetLocChar(current_location, current_character)

# Increase the current memory location...
current_location += 1

# Make sure that our string ends with a NULL character...
SetLocChar(current_location, '\x00')

# Returns the new pointer...
return ptr

So well, play with those for now and let us know. :)

EDIT: At some point, I think that I can add them and let users use them at their own risk, oh well...

L'In20Cible
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Sat Dec 22, 2012 1:51 pm

I don't see a problem with getting strings. If we got a char *, we can safely use our function. A char ** is obviously not a char * and we need to turn it into a char * via GetLocPointer() (or did I understand you not correctly?). And isn't realloc() made to extend/shorten pointers? So there wouldn't be a problem with setting strings.
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Sat Dec 22, 2012 10:49 pm

Hey Ayuto,

The problem is not to get but to set them. Cause if the new string is larger than the old one, its pointer will have to change if there are not enough space before the next block. And the question is how the server will actually react if the string is moved to a different location while the old pointer is still referenced somewhere else (which is the case for string allocated using AllocatePooledString). And if you don't reallocate the pointer, you will get a heap error if you are writting data further the actual heap buffer. So even though it works what will be the result later? I still have to make some tests about that, I don't want to rush things while I'm not sure they are as safe as they can/could be.

L'In20Cible
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Sat Dec 22, 2012 11:28 pm

Ah, I see the problem. I didn't know that realloc() returns a new pointer, if the size has been exeeded. But I'm sure that there is a safe way. E.g. in ES we can set string properties via es.set*prop(). But maybe it uses this risky way.
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Sat Dec 22, 2012 11:32 pm

That's not right, you can only get string properties.

L'In20Cible
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Sun Dec 23, 2012 8:25 pm

Indeed, Mattie only ever added "getting" string properties, not "setting" them. This is probably a big part of the reason why.

Satoon

Return to “News & Announcements”

Who is online

Users browsing this forum: No registered users and 13 guests