diff options
Diffstat (limited to 'aoe2hd/src')
-rwxr-xr-x | aoe2hd/src/CodeGenerator.cpp | 105 | ||||
-rwxr-xr-x | aoe2hd/src/CodeInjector.cpp | 171 | ||||
-rwxr-xr-x | aoe2hd/src/CodePatcher.cpp | 111 | ||||
-rwxr-xr-x | aoe2hd/src/ModuleMemory.cpp | 225 | ||||
-rwxr-xr-x | aoe2hd/src/main.cpp | 222 | ||||
-rwxr-xr-x | aoe2hd/src/native.c | 199 | ||||
-rwxr-xr-x | aoe2hd/src/utils.cpp | 19 |
7 files changed, 0 insertions, 1052 deletions
diff --git a/aoe2hd/src/CodeGenerator.cpp b/aoe2hd/src/CodeGenerator.cpp deleted file mode 100755 index cbae48d..0000000 --- a/aoe2hd/src/CodeGenerator.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "CodeGenerator.h" - -#include <assert.h> -#include <sstream> -#include <iomanip> - -#include "native.h" -#include "utils.h" - - -std::vector<unsigned char> x86_relJump(unsigned long dst, - unsigned long src) -{ - std::vector<unsigned char> code(5); - code[0] = 0xE9; - unsigned long addr = dst - src; - code[1] = (*((unsigned char *)(&addr)+0)); - code[2] = (*((unsigned char *)(&addr)+1)); - code[3] = (*((unsigned char *)(&addr)+2)); - code[4] = (*((unsigned char *)(&addr)+3)); - return code; -} - -CodeGenerator::CodeGenerator(const native_data& nd) - : nd(nd), codes() -{ -} - -CodeGenerator::~CodeGenerator() -{ -} - -CodeGenerator& CodeGenerator::addCode(const std::vector<unsigned char>& code) -{ - codes.push_back(code); - return *this; -} - -CodeGenerator& CodeGenerator::addCode(const std::string& code) -{ - return *this; -} - -CodeGenerator& CodeGenerator::setCode(int index, const std::vector<unsigned char>& code) -{ - codes.at(index) = code; - return *this; -} - -CodeGenerator& CodeGenerator::setCodeSized(int index, const std::vector<unsigned char>& code) -{ - assert(codes.at(index).size() == code.size()); - return setCode(index, code); -} - -CodeGenerator& CodeGenerator::setRel32JMP(int index, unsigned long dst, unsigned long src, bool reversed) -{ - if (!reversed) - { - dst += (unsigned long) nd.proc.modbase - diffRel32JMP(reversed, index); - } - else - { - src += (unsigned long) nd.proc.modbase + diffRel32JMP(reversed, index); - } - auto jmp = x86_relJump(dst, src); - setCodeSized(index, jmp); - return *this; -} - -std::vector<unsigned char>::size_type CodeGenerator::buildSize(int maxCodes) -{ - std::vector<unsigned char>::size_type total = 0; - for (auto& code : codes) - { - total += code.size(); - if (maxCodes-- == 0) - break; - } - return total; -} - -std::vector<unsigned char> CodeGenerator::build() -{ - std::vector<unsigned char> result; - for (auto& code : codes) - { - result.insert(result.end(), code.begin(), code.end()); - } - return result; -} - -std::vector<unsigned char> CodeGenerator::buildAndClear() -{ - auto result = build(); - clear(); - return result; -} - -std::string CodeGenerator::toString() -{ - std::stringstream out; - out << "CodeBin: " << utils::convertBinToHexstr(build()) << std::endl; - return out.str(); -} diff --git a/aoe2hd/src/CodeInjector.cpp b/aoe2hd/src/CodeInjector.cpp deleted file mode 100755 index 5f63d8f..0000000 --- a/aoe2hd/src/CodeInjector.cpp +++ /dev/null @@ -1,171 +0,0 @@ -#include <assert.h> - -#include <sstream> -#include <iomanip> -#include <algorithm> - -#include "CodeInjector.h" - -CodeInjector::CodeInjector(const native_data& nd) - : nd(nd) -{ - assert(nd.alloc_fn && nd.write_fn); -} - -CodeInjector::~CodeInjector() -{ -} - -bool CodeInjector::allocCodeSegment(const std::string& name, unsigned long siz) -{ - if (codeSegExists(name)) - return false; - code_seg seg = {0}; - seg.siz = siz; - seg.addr = nd.alloc_fn(&nd, siz); - if (!seg.addr) - return false; - code_map[name] = seg; - return true; -} - -bool CodeInjector::addCode(const std::string& name, const std::string& code_name, - const std::vector<unsigned char>& code) -{ - assert(code.size()); - if (!codeSegExists(name) - || codeBinExists(name, code_name)) - return false; - auto cave = findCodeCave(name, code.size()); - if (!cave) - return false; - code_bin bin = {0}; - bin.addr = cave; - bin.siz = code.size(); - if (!nd.write_fn(&nd, bin.addr, &code[0], bin.siz)) - return false; - code_map[name].children[code_name] = bin; - return true; -} - -bool CodeInjector::addCode(const std::string& name, const std::string& code_name, - const std::string& code) -{ - return false; -} - -bool CodeInjector::addCode(const std::string& name, const std::string& code_name, - unsigned long siz) -{ - assert(siz); - std::vector<unsigned char> code(siz, 0x90); - return addCode(name, code_name, code); -} - -bool CodeInjector::setCode(const std::string& name, const std::string& code_name, - const std::vector<unsigned char>& code, - unsigned long offset) -{ - assert(code.size()); - if (!codeSegExists(name) - || !codeBinExists(name, code_name)) - return false; - code_bin bin = {0}; - if (!getCodeBin(name, code_name, &bin)) - return false; - assert(bin.addr && bin.siz); - if (bin.addr + offset + code.size() > bin.addr + bin.siz) - return false; - return nd.write_fn(&nd, bin.addr + offset, &code[0], code.size()); -} - -bool CodeInjector::delCode(const std::string& name, const std::string& code_name) -{ - if (!codeBinExists(name, code_name)) - return false; - code_map[name].children[code_name]; - return code_map[name].children.erase(code_name) > 0; -} -unsigned long CodeInjector::getCodeAddr(const std::string& name, const std::string& code_name) -{ - assert(codeBinExists(name, code_name)); - assert(code_map[name].children[code_name].addr); - return code_map[name].children[code_name].addr; -} - -bool CodeInjector::getCodeSeg(const std::string& name, code_seg *seg) -{ - assert(seg); - if (!codeSegExists(name)) - return false; - *seg = code_map[name]; - return true; -} - -bool CodeInjector::getCodeBin(const std::string& name, const std::string& code_name, code_bin *bin) -{ - assert(bin); - if (!codeBinExists(name, code_name)) - return false; - *bin = code_map[name].children[code_name]; - return true; -} - -std::string CodeInjector::toString() -{ - std::stringstream out; - for (auto& code : code_map) - { - out << std::setw(16) << code.first << "[ " - << std::setw(8) << std::hex << code.second.addr << " , " - << std::setw(8) << std::hex << code.second.siz - << " ]" << std::endl; - for (auto& child : code.second.children) - { - out << std::setw(18) << child.first << "[ " - << std::setw(8) << std::hex << child.second.addr << " , " - << std::setw(6) << std::hex << child.second.siz - << " ]" << std::endl; - } - } - return out.str(); -} - -bool CodeInjector::codeBinExists(const std::string& name, const std::string& code_name) -{ - if (!codeSegExists(name)) - return false; - return code_map[name].children.find(code_name) - != code_map[name].children.end(); -} - -std::vector<code_bin> CodeInjector::convertCodeSegChildren(const std::string& name) -{ - auto cs = code_map[name].children; - std::vector<code_bin> ret; - ret.reserve(cs.size()); - std::for_each(cs.begin(), cs.end(), [&ret](std::pair<const std::string, code_bin> element) - { - ret.push_back(element.second); - }); - return ret; -} - -unsigned long CodeInjector::findCodeCave(const std::string& name, unsigned long siz) -{ - auto& cs = code_map[name]; - auto cl = convertCodeSegChildren(name); - std::sort(cl.begin(), cl.end()); - unsigned long end_addr = cs.addr; - for (auto& el : cl) - { - if (el.addr >= end_addr + siz) - { - return end_addr; - } - end_addr = el.addr + el.siz; - } - if (end_addr <= cs.addr + cs.siz) - return end_addr; - return 0; -} diff --git a/aoe2hd/src/CodePatcher.cpp b/aoe2hd/src/CodePatcher.cpp deleted file mode 100755 index be60680..0000000 --- a/aoe2hd/src/CodePatcher.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include <assert.h> - -#include <sstream> -#include <iomanip> - -#include "CodePatcher.h" -#include "utils.h" -#include "native.h" - - -CodePatcher::CodePatcher(const native_data& nd) - : nd(nd) -{ - assert(nd.read_fn && nd.write_fn && nd.suspend_fn); -} - -CodePatcher::~CodePatcher() -{ -} - -bool CodePatcher::addPatch(const std::string& name, - unsigned long addr, - const std::vector<unsigned char>& old_code, - const std::vector<unsigned char>& new_code, - long new_offset) -{ - assert(addr); - assert(old_code.size() == new_code.size()); - if (codePatchExists(name)) - return false; - code_patch patch = {0}; - patch.addr = (unsigned long) nd.proc.modbase + addr; - patch.old_code = old_code; - patch.new_code = new_code; - patch.new_offset = new_offset; - patch_map[name] = patch; - return true; -} - -void CodePatcher::setPatchSuspend(const std::string& name, long doSuspend) -{ - if (codePatchExists(name)) - patch_map[name].suspend = doSuspend; -} - -bool CodePatcher::doPatch(const std::string& name, int doUnPatch) -{ - if (!codePatchExists(name)) - return false; - auto& patch = patch_map[name]; - if (codeCmp(patch.addr + patch.new_offset, patch.new_code)) - return false; - if (patch.suspend) - nd.suspend_fn(&nd, 0); - bool ret = false; - if (doUnPatch) - { - ret = nd.write_fn(&nd, patch.addr, &patch.old_code[0], patch.old_code.size()); - } - else - { - ret = nd.write_fn(&nd, patch.addr, &patch.new_code[0], patch.new_code.size()); - } - if (patch.suspend) - nd.suspend_fn(&nd, 1); - return ret; -} - -bool CodePatcher::autoPatch(const std::string& name) -{ - if (!doPatch(name, 0)) - { - if (!doPatch(name, 1)) - return false; - return doPatch(name, 0); - } - return true; -} - -std::string CodePatcher::toString() -{ - std::stringstream out; - for (auto& patch : patch_map) - { - out << std::setw(16) << patch.first << "[ " - << std::setw(8) << std::hex << patch.second.addr << " , " - << std::setw(8) << std::hex << patch.second.new_offset - << " ]" << std::endl - << std::setw(23) << "Old: " - << utils::convertBinToHexstr(patch.second.old_code) << std::endl - << std::setw(23) << "New: " - << utils::convertBinToHexstr(patch.second.new_code) << std::endl; - } - return out.str(); -} - -bool CodePatcher::codeCmp(unsigned long addr, std::vector<unsigned char> code) -{ - if (code.size() == 0) - return true; - unsigned char buf[code.size()] = {0}; - if (!nd.read_fn(&nd, addr, &buf[0], code.size())) - return false; - /* TODO: replace with memcmp? */ - for (unsigned i = 0; i < code.size(); ++i) - { - if (buf[i] != code[i]) - return false; - } - return true; -} diff --git a/aoe2hd/src/ModuleMemory.cpp b/aoe2hd/src/ModuleMemory.cpp deleted file mode 100755 index 429b283..0000000 --- a/aoe2hd/src/ModuleMemory.cpp +++ /dev/null @@ -1,225 +0,0 @@ -#include <assert.h> - -#include <sstream> -#include <iomanip> -#include <vector> -#include <algorithm> - -#include "ModuleMemory.h" - -ModuleMemory::ModuleMemory(const native_data& nd) - : nd(nd), ptr_map(), ptr_read_count(0), ptr_invalid_count(0) -{ - assert(nd.read_fn && nd.iterate_fn); -} - -ModuleMemory::~ModuleMemory() -{ -} - -unsigned long ModuleMemory::scanProcMem(const std::string& name, const std::string& pattern, long offset, bool retPtr) -{ - unsigned long ret = scanPattern((unsigned long) nd.proc.modbase, nd.proc.modsize, pattern); - if (ret != (unsigned long) -1) - { - return (retPtr ? getPtr(name, (unsigned long) nd.proc.modbase, offset + ret) : - ((unsigned long) nd.proc.modbase + offset + ret)); - } - return (unsigned long) -1; -} - -unsigned long ModuleMemory::scanMappedMem(const std::string& name, const std::string& pattern, long offset, bool retPtr) -{ - unsigned long addr = 0; - unsigned long size = 0; - unsigned long ret; - do - { - addr += size; - iterate_mem(&nd, &addr, &size); - ret = scanPattern(addr, size, pattern); - if (ret != (unsigned long) -1) - return (retPtr ? getPtr(name, addr, offset + ret) : (addr + offset + ret)); - } - while (size); - return (unsigned long) -1; -} - -unsigned long ModuleMemory::getPtr(const std::string& name) -{ - bool valid = ptrExists(name) && ptrValid(name); - if (!valid) - return 0; - return ptr_map[name].ptr; -} - -unsigned long ModuleMemory::getPtr(const std::string& name, unsigned long *dest_ptr) -{ - assert(dest_ptr); - unsigned long ret = getPtr(name); - *dest_ptr = ret; - return ret; -} - -unsigned long ModuleMemory::getPtr(const std::string& name, unsigned long base, - long offset) -{ - target_ptr out = {0}; - out.base = base; - out.offset = offset; - out.valid = nd.read_fn(&nd, base + offset, &out.ptr, sizeof(out.ptr)); - ptr_map[name] = out; - if (out.valid) - { - ++ptr_read_count; - return out.ptr; - } - else - { - return 0; - } -} - -unsigned long ModuleMemory::recheckPtr(const std::string& name) -{ - if (!ptrExists(name)) - return 0; - target_ptr old = ptr_map[name]; - unsigned long new_ptr = getPtr(name, old.base, old.offset); - if (!new_ptr) - { - ptr_map[name].valid = false; - } - return new_ptr; -} - -void ModuleMemory::revalidateAllPtr() -{ -} - -bool ModuleMemory::getData(const std::string& name, void *buffer, unsigned long siz) -{ - assert(buffer); - if (!getPtr(name)) - return false; - if (!nd.read_fn(&nd, ptr_map[name].ptr, buffer, siz)) - { - ptr_map[name].valid = false; - } - return ptr_map[name].valid; -} - -bool ModuleMemory::ptrSetDependency(const std::string& name, const std::string& dependency) -{ - if (!getPtr(name) || !getPtr(dependency)) - return false; - ptr_map[name].dependency = dependency; - ptr_map[dependency].children.insert(name); - return true; -} - -std::string ModuleMemory::toString() -{ - std::stringstream out; - for (auto& ptr : ptr_map) - { - out << std::setw(16) << ptr.first << "[ " - << std::setw(8) << std::hex << ptr.second.base << " + " - << std::setw(8) << std::hex << ptr.second.offset << " = " - << std::setw(8) << std::hex << ptr.second.ptr << " , " - << std::setw(5) << (ptr.second.valid ? "TRUE" : "FALSE") << " , " - << std::setw(16) << (ptr.second.dependency.c_str() ? ptr.second.dependency.c_str() : "") - << " ]"; - for (auto& child : ptr.second.children) - { - out << ", " << child; - } - out << std::endl; - } - return out.str(); -} - -std::string ModuleMemory::toStringStats() -{ - std::stringstream out; - out << "PtrReadCount: " << ptr_read_count << " , " - << "PtrInvalidCount: " << ptr_invalid_count; - return out.str(); -} - -unsigned long ModuleMemory::scanPattern(unsigned long addr, unsigned long size, const std::string& pattern) -{ - unsigned char *buffer; - std::string new_pattern(pattern); - std::vector<unsigned char> binary_pattern; - unsigned long i, match_required, match_found; - - if (!size) - return (unsigned long) -1; - - buffer = new unsigned char [size]; - if (!nd.read_fn(&nd, addr, buffer, size)) - goto error; - - new_pattern.erase(std::remove_if(new_pattern.begin(), new_pattern.end(), isspace), new_pattern.end()); - - if (new_pattern.length() % 2) - goto error; - - match_required = 0; - for (i = 0; i < new_pattern.length(); i += 2) - { - char *endptr; - std::string byteString = new_pattern.substr(i, 2); - - if (byteString[0] == '?' && byteString[1] == '?') - { - binary_pattern.push_back(0x00); - continue; - } - - unsigned char byte = (unsigned char) strtoul(byteString.c_str(), &endptr, 16); - - if (endptr == byteString.c_str() || *endptr != 0x00) - goto error; - - match_required++; - binary_pattern.push_back(byte); - } - - match_found = 0; - for (i = 0; i < size; ++i) - { - for (size_t j = 0; i < size && j < binary_pattern.size(); ++j) - { - if (new_pattern[j*2] == '?' && new_pattern[j*2+1] == '?') - { - i++; - continue; - } - - if (buffer[i] == binary_pattern[j]) - { - i++; - match_found++; - } - else - { - match_found = 0; - break; - } - - if (match_found == match_required) - { - goto success; - } - } - } - -success: - delete buffer; - return (match_found == match_required ? i - binary_pattern.size() : (unsigned long) -1); -error: - delete buffer; - return (unsigned long) -1; -} diff --git a/aoe2hd/src/main.cpp b/aoe2hd/src/main.cpp deleted file mode 100755 index 521563f..0000000 --- a/aoe2hd/src/main.cpp +++ /dev/null @@ -1,222 +0,0 @@ -#include <windows.h> -#include <psapi.h> -#include <stdio.h> -#include <assert.h> - -#include <vector> -#include <iostream> -#include <iomanip> -#include <string> -#include <sstream> - -#include "CodeGenerator.h" -#include "CodePatcher.h" -#include "CodeInjector.h" -#include "ModuleMemory.h" -extern "C" { -#include "native.h" -#include "aoe2hd.h" -} - - -int main() -{ - using namespace std; - - native_data nd = {0}; - initNativeData(&nd); - - assert(get_module_proc(&nd, "Age of Empires II: HD Edition")); - assert(get_module_info(&nd, "AoK HD.exe")); - - ModuleMemory mm(nd); - printf("PlayerCurrent........: 0x%08lX\n", mm.scanProcMem("PlayerCurrent1", "C7 45 FC 01 00 00 00 C7 05 ?? ?? ?? ?? 00 00 00 00 8B 8E 30 01 00 00", 9)); - printf("PlayerCurrent........: 0x%08lX\n", mm.scanMappedMem("PlayerCurrent2", "C7 45 FC 01 00 00 00 C7 05 ?? ?? ?? ?? 00 00 00 00 8B 8E 30 01 00 00", 9)); - printf("PlayerNameArray......: 0x%08lX\n", mm.scanMappedMem("PlayerNameArray", "D8 1F ?? ?? 3E 00 00 00 80 2A ?? ?? 3E 00 00 00", 16)); - printf("PlayerNameArraySub1..: 0x%08lX\n", mm.getPtr("PlayerNameArraySub1", mm.getPtr("PlayerNameArray"), 0x5C)); - printf("PlayerStructArray....: 0x%08lX\n", mm.scanProcMem("PlayerStructArray", "01 34 47 30 01 AC A2 2E 01 00 00 00 00 9C F2 2F 01", -155)); - printf("PlayerStructArraySub1: 0x%08lX\n", mm.getPtr("PlayerStructArraySub1", mm.getPtr("PlayerStructArray"), 0xC8)); - printf("PlayerStructArraySub2: 0x%08lX\n", mm.getPtr("PlayerStructArraySub2", mm.getPtr("PlayerStructArraySub1"), 0x184)); - - mm.ptrSetDependency("PlayerNameArraySub1", "PlayerNameArray"); - mm.ptrSetDependency("PlayerStructArraySub1", "PlayerStructArray"); - mm.ptrSetDependency("PlayerStructArraySub2", "PlayerStructArraySub1"); - - for (unsigned long i = 1; i < 9; ++i) - { - stringstream player; - player << "Player" << i; - mm.getPtr(player.str(), (unsigned long) mm.getPtr("PlayerStructArraySub2"), 0x8 * i); - mm.ptrSetDependency(player.str(), "PlayerStructArraySub2"); - - stringstream player_res; - player_res << "Player" << i << "Resources"; - mm.getPtr(player_res.str(), (unsigned long) mm.getPtr(player.str()), 0x3C); - mm.ptrSetDependency(player_res.str(), player.str()); - - stringstream player_name; - player_name << "Player" << i << "Name"; - mm.getPtr(player_name.str(), (unsigned long) mm.getPtr("PlayerNameArraySub1"), 0xBC + (0x68 * (i-1))); - mm.ptrSetDependency(player_name.str(), "PlayerNameArraySub1"); - - printf("%s: 0x%08lX | Resources: 0x%08lX | Name: 0x%08lX\n", player.str().c_str(), mm.getPtr(player.str()), - mm.getPtr(player_res.str()), mm.getPtr(player_name.str())); - } - - printf("DRAW_HIGHSCORE_CALL..: 0x%08lX\n", mm.scanProcMem("DRAW_HIGHSCORE_CALL", "FF B5 7C FF FF FF 2B 8D 78 FF FF FF 8D 45 D8 50 51 52 8D 45 8C 50 8D 4D C0", 19, false)); - printf("DRAW_HIGHSCORE_FN....: 0x%08lX\n", mm.scanProcMem("DRAW_HIGHSCORE_FN", "55 8B EC 6A FF 68 ?? ?? ?? ?? 64 A1 ?? ?? ?? ?? 50 83 EC 38 A1 ?? ?? ?? ?? 33 C5 89 45 F0 53 56 57 50 8D 45 F4 64 A3 ?? ?? ?? ?? 8B F1 8B 5D 08", 0, false)); - - system("pause"); - - CodeInjector ci(nd); - assert(ci.allocCodeSegment("HighscoreHack")); - CodeGenerator original(nd), inject(nd); - - inject.addCode("8B 85 1C FF FF FF 8A 00 3C 89 0F 85 6B 00 00 00 60 8B 85 1C FF FF FF FF 48 05 83 85 14 FF FF FF 50" - "8B 85 14 FF FF FF C7 00 41 41 41 41 C7 40 04 42 42 42 42 FF B5 20 FF FF FF FF B5 1C FF FF FF" - "8B 85 14 FF FF FF 80 38 00 0F 84 03 00 00 00 40 EB F4 2B 85 14 FF FF FF 50 FF B5 14 FF FF FF" - "FF B5 10 FF FF FF E8 ?? ?? ?? ?? 61 8B 85 1C FF FF FF FF 40 05 83 AD 14 FF FF FF 50" - "E8 ?? ?? ?? ?? E9 ?? ?? ?? ??"); - -#if 0 - mm.getPtr("MainClass", nd.proc.modbase, 0x009C7774); - mm.getPtr("GameClass", mm.getPtr("MainClass"), 0x4); - mm.getPtr("PlayerArray", mm.getPtr("GameClass"), 0x184); - mm.getPtr("PlayerNameBase", nd.proc.modbase, 0x006DB62C); - mm.getPtr("PlayerNamePtr0", mm.getPtr("PlayerNameBase"), 0x794); - mm.getPtr("PlayerNamePtr1", mm.getPtr("PlayerNamePtr0"), 0x5C); - - mm.ptrSetDependency("GameClass", "MainClass"); - mm.ptrSetDependency("PlayerArray", "GameClass"); - mm.ptrSetDependency("PlayerNamePtr0", "PlayerNameBase"); - mm.ptrSetDependency("PlayerNamePtr1", "PlayerNamePtr0"); - - for (unsigned long i = 1; i < 9; ++i) - { - stringstream player; - player << "Player" << i; - mm.getPtr(player.str(), (unsigned long)mm.getPtr("PlayerArray"), 0x8 * i); - mm.ptrSetDependency(player.str(), "PlayerArray"); - - stringstream player_res; - player_res << "Player" << i << "Resources"; - mm.getPtr(player_res.str(), (unsigned long)mm.getPtr(player.str()), 0x3C); - mm.ptrSetDependency(player_res.str(), player.str()); - - stringstream player_name; - player_name << "Player" << i << "Name"; - mm.getPtr(player_name.str(), (unsigned long)mm.getPtr("PlayerNamePtr1"), 0xBC + (0x60 * (i-1))); - mm.ptrSetDependency(player_name.str(), "PlayerNamePtr1"); - } - - CodeInjector ci(nd); - assert(ci.allocCodeSegment("MapCode")); - CodePatcher cp(nd); - CodeGenerator original(nd), injected(nd); - - { - original.addCode({DUMMY5}); - injected.addCode({MAP_NOFOG0}).addCode({MAP_NOFOGI}).addCode({MAP_NOFOG1}).addCode({DUMMY5}); - - assert(ci.addCode("MapCode", "NoFog", injected.buildSize())); - injected.setRel32JMP(3, MAP_NOFOG, ci.getCodeAddr("MapCode", "NoFog")); - ci.setCode("MapCode", "NoFog", injected.buildAndClear()); - - original.setRel32JMP(0, ci.getCodeAddr("MapCode", "NoFog"), MAP_NOFOG, true).addCode({0x90}); - assert(cp.addPatch("NoFog", MAP_NOFOG, {MAP_NOFOG0,MAP_NOFOG1}, original.buildAndClear())); - cp.setPatchSuspend("NoFog", 1); - assert(cp.autoPatch("NoFog")); - } - { - original.addCode({DUMMY5}); - injected.addCode({MAP_MINI0}).addCode({MAP_MINII}).addCode({MAP_MINI1}).addCode({DUMMY5}); - - assert(ci.addCode("MapCode", "MiniMap", injected.buildSize())); - injected.setRel32JMP(3, MAP_MINI, ci.getCodeAddr("MapCode", "MiniMap")); - ci.setCode("MapCode", "MiniMap", injected.buildAndClear()); - - original.setRel32JMP(0, ci.getCodeAddr("MapCode", "MiniMap"), MAP_MINI, true).addCode({0x90,0x90,0x90,0x90}); - assert(cp.addPatch("MiniMap", MAP_MINI, {MAP_MINI0,MAP_MINI1}, original.buildAndClear())); - cp.setPatchSuspend("MiniMap", 1); - assert(cp.autoPatch("MiniMap")); - } - { - original.addCode({DUMMY5}); - injected.addCode({MAP_SMTH0}).addCode({MAP_SMTHI}).addCode({MAP_SMTH1}).addCode({DUMMY5}) - .addCode({DUMMY5,DUMMY5,DUMMY5,DUMMY5,DUMMY5}); - - assert(ci.addCode("MapCode", "Smth", injected.buildSize())); - injected.setRel32JMP(3, MAP_SMTH, ci.getCodeAddr("MapCode", "Smth")); - ci.setCode("MapCode", "Smth", injected.buildAndClear()); - - original.setRel32JMP(0, ci.getCodeAddr("MapCode", "Smth"), MAP_SMTH, true).addCode({0x90,0x90,0x90,0x90}); - assert(cp.addPatch("Smth", MAP_SMTH, {MAP_SMTH0,MAP_SMTH1}, original.buildAndClear())); - cp.setPatchSuspend("Smth", 1); - assert(cp.autoPatch("Smth")); - } - { - original.addCode({DUMMY5}); - injected.addCode({MAP_UNIT0}).addCode({MAP_UNITI}).addCode({MAP_UNIT1}).addCode({DUMMY5}); - - assert(ci.addCode("MapCode", "Units", injected.buildSize())); - injected.setRel32JMP(3, MAP_UNIT, ci.getCodeAddr("MapCode", "Units")); - ci.setCode("MapCode", "Units", injected.buildAndClear()); - - original.setRel32JMP(0, ci.getCodeAddr("MapCode", "Units"), MAP_UNIT, true).addCode({0x90,0x90,0x90,0x90,0x90}); - assert(cp.addPatch("Units", MAP_UNIT, {MAP_UNIT0,MAP_UNIT1}, original.buildAndClear())); - cp.setPatchSuspend("Units", 1); - assert(cp.autoPatch("Units")); - } - - cout << ci.toString() << endl; - cout << cp.toString() << endl; - cout << "[PRESS A KEY TO CONTINUE]" << endl; - system("pause"); -#endif - - while (1) - { - cls( GetStdHandle( STD_OUTPUT_HANDLE )); - - while (!mm.recheckPtr("PlayerStructArray")) - { - Sleep(1000); - } - mm.revalidateAllPtr(); - - for (unsigned long i = 1; i < 9; ++i) - { - - stringstream player_res; - player_res << "Player" << i << "Resources"; - struct resources res = {0}; - if (!mm.getData(player_res.str(), &res, sizeof(res))) - { - continue; - } - - cout << "player[" << i << "]: " - << "wood.: " << setw(8) << dec << (unsigned long)res.wood << ", " - << "food.: " << setw(8) << dec << (unsigned long)res.food << ", " - << "gold.: " << setw(8) << dec << (unsigned long)res.gold << ", " - << "stone: " << setw(8) << dec << (unsigned long)res.stone << endl; - cout << " " << setw(8) - << "rpop.: " << setw(8) << dec << res.remainingPop << ", " - << "tpop.: " << setw(8) << dec << res.currentPop << endl; - - stringstream player_name; - player_name << "Player" << i << "Name"; - char name[32] = {0}; - mm.getData(player_name.str(), &name, 31); - cout << " " << name << endl; - } - - //cout << mm.toString() << endl; - //cout << mm.toStringStats() << endl; - //system("pause"); - Sleep(1000); - } - CloseHandle(nd.proc.hndl); - - return 0; -} diff --git a/aoe2hd/src/native.c b/aoe2hd/src/native.c deleted file mode 100755 index 5186e6d..0000000 --- a/aoe2hd/src/native.c +++ /dev/null @@ -1,199 +0,0 @@ -#include <windows.h> -#include <psapi.h> -#include <stdio.h> -#include <stdbool.h> -#include <assert.h> - -#include "native.h" - - -typedef LONG (NTAPI *NtSuspendProcess)(IN HANDLE ProcessHandle); -typedef LONG (NTAPI *NtResumeProcess)(IN HANDLE ProcessHandle); - -/* Standard error macro for reporting API errors */ -#define PERR(bSuccess, api){if(!(bSuccess)) printf("%s:Error %ld from %s \ - on line %ld\n", __FILE__, GetLastError(), api, (long)__LINE__);} - -void initNativeData(native_data *nd) -{ - assert(nd); - nd->alloc_fn = mem_alloc; - nd->read_fn = read_procmem; - nd->write_fn = write_procmem; - nd->suspend_fn = suspendProcess; - nd->iterate_fn = iterate_mem; -} - -/* see: https://support.microsoft.com/en-us/help/99261/how-to-performing-clear-screen-cls-in-a-console-application */ -void cls(HANDLE hConsole) -{ - COORD coordScreen = { 0, 0 }; /* here's where we'll home the - cursor */ - BOOL bSuccess; - DWORD cCharsWritten; - CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ - DWORD dwConSize; /* number of character cells in - the current buffer */ - - /* get the number of character cells in the current buffer */ - - bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi ); - PERR( bSuccess, "GetConsoleScreenBufferInfo" ); - dwConSize = csbi.dwSize.X * csbi.dwSize.Y; - - /* fill the entire screen with blanks */ - - bSuccess = FillConsoleOutputCharacter( hConsole, (TCHAR) ' ', - dwConSize, coordScreen, &cCharsWritten ); - PERR( bSuccess, "FillConsoleOutputCharacter" ); - - /* get the current text attribute */ - - bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi ); - PERR( bSuccess, "ConsoleScreenBufferInfo" ); - - /* now set the buffer's attributes accordingly */ - - bSuccess = FillConsoleOutputAttribute( hConsole, csbi.wAttributes, - dwConSize, coordScreen, &cCharsWritten ); - PERR( bSuccess, "FillConsoleOutputAttribute" ); - - /* put the cursor at (0, 0) */ - - bSuccess = SetConsoleCursorPosition( hConsole, coordScreen ); - PERR( bSuccess, "SetConsoleCursorPosition" ); - return; -} - -bool get_module_proc(native_data *nd, LPCTSTR window_name) -{ - HWND hwnd; - - assert(window_name); - hwnd = FindWindow(NULL, window_name); - if (!hwnd) - goto error; - GetWindowThreadProcessId(hwnd, &nd->proc.pid); - if (!nd->proc.pid) - goto error; - nd->proc.hndl = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION - | PROCESS_VM_READ | PROCESS_VM_WRITE, 0, nd->proc.pid); -error: - return nd->proc.hndl != NULL; -} - -bool get_module_info(native_data *nd, LPCTSTR module_name) -{ - HMODULE hMods[1024]; - DWORD cbNeeded; - unsigned int i; - - assert(module_name); - if (EnumProcessModules(nd->proc.hndl, hMods, sizeof(hMods), &cbNeeded)) - { - for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) - { - TCHAR szModName[MAX_PATH]; - TCHAR szModPath[MAX_PATH]; - - if (GetModuleBaseName(nd->proc.hndl, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)) - && GetModuleFileNameEx(nd->proc.hndl, hMods[i], szModPath, - sizeof(szModPath) / sizeof(TCHAR))) - { - if (strncmp(szModName, module_name, MAX_PATH) == 0) - { - nd->proc.modbase = hMods[i]; - MODULEINFO modinfo; - if (GetModuleInformation(nd->proc.hndl, nd->proc.modbase, &modinfo, sizeof modinfo)) - nd->proc.modsize = modinfo.SizeOfImage; - else - return false; - - return true; - } - } - } - } - return false; -} - -bool read_procmem(const native_data *nd, unsigned long addr, - void *buffer, unsigned long siz) -{ - SIZE_T bytes_read = 0; - unsigned long *vmptr = (unsigned long *)addr; - - assert(buffer && siz); - if (!ReadProcessMemory(nd->proc.hndl, vmptr, buffer, siz, &bytes_read)) - return false; - if (bytes_read != siz) - return false; - - return true; -} - -bool write_procmem(const native_data *nd, unsigned long addr, const void *buffer, unsigned long siz) -{ - SIZE_T bytes_written = 0; - unsigned long *vmptr = (unsigned long *)addr; - - assert(addr && buffer && siz); - if (!WriteProcessMemory(nd->proc.hndl, vmptr, buffer, siz, &bytes_written)) - return false; - if (bytes_written != siz) - return false; - - return true; -} - -unsigned long mem_alloc(const native_data *nd, unsigned long siz) -{ - return (unsigned long)VirtualAllocEx(nd->proc.hndl, NULL, siz, - MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE); -} - -/* see: https://github.com/mridgers/clink/issues/420 */ -bool suspendProcess(const native_data *nd, int doResume) -{ - bool ret = false; - NtSuspendProcess pfnNtSuspendProcess = - (NtSuspendProcess)GetProcAddress(GetModuleHandle("ntdll"), "NtSuspendProcess"); - NtResumeProcess pfnNtResumeProcess = - (NtResumeProcess)GetProcAddress(GetModuleHandle("ntdll"), "NtResumeProcess"); - - HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, nd->proc.pid); - if (!processHandle) - return false; - if (doResume) - { - if (pfnNtResumeProcess(processHandle) == 0) - ret = true; - } - else - { - if (pfnNtSuspendProcess(processHandle) == 0) - ret = true; - } - CloseHandle(processHandle); - return ret; -} - -unsigned long iterate_mem(const native_data *nd, - unsigned long *addr, - unsigned long *size) -{ - MEMORY_BASIC_INFORMATION info; - SIZE_T ret; - - ret = VirtualQueryEx(nd->proc.hndl, (LPCVOID) *addr, &info, sizeof info); - if (ret != sizeof(info)) - goto error; - *addr = (unsigned long) info.BaseAddress; - *size = info.RegionSize; - return info.State != MEM_COMMIT; -error: - *addr = 0; - *size = 0; - return 1; -} diff --git a/aoe2hd/src/utils.cpp b/aoe2hd/src/utils.cpp deleted file mode 100755 index 7639ab7..0000000 --- a/aoe2hd/src/utils.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "utils.h" - -#include <sstream> -#include <iomanip> - - -namespace utils -{ -std::string convertBinToHexstr(const std::vector<unsigned char>& bin) -{ - std::stringstream buffer; - for (auto byte : bin) - { - buffer << std::hex << std::setfill('0'); - buffer << std::setw(2) << static_cast<unsigned>(byte); - } - return buffer.str(); -} -} |