Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Pointer Scan Results parser in C or C++? PTR structure?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
grasmanek94
Master Cheater
Reputation: 0

Joined: 03 Jun 2008
Posts: 283
Location: The Netherlands

PostPosted: Sat Sep 28, 2013 4:35 pm    Post subject: Pointer Scan Results parser in C or C++? PTR structure? Reply with quote

I want to write my own program to compare different pointer scan results (eg finding a base pointer of a container with all players, all the offsets, etc).

I read the source file..
http://cheat-engine.googlecode.com/svn/trunk/Cheat%20Engine/PointerscanresultReader.pas (the class isn't really "convertable" for someone who only knows C++, like me)

But I don't really understand it that well..

Could someone help me a bit reconstruct the structure to read .ptr files in C++? Smile

P.S: name me crazy but the LEAST amount of pointers I can get is 20,000 in one pointer scan, others 50,000 etc.. so....

And,... I'm running this: XD


So what's running... VMWare with windows XP, NFS UG:2 in it, CE..

Then my host OS running 2 copies of NFS:UG2, cheatengine and Windows 8 xD

and what I do: Do pointer scan in one client, switch CE to another process for the same game, run pointer scan again, then open the pointer scan in vmware and rescan again, so I go down from around 50,000,000 results to 20,000. Then I restart all processes and repeat and seems it stays at 20,000
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25840
Location: The netherlands

PostPosted: Sat Sep 28, 2013 6:02 pm    Post subject: Reply with quote

Before you go this route, are you sure this problem isn't easier to solve using the structure spider ?
You can use that to figure out pointer paths from a specific base to a specific target and compare it with another different base

Quote:

P.S: name me crazy but the LEAST amount of pointers I can get is 20,000 in one pointer scan, others 50,000 etc.. so....

That's actually quite low.
Imagine the pointerscan as a routeplanner that returns every possible path you can go from your house to a specific shopping mall.
There's not just 1 way. there a thousands and if not millions of paths you can take to get there (some really long and inefficient)


anyhow, the structure of the pointerscanner main .ptr file:

(While I may have written this as a C compatible structure, it's not. Don't use it. The ptr file is just a stream of data)
Code:

uint32 modulelistlength;
struct {
  uint32 modulenamesize;
  char modulename[modulenamesize]; //no 0 terminator
} modulelist[modulelistlength]

uint32 maxlevel; //number of offsets in each row
uint32 numberofptrfiles;
struct
{
  uint32 ptrnamesize;
  char ptrname[ptrnamesize]; 

}  ptrfiles[numberofptrfiles]

Optional:
  uint32 NumberOfDistributedScanners
  uint32 WorkerID


number of entries in a .PTR file is filesize divided by (12+4*maxlevel)

The .PTR.# files are build up as:
Code:

  struct {
    int32 modulenr //the moduleid in the .ptr file (-1, -2, ... for thread stacks -1=threadstack0 -2=threadtack1)
    uint32 moduleoffset //the offset from the modulebase
    int32 offsetcount //the number of offsets this entry actually uses
    int32 offsets[maxlevel]
  } pointrresult[numberofentries]


Tip: NEVER load a full .ptr file into memory. If you wish to look up a specific entry just seek to the specific offset using the entrysize (12+4*maxlevel) and read from there (that's why compression isn't an option)

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
grasmanek94
Master Cheater
Reputation: 0

Joined: 03 Jun 2008
Posts: 283
Location: The Netherlands

PostPosted: Sat Sep 28, 2013 6:37 pm    Post subject: Reply with quote

Oh didn't know the structure for PTR.0 is that easy! Very Happy

Well, my end-pointer files are a total of 4 mb (after many rescans, they were 16GB+).

I really suck at using the spider, If I only knew how to effectively use it, Cheat Engine is so awesome, I use it for like, since I was 10! (i'm now 19) and I still have only mastered 1% or something of all its features.

I really appreciate your work and look up to you :O

Really, thanks for the structure! this means alot to me!

And P.S. I am willing to learn how to effectively use the spider, but a nice 1H long video walkthroug is something I need Smile

Edit:
Hehe I love you <3 (no gay feelings)



Code:

//--------------------------------------------------------------------------------------------------
#include <iostream>
#include <unordered_map>
#include <map>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <array>
#include <Windows.h>
//--------------------------------------------------------------------------------------------------
struct PointerEntry
{
   int modulenr; //the moduleid in the .ptr file (-1, -2, ... for thread stacks -1=threadstack0 -2=threadtack1)
   unsigned int moduleoffset; //the offset from the modulebase
   int offsetcount; //the number of offsets this entry actually uses
   int offsets[8];
};
//--------------------------------------------------------------------------------------------------
//moduleoffset,offsets
//
   std::unordered_map<
      unsigned int,
      std::unordered_map<
         int,
         std::vector<
            std::pair<int,std::array<int,8>>
         >
      >
   >
   DATA;
//

std::string string_format(const std::string fmt, ...)
{
   int size = 512;
   std::string str;
   va_list ap;
   while (1) {
      str.resize(size);
      va_start(ap, fmt);
      int n = vsnprintf((char *)str.c_str(), size, fmt.c_str(), ap);
      va_end(ap);
      if (n > -1 && n < size) {
         str.resize(n);
         return str;
      }
      if (n > -1)
         size = n + 1;
      else
         size *= 2;
   }
   return str;
}

std::ifstream& operator>>(std::ifstream& stream, PointerEntry &info)
{
   stream.read(reinterpret_cast<char*>(&info.modulenr), sizeof(int));
   stream.read(reinterpret_cast<char*>(&info.moduleoffset), sizeof(unsigned int));
   stream.read(reinterpret_cast<char*>(&info.offsetcount), sizeof(int));
   stream.read(reinterpret_cast<char*>(&info.offsets), sizeof(int)*8);
   return stream;
}
std::stringstream& operator<<(std::stringstream& stream, PointerEntry &info)
{
   stream.write(reinterpret_cast<char*>(&info.modulenr), sizeof(int));
   stream.write(reinterpret_cast<char*>(&info.moduleoffset), sizeof(unsigned int));
   stream.write(reinterpret_cast<char*>(&info.offsetcount), sizeof(int));
   stream.write(reinterpret_cast<char*>(&info.offsets), sizeof(int)*8);
   return stream;
}

std::pair<std::array<int,8>,int> GetDifference(std::array<int,8> &first, std::array<int,8> &second)
{
   std::array<int,8> xx =
   {
      abs(second[0]-first[0]),
      abs(second[1]-first[1]),
      abs(second[2]-first[2]),
      abs(second[3]-first[3]),
      abs(second[4]-first[4]),
      abs(second[5]-first[5]),
      abs(second[6]-first[6]),
      abs(second[7]-first[7])
   };
   return std::pair<std::array<int,8>,int>(xx,xx[0]+xx[1]+xx[2]+xx[3]+xx[4]+xx[5]+xx[6]+xx[7]);
}

int main()
{
   int iterations[3] = {154,94,86};
   std::ifstream file_process;
   int read = 0;
   int attempts = 0;
   int entries = 0;
   int unique_removed = 0;
   for(int i = 0; i < 3; ++i)
   {
      for(int j = 0; j < iterations[i]; ++j)
      {
         file_process.open(string_format("./data/%d.%d",j,i).c_str(),std::ios::binary);
         if(file_process.good())
         {
            while(!file_process.eof())
            {
               PointerEntry temp;
               file_process >> temp;
               std::array<int,8> arraytemp = {temp.offsets[0],temp.offsets[1],temp.offsets[2],temp.offsets[3],temp.offsets[4],temp.offsets[5],temp.offsets[6],temp.offsets[7]};
               DATA[temp.moduleoffset][i].push_back(std::pair<int,std::array<int,8>>(temp.offsetcount,arraytemp));
               ++entries;
            }
            file_process.close();
            read++;
         }
         attempts++;
      }
   }

   std::unordered_map<unsigned int,
      std::unordered_map<
         int,
         std::vector<
            std::pair<int,std::array<int,8>>
         >
      >>::iterator itr = DATA.begin();
   while (itr != DATA.end()) {
      if ((*itr).second.size() != 3) {
         DATA.erase(itr++);
         ++unique_removed;//nothing to compare if the pointer is unique bitch
      } else {
         ++itr;
      }
   }   


   struct compared
   {
      int baseoffset;
      int offsets;
      std::array<std::array<int,8>,2> offset_data;
   };
   //compare least offsets
   //loop all offsets
   for(auto i: DATA)
   {
      //compare index 0 entries against index 1
      int minimumdiff[3] = {999999999,999999999,999999999};
      compared current[3];

      //idx 0...
      for(auto j: i.second[0])
      {
         //...with idx 1
         for(auto k: i.second[1])
         {
            //check if amount of offsets is the same
            if(j.first == k.first)
            {
               //get difference :)
               int diff = GetDifference(j.second,k.second).second;
               //offsets are the same with same base addresses... erm.. ignore !!!!duplicate!!!!
               if(diff > 0)
               {
                  //is the difference smaller than the last one?
                  if(diff < minimumdiff[0])
                  {
                     minimumdiff[0] = diff;
                     current[0].baseoffset = i.first;
                     current[0].offsets = j.first;
                     current[0].offset_data[0] = j.second;
                     current[0].offset_data[1] = k.second;
                  }
               }
            }
         }
      }

      for(auto j: i.second[0])
      {
         for(auto k: i.second[2])
         {
            if(j.first == k.first)
            {
               int diff = GetDifference(j.second,k.second).second;
               if(diff > 0)
               {
                  if(diff < minimumdiff[1])
                  {
                     minimumdiff[1] = diff;
                     current[1].baseoffset = i.first;
                     current[1].offsets = j.first;
                     current[1].offset_data[0] = j.second;
                     current[1].offset_data[1] = k.second;
                  }
               }
            }
         }
      }

      for(auto j: i.second[1])
      {
         for(auto k: i.second[2])
         {
            if(j.first == k.first)
            {
               int diff = GetDifference(j.second,k.second).second;
               if(diff > 0)
               {
                  if(diff < minimumdiff[2])
                  {
                     minimumdiff[2] = diff;
                     current[2].baseoffset = i.first;
                     current[2].offsets = j.first;
                     current[2].offset_data[0] = j.second;
                     current[2].offset_data[1] = k.second;
                  }
               }
            }
         }
      }

      //print results for this base address
      std::string tempstring[2] = {"",""};

      for(int k = 0; k < 2; ++k)
         for(int j = 0; j < current[0].offsets; ++j)
            tempstring[k].insert(0,string_format("[%02x]",current[0].offset_data[k][j]));
      std::cout << string_format("[%08x][0]->[1]",current[0].baseoffset).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[0].c_str()).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[1].c_str()).c_str() << std::endl;
      tempstring[0].clear();
      tempstring[1].clear();

      for(int k = 0; k < 2; ++k)
         for(int j = 0; j < current[1].offsets; ++j)
            tempstring[k].insert(0,string_format("[%02x]",current[1].offset_data[k][j]));
      std::cout << string_format("[%08x][1]->[2]",current[1].baseoffset).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[0].c_str()).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[1].c_str()).c_str() << std::endl;
      tempstring[0].clear();
      tempstring[1].clear();

      for(int k = 0; k < 2; ++k)
         for(int j = 0; j < current[2].offsets; ++j)
            tempstring[k].insert(0,string_format("[%02x]",current[2].offset_data[k][j]));
      std::cout << string_format("[%08x][0]->[2]",current[2].baseoffset).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[0].c_str()).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[1].c_str()).c_str() << std::endl;
      tempstring[0].clear();
      tempstring[1].clear();
   }
   std::cout << "Read " << read << " Files from " << attempts << " attempted reads, removed " << unique_removed << " entries from " << entries << " loaded. There are " << DATA.size() << " unique base addresses to analyse." << std::endl;

   while(!GetAsyncKeyState('Q')){}
   return 0;
}


or the "only one difference" code:
Code:

//--------------------------------------------------------------------------------------------------
#include <iostream>
#include <unordered_map>
#include <map>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <array>
#include <Windows.h>
//--------------------------------------------------------------------------------------------------
struct PointerEntry
{
   int modulenr; //the moduleid in the .ptr file (-1, -2, ... for thread stacks -1=threadstack0 -2=threadtack1)
   unsigned int moduleoffset; //the offset from the modulebase
   int offsetcount; //the number of offsets this entry actually uses
   int offsets[8];
};
//--------------------------------------------------------------------------------------------------
//moduleoffset,offsets
//
   std::unordered_map<
      unsigned int,
      std::unordered_map<
         int,
         std::vector<
            std::pair<int,std::array<int,8>>
         >
      >
   >
   DATA;
//

std::string string_format(const std::string fmt, ...)
{
   int size = 512;
   std::string str;
   va_list ap;
   while (1) {
      str.resize(size);
      va_start(ap, fmt);
      int n = vsnprintf((char *)str.c_str(), size, fmt.c_str(), ap);
      va_end(ap);
      if (n > -1 && n < size) {
         str.resize(n);
         return str;
      }
      if (n > -1)
         size = n + 1;
      else
         size *= 2;
   }
   return str;
}

std::ifstream& operator>>(std::ifstream& stream, PointerEntry &info)
{
   stream.read(reinterpret_cast<char*>(&info.modulenr), sizeof(int));
   stream.read(reinterpret_cast<char*>(&info.moduleoffset), sizeof(unsigned int));
   stream.read(reinterpret_cast<char*>(&info.offsetcount), sizeof(int));
   stream.read(reinterpret_cast<char*>(&info.offsets), sizeof(int)*8);
   return stream;
}
std::stringstream& operator<<(std::stringstream& stream, PointerEntry &info)
{
   stream.write(reinterpret_cast<char*>(&info.modulenr), sizeof(int));
   stream.write(reinterpret_cast<char*>(&info.moduleoffset), sizeof(unsigned int));
   stream.write(reinterpret_cast<char*>(&info.offsetcount), sizeof(int));
   stream.write(reinterpret_cast<char*>(&info.offsets), sizeof(int)*8);
   return stream;
}

std::pair<std::array<int,8>,int> GetDifference(std::array<int,8> &first, std::array<int,8> &second)
{
   std::array<int,8> xx =
   {
      abs(second[0]-first[0]),
      abs(second[1]-first[1]),
      abs(second[2]-first[2]),
      abs(second[3]-first[3]),
      abs(second[4]-first[4]),
      abs(second[5]-first[5]),
      abs(second[6]-first[6]),
      abs(second[7]-first[7])
   };
   return std::pair<std::array<int,8>,int>(xx,xx[0]+xx[1]+xx[2]+xx[3]+xx[4]+xx[5]+xx[6]+xx[7]);
}

int main()
{
   int iterations[3] = {154,94,86};
   std::ifstream file_process;
   int read = 0;
   int attempts = 0;
   int entries = 0;
   int unique_removed = 0;
   for(int i = 0; i < 3; ++i)
   {
      for(int j = 0; j < iterations[i]; ++j)
      {
         file_process.open(string_format("./data/%d.%d",j,i).c_str(),std::ios::binary);
         if(file_process.good())
         {
            while(!file_process.eof())
            {
               PointerEntry temp;
               file_process >> temp;
               std::array<int,8> arraytemp = {temp.offsets[0],temp.offsets[1],temp.offsets[2],temp.offsets[3],temp.offsets[4],temp.offsets[5],temp.offsets[6],temp.offsets[7]};
               DATA[temp.moduleoffset][i].push_back(std::pair<int,std::array<int,8>>(temp.offsetcount,arraytemp));
               ++entries;
            }
            file_process.close();
            read++;
         }
         attempts++;
      }
   }

   std::unordered_map<unsigned int,
      std::unordered_map<
         int,
         std::vector<
            std::pair<int,std::array<int,8>>
         >
      >>::iterator itr = DATA.begin();
   while (itr != DATA.end()) {
      if ((*itr).second.size() != 3) {
         DATA.erase(itr++);
         ++unique_removed;//nothing to compare if the pointer is unique bitch
      } else {
         ++itr;
      }
   }   


   struct compared
   {
      int baseoffset;
      int offsets;
      std::array<std::array<int,8>,2> offset_data;
   };
   //compare least offsets
   //loop all offsets
   for(auto i: DATA)
   {
      //compare index 0 entries against index 1
      int minimumdiff[3] = {999999999,999999999,999999999};
      compared current[3];

      //idx 0...
      for(auto j: i.second[0])
      {
         //...with idx 1
         for(auto k: i.second[1])
         {
            //check if amount of offsets is the same
            if(j.first == k.first)
            {
               std::pair<std::array<int,8>,int> difcomp = GetDifference(j.second,k.second);
               int differeces = 0;
               for(int l = 0; l < 8; ++l)
               {
                  if(difcomp.first[l] != 0)
                     differeces++;
               }
               if(differeces == 1)
               {
                  //get difference :)
                  int diff = difcomp.second;
                  //offsets are the same with same base addresses... erm.. ignore !!!!duplicate!!!!
                  if(diff > 0)
                  {
                     //is the difference smaller than the last one?
                     if(diff < minimumdiff[0])
                     {
                        minimumdiff[0] = diff;
                        current[0].baseoffset = i.first;
                        current[0].offsets = j.first;
                        current[0].offset_data[0] = j.second;
                        current[0].offset_data[1] = k.second;
                     }
                  }
               }
            }
         }
      }

      for(auto j: i.second[0])
      {
         for(auto k: i.second[2])
         {
            if(j.first == k.first)
            {
               std::pair<std::array<int,8>,int> difcomp = GetDifference(j.second,k.second);
               int differeces = 0;
               for(int l = 0; l < 8; ++l)
               {
                  if(difcomp.first[l] != 0)
                     differeces++;
               }
               if(differeces == 1)
               {
                  int diff = difcomp.second;
                  if(diff > 0)
                  {
                     if(diff < minimumdiff[1])
                     {
                        minimumdiff[1] = diff;
                        current[1].baseoffset = i.first;
                        current[1].offsets = j.first;
                        current[1].offset_data[0] = j.second;
                        current[1].offset_data[1] = k.second;
                     }
                  }
               }
            }
         }
      }

      for(auto j: i.second[1])
      {
         for(auto k: i.second[2])
         {
            if(j.first == k.first)
            {
               std::pair<std::array<int,8>,int> difcomp = GetDifference(j.second,k.second);
               int differeces = 0;
               for(int l = 0; l < 8; ++l)
               {
                  if(difcomp.first[l] != 0)
                     differeces++;
               }
               if(differeces == 1)
               {
                  int diff = difcomp.second;
                  if(diff > 0)
                  {
                     if(diff < minimumdiff[2])
                     {
                        minimumdiff[2] = diff;
                        current[2].baseoffset = i.first;
                        current[2].offsets = j.first;
                        current[2].offset_data[0] = j.second;
                        current[2].offset_data[1] = k.second;
                     }
                  }
               }
            }
         }
      }

      //print results for this base address
      std::string tempstring[2] = {"",""};

      for(int k = 0; k < 2; ++k)
         for(int j = 0; j < current[0].offsets; ++j)
            tempstring[k].insert(0,string_format("[%02x]",current[0].offset_data[k][j]));
      std::cout << string_format("[%08x][0]->[1]",current[0].baseoffset).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[0].c_str()).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[1].c_str()).c_str() << std::endl;
      tempstring[0].clear();
      tempstring[1].clear();

      for(int k = 0; k < 2; ++k)
         for(int j = 0; j < current[1].offsets; ++j)
            tempstring[k].insert(0,string_format("[%02x]",current[1].offset_data[k][j]));
      std::cout << string_format("[%08x][1]->[2]",current[1].baseoffset).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[0].c_str()).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[1].c_str()).c_str() << std::endl;
      tempstring[0].clear();
      tempstring[1].clear();

      for(int k = 0; k < 2; ++k)
         for(int j = 0; j < current[2].offsets; ++j)
            tempstring[k].insert(0,string_format("[%02x]",current[2].offset_data[k][j]));
      std::cout << string_format("[%08x][0]->[2]",current[2].baseoffset).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[0].c_str()).c_str() << std::endl;
      std::cout << string_format("\t%s",tempstring[1].c_str()).c_str() << std::endl;
      tempstring[0].clear();
      tempstring[1].clear();
   }
   std::cout << "Read " << read << " Files from " << attempts << " attempted reads, removed " << unique_removed << " entries from " << entries << " loaded. There are " << DATA.size() << " unique base addresses to analyse." << std::endl;

   while(!GetAsyncKeyState('Q')){}
   return 0;
}


if anybody wants it... Smile
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites