forked from ReScrap/ScrapHacks
Code cleanup
This commit is contained in:
parent
bef8fcbaaa
commit
ffbcc30427
14 changed files with 328 additions and 288 deletions
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"spellright.language": [
|
||||
"de"
|
||||
"en"
|
||||
],
|
||||
"spellright.documentTypes": [
|
||||
"markdown",
|
||||
|
|
20
NOTES.md
20
NOTES.md
|
@ -2,7 +2,7 @@
|
|||
- Engine: ScrapEngine
|
||||
- Ingame Scripting Language: Python 1.5.2
|
||||
|
||||
# Ingame-Console (Ctrl+\^) (Handler@0x402190):
|
||||
# Ingame-Console (Ctrl+\^ or right click on titlebar and select "switch console") (Handler@0x402190):
|
||||
* `<Command>`: Try to evaluate Command as Python expression
|
||||
* `:<Var>`: Get Game Engine Global Variable
|
||||
* `:<Var> <Val>`: Set Game Engine Global Variable
|
||||
|
@ -14,7 +14,7 @@
|
|||
# External Console (Scenegraph Debugging?) (Handler@0x5f9520):
|
||||
* `listar luces`
|
||||
* `listar`
|
||||
* `arbol` (Patch Scrap.exe@offset 0x314bc0 replace 0x20 with 0x00 (or just type `arbol ` with the space at the end))
|
||||
* `arbol` (Patch Scrap.exe@offset 0x314bc9 replace 0x20 with 0x00 (or just type `arbol ` with the space at the end))
|
||||
* `mem`
|
||||
* `ver uniones`
|
||||
* Easter Eggs:
|
||||
|
@ -23,17 +23,18 @@
|
|||
- `capullo`
|
||||
|
||||
# Python Stuff
|
||||
- Modules List @ 0x0079C698 (char* to Module Name followed by Pointer to Init Function)
|
||||
- InitPyMod @ 0x005A8FB0
|
||||
- PyExec @ 0x005A8390
|
||||
- Modules List @ 0x79C698 (Module Name as `char*` followed by Pointer to Init Function)
|
||||
- InitPyMod @ 0x5A8FB0
|
||||
- PyExec @ 0x5A8390
|
||||
|
||||
## m3d.ini loader @ 0x05f7000
|
||||
|
||||
## SM3 Secene Loader @ 0x650f80 (?)
|
||||
## SM3 Scene Loader @ 0x650f80 (?)
|
||||
|
||||
## M3D File Loader @ 0x6665a0 (??)
|
||||
|
||||
## *.packed File Format:
|
||||
```
|
||||
Header:
|
||||
"BFPK\0\0\0\0"
|
||||
Int32ul: number of files
|
||||
|
@ -42,8 +43,9 @@
|
|||
String: path
|
||||
Int32ul: size
|
||||
Int32ul: offset in file
|
||||
```
|
||||
|
||||
## Loading Custom Content
|
||||
## Loading Custom Content (not really working)
|
||||
1. Create a folder `mods`
|
||||
2. Drop a `*.packed` file into it
|
||||
|
||||
|
@ -54,9 +56,9 @@
|
|||
|
||||
# How to enable External Console:
|
||||
1. exctract `Data.packed`
|
||||
2. in m3d.ini uncomment "ConsolaWnd" (GUI Console) or "ConsolaTxt" (Text Console) and set the value to "SI"
|
||||
2. in m3d.ini uncomment (remove `;`) "ConsolaWnd" (GUI Console) or "ConsolaTxt" (Text Console) and set the value to "SI"
|
||||
3. repack "Data.packed"
|
||||
or Use a custom Content Pack
|
||||
or Use a custom Content Pack (**untested!**)
|
||||
|
||||
# Misc. Interesting things
|
||||
- sys.path contains "./lib" so you can load your own Python Modules
|
12
README.md
12
README.md
|
@ -9,15 +9,21 @@
|
|||
this will load all builtin modules and enable godmode
|
||||
- The dbg module also enables writing to the ingame console using `print <var>`
|
||||
and defines two global functions s_write() and e_write() for writing to the Ingame Console's Stdout and Stderr Stream
|
||||
- `dbg.menu()` Displays the Game's built in Debug Menu (you can't exit it though)
|
||||
- `dbg.menu()` Displays the Game's built in Debug Menu (doesn't work properly)
|
||||
- `dbg.enable_all_conv()` allows you to "overwrite" any character, even if they are protected/invulnerable
|
||||
- `dbg.become(name)` allows you to transform into any character
|
||||
- `dbg.helplib()` generates a file `helplib.txt` in the Game's folder containing all available Documentation for all available classes and functions
|
||||
- `dbg.settrace()` Logs all Python function calls together with their arguments into a
|
||||
- `dbg.txt` file inside the Game's folder
|
||||
- `dbg.settrace()` Logs all Python function calls together with their arguments into a `dbg.txt` file inside the Game's folder
|
||||
|
||||
## [ScrapHacks](ScrapHacks/README.md)
|
||||
|
||||
WIP Memory hacking library
|
||||
|
||||
## [Notes](NOTES.md)
|
||||
|
||||
# Tools used:
|
||||
|
||||
- [Python 3](https://python.org/) + [Construct](https://construct.readthedocs.io/en/latest/)
|
||||
- [IDA](https://www.hex-rays.com/products/ida/index.shtml) and [x32dbg](https://x64dbg.com/#start)
|
||||
- [Reclass.NET](https://github.com/ReClassNET/ReClass.NET)
|
||||
- [HxD](https://mh-nexus.de/en/hxd/)
|
||||
|
|
|
@ -230,13 +230,8 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
Sleep(100);
|
||||
GetWindowThreadProcessId(FindWindowA("ScrapClass", NULL), &PID);
|
||||
if (PID)
|
||||
{
|
||||
}
|
||||
cout << "[+] Found PID: " << PID << endl;
|
||||
cout << "[*] Sleeping 10 seconds to wait for it to fully load" << endl;
|
||||
Sleep(10000);
|
||||
}
|
||||
}
|
||||
InjectDll(PID);
|
||||
cout << "[*] Done!" << endl;
|
||||
return 0;
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
0. Build Project
|
||||
1. Run Injector `.\Injector.exe`
|
||||
2. Run Game
|
||||
3. Wait ~10 Seconds for game to load and Injector to works its magic
|
||||
|
||||
|
||||
```
|
||||
[F3 ] Unload ScrapHacks
|
||||
[F7 ] Set Money to 0x7fffffff
|
||||
[F8 ] Dump python modules to console
|
||||
[F10] Enable python tracing
|
||||
[ F ] "Handbrake" (*Will* crash the game after some time!)
|
||||
```
|
61
ScrapHacks/ScrapHack/Py_Utils.h
Normal file
61
ScrapHacks/ScrapHack/Py_Utils.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
#include "Structures.h"
|
||||
|
||||
map<string, Module> Py;
|
||||
|
||||
PyMethodDef *find_method_table(uintptr_t base, uintptr_t needle)
|
||||
{
|
||||
for (ptrdiff_t offset = 0; offset < 64; ++offset)
|
||||
{
|
||||
uintptr_t instr = reinterpret_cast<uintptr_t *>(base + offset)[0];
|
||||
if (instr == needle) {
|
||||
uintptr_t mod_addr = reinterpret_cast<uintptr_t *>(base + offset - (1 + 4))[0];
|
||||
return reinterpret_cast<PyMethodDef*>(mod_addr);
|
||||
}
|
||||
}
|
||||
return reinterpret_cast<PyMethodDef *>(0);
|
||||
}
|
||||
|
||||
map<string, Module> get_modules(uintptr_t base)
|
||||
{
|
||||
map<string, Module> Py;
|
||||
PyMod *modules = reinterpret_cast<PyMod *>(base);
|
||||
for (size_t i = 0; modules[i].init_func != NULL; i++)
|
||||
{
|
||||
Module mod;
|
||||
mod.mod = &modules[i];
|
||||
PyMethodDef *method_table = find_method_table((size_t)modules[i].init_func, reinterpret_cast<uintptr_t>(modules[i].name));
|
||||
for (size_t j = 0; method_table != NULL && method_table[j].ml_name != NULL; j++)
|
||||
{
|
||||
mod.methods[method_table[j].ml_name] = method_table[j];
|
||||
}
|
||||
Py[mod.mod->name] = mod;
|
||||
}
|
||||
return Py;
|
||||
}
|
||||
|
||||
void *get_py(const char *mod, const char *meth)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Py.at(mod).methods.at(meth).ml_meth;
|
||||
}
|
||||
catch (out_of_range)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void inject(const char *mod, const char *meth, void *detour)
|
||||
{
|
||||
try
|
||||
{
|
||||
void *orig = get_py(mod, meth);
|
||||
Py.at(mod).methods.at(meth).ml_meth = detour;
|
||||
cout << mod << "." << meth << ": " << orig << " -> " << detour << endl;
|
||||
}
|
||||
catch (out_of_range)
|
||||
{
|
||||
cout << mod << "." << meth << " not found!" << endl;
|
||||
}
|
||||
}
|
|
@ -3,251 +3,35 @@
|
|||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <Windows.h>
|
||||
#include <TlHelp32.h>
|
||||
#include "Scrapland.h"
|
||||
//#include <D3d8.h>
|
||||
|
||||
#define DLL_EXPORT extern "C" __declspec(dllexport)
|
||||
|
||||
struct Module;
|
||||
using namespace std;
|
||||
|
||||
map<string, Module> Py;
|
||||
#include "Scrapland.h"
|
||||
#include "Util.h"
|
||||
#include "Structures.h"
|
||||
#include "Py_Utils.h"
|
||||
|
||||
HMODULE hD3D8Dll = 0;
|
||||
|
||||
bool initialized = false;
|
||||
bool running = true;
|
||||
HMODULE mod = 0;
|
||||
|
||||
string GetLastErrorAsString()
|
||||
{
|
||||
DWORD errorMessageID = GetLastError();
|
||||
if (errorMessageID == 0)
|
||||
return "No error";
|
||||
LPSTR messageBuffer = NULL;
|
||||
size_t m_size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
|
||||
string message(messageBuffer, m_size);
|
||||
LocalFree(messageBuffer);
|
||||
if (!message.empty() && message[message.length() - 1] == '\n')
|
||||
{
|
||||
message.erase(message.length() - 1);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
void SetupStreams()
|
||||
{
|
||||
FILE *fIn;
|
||||
FILE *fOut;
|
||||
freopen_s(&fIn, "conin$", "r", stdin);
|
||||
freopen_s(&fOut, "conout$", "w", stdout);
|
||||
freopen_s(&fOut, "conout$", "w", stderr);
|
||||
ios::sync_with_stdio();
|
||||
std::wcout.clear();
|
||||
std::cout.clear();
|
||||
std::wcerr.clear();
|
||||
std::cerr.clear();
|
||||
std::wcin.clear();
|
||||
std::cin.clear();
|
||||
}
|
||||
|
||||
void SetupConsole()
|
||||
{
|
||||
if (!AllocConsole())
|
||||
{
|
||||
FreeConsole();
|
||||
AllocConsole();
|
||||
}
|
||||
AttachConsole(GetCurrentProcessId());
|
||||
SetupStreams();
|
||||
}
|
||||
|
||||
void SetupConsole(const char *title)
|
||||
{
|
||||
SetupConsole();
|
||||
SetConsoleTitleA(title);
|
||||
}
|
||||
|
||||
void FreeConsole(bool wait)
|
||||
{
|
||||
if (wait)
|
||||
{
|
||||
cout << "[?] Press Enter to Exit";
|
||||
cin.ignore();
|
||||
}
|
||||
FreeConsole();
|
||||
}
|
||||
|
||||
bool in_foreground = false;
|
||||
BOOL CALLBACK EnumWindowsProcMy(HWND hwnd, LPARAM lParam)
|
||||
{
|
||||
DWORD lpdwProcessId;
|
||||
GetWindowThreadProcessId(hwnd, &lpdwProcessId);
|
||||
if (lpdwProcessId == lParam)
|
||||
{
|
||||
in_foreground = (hwnd == GetForegroundWindow()) || (hwnd == GetActiveWindow());
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool key_down(int keycode, int delay = 100)
|
||||
{
|
||||
in_foreground = false;
|
||||
EnumWindows(EnumWindowsProcMy, GetCurrentProcessId());
|
||||
if (in_foreground)
|
||||
{
|
||||
if (GetAsyncKeyState(keycode))
|
||||
{
|
||||
Sleep(delay);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool key_down_norepeat(int keycode, int delay = 100)
|
||||
{
|
||||
in_foreground = false;
|
||||
EnumWindows(EnumWindowsProcMy, GetCurrentProcessId());
|
||||
if (in_foreground)
|
||||
{
|
||||
if (GetAsyncKeyState(keycode))
|
||||
{
|
||||
while (GetAsyncKeyState(keycode))
|
||||
{
|
||||
Sleep(delay);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct PyMethodDef
|
||||
{
|
||||
char *ml_name;
|
||||
void *ml_meth;
|
||||
int ml_flags;
|
||||
char *ml_doc;
|
||||
};
|
||||
|
||||
struct PyMod
|
||||
{
|
||||
char *name;
|
||||
void *init_func;
|
||||
};
|
||||
|
||||
struct Module
|
||||
{
|
||||
PyMod *mod;
|
||||
map<string, PyMethodDef> methods;
|
||||
};
|
||||
|
||||
void hexdump(void *addr, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
unsigned int val = (unsigned int)((unsigned char *)addr)[i];
|
||||
cout << setfill('0') << setw(2) << std::hex << val << " ";
|
||||
if (((i + 1) % 16) == 0)
|
||||
{
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
PyMethodDef *find_method_table(size_t base, size_t size)
|
||||
{
|
||||
uint8_t *ptr = reinterpret_cast<uint8_t *>(base);
|
||||
for (size_t offset = 0; offset < size; ++offset)
|
||||
{
|
||||
if ((uint16_t)ptr[offset] == 0x68)
|
||||
{
|
||||
uint32_t mod_addr = reinterpret_cast<uint32_t *>(base + offset + 1)[0];
|
||||
if ((mod_addr & 0xf00000) == 0x700000)
|
||||
{
|
||||
if (strlen(reinterpret_cast<char *>(mod_addr)) == 3)
|
||||
{
|
||||
return reinterpret_cast<PyMethodDef *>(mod_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return reinterpret_cast<PyMethodDef *>(0);
|
||||
}
|
||||
|
||||
map<string, Module> get_modules(size_t base)
|
||||
{
|
||||
map<string, Module> Py;
|
||||
PyMod *modules = reinterpret_cast<PyMod *>(base);
|
||||
for (int i = 0; modules[i].init_func != NULL; i++)
|
||||
{
|
||||
Module mod;
|
||||
mod.mod = &modules[i];
|
||||
PyMethodDef *method_table = find_method_table((size_t)modules[i].init_func, 64);
|
||||
for (int j = 0; method_table != NULL && method_table[j].ml_name != NULL; j++)
|
||||
{
|
||||
mod.methods[method_table[j].ml_name] = method_table[j];
|
||||
}
|
||||
Py[mod.mod->name] = mod;
|
||||
}
|
||||
return Py;
|
||||
}
|
||||
|
||||
void *get_py(const char *mod, const char *meth)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Py.at(mod).methods.at(meth).ml_meth;
|
||||
}
|
||||
catch (out_of_range)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void inject(const char *mod, const char *meth, void *detour)
|
||||
{
|
||||
try
|
||||
{
|
||||
void *orig = get_py(mod, meth);
|
||||
Py.at(mod).methods.at(meth).ml_meth = detour;
|
||||
cout << mod << "." << meth << ": " << orig << " -> " << detour << endl;
|
||||
}
|
||||
catch (out_of_range)
|
||||
{
|
||||
cout << mod << "." << meth << " not found!" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ptr(uint32_t addr, vector<uint32_t> offsets)
|
||||
{
|
||||
cout << "[" << (void *)addr << "]";
|
||||
for (uint32_t offset : offsets)
|
||||
{
|
||||
addr = reinterpret_cast<uint32_t *>(addr)[0];
|
||||
cout << " -> [" << (void *)addr << " + " << offset << "]";
|
||||
addr += offset;
|
||||
};
|
||||
cout << " -> " << (void *)addr;
|
||||
cout << endl;
|
||||
return addr;
|
||||
}
|
||||
|
||||
void MainLoop(HMODULE mod)
|
||||
{
|
||||
Sleep(100);
|
||||
cout << "[*] Starting main Loop" << endl;
|
||||
cout << endl;
|
||||
cout << "[F3 ] Unload ScrapHacks" << endl;
|
||||
cout << "[F7 ] Set Money to 0x7fffffff" << endl;
|
||||
cout << "[F8 ] Dump python modules" << endl;
|
||||
cout << "[F10] Enable python tracing" << endl;
|
||||
cout << "[F11] Unload ScrapHacks" << endl;
|
||||
cout << "[ F ] \"Handbrake\" (*Will* crash the game after some time!)" << endl;
|
||||
|
||||
while (running)
|
||||
|
@ -274,9 +58,8 @@ void MainLoop(HMODULE mod)
|
|||
mov ecx, [7FE944h]
|
||||
mov edx, [ecx + 2090h]
|
||||
==========================*/
|
||||
int32_t *money = reinterpret_cast<int32_t *>(ptr(WORLD, {0x2090}));
|
||||
cout << "Money: " << money[0] << endl;
|
||||
money[0] = 0x7fffffff;
|
||||
int32_t *money = ptr<int32_t>(P_WORLD,O_MONEY);
|
||||
*money = 0x7fffffff;
|
||||
}
|
||||
if (key_down_norepeat(VK_F8))
|
||||
{
|
||||
|
@ -284,14 +67,11 @@ void MainLoop(HMODULE mod)
|
|||
{
|
||||
for (auto meth : mod.second.methods)
|
||||
{
|
||||
if (meth.second.ml_doc != NULL)
|
||||
{
|
||||
cout << mod.first << "." << meth.first << " @ " << meth.second.ml_meth << " [" << &(meth.second) << "]" << endl;
|
||||
cout << mod.first << "." << meth.first << " @ " << meth.second.ml_meth << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key_down_norepeat(VK_F11))
|
||||
if (key_down_norepeat(VK_F3))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -318,12 +98,15 @@ void DllInit(HMODULE _mod)
|
|||
InitConsole();
|
||||
GetModuleFileName(0, mfn, 1024);
|
||||
cout << "[+] ScrapHacks v0.1 Loaded in " << mfn << endl;
|
||||
Py = get_modules(PY_MODS);
|
||||
Sleep(3000);
|
||||
Py = get_modules(P_PY_MODS);
|
||||
cout << "[*] Importing python dbg module" << endl;
|
||||
scrap_exec("import dbg");
|
||||
cout << "[*] World: " << ptr<void>(P_WORLD,0) << endl;
|
||||
hD3D8Dll = GetModuleHandle("d3d8.dll");
|
||||
cout << "[*] D3D8 DLL @0x"<< hD3D8Dll << endl;
|
||||
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainLoop, mod, 0, 0);
|
||||
cout << "[*] Starting message pump" << endl;
|
||||
;
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
|
|
|
@ -150,9 +150,12 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Py_Utils.h" />
|
||||
<ClInclude Include="Structures.h" />
|
||||
<ClInclude Include="Scrapland.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="Util.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
|
|
|
@ -24,6 +24,15 @@
|
|||
<ClInclude Include="Scrapland.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Util.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Structures.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Py_Utils.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#define WORLD 0x7FE944
|
||||
#define PY_MODS 0x79C698
|
||||
#define P_WORLD 0x7FE944
|
||||
#define P_PY_MODS 0x79C698
|
||||
#define O_MONEY 0x2090
|
||||
|
||||
auto scrap_log = (int(_cdecl*)(int, const char*))0x4134C0;
|
||||
auto scrap_exec = (void(_cdecl*)(const char*))0x5a8390;
|
||||
|
|
34
ScrapHacks/ScrapHack/Structures.h
Normal file
34
ScrapHacks/ScrapHack/Structures.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
struct Vector3 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
struct Matrix3x3 {
|
||||
Vector3 a;
|
||||
Vector3 b;
|
||||
Vector3 c;
|
||||
};
|
||||
|
||||
|
||||
struct PyMethodDef
|
||||
{
|
||||
char *ml_name;
|
||||
void *ml_meth;
|
||||
int ml_flags;
|
||||
char *ml_doc;
|
||||
};
|
||||
|
||||
struct PyMod
|
||||
{
|
||||
char *name;
|
||||
void *init_func;
|
||||
};
|
||||
|
||||
struct Module
|
||||
{
|
||||
PyMod *mod;
|
||||
map<string, PyMethodDef> methods;
|
||||
};
|
159
ScrapHacks/ScrapHack/Util.h
Normal file
159
ScrapHacks/ScrapHack/Util.h
Normal file
|
@ -0,0 +1,159 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#define DLL_EXPORT extern "C" __declspec(dllexport)
|
||||
|
||||
string GetLastErrorAsString()
|
||||
{
|
||||
DWORD errorMessageID = GetLastError();
|
||||
if (errorMessageID == 0)
|
||||
return "No error";
|
||||
LPSTR messageBuffer = NULL;
|
||||
size_t m_size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
|
||||
string message(messageBuffer, m_size);
|
||||
LocalFree(messageBuffer);
|
||||
if (!message.empty() && message[message.length() - 1] == '\n')
|
||||
{
|
||||
message.erase(message.length() - 1);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
void SetupStreams()
|
||||
{
|
||||
FILE *fIn;
|
||||
FILE *fOut;
|
||||
freopen_s(&fIn, "conin$", "r", stdin);
|
||||
freopen_s(&fOut, "conout$", "w", stdout);
|
||||
freopen_s(&fOut, "conout$", "w", stderr);
|
||||
ios::sync_with_stdio();
|
||||
std::wcout.clear();
|
||||
std::cout.clear();
|
||||
std::wcerr.clear();
|
||||
std::cerr.clear();
|
||||
std::wcin.clear();
|
||||
std::cin.clear();
|
||||
}
|
||||
|
||||
void SetupConsole()
|
||||
{
|
||||
if (!AllocConsole())
|
||||
{
|
||||
FreeConsole();
|
||||
AllocConsole();
|
||||
}
|
||||
AttachConsole(GetCurrentProcessId());
|
||||
SetupStreams();
|
||||
}
|
||||
|
||||
void SetupConsole(const char *title)
|
||||
{
|
||||
SetupConsole();
|
||||
SetConsoleTitleA(title);
|
||||
}
|
||||
|
||||
void FreeConsole(bool wait)
|
||||
{
|
||||
if (wait)
|
||||
{
|
||||
cout << "[?] Press Enter to Exit";
|
||||
cin.ignore();
|
||||
}
|
||||
FreeConsole();
|
||||
}
|
||||
|
||||
|
||||
bool in_foreground = false;
|
||||
BOOL CALLBACK EnumWindowsProcMy(HWND hwnd, LPARAM lParam)
|
||||
{
|
||||
DWORD lpdwProcessId;
|
||||
GetWindowThreadProcessId(hwnd, &lpdwProcessId);
|
||||
if (lpdwProcessId == lParam)
|
||||
{
|
||||
in_foreground = (hwnd == GetForegroundWindow()) || (hwnd == GetActiveWindow());
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool key_down(int keycode, int delay = 100)
|
||||
{
|
||||
in_foreground = false;
|
||||
EnumWindows(EnumWindowsProcMy, GetCurrentProcessId());
|
||||
if (in_foreground)
|
||||
{
|
||||
if (GetAsyncKeyState(keycode))
|
||||
{
|
||||
Sleep(delay);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool key_down_norepeat(int keycode, int delay = 100)
|
||||
{
|
||||
in_foreground = false;
|
||||
EnumWindows(EnumWindowsProcMy, GetCurrentProcessId());
|
||||
if (in_foreground)
|
||||
{
|
||||
if (GetAsyncKeyState(keycode))
|
||||
{
|
||||
while (GetAsyncKeyState(keycode))
|
||||
{
|
||||
Sleep(delay);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void hexdump(void *addr, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
unsigned int val = (unsigned int)((unsigned char *)addr)[i];
|
||||
cout << setfill('0') << setw(2) << std::hex << val << " ";
|
||||
if (((i + 1) % 16) == 0)
|
||||
{
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
T* __ptr(uintptr_t addr)
|
||||
{
|
||||
return reinterpret_cast<T*>(addr);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
T* __ptr(uintptr_t addr, ptrdiff_t offset)
|
||||
{
|
||||
cout << "[" << (void*)addr << "] + " << (void*)offset << " = ";
|
||||
addr = reinterpret_cast<uintptr_t*>(addr)[0] + offset;
|
||||
cout << (void*)addr << endl;;
|
||||
auto ret = __ptr<T>(addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename... Offsets>
|
||||
T* __ptr(uintptr_t addr, ptrdiff_t offset, Offsets... offsets) {
|
||||
cout << "[" << (void*)addr << "] + " << (void*)offset << " = ";
|
||||
addr = reinterpret_cast<uintptr_t*>(addr)[0] + offset;
|
||||
cout << (void*)addr << endl;;
|
||||
auto ret = __ptr<T>(addr, offsets...);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T, typename... Offsets>
|
||||
T* ptr(uintptr_t addr, Offsets... offsets) {
|
||||
auto ret = __ptr<T>(addr, offsets...);
|
||||
return ret;
|
||||
}
|
|
@ -10,6 +10,7 @@ BOOL APIENTRY DllMain(HMODULE hModule,
|
|||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
DisableThreadLibraryCalls(hModule);
|
||||
hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DllInit, hModule, 0, 0);
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
Stack trace:
|
||||
Frame Function Args
|
||||
00180000000 0018006021E (00180233AB9, 001802340B9, 000FFFFC560, 000FFFFB6F0)
|
||||
00180000000 00180048859 (FFFFFF00EEEEEE, 557BDB00453FCD, 56CA9F0069CDE6, 00000F22C80)
|
||||
00180000000 00180048892 (00180233A96, 000FFFFC458, 000FFFFC560, 453FCD00FFFFFF)
|
||||
00180000000 001800454A3 (00000000000, 00180000000, 00000000000, 001800004EC)
|
||||
00180000000 0018006DF51 (FFFFFF00EEEEEE, 557BDB00453FCD, 56CA9F0069CDE6, DBB55500BEDB55)
|
||||
00180000000 0018006EDDE (00000000000, 00100674A28, 00000000000, 00000000000)
|
||||
00180000000 001800713A4 (00000000000, 00000000008, 00000000000, 00000000000)
|
||||
006000331E0 0018013ABC1 (00100674A20, 00000000008, 00000000000, 00000000000)
|
||||
006000331E0 001801214AB (00100674A20, 00000000008, 00000000000, 00000000000)
|
||||
006000331E0 001004FC754 (0010057D324, 0010067B2B8, 00000000000, 0010067B2BC)
|
||||
006000331E0 0010058CC73 (00600000008, 0010067C940, 00000000000, 00000000000)
|
||||
006000331E0 0010057E416 (00000000000, 0005C16CB0E, 0001FCBD224, 00000010000)
|
||||
006000331E0 001005E614F (00000000002, 0000000000E, 00000000002, 005FCB11020)
|
||||
006000331E0 001005F46A7 (0000000002F, 00000000000, 00180214320, 00180329968)
|
||||
000FFFFCCD0 00180049E84 (00000000000, 00000000000, 00000000000, 00000000000)
|
||||
00000000000 00180047963 (00000000000, 00000000000, 00000000000, 00000000000)
|
||||
End of stack trace (more stack frames may be present)
|
Loading…
Reference in a new issue