 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
grasmanek94 Master Cheater
Reputation: 0
Joined: 03 Jun 2008 Posts: 283 Location: The Netherlands
|
Posted: Sat Sep 28, 2013 4:35 pm Post subject: Pointer Scan Results parser in C or C++? PTR structure? |
|
|
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++?
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 |
|
 |
Dark Byte Site Admin
Reputation: 471
Joined: 09 May 2003 Posts: 25840 Location: The netherlands
|
Posted: Sat Sep 28, 2013 6:02 pm Post subject: |
|
|
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 |
|
 |
grasmanek94 Master Cheater
Reputation: 0
Joined: 03 Jun 2008 Posts: 283 Location: The Netherlands
|
Posted: Sat Sep 28, 2013 6:37 pm Post subject: |
|
|
Oh didn't know the structure for PTR.0 is that easy!
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
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...
|
|
| Back to top |
|
 |
|
|
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
|
|