Results 1 to 15 of 17

Threaded View

  1. #1
    WasserEsser's Avatar
    Join Date
    Jul 2015
    Gender
    male
    Posts
    735
    Reputation
    174
    Thanks
    677
    My Mood
    Busy

    Understanding Pattern Scanning

    This post is for people that know how to code but don't know what pattern scanning is. It's meant as an informative post and i'm more than open to critism. I'd also like you to spot any errors / mistakes / false information so i can fix them as soon as possible.

    Intro

    Since alot of people have problems understanding the concept of pattern scanning and how to implement it into their own cheats, i quickly wanted to cover the concept of pattern scanning and how to implement it. My goal of this article is to teach you the concept so you can implement it into your own code and apply it to any game.

    What is pattern scanning?

    When you write your program in C++, the code is getting compiled into machine code. The Visual C++ compiler compiles the code directly into binary, but we can use tools like OllyDbg, x64dbg or any other debugger to display it in assembly. In cheat developement we use so called offsets to access certain variables / addresses. These offsets are in most cases also used in memory to access certain data as described below. To eliminate the hassle with updating your cheat on every update by either grabbing the offsets yourself or using an offset dumper, you can implement pattern scanning. Depending on your implementation, you can provide your pattern scanning function a specific pattern which should be found inside of a range of bytes. It will scan over the bytes and find the address of where the desired offset is used, making it easy for you to copy it. This way you don't have to update your cheat whenever an offset changes, you only need to change the pattern if the code where it's used changes, which doesn't happen as often.

    What are offsets and how are they generated?


    Offsets are addresses, often used with another address, for example a player address. To understand offsets, you need to know about the size of datatypes. On a 32 bit machine, an integer if not otherwise specified is 4 bytes long. A bool is one byte long. These variables will later be layed out in memory at certain addresses. I'll show you an example by coding a small player class.


    Code:
    class CPlayer
    {
    public:
         CPlayer( int Health, int Team, int Armor, CVector Pos, bool Valid, bool Alive ) 
             : m_iHealth( Health ), m_iTeam( Team ), m_iArmor( Armor ), m_vecPosition( Pos ), m_bValidPlayer( Valid ), m_bIsAlive( Alive )
         {
     
         }
         ~CPlayer( )
         {
     
         }
    
         int m_iHealth;
         int m_iTeam;
         int m_iArmor;
    
         CVector m_vecPosition;
    
         bool m_bValidPlayer;
         bool m_bIsAlive;
    };
    If we instantiate a player object, give it dummy values and browse the memory region in cheat engine, we can rebuild our data structure.



    Here we can see our class layed out in memory, along with it's addresses. The address 18FDAC is our base address, the address of our player class. If the game wants to check if the player is valid, it might check the bool m_bIsValid inside this class. In most cases, the address of the player is saved in one of the registers. The game will most likely have an instruction like

    Code:
    mov eax, [ecx + 00000018]
    0x18 is called an offset. To access the boolean m_bIsValid, we use the address of the player + 0x18. The same principle can be applied to any pointer. Static pointers that point to our player class for example might be accessed using the base address of a certain dynamic link library + an offset. If we can find the instruction where the address is accessed, we can read out our offset. Since the instruction is also stored in memory, we can simply read the .text section. In there we can find our offset. To be able to find the address where this offset is stored, we can use pattern scanning.

    How can i implement pattern scanning?


    Let's take an actual look at a game. I'll be using Counter-Strike: Global Offensive here as it's one of the most documented games out there. First, you need to know the current offset. Get it by either looking for it with cheat engine, using an offset dumper or visiting the offset thread. We attach Cheat Engine to our game and click on "Add Address Manually".



    I'll be using the health offset for our LocalPlayer for this example. I first add a pointer to our LocalPlayer, so we know the address of our LocalPlayer.



    Rightclick, show as decimal and you got the address of the LocalPlayer. Make sure to be in a bot game. Now we can take that address and add 0xFC onto it to access our health.



    You can also use the "Pointer" checkbox, however i only use it for multi-level pointers.

    Now rightclick it and click on "Find out what accesses this address". It will attach a debugger to the process and list you every instruction accessing the address.



    As we can see in the screenshot, the game accesses the address differently in different places. Interesting for us are the instructions that access our address using the offset we want to grab. The first instruction accesses our address by moving the value of ecx + 000000FC into the eax register. This instruction is somewhere in the .text section. We want to find it and read out the offset. If youv double click on the first instruction you can see more information about this instruction together with the register states after the instruction occured and the surrounding instructions. This information is useful for us. We can see that the ecx register holds the address of our LocalPlayer, and it accesses the health by copying the value of ecx + 000000FC. But there is one problem. The surrounding assembly instructions are most likely going to cause problems if the permutation of bytes is used in multiple places. It could find the wrong instructions and therefore may result in wrong results. We want to find a pattern which will result in a single result, meaning that the permutation of bytes are only present once in the entire chunck of bytes we search for our pattern in. Let's try the fourth instruction in the list. It looks much better as it doesn't have a bunch of int3 instructions, the actual instruction and a return instruction. Now rightclick, copy the information and paste it into an editor for now.

    Close Cheat Engine and open up OllyDbg. Make sure you have the SigMaker plugin installed. Attach OllyDbg to the game and wait for it to load.



    Once it's finished loading, rightclick, click on "Go to" and click on expression.



    Now you need to copy the address which contains the address of the instruction and paste it into the "Go to expression" dialog. Important is that you do not close your game inbetween copying the address from Cheat Engine and going to the address in OllyDbg or else it will most likely have a different address.



    Once done, you can scroll up a little bit to see the the surrounding instruction bytes at that instruction.

    The instructions can be found in the middle while the hexadecimal representation can be found on the left of the instructions.



    Since hexadecimal is base 16, each byte has to have 2 characters representing them.



    Now we need to make ourself a pattern. Like mentioned above, we want to make a pattern which can only be found once in the block of memory we copy.

    If we would now rightclick, Make Sig, Test Sig and click on Scan, we would end up with 6 results. We want to increase the size of the signature to assure that we only get one result.
    We can start further above, further down, as long as we can still count the byte difference. However, we don't want a signature which is too big or else it is much more likely that we have to update our pattern in the future. The instructions could change, so try to keep the pattern as small as possible while only getting one result. Let's start 1 line above and mark until the line underneath our instruction.



    You may have already noticed that the hexadecimal representation has our offset stored inside of it. It's stored in reverse order, though if we read it out later we will end up with the right address.



    Again, the pattern scanning function is iterating through the bytes until it finds the signature matching to the pattern.



    Once it found the place where it matches, it will return us depending on your implementation an address or an index. My pattern scanning function will return you an index so you can copy the offset directly from the filled allocated memory.



    But wait, let's assume the offset changed. It's now 0x100, the pattern on the right side wouldn't match with the bytes on the left side since FC000000 would be 00010000 now. That's what so called "wildcards" are for. Wildcards will skip bytes that might differ, for example the offset, but also other addresses that might change each time. Usually, the SigMaker plugin catches those addresses and replaces them with wildcards in the pop up window, however it didn't do it for this offset, probably since it's a very small address. Usually, it would replace those might changing addresses with \x00 in the pattern (also called signature ) and replace the according 'x' in the mask with a '?'. This time we have to do it manually. Since an address is four bytes long, we want to zero out the four bytes that store the address. Depending on your implementation, you might need the mask aswell, so make sure you change it aswell. Make sure that you only get one result by clicking on scan before you use the pattern. It only found the pattern once, which means we can use this pattern.

    Since i don't use a mask for my implementation, i only have to replace the \xFC with a \x00.





    Now we can code ourself a pattern scanning function. I'll be using my CPatternScan class which will load a module's bytes into the heap and will store it until the object is destroyed. At the end of this tutorial, you should've fully understood the concept of pattern scanning, and with a bit of thinking, you should be able to create your own pattern scanning class depending on your needs.

    Code:
    class CPatternScan
    {
        CPatternScan( )
        {
            Process = nullptr;
            Data = nullptr;
            Size = nullptr;
        }
    
        const CProcess* Process;
    
        std::unique_ptr< BYTE[ ] > Data;
    
        const DWORD* Size;
    
    public:
    
        CPatternScan( CProcess* Process, char* ModuleName )
        {
            if ( Process != nullptr && ModuleName != nullptr )
            {
                this->Process = Process;
    
                Size = this->Process->GetModuleSize( ModuleName );
    
                Data = std::make_unique< BYTE[ ] >( *Size );
    
                auto BytesRead{ SIZE_T( ) };
    
                if ( !ReadProcessMemory( *this->Process->GetHandle( ), reinterpret_cast< LPCVOID >( this->Process->GetModuleBaseAddress( ModuleName ) ), Data.get( ), *Size, &BytesRead ) || BytesRead != *Size )
                {
                    memset( &Data, 0, *Size );
                }
            }
    
        ~CPatternScan( )
        {
    
        }
    
        auto FindPattern( std::vector< BYTE > Pattern ) const -> DWORD
        {
    
            Pattern.shrink_to_fit( );
    
            for ( DWORD i = 0; i < *Size; i++ )
            {
                auto DoesMatch{ true };
    
                for ( DWORD j = 0; j < Pattern.size( ); j++ )
                {
                    if ( Pattern[ j ] == 0 ) continue;
                    if ( Pattern[ j ] == Data[ i + j ] ) { DoesMatch = false; break; }
                }
    
                if ( DoesMatch ) return i;
           }
    
           return 0;
        }
    
        auto GetOffset( DWORD Offset ) const -> DWORD
        {
            auto Buffer{ DWORD( 0 ) };
    
            memcpy( &Buffer, &Data[ Offset ], sizeof( DWORD ) );
    
            return Buffer;
        }
    
        auto GetOffset( std::vector< BYTE > Pattern, DWORD Offset ) const -> DWORD
        {
            return GetOffset( FindPattern( Pattern ) + Offset );
        }
    };
    Let's take a closer look at it. Once the object is created, i create a unique_ptr which will allocate space on the heap. Once this space is allocated, i copy the bytes of the dynamic link library into the allocated space on the heap. I use a vector for my pattern, with zeros ( 0x00 ) as wildcards. Once the pattern is found, i can return the index at which the pattern is found. I could also return the address at which the pattern is located in memory to read the offset from the original process, but since i already copied the entire dynamic link library, i can also copy the offset from the allocated space.

    But wait, did we miss something? Why is this not giving me the right offset? Well, let's take a look again. The function will return us the address at which the pattern is found, this means that it will return us this position ( a relative index in my case, it could also return you an address which you can read via ReadProcessMemory ):



    If you would read the next four bytes at the address the pattern scanning function returned, you would essentially read the following:



    This is obviously not the result you want, as it's not the offset you desired. This being said, you need to add your own offset on top of the returned address / index. Since we know that hexadecimal is base 16 and therefore needs 2 characters for one byte being displayed, the box we marked is all together four bytes long. Right after these four bytes is our desired offset. This means that you need to read / copy the address the function returned + 4 bytes. This would be the address / index where the offset is stored. Let's assume you want to read out the bytes 00 00 7F 2D. To get the right address, you need to count the bytes before the bytes you want read.

    In the above case it would be 7 bytes. Take the address / index the pattern scanning function returned and add 7 bytes on to it and you should end up with the right offset.

    Let's pick another example, this time with a static pointer to our LocalPlayer. If we perform a pointer scan in cheat engine, preferably multiple times to make sure every result is always pointing at our LocalPlayer we can see multiple pointers that point to the address of our LocalPlayer. Let's try to make a pattern for the LocalPlayer pointer which we used earlier to make ourself a health offset pattern.

    We scan multiple times by rescanning over the previous results after restarting the game. This will eliminate temporary pointers and show us the pointers that seem to always pointer at our LocalPlayer.



    The first result is a valid pointer to our LocalPlayer. Since almost everyone who uses a LocalPlayer pointer uses it, so we could try and create a signature using that pointer.

    If we doubleclick, the pointer gets added to our address list. Rightclicking and clicking on "Find out what accesses this address" brings up a different dialog now. We can either find out what accesses the pointer itself ( which we want to grab ) or find out what accesses the address pointed to by this pointer. We want to grab the pointer itself, so we click on "Find out what accesses this pointer".

    But wait, there is only one instruction that accesses this pointer at this point in time and it doesn't contain the actual offset in it's instruction. How should we grab it?



    We could look for surrounding instructions by clicking on the instruction, then on "Show Dissasembly" and see how the instructions are formed and accessed, but we don't want to bother with that now, we have many other pointers that point to our LocalPlayer, so we'll just take a look at a different one.

    So let's take the next one, client.dll + 4A98144. Double click it to add it to our address list and find out what accesses this pointer. We can see alot of instructions that move registers, so we can't read out the registers without hooking the function and reading out the registers at that point of time. But we also have instructions that contian an absolute address. By clicking on it once, we can see that this absolute address is formed of client.dll + 4A98164, meaning it's a static global pointer which is always going to be at the base address of the client.dll module + 4A98164. But if we compare that offset to our offset in the pointer list, we can see that it differs by 10 bytes. How come? Let's add the pointer to our list and browse the memory region it points to. The current pointer in the list points to the address the first entry in the player class points to, so we can't browse this memory region.





    We can see alot of addresses in this memory region, and with a closer look we can spot our LocalPlayer address in there, again saved in reverse order.



    With further investigation this turns out to be the EntityList, which contains pointers to every entity in the game. client.dll + 4A98164 always points to the world, while client.dll + 4A98174 points to the first entity in the world, which in a local bot game is our own player, since the bots spawn once we are on the server and "started" the server. This is differnt in online servers, we will rarely be the first entity in the list. I'm not going to go too much into detail about the source engine since this article is about pattern scanning, however, we can see that this is not a good pointer to our LocalPlayer since we are not always at the same position in this list.

    Let's take the next pointer in our pointer list. If we find out what accesses this address, we do again see a list with a different offset, so we can't read out our offset from these instructions.



    Onto the next pointer. This time we can see alot more instructions that access this pointer, together with the same offset every time. This could mean that it's a static global pointer again, being in the same address on every game start relative to the module's base address. If we click on the first instruction and take a look at the window at the bottom we can see that the absolute address in the instruction is formed out of client.dll + 4F2B50C, exactly what we can use, so let's double click this instruction and copy the information. But hey, we got a instruction which doesn't contain a lot of valueable instructions around it, meaning that it could be found in multiple places again, so we look for a different instruction which might have better surrounding instructions. Double clicking the next one gives us better surrounding instructions, so let's copy the information and paste it into an editor again.



    Close Cheat Engine, open up OllyDbg, attach to our process and go to the copied expression. After marking different parts of the bytes, i came up with the following which will give you one result when scanning for it.



    This time, the SigMaker plugin formed the right signature and mask out of the bytes in the hexadecimal representation, so we don't have to correct the pattern.



    Now, since we have a pointer to our LocalPlayer, we can dereference it / ReadProcessMemory it and grab the base address of our LocalPlayer, add the health offset and dereference it again / ReadProcessMemory it and read out our current health.
    Last edited by WasserEsser; 03-16-2016 at 10:17 AM.

  2. The Following 37 Users Say Thank You to WasserEsser For This Useful Post:

    ***HELLSANGEL*** (06-30-2016),1C4ST4W4Y1 (04-17-2018),a26401618 (10-01-2018),affe2626 (07-10-2016),canown (07-04-2016),cironio (07-08-2017),csgocheatxddd123 (06-04-2017),CyanRed3 (11-21-2016),Delision (11-30-2016),DonkeyHorse (08-23-2017),grannycrazy (01-06-2018),HexMurder (03-15-2016),Hunter (04-04-2016),ImStyL (05-06-2016),inieuwoudt1 (02-11-2019),iTzCode (08-21-2016),jonluke (09-28-2017),Josh155 (03-16-2016),KappaMang (03-16-2016),kollingmaster (12-06-2017),lordbatt29 (02-07-2021),mariogk2 (06-14-2016),Matrix Cow (01-17-2018),MegaProphet (05-12-2016),monsterx69 (05-13-2016),NightDev (03-17-2016),RowSkidrowAnon (12-11-2018),SP1K3CSGO (04-19-2016),suppmate (04-30-2019),Sytrux (12-13-2016),The.Asian (09-26-2016),The4byssWacther (04-15-2019),TheNamless (07-10-2016),Urzeitkrebs (09-07-2016),utlmamba (07-04-2016),vidsac (09-17-2017),Yemiez (03-16-2016)

Similar Threads

  1. Address Logger Pattern Scan Problems
    By [H]aaBX in forum Crossfire Coding Help & Discussion
    Replies: 8
    Last Post: 01-20-2014, 03:01 AM
  2. [Release] Pattern Scans
    By N3OH4X in forum Combat Arms Hack Coding / Programming / Source Code
    Replies: 19
    Last Post: 02-09-2013, 05:55 AM
  3. [Release] List of Patterns Scans
    By luizimloko in forum CrossFire Hack Coding / Programming / Source Code
    Replies: 13
    Last Post: 12-19-2012, 10:28 PM
  4. Pattern Scan
    By GoldWhite in forum Combat Arms Coding Help & Discussion
    Replies: 11
    Last Post: 11-27-2012, 11:15 AM
  5. [Help] Pattern scanning
    By pyton789 in forum Visual Basic Programming
    Replies: 27
    Last Post: 03-09-2011, 03:44 AM