Script search

Need Help With an Existing Feature in Memory Hacking Software? Ask Here

Moderators: g3nuin3, SpeedWing, WhiteHat, mezzo

Script search

Postby kai » Sat Sep 16, 2006 12:33 pm

I was wondering, how would I right a script search first, to see if a particular address were a certain value, say 154, then to look at the last charater of the hex address, and if it is not a 0, a C, a 4, or an 8, and to reject the address if it's not.

The reason I am doing this is because, right now I am trying to hack a game where there are a lot of units running around and there is a certain pattern to the addresses of their health and exp when they spawn in, as it is it is very tedious to search for the values over and over again as they change every time they level up, also, they each will have random attributes that will effect their max health or max exp before leveling so if I tried creating a template, I would have to put so many possibilties it would take forever! With their health addresses, they seem to be random, but they always have an ending hex character of a 0 or an 8, with exp, C or 4, I'm trying to do this because, on average, the search will yield tons of addresses when I search for a value in this particular game and with how small of a number their health usually is, they will die within 2 searches and it will have been in vain, I have looked at the found addresses and a lot of the useless values or always non 0,C,4, 0r 8 at the end, so if I was able to right a script search for this it would be very helpful
kai
Sir Hacks-A-Lot
 
Posts: 32
Joined: Sat Sep 16, 2006 12:17 pm
Location: The Not so Golden State

Postby AlaXul » Sun Sep 17, 2006 1:49 pm

Another possible way you could accomplish your goal would be use a program such as Olly Debugger or the one that comes with MHS. Simply find the DMA Value that you wish to change, like 154, then tell the assembler to break on access. This will list the static memory code that access the value and uses it in it's procedure. There you can simply modify the logic and set a static value to whatever you wish. This memory area would always be the same on every computer. You would never have to search for it again.
User avatar
AlaXul
Sir Hacks-A-Lot
 
Posts: 34
Joined: Thu Jul 27, 2006 7:50 am

Postby L. Spiro » Sun Sep 17, 2006 1:53 pm

In fact the phenomena you are observing has to do with alignment.
Alignment forces data values to be on addresses that are multiples of 1, 2, 4, or 8.

Your game either uses a 4-byte alignment or the character structures are simply created in such a way that your health just happens to always be on a 4th-byte address (and this is not a coincidence, and will always be the case).


Regardless of the alignment, when the game needs to allocate some memory, Windows® returns an address that is divisible by 4. This is because data aligned on 4-byte boundaries is faster to access/use.
The address Windows® gives to your game will be used by the game as the base of your player class.

From there, your health will always be the same distance away.
So if your health is 0x180 bytes from the base, it will then always be on an address divisible by 4 (?0, ?4, ?8, or ?C).



Because this is the most common way for data to be stored in games (as it improves speed), I have included an “Aligned” option in every search type (some may call it “Search Every Four Bytes”).


So luckily for you, you do not need to write any scripts just yet (however you are correct that a script can help you solve this problem).
In the Data-Type Search, just check Aligned.

Aligned searches should almost always be used in Data-Type Searches, Group Searches, and Script Searches.
Pointer Search always uses Aligned, so it is not an option.

Using a non-aligned search should only be done if an aligned search fails.


Also note that once you use Aligned searches, your searches will be 4 times faster (more good news for you).



If this does not solve the problem then I have misunderstood exactly what the problem is, so post back with more information and I will write a script function to handle it.


L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby kai » Mon Sep 18, 2006 1:25 am

This is what I mean, one guy's health is stored at 012E4720 with his experience at 01DE472C, the next guy might be 016AF9378 with 016AF9384 as is exp, with yet another at 0153BC20 with exp at 0I53BC2C, I have searched many times and found out that health is always at an address ending with a zero or an 8 and exp is always spaced 12 over from that. there are about 20 characters that I may be playing on the game with their addresses scattered everywhere through ram. Also there are anywhere from 15 to 35 enemy units on that map that get values of their oown. In addition to this, every time I start a new scenario or have one of them level up te address changes. They are on every fourth byte, i was just wondering, is there a way to only search 0's, or 8's for health or to be able to search for two values at once almost and only return addresses that meet criteria such as: search for value 105, then search for a value 35, twelve places after that.
I already search only every fourth byte with the 4 byte search if that's what you mean, if I were to search with a one or two byte then I would get results in the hundred thousands.
kai
Sir Hacks-A-Lot
 
Posts: 32
Joined: Sat Sep 16, 2006 12:17 pm
Location: The Not so Golden State

Postby L. Spiro » Mon Sep 18, 2006 10:45 am

Code: Select all
INT g_iCusHealth = 100;
INT g_iCusExp = 13000;
INT CustomSearch( LPVOID lpvAddress, LPVOID lpvBuffer, INT iSize ) {
   // Check that lpvAddress is divisible by 8 (change to anything
   //   you need).
   if ( (DWORD)lpvAddress % 0x8 == 0 ) {
      // Create a simple structure that maps the player class.
      // We only know the health and experience for now, and
      //   we know that the experience is 12 (0xC) bytes after
      //   the health.  Use meaningless values to buffer the
      //   space between.
      struct CUSDATA {
         INT iHealth;         // Offset 0x0.
         INT iBuffer0x04;      // Offset 0x4.
         INT iBuffer0x08;      // Offset 0x8.
         INT iExperience;      // Offset 0xC.
      };
      // If the size of the buffer is not large enough to hold
      //   this class, then of course it is not a valid value
      //   (note that if the size of the search data is specified
      //   before the search, iSize will always be large enough
      //   and this check can be removed to improve speed).
      if ( iSize >= sizeof( CUSDATA ) ) {
         // Cast the buffer to our data type.
         CUSDATA * pcdData = lpvBuffer;
         
         // Check the values we know.
         // Change g_iCusHealth and g_iCusExp to whatever values
         //   you like.
         if ( pcdData->iHealth == g_iCusHealth ) {
            if ( pcdData->iExperience == g_iCusExp ) {
               // Return the size of the structure to ensure
               //   compatibility with both types of Script
               //   Searches.
               return sizeof( CUSDATA );
            }
         }
      }
   }
   return 0;
}
// Decode the returned values in the result list.
VOID CustomDecoder( LPVOID lpvAddress, LPVOID lpvBuffer, DWORD dwLength, CHAR * pcReturn, INT iMaxLength ) {
   // Cast the buffer to our data type.
   CUSDATA * pcdData = lpvBuffer;
   // Print health and experience (and more if desired).
   SNPrintF( pcReturn, iMaxLength, "Health: %d.  Exp: %d", pcdData->iHealth, pcdData->iExperience );
}

// Create a function to wrap all of this together.
VOID CustomSearchSetup( INT * piDataSize, INT * piAlign, CHAR ** ppcCallback, CHAR ** ppcDecoder ) {
    // Size of the data is constant (and this allows us to remove the
    //   size check in CustomSearch() to improve speed).
    (*piDataSize) = sizeof( CUSDATA );

    // We can specify an 8-byte alignment here which eliminates the need
    //   for the “if ( (DWORD)lpvAddress % 0x8 == 0 ) {” code in
   //   CustomSearch().
    (*piAlign) = 8;

    // And the rest.
    (*ppcCallback) = "CustomSearch";
    (*ppcDecoder) = "CustomDecoder";
}



Now in the Script Search dialog, all you need to do is set it to Programmatic and specify CustomSearchSetup().
Modify g_iCusHealth and g_iCusExp as you need.
I set these as globals that are not constants because it allows you to change them on-the-fly programmatically.

In the future I will have dialogs boxes that will allow you to prompt the user for input.
You would ask the user for the health and experience values, change g_iCusHealth and g_iCusExp accordingly, and search.

Unfortunately those dialogs aren’t added yet, so there aren’t any good ways to change g_iCusHealth and g_iCusExp except by actually modifying the script and recompiling.



Modify as you please to suit your needs.


L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby kai » Mon Sep 18, 2006 11:16 am

Ahh, thank you very much! :D

So the only things I need to modify are the g_iCusHealth and g_CusEXP values?

Just checking so I don't mess anything up.
kai
Sir Hacks-A-Lot
 
Posts: 32
Joined: Sat Sep 16, 2006 12:17 pm
Location: The Not so Golden State

Postby L. Spiro » Mon Sep 18, 2006 11:52 am

Probably.

If you want to change the alignment (go back to 4 bytes) you have to change both of the 8’s to 4’s (“if ( (DWORD)lpvAddress % 0x8 == 0 ) {” and “(*piAlign) = 8;”).

You could make it easier to change alignments by changing them to a single global and then modify the global.
That is, if you ever find that the health lands on addresses other than ?0 and ?8.





The script is copy/paste and tested to work as long as you are searching for the correct health and experience.


As you find more values in your player structure, you can modify CUSDATA accordingly.


L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby kai » Mon Sep 18, 2006 12:19 pm

hmm... how do I add the search to the list on the script search dialog box? I put the script in the script editor, compiled it, saved it as custom-search in the memhack directory, then added it to the script list.
When I go to the dialog box even after reopening the Memory hacking software it neither shows up in the list for searching in the progammatic nor does it work when I type the name of the file in the box either with the extension or not.
Can you tell me what I am doing wrong? :oops:
kai
Sir Hacks-A-Lot
 
Posts: 32
Joined: Sat Sep 16, 2006 12:17 pm
Location: The Not so Golden State

Postby L. Spiro » Mon Sep 18, 2006 12:25 pm

In the help file:
Script Search


Enter “CustomSearchSetup” into the Setup Function, not the name of the script file.


L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby kai » Mon Sep 18, 2006 12:37 pm

it keeps giving me this error in the compiling process:

ERROR: Pos: 23 Unable to declare variable “g_iCusHealth” (identifier already declared). File: (null)

And CustomSearchSetup keeps giving me an error.
kai
Sir Hacks-A-Lot
 
Posts: 32
Joined: Sat Sep 16, 2006 12:17 pm
Location: The Not so Golden State

Postby L. Spiro » Mon Sep 18, 2006 2:20 pm

Did you post the code into two locations in your script set?


“Unable to declare variable “g_iCusHealth” (identifier already declared).” means just that.
You already declared g_iCusHealth somewhere else.

If this is really the case, you can just remove that line or comment it out.

Code: Select all
//INT g_iCusHealth = 100;
//INT g_iCusExp = 13000;




“File: (null)” is normal; it indicates an error outside of a function before any functions have been compiled (g_iCusHealth happens to be in front of all functions).



And CustomSearchSetup keeps giving me an error.

Everything indicates you posted the code into two locations in the script.


L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby kai » Tue Sep 19, 2006 7:41 am

Well, the only other place I can find the variable g_iHealth is:


Code: Select all
    if ( pcdData->iHealth == g_iCusHealth ) {
            if ( pcdData->iExperience == g_iCusExp ) {
               // Return the size of the structure to ensure
               //   compatibility with both types of Script
               //   Searches.
               return sizeof( CUSDATA );


And I only pasted once, so there is really no reason why it should be saying that from my point of view.
kai
Sir Hacks-A-Lot
 
Posts: 32
Joined: Sat Sep 16, 2006 12:17 pm
Location: The Not so Golden State

Postby L. Spiro » Tue Sep 19, 2006 3:03 pm

You can mail your Memory Hacking Software directory to yogurtemperor (ach) gmail (doch) com.

Then I can see exactly what the problem is.


L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby kai » Wed Sep 20, 2006 9:40 am

Ok here it comes.
kai
Sir Hacks-A-Lot
 
Posts: 32
Joined: Sat Sep 16, 2006 12:17 pm
Location: The Not so Golden State

Postby kai » Thu Sep 21, 2006 8:31 am

Did you get the email?

EDIT: Your Gmail won't allow me to send the attachment apparently, I got a message back from the email service that said that it wasn't okay to send the attachment, it probably detected the word hack or something and flipped out.
kai
Sir Hacks-A-Lot
 
Posts: 32
Joined: Sat Sep 16, 2006 12:17 pm
Location: The Not so Golden State

Next

Return to Help

Who is online

Users browsing this forum: No registered users and 0 guests