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", | ||||
|  |  | |||
							
								
								
									
										24
									
								
								NOTES.md
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								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,18 +23,19 @@ | |||
|  - `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 | ||||
| ## m3d.ini loader @ 0x05f7000 | ||||
| 
 | ||||
| ## SM3 Secene Loader @ 0x650f80 (?) | ||||
| ## SM3 Scene Loader @ 0x650f80 (?) | ||||
| 
 | ||||
| ## M3D File Loader @ 0x6665a0 (??) | ||||
| 
 | ||||
| ## *.packed File Format: | ||||
|     Header: | ||||
| ``` | ||||
| Header: | ||||
|     "BFPK\0\0\0\0" | ||||
|     Int32ul: number of files | ||||
|     for each file: | ||||
|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue