Last active
November 5, 2017 18:28
-
-
Save koemeet/618f7c8ad12c2fec21f17ea6d590e4b6 to your computer and use it in GitHub Desktop.
Dynamic recursive pointer scanner
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include "Scanner.h" | |
using namespace std; | |
int main() { | |
std::cout << "============= CHANSELISEE SCANNER ==============" << std::endl; | |
uintptr_t somePointer = 0x0000394884E; // put some pointer to for example your local player here | |
// start scanning from some base pointer. scan results are stored in scan_1.txt | |
Scanner scanner(somePointer, "scan_1.txt"); | |
scanner.setLevel(4); // max recursion level | |
scanner.setMaxOffset(0x600); // max offset per structure | |
// this callback will be used to check if the current offset path needs to be saved | |
scanner.setCallback([](uintptr_t address, void *data) -> bool { | |
int teamId = *reinterpret_cast<int*>(data); | |
// in this example the scan gets all offsets which have the value `1`. this will of course yiels a lot of offsets. | |
// the idea here is to save those results and do a second scan when you have rejoined in a different team. | |
if (teamId == 1) { | |
return true; | |
} | |
return false; | |
}); | |
// the first time you scan, don't provide any arguments, it will do a full scan. | |
scanner.scan(); | |
// the 2th+ times provide the latest scanfile, so you can filter out paths and ultimately find your offset path! | |
// scanner.scan("scan_1.txt"); | |
scanner.printFoundOffsets(); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Scanner.h" | |
#include <sstream> | |
#include <fstream> | |
Scanner::Scanner(uintptr_t base, char* outputFile) : base(base), outputFile(outputFile) | |
{ | |
} | |
void Scanner::scan(char *compareScan) | |
{ | |
cout << "Scanning..." << endl; | |
if (compareScan) { | |
// read scan file | |
std::ifstream input; | |
input.open(compareScan); | |
std::string line; | |
while (getline(input, line)) { | |
std::istringstream ss(line); | |
std::string token; | |
vector<int> path; | |
while (std::getline(ss, token, ',')) { | |
path.push_back(stoi(token)); | |
} | |
offsetsCompare.push_back(path); | |
} | |
scanStructureCompare(); | |
} | |
else { | |
scanStructure(base); | |
} | |
cout << "Found paths: " << offsetsFound.size() << endl; | |
cout << "Scanned addresses: " << scanCount << endl; | |
// write scan file | |
std::ofstream fs; | |
fs.open(outputFile, std::ofstream::out | std::ofstream::in | std::ofstream::trunc); | |
for (auto offsetPath : offsetsFound) { | |
std::stringstream ss; | |
for (int i = 0; i < offsetPath.size(); i++) { | |
if (i > 0) { | |
ss << ","; | |
} | |
ss << offsetPath[i]; | |
} | |
fs << ss.str() << endl; | |
} | |
fs.close(); | |
cout << "Written to file" << endl; | |
} | |
void Scanner::scanStructureCompare() | |
{ | |
/*for (auto offsets : offsetsCompare) { | |
uintptr_t address = base; | |
for (auto i = 0; i < offsets.size(); i++) { | |
if (i == offsets.size() - 1) | |
{ | |
if (callback(address + offsets[i])) { | |
offsetsFound.push_back(offsets); | |
} | |
break; | |
} | |
address = Read<uintptr_t>(address + offsets[i]); | |
} | |
}*/ | |
} | |
void Scanner::scanStructure(uintptr_t address, int level) | |
{ | |
scanCount++; | |
// skip if we exceed recursion limit | |
if (level > this->level) | |
{ | |
return; | |
} | |
level++; | |
// skip already processed addresses | |
//if (processed.find(address) != processed.end()) | |
//{ | |
// return; | |
//} | |
auto data = std::vector<byte>(maxOffset+0x4); | |
Read(address, maxOffset, data.data()); | |
auto found = false; | |
for (auto offset = 0; offset <= maxOffset; offset += 0x4) | |
{ | |
if (level == 1) | |
{ | |
printf("Offset: %x\n", offset); | |
} | |
auto pointer = *reinterpret_cast<uintptr_t*>(&data[offset]); | |
// add current offset to current offset path | |
currentPath.push_back(offset); | |
// check if this pointer agrees to the user-defined check | |
if (callback(address + offset, &data[offset])) { | |
offsetsFound.push_back(currentPath); | |
std::stringstream ss; | |
for (int i = 0; i < currentPath.size(); i++) { | |
if (i > 0) { | |
ss << "] + "; | |
} | |
ss << "0x" << hex << currentPath[i]; | |
} | |
cout << "Offset path: " << ss.str() << endl; | |
found = true; | |
} | |
// if it is a pointer, recursively scan it | |
if (pointer > 0x100000 && pointer < 0x7fffffffffff) { | |
scanStructure(pointer, level); | |
} | |
// we are leaving this offset, time to pop it | |
currentPath.pop_back(); | |
} | |
// we have fully processed this whole address tree | |
//if (!found) | |
//{ | |
// processed.emplace(address); | |
//} | |
} | |
void Scanner::printFoundOffsets() | |
{ | |
for (auto offsetPath : offsetsFound) { | |
std::stringstream ss; | |
for (int i = 0; i < offsetPath.size(); i++) { | |
if (i > 0) { | |
ss << "] + "; | |
} | |
ss << "0x" << hex << offsetPath[i]; | |
} | |
cout << "Offset path: " << ss.str() << endl; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <memory> | |
#include <iostream> | |
#include <unordered_set> | |
#include <vector> | |
#include <functional> | |
#include "../Memory/MemoryAware.h" | |
using namespace std; | |
class Scanner : protected Common::Memory::MemoryAware | |
{ | |
protected: | |
uintptr_t base; | |
char* outputFile; | |
function<bool(uintptr_t, void*)> callback; | |
int level = 1; | |
int maxOffset = 0x800; | |
int64_t scanCount = 0; | |
unordered_set<uintptr_t> processed; | |
vector<int> currentPath; | |
vector<vector<int>> offsetsFound; | |
vector<vector<int>> offsetsCompare; | |
public: | |
Scanner(uintptr_t base, char* outputFile); | |
void scan(char *compareScan = nullptr); | |
void scanStructureCompare(); | |
void setLevel(int level) | |
{ | |
this->level = level; | |
} | |
void setMaxOffset(int maxOffset) | |
{ | |
this->maxOffset = maxOffset; | |
} | |
void setCallback(function<bool(uintptr_t, void*)> f) | |
{ | |
callback = f; | |
} | |
vector<vector<int>> getFoundOffsets() | |
{ | |
return offsetsFound; | |
} | |
void printFoundOffsets(); | |
protected: | |
void scanStructure(uintptr_t address, int level = 0); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment