1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. FYI - Your missing Content - your only seeing non-registered Guest Information... Quickly register and sign on to see more! (Shoutbox, current activity etc, more forums)
    Dismiss Notice
  3. Hi There Guest! If your not sure about buying from us at HackersAdvantage, or unsure of our Detection Rates - Please Register and make a post asking! Our Staff and Members will reply to every question! We have the longest non-detection streaks in the industry! We offer a 3 day refund on hacks that you can not get to work on your PC. NO OTHER SITE DOES THIS!
    Dismiss Notice

Info The "correct" Way Of Reading Memory Via Readprocessmemory (.net Edition)

Discussion in 'Hack Coding Section' started by Helios, Nov 22, 2015.

  1. Helios
    Offline

    Helios NOOB

    NOTE: This thread requires the reader to understand how variables are stored in memory.

    Although I'm not that experienced a reverser yet, I'm quite alright with code, and one thing I constantly notice over and over is people doing external cheats "incorrectly".

    So what do I mean by that? Well, have a look at the example below:
    Code:
    ReadProcessMemory(ProcessHandle, BaseAddress + PlayerName, Name, Marshal.SizeOf(Name), 0)
    ReadProcessMemory(ProcessHandle, BaseAddress + PlayerScore, Score, Marshal.SizeOf(Score), 0)
    ReadProcessMemory(ProcessHandle, BaseAddress + PlayerPosition, Position, Marshal.SizeOf(Position), 0)
    
    Now you might say, "Well, what's wrong with that?", and technically nothing is wrong, but, it's just not very efficient.

    What ReadProcessMemory does, is read memory from a certain address and x amount of bytes forward. The thing is, ReadProcessMemory is slow, so we wont want to call it too many times. Now, if ReadProcessMemory functions this way, why aren't everybody reading larger blocks of memory, instead of reading a single data type size of memory?

    I'll tell you why,- it's because inexperienced people tried to teach others.

    Now, you won't necessarily always be able to read the data you want in one try, but what we're going for is trying to optimize our hack. So for us to be able to read a larger block of memory, the data we want needs to be somewhat close in memory, and I'll show you what I mean by that, by using an example.

    I'll use the game "Build And Shoot" formerly known as "Ace Of Spades" to demonstrate examples, as it's a very simple game.

    In this image we have the entity structure, the structure that holds player information like name, kills, position, etc. The reason I named it entity is that it covers both the player and the enemy. The size of this structure is 304 bytes.
    [​IMG]

    So as you can see in the image, we have the address 0x890140 and at that address the position of the player is stored, 12 bytes from that is the minimap poisition of the player, and 228 bytes later we have the name. What we can gather from the picture, is that player information is stored right next to each other in memory, and because of that we should retrieve the information in one call, instead of 32 calls....

    BUT, the data you want from memory is not always very close or close enough in memory so that you can actually read it without taking a performance hit. So what do I mean by that? Well, let's use another example.

    Let's think about it this way:
    1. In Build And Shoot the max amount of players a server can have is 32 players.
    2. The player and enemy have the same structure, therefor the same size, 304 bytes.
    3. Players are stored in memory with an offset of 0x3A8 (936 bytes) from each other.

    So with this in mind, we know that to read the whole player list array, we'd have to read a memory block the size of 30256 bytes! That's a bit too much. See the hardware in your computer also plays a role in how much memory you can read at the time, if you have a good computer you can read a bigger amount of memory without a performance hit, but if you've got a bad computer, you'll definitely have some issues. So using this example, I guess the smart or sane thing to do, would be to read every player by themselves.

    Anyway, let's get back to what we were talking about, reading memory in one call instead of 32 calls.

    So instead of doing this:
    Code:
    ReadProcessMemory(ProcessHandle, BaseAddress + PlayerPosition, Position, Marshal.SizeOf(Position), 0)
    ReadProcessMemory(ProcessHandle, BaseAddress + PlayerMiniMapPosition, MiniMapPosition, Marshal.SizeOf(MiniMapPosition), 0)
    ReadProcessMemory(ProcessHandle, BaseAddress + PlayerName, Name, Marshal.SizeOf(Name), 0)
    
    We should be doing this:
    Code:
    Dim PlayerStructureInBytes(304) As Byte
    ReadProcessMemory(ProcessHandle, BaseAddress + PlayerPosition, PlayerStructureInBytes, Marshal.SizeOf(PlayerStructureInBytes), 0)
    
    So what's done in the code above, is that we declare an array of bytes with the size of 304. Now why do we do that? We do that because the whole player structure, all the information on the player that we want, is as mentioned earlier, 304 bytes in size. We then read 304 bytes from the address "BaseAddress + PlayerPosition", and store it in the byte array "PlayerStructureInBytes".

    Now that's much better.

    Cool, now we have all the bytes, but how do we actually get the player information from the bytes then? Well, there's a couple of ways of doing that, but I'll just show you two ways.

    1. Manually assigning everything using e.g. the BitConverter class.
    Code:
    Player.Position = New Vector3(BitConverter.ToSingle(PlayerStructureInBytes, 0), _
                                                    BitConverter.ToSingle(PlayerStructureInBytes, 4), _
                                                    BitConverter.ToSingle(PlayerStructureInBytes, 8))
    Player.MiniMapPosition = New Vector3(BitConverter.ToSingle(PlayerStructureInBytes, 8), _
                                                    BitConverter.ToSingle(PlayerStructureInBytes, 12), _
                                                    BitConverter.ToSingle(PlayerStructureInBytes, 16))
    Player.Name = System.Text.Encoding.ASCII.GetString(PlayerStructureInBytes, 244, 60)
    

    2. Creating a "special" structure and a generic function (preferred way).
    Code:
    Public Structure Entity
        Public Position As Vector3
        Public MiniMapPosition As Vector3
        Public MovementSpeed As Vector3
        Public CameraRight As Vector3
        Public CameraUp As Vector3
        Public CameraForward As Vector3
        Public Team As Integer
        Public Classs As Integer
        Public MovingForward As Integer
        Public MovingBackward As Integer
        Public MovingLeft As Integer
        Public MovingRight As Integer
        Public SomethingAlwaysZero As Integer
        Public IsDucking As Integer
        Public SomethingAlways0 As Integer
        Public IsSprinting As Integer
        Public IsLeftButtonDown As Integer
        Public IsAiming As Integer
        Public Tool As Tool
        Public BlockColor As Integer
        Public IsAlive As Integer
        Public SomethingAlwaysOne As Integer
        Public IsInAir As Integer
        Public IsInWater As Integer
        Public Kills As Integer
        Public Blocks As Integer
        Public Ammo As Integer
        Public MaxAmmo As Integer
        Public Grenades As Integer
        Public Health As Integer
        Public LefButtonCounter As Single
        Public RightButtonCounter As Single
        Public Padding As Integer
        Public ReloadCounter As Single
        Public MovementLevelCounter As Single
        Public MovementUpCounter As Single
        Public DeathCounter As Single
        Public Padding1 As Integer
        Public Padding2 As Integer
        Public Padding3 As Integer
        Public Padding4 As Integer
        Public Padding5 As Integer
        Public SetToOneAfterDying0 As Integer
        Public SetToOneAfterDying1 As Integer
        Public SetToOneAfterDying2 As Integer
        Public Index As Integer
        Public Padding6 As Integer
        Public Padding7 As Integer
        Public Padding8 As Integer
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=60)> _
        Public Name As String
    End Structure
    
    So the only difference from a normal structure is that you have to set the byte size for strings, as a string can have a variable length. Have a look at the Name property for an example.

    Code:
        Public Function ConvertByteArrayToStructure(Of T As Structure)(Bytes As Byte()) As T
            Dim handle As GCHandle = GCHandle.Alloc(Bytes, GCHandleType.Pinned)
            Dim struct As T = DirectCast(Marshal.PtrToStructure(handle.AddrOfPinnedObject(), GetType(T)), T)
            handle.Free()
            Return struct
        End Function
    
    In the code above, we declare a generic method, that gets the memory address of the byte array we declared earlier, and then uses a function to turn the byte array into the chosen structure.

    That's it.

    I know this thread was a bit long and unstructured, but I decided to just go for it and write it chronology. If you have any corrections or if I need to clarify something, please comment.

    Best regards
    Helios
     
  2. Hawkeye
    Offline

    Hawkeye Jaidee's Evil American Clone H.A. LifeTime Friend

    Are you that Helios from that other site?
     
    AbsoluteKaos likes this.
  3. Khariz
    Offline

    Khariz LifeTime Friend H.A. LifeTime Friend Ultimate Hax

    Was wondering the same thing. Seems unlikely, by possible.
     
    AbsoluteKaos likes this.
  4. ShadowKiller
    Offline

    ShadowKiller RAC MASTER

    I doubt it. He is a danish guy who i met some years ago. Did not know that he was still active. Me and him were customers on another site that went down and never came back. Then we went to here. He had another nickname before he joined this site. He was never named Helios before 2012 when he signed up here.

    But i dont understand shit of all this coding stuff - i will go play some games now and drink my milk, that is much more simple :))
     
    Last edited: Nov 22, 2015
  5. Smockled
    Offline

    Smockled KOZBOT GOD Staff Member

    Doubt its HelioS, he spells his name differently
     
  6. Helios
    Offline

    Helios NOOB

    I wish, lol. There's actually a very subtle difference between our names, his name is "HelioS" and mine "Helios". I actually didn't get it from him, I was influenced by a game (Global Agenda), a movie (Clash of the titans) and some mythology (Greek).

    Ha ha, it's good to see you again my old friend :) I haven't been active in the cheating scene for a couple of years now, I kinda just dropped of the map. I had some real life stuff going on, like entering the workforce, temporarily relocating, just playing CSS, etc.

    I'm back now though, I suddenly got the urge because of StarWars Battlefront. I'll probably try out some cheats here because I know they are high quality cheats and I love the small tight knit community compared to the other sites. I'll most likely end up making some videos too, as I've actually missed that quite a lot.

    I have to mention that I absolutely love the draft functionality! I can take ages replying to threads without it forgetting what I wrote.

    EDIT:
    Bingo! Nice spot! I have not seen one person to spot that difference xD
     
    ShadowKiller likes this.
  7. Smockled
    Offline

    Smockled KOZBOT GOD Staff Member

    Yeah....

    I've been around for ages... know a lot of the old school folks from back when I was in the coding scene during America's Army in early 2000's

    edit: google the quote in my sig
     
    Hawkeye likes this.
  8. Dark_Rose
    Offline

    Dark_Rose RAC MARAUDAR

    It's all a foreign language to me. Hopefully I can learn such languages in the future.
    I enjoyed reading it, though. I can pick out the bits.
    I want to be a Jedi, like my father before me.
     

Share This Page