Auto format everything

This commit is contained in:
Daniel S. 2019-09-02 21:44:17 +02:00
parent e21faa76a1
commit a920c63d41
16 changed files with 1165 additions and 5336 deletions

View file

@ -1,19 +1,19 @@
cmake_minimum_required (VERSION 2.6) cmake_minimum_required(VERSION 2.6)
project(ScrapHacks) project(ScrapHacks)
SET(CMAKE_BUILD_TYPE "Release") set(CMAKE_BUILD_TYPE "Release")
SET(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}") set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}")
if(WIN32) if(WIN32)
if(MSVC) if(MSVC)
# ensure we use minimal "windows.h" lib without the crazy min max macros # ensure we use minimal "windows.h" lib without the crazy min max macros
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D \"WIN32_LEAN_AND_MEAN\"") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D \"WIN32_LEAN_AND_MEAN\"")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D \"NOMINMAX\"") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D \"NOMINMAX\"")
# disable SAFESEH - to avoid "LNK2026: module unsafe" # disable SAFESEH - to avoid "LNK2026: module unsafe"
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D \"SAFESEH:NO\"") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D \"SAFESEH:NO\"")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
endif(MSVC) endif(MSVC)
endif(WIN32) endif(WIN32)
add_subdirectory(Injector) add_subdirectory(Injector)
add_subdirectory(ScrapHack) add_subdirectory(ScrapHack)

View file

@ -1,2 +1,2 @@
add_executable(Injector Injector.cpp) add_executable(Injector Injector.cpp)
install(TARGETS Injector DESTINATION bin) install(TARGETS Injector DESTINATION bin)

View file

@ -1,4 +1,3 @@
#include "stdafx.h"
#include <iostream> #include <iostream>
#include <windows.h> #include <windows.h>
#include <TlHelp32.h> #include <TlHelp32.h>
@ -12,245 +11,254 @@ using namespace std;
string GetLastErrorAsString() string GetLastErrorAsString()
{ {
DWORD errorMessageID = GetLastError(); DWORD errorMessageID = GetLastError();
if (errorMessageID == 0) if (errorMessageID == 0)
return "No error"; return "No error";
LPSTR messageBuffer = NULL; LPSTR messageBuffer = NULL;
size_t m_size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 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); NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
string message(messageBuffer, m_size); string message(messageBuffer, m_size);
LocalFree(messageBuffer); LocalFree(messageBuffer);
if (!message.empty() && message[message.length() - 1] == '\n') if (!message.empty() && message[message.length() - 1] == '\n')
{ {
message.erase(message.length() - 1); message.erase(message.length() - 1);
} }
return message; return message;
} }
void fail(char* msg) { void fail(char *msg)
cerr << "[!] "<<msg<<": "<<GetLastErrorAsString()<<endl; {
exit(1); cerr << "[!] " << msg << ": " << GetLastErrorAsString() << endl;
exit(1);
} }
string fromhex(string input) string fromhex(string input)
{ {
transform(input.begin(), input.end(), input.begin(), ::toupper); transform(input.begin(), input.end(), input.begin(), ::toupper);
string hc = "0123456789ABCDEF"; string hc = "0123456789ABCDEF";
string o = ""; string o = "";
int n = 0; int n = 0;
int v = 0; int v = 0;
for (unsigned char c : input) for (unsigned char c : input)
{ {
if (hc.find(c) != size_t(-1)) if (hc.find(c) != size_t(-1))
{ {
if ((n++) % 2 == 0) if ((n++) % 2 == 0)
{ {
v = hc.find(c) << 4; v = hc.find(c) << 4;
} }
else else
{ {
o += char(v + hc.find(c)); o += char(v + hc.find(c));
} }
} }
else else
{ {
cout << "Invalid Character in hex string" << endl; cout << "Invalid Character in hex string" << endl;
return ""; return "";
} }
} }
return o; return o;
} }
vector<string> split(string str, char sep) vector<string> split(string str, char sep)
{ {
vector<string> ret; vector<string> ret;
string part; string part;
for (auto n : str) for (auto n : str)
{ {
if (n == sep) if (n == sep)
{ {
ret.push_back(part); ret.push_back(part);
part.clear(); part.clear();
} }
else else
{ {
part = part + n; part = part + n;
} }
} }
if (part != "") if (part != "")
ret.push_back(part); ret.push_back(part);
return ret; return ret;
} }
bool fexists(const char *filename) bool fexists(const char *filename)
{ {
ifstream ifile(filename); ifstream ifile(filename);
bool ret = ifile.good(); bool ret = ifile.good();
ifile.close(); ifile.close();
return ret; return ret;
} }
bool HasModule(int PID, const char *modname) bool HasModule(int PID, const char *modname)
{ {
HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID); HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID);
MODULEENTRY32 me; MODULEENTRY32 me;
me.dwSize = sizeof(MODULEENTRY32); me.dwSize = sizeof(MODULEENTRY32);
if (hModuleSnap == INVALID_HANDLE_VALUE) if (hModuleSnap == INVALID_HANDLE_VALUE)
{ {
return false; return false;
} }
if (!Module32First(hModuleSnap, &me)) if (!Module32First(hModuleSnap, &me))
{ {
CloseHandle(hModuleSnap); CloseHandle(hModuleSnap);
cout << "Error reading Module Snapshot" << endl; cout << "Error reading Module Snapshot" << endl;
} }
else else
{ {
do do
{ {
if (strstr((const char *)me.szModule, modname) != NULL) if (strstr((const char *)me.szModule, modname) != NULL)
return true; return true;
} while (Module32Next(hModuleSnap, &me)); } while (Module32Next(hModuleSnap, &me));
CloseHandle(hModuleSnap); CloseHandle(hModuleSnap);
} }
return false; return false;
} }
bool ProcRunning(DWORD PID) bool ProcRunning(DWORD PID)
{ {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID); HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID);
if (hSnap == INVALID_HANDLE_VALUE) if (hSnap == INVALID_HANDLE_VALUE)
{ {
return false; return false;
} }
CloseHandle(hSnap); CloseHandle(hSnap);
return true; return true;
} }
bool adjustPrivs(HANDLE hProc) bool adjustPrivs(HANDLE hProc)
{ {
HANDLE hToken; HANDLE hToken;
LUID luid; LUID luid;
TOKEN_PRIVILEGES tkprivs; TOKEN_PRIVILEGES tkprivs;
if (!OpenProcessToken(hProc, (TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY), &hToken)) if (!OpenProcessToken(hProc, (TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY), &hToken))
{ {
fail("Could not open process token:"); fail("Could not open process token:");
} }
if (!LookupPrivilegeValue(0, SE_DEBUG_NAME, &luid)) if (!LookupPrivilegeValue(0, SE_DEBUG_NAME, &luid))
{ {
CloseHandle(hToken); CloseHandle(hToken);
fail("Error looking up privilege value for SE_DEBUG_NAME"); fail("Error looking up privilege value for SE_DEBUG_NAME");
} }
tkprivs.PrivilegeCount = 1; tkprivs.PrivilegeCount = 1;
tkprivs.Privileges[0].Luid = luid; tkprivs.Privileges[0].Luid = luid;
tkprivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tkprivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
bool bRet = AdjustTokenPrivileges(hToken, 0, &tkprivs, sizeof(tkprivs), NULL, NULL); bool bRet = AdjustTokenPrivileges(hToken, 0, &tkprivs, sizeof(tkprivs), NULL, NULL);
CloseHandle(hToken); CloseHandle(hToken);
if (!bRet) if (!bRet)
{ {
fail("Could not adjust privileges"); fail("Could not adjust privileges");
} }
return bRet; return bRet;
} }
bool Injected(DWORD PID) bool Injected(DWORD PID)
{ {
return HasModule(PID, DLL_NAME); return HasModule(PID, DLL_NAME);
} }
void InjectDll(DWORD PID) void InjectDll(DWORD PID)
{ {
HANDLE hRemThread, hProc; HANDLE hRemThread, hProc;
const char *dll_name = DLL_NAME; const char *dll_name = DLL_NAME;
char dll_full_path[MAX_PATH]; char dll_full_path[MAX_PATH];
char executable_dir[MAX_PATH]; char executable_dir[MAX_PATH];
GetModuleFileNameA(NULL,executable_dir,MAX_PATH); GetModuleFileNameA(NULL, executable_dir, MAX_PATH);
if (!fexists(dll_name)) if (!fexists(dll_name))
{ {
fail("DLL not found"); fail("DLL not found");
return; return;
} }
cout << "[*] Injecting DLL " << dll_name << " into PID " << PID << endl; cout << "[*] Injecting DLL " << dll_name << " into PID " << PID << endl;
cout << "[*] Opening process handle" << endl; cout << "[*] Opening process handle" << endl;
hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, PID); hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, PID);
GetFullPathNameA(dll_name, MAX_PATH, dll_full_path, 0); GetFullPathNameA(dll_name, MAX_PATH, dll_full_path, 0);
cout << "[*] Adjusting privileges of process" << endl; cout << "[*] Adjusting privileges of process" << endl;
adjustPrivs(hProc); adjustPrivs(hProc);
if (HasModule(PID, dll_name)) if (HasModule(PID, dll_name))
{ {
cout << "[*] DLL already loaded" << endl; cout << "[*] DLL already loaded" << endl;
CloseHandle(hProc); CloseHandle(hProc);
return; return;
}; };
if (!fexists(dll_full_path)) if (!fexists(dll_full_path))
{ {
CloseHandle(hProc); CloseHandle(hProc);
fail("DLL file not found"); fail("DLL file not found");
} }
HINSTANCE hK32 = LoadLibraryA("kernel32"); HINSTANCE hK32 = LoadLibraryA("kernel32");
cout << "[*] Getting address of LoadLibrary" << endl; cout << "[*] Getting address of LoadLibrary" << endl;
LPVOID LoadLibrary_Address = (LPVOID)GetProcAddress(hK32, "LoadLibraryA"); LPVOID LoadLibrary_Address = (LPVOID)GetProcAddress(hK32, "LoadLibraryA");
FreeLibrary(hK32); FreeLibrary(hK32);
cout << "[+] LoadLibrary is at " << LoadLibrary_Address << endl; cout << "[+] LoadLibrary is at " << LoadLibrary_Address << endl;
cout << "[*] Allocating " << strlen(dll_full_path) << " Bytes of Memory" << endl; cout << "[*] Allocating " << strlen(dll_full_path) << " Bytes of Memory" << endl;
LPVOID mem = VirtualAllocEx(hProc, NULL, strlen(dll_full_path), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); LPVOID mem = VirtualAllocEx(hProc, NULL, strlen(dll_full_path), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (mem == NULL) if (mem == NULL)
{ {
fail("Could not allocate memory"); fail("Could not allocate memory");
return; return;
} }
cout << "[*] Writing DLL Name to Process Memory at " << mem << endl; cout << "[*] Writing DLL Name to Process Memory at " << mem << endl;
WriteProcessMemory(hProc, mem, dll_full_path, strlen(dll_full_path), 0); WriteProcessMemory(hProc, mem, dll_full_path, strlen(dll_full_path), 0);
cout << "[*] Creating Thread to Load DLL" << endl; cout << "[*] Creating Thread to Load DLL" << endl;
hRemThread = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibrary_Address, mem, 0, 0); hRemThread = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibrary_Address, mem, 0, 0);
cout << "[*] Waiting for DLL to load" << endl; cout << "[*] Waiting for DLL to load" << endl;
WaitForSingleObject(hRemThread, INFINITE); WaitForSingleObject(hRemThread, INFINITE);
CloseHandle(hRemThread); CloseHandle(hRemThread);
cout << "[*] Closing Process Handle" << endl; cout << "[*] Closing Process Handle" << endl;
CloseHandle(hProc); CloseHandle(hProc);
return; return;
} }
vector<HANDLE> spawn(char* binary) { vector<HANDLE> spawn(char *binary)
STARTUPINFO startupinfo; {
PROCESS_INFORMATION processinfo; STARTUPINFO startupinfo;
ZeroMemory(&startupinfo, sizeof(startupinfo)); PROCESS_INFORMATION processinfo;
ZeroMemory(&processinfo, sizeof(processinfo)); ZeroMemory(&startupinfo, sizeof(startupinfo));
startupinfo.cb = sizeof(startupinfo); ZeroMemory(&processinfo, sizeof(processinfo));
if (!CreateProcessA(NULL, binary, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupinfo, &processinfo)) { startupinfo.cb = sizeof(startupinfo);
return {}; if (!CreateProcessA(NULL, binary, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupinfo, &processinfo))
} {
return { processinfo.hProcess,processinfo.hThread }; return {};
}
return {processinfo.hProcess, processinfo.hThread};
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
string prog; string prog;
HANDLE hProc = INVALID_HANDLE_VALUE; HANDLE hProc = INVALID_HANDLE_VALUE;
HANDLE hThread = INVALID_HANDLE_VALUE; HANDLE hThread = INVALID_HANDLE_VALUE;
DWORD PID = 0; DWORD PID = 0;
char s_PID[MAX_PATH]; char s_PID[MAX_PATH];
snprintf(s_PID, MAX_PATH, "%d", GetCurrentProcessId()); snprintf(s_PID, MAX_PATH, "%d", GetCurrentProcessId());
SetEnvironmentVariableA("Inj_PID", s_PID); SetEnvironmentVariableA("Inj_PID", s_PID);
if ((argc>1)&&fexists(argv[1])) { if ((argc > 1) && fexists(argv[1]))
cout << "[*] Injector PID: " << GetCurrentProcessId() << endl; {
cout << "[*] Spawning process for \"" << argv[1] << "\"" << endl; cout << "[*] Injector PID: " << GetCurrentProcessId() << endl;
vector<HANDLE> handles = spawn(argv[1]); cout << "[*] Spawning process for \"" << argv[1] << "\"" << endl;
if (handles.empty()) { vector<HANDLE> handles = spawn(argv[1]);
fail("Failed to spawn process"); if (handles.empty())
} {
hProc = handles[0]; fail("Failed to spawn process");
hThread = handles[1]; }
PID = GetProcessId(hProc); hProc = handles[0];
} else { hThread = handles[1];
cerr<<"Usage: " << argv[0] << " <Path to Scrap.exe>"<<endl; PID = GetProcessId(hProc);
return 1; }
} else
InjectDll(PID); {
if (hThread != INVALID_HANDLE_VALUE) { cerr << "Usage: " << argv[0] << " <Path to Scrap.exe>" << endl;
while (ResumeThread(hThread)); return 1;
} }
SetEnvironmentVariableA("Inj_PID", NULL); InjectDll(PID);
cout << "[*] Done!" << endl; if (hThread != INVALID_HANDLE_VALUE)
return 0; {
while (ResumeThread(hThread))
;
}
SetEnvironmentVariableA("Inj_PID", NULL);
cout << "[*] Done!" << endl;
return 0;
} }

View file

@ -1,17 +1,21 @@
include(ExternalProject) include(ExternalProject)
ExternalProject_Add(DirectX ExternalProject_Add(
PREFIX ${CMAKE_CURRENT_BINARY_DIR} DirectX
CONFIGURE_COMMAND "" PREFIX ${CMAKE_CURRENT_BINARY_DIR}
BUILD_COMMAND "" CONFIGURE_COMMAND ""
INSTALL_COMMAND "" BUILD_COMMAND ""
URL https://archive.org/download/DirectX.8.0a.SDK_includes_libs_only/DirectX.8.0a.SDK.zip INSTALL_COMMAND ""
URL_HASH SHA1=39f168336d0df92ff14d62d5e3aef1b9e3191312 URL
) https://archive.org/download/DirectX.8.0a.SDK_includes_libs_only/DirectX.8.0a.SDK.zip
URL_HASH SHA1=39f168336d0df92ff14d62d5e3aef1b9e3191312)
ExternalProject_Get_Property(DirectX SOURCE_DIR) ExternalProject_Get_Property(DirectX SOURCE_DIR)
include_directories(AFTER ${SOURCE_DIR}/8.0/include/) include_directories(AFTER ${SOURCE_DIR}/8.0/include/)
link_directories(AFTER ${SOURCE_DIR}/8.0/lib/) link_directories(AFTER ${SOURCE_DIR}/8.0/lib/)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS) add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
add_compile_definitions(POINTER_64=__ptr64) add_compile_definitions(POINTER_64=__ptr64)
add_library(ScrapHack SHARED ScrapHack.cpp dllmain.cpp) add_library(ScrapHack SHARED ScrapHack.cpp dllmain.cpp)
target_link_libraries(ScrapHack d3d8 d3dx8 legacy_stdio_definitions) target_link_libraries(ScrapHack
d3d8
d3dx8
legacy_stdio_definitions)
install(TARGETS ScrapHack DESTINATION bin) install(TARGETS ScrapHack DESTINATION bin)

View file

@ -2,92 +2,104 @@
#include <d3d8.h> #include <d3d8.h>
#include <d3dx8.h> #include <d3dx8.h>
uintmax_t frame = 0; uintmax_t frame = 0;
DWORD* GetVTable(void* addr) { DWORD *GetVTable(void *addr)
return (DWORD*)(*(DWORD*)addr); {
return (DWORD *)(*(DWORD *)addr);
} }
bool overlay = false; bool overlay = false;
LPD3DXFONT m_pFont; LPD3DXFONT m_pFont;
HFONT hFont; HFONT hFont;
HBRUSH hBrush; HBRUSH hBrush;
D3DCOLOR color = D3DCOLOR_ARGB(255,255, 0, 0); D3DCOLOR color = D3DCOLOR_ARGB(255, 255, 0, 0);
RECT Rect = { 0,0,0,0 }; RECT Rect = {0, 0, 0, 0};
D3DRECT panel; D3DRECT panel;
size_t size_ht(HashTable<EntityList>* ht); size_t size_ht(HashTable<EntityList> *ht);
size_t size_ht(HashTable<Entity>* ht); size_t size_ht(HashTable<Entity> *ht);
LPDIRECT3DDEVICE8 Render(LPDIRECT3DDEVICE8 dev) { LPDIRECT3DDEVICE8 Render(LPDIRECT3DDEVICE8 dev)
if (!overlay) { {
return dev; if (!overlay)
} {
char text[4096]; return dev;
int32_t money = 0; }
size_t num_ents = 0; char text[4096];
size_t num_ent_lst = 0; int32_t money = 0;
if (ptr<void>(P_WORLD, 0)!=nullptr) { size_t num_ents = 0;
money = ptr<int32_t>(P_WORLD, O_MONEY)[0]; size_t num_ent_lst = 0;
num_ents= size_ht(ptr<HashTable<Entity>>(P_WORLD, O_ENTS)); if (ptr<void>(P_WORLD, 0) != nullptr)
num_ent_lst = size_ht(ptr<HashTable<EntityList>>(P_WORLD, O_ENTLISTS)); {
} money = ptr<int32_t>(P_WORLD, O_MONEY)[0];
snprintf(text, 4096, "ScrapHack v0.1\nFrame: [%lld]\nMoney: [%d]\nEntities: [%ld]\nEntity Lists: [%ld]", ++frame, money, num_ents,num_ent_lst); num_ents = size_ht(ptr<HashTable<Entity>>(P_WORLD, O_ENTS));
if (m_pFont == nullptr) { num_ent_lst = size_ht(ptr<HashTable<EntityList>>(P_WORLD, O_ENTLISTS));
D3DXCreateFont(dev, hFont, &m_pFont); }
CloseHandle(hFont); snprintf(text, 4096, "ScrapHack v0.1\nFrame: [%lld]\nMoney: [%d]\nEntities: [%ld]\nEntity Lists: [%ld]", ++frame, money, num_ents, num_ent_lst);
} if (m_pFont == nullptr)
m_pFont->Begin(); {
m_pFont->DrawTextA(text, -1, &Rect, DT_CALCRECT, 0); D3DXCreateFont(dev, hFont, &m_pFont);
m_pFont->DrawTextA(text, -1, &Rect, DT_LEFT, color); CloseHandle(hFont);
m_pFont->End(); }
return dev; m_pFont->Begin();
m_pFont->DrawTextA(text, -1, &Rect, DT_CALCRECT, 0);
m_pFont->DrawTextA(text, -1, &Rect, DT_LEFT, color);
m_pFont->End();
return dev;
} }
HRESULT WINAPI H_EndScene(LPDIRECT3DDEVICE8 dev) { HRESULT WINAPI H_EndScene(LPDIRECT3DDEVICE8 dev)
typedef HRESULT(WINAPI *t_func)(LPDIRECT3DDEVICE8); {
shared_ptr<Hook> hook = Hook::get(H_EndScene); typedef HRESULT(WINAPI * t_func)(LPDIRECT3DDEVICE8);
return hook->func<t_func>(Render(dev)); shared_ptr<Hook> hook = Hook::get(H_EndScene);
return hook->func<t_func>(Render(dev));
} }
HRESULT WINAPI H_CreateDevice(void* pDirect3D, unsigned int uiAdapter, D3DDEVTYPE pDeviceType, HWND hFocusWindow, HRESULT WINAPI H_CreateDevice(void *pDirect3D, unsigned int uiAdapter, D3DDEVTYPE pDeviceType, HWND hFocusWindow,
unsigned long ulBehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, unsigned long ulBehaviorFlags, D3DPRESENT_PARAMETERS *pPresentationParameters,
LPDIRECT3DDEVICE8* ppReturnedDeviceInterface) { LPDIRECT3DDEVICE8 *ppReturnedDeviceInterface)
typedef HRESULT(WINAPI *t_func)(void*, unsigned int, D3DDEVTYPE, HWND, unsigned long, D3DPRESENT_PARAMETERS*, LPDIRECT3DDEVICE8*); {
shared_ptr<Hook> hook = Hook::get(H_CreateDevice); typedef HRESULT(WINAPI * t_func)(void *, unsigned int, D3DDEVTYPE, HWND, unsigned long, D3DPRESENT_PARAMETERS *, LPDIRECT3DDEVICE8 *);
HRESULT ret = hook->func<t_func>(pDirect3D, uiAdapter, pDeviceType, hFocusWindow, ulBehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface); shared_ptr<Hook> hook = Hook::get(H_CreateDevice);
cout << "CreateDevice -> " << ret << endl; HRESULT ret = hook->func<t_func>(pDirect3D, uiAdapter, pDeviceType, hFocusWindow, ulBehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
void* EndScene = reinterpret_cast<void*>(GetVTable(ppReturnedDeviceInterface[0])[35]); cout << "CreateDevice -> " << ret << endl;
cout << "EndScene @ " << EndScene << endl; // EndScene void *EndScene = reinterpret_cast<void *>(GetVTable(ppReturnedDeviceInterface[0])[35]);
Hook::addr(EndScene, H_EndScene); cout << "EndScene @ " << EndScene << endl; // EndScene
Hook::drop(H_CreateDevice); Hook::addr(EndScene, H_EndScene);
return ret; Hook::drop(H_CreateDevice);
return ret;
} }
LPDIRECT3D8 WINAPI H_Direct3DCreate8(unsigned int SDKVersion) { LPDIRECT3D8 WINAPI H_Direct3DCreate8(unsigned int SDKVersion)
typedef LPDIRECT3D8(_stdcall *t_func)(unsigned int); {
shared_ptr<Hook> hook = Hook::get(H_Direct3DCreate8); typedef LPDIRECT3D8(_stdcall * t_func)(unsigned int);
shared_ptr<Hook> hook = Hook::get(H_Direct3DCreate8);
LPDIRECT3D8 ret = hook->func<t_func>(SDKVersion);
cout << "D3D8-Create: " << SDKVersion << " -> " << ret << endl; LPDIRECT3D8 ret = hook->func<t_func>(SDKVersion);
void *CreateDevice = reinterpret_cast<void*>(GetVTable(ret)[15]); cout << "D3D8-Create: " << SDKVersion << " -> " << ret << endl;
void *Release = reinterpret_cast<void*>(GetVTable(ret)[2]); void *CreateDevice = reinterpret_cast<void *>(GetVTable(ret)[15]);
cout << "CreateDevice @ " << CreateDevice << endl; // CreateDevice void *Release = reinterpret_cast<void *>(GetVTable(ret)[2]);
Hook::addr(CreateDevice, H_CreateDevice); cout << "CreateDevice @ " << CreateDevice << endl; // CreateDevice
Hook::drop(H_Direct3DCreate8); Hook::addr(CreateDevice, H_CreateDevice);
Hook::drop(H_Direct3DCreate8);
return ret;
return ret;
} }
void unhook_d3d8() { void unhook_d3d8()
if (hFont != INVALID_HANDLE_VALUE) { {
CloseHandle(hFont); if (hFont != INVALID_HANDLE_VALUE)
} {
if (m_pFont != nullptr) { CloseHandle(hFont);
m_pFont->Release(); }
} if (m_pFont != nullptr)
Hook::drop(H_EndScene); {
m_pFont->Release();
}
Hook::drop(H_EndScene);
} }
void hook_d3d8() { void hook_d3d8()
hFont = CreateFont(20, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, "Verdana"); {
hBrush = CreateSolidBrush(D3DCOLOR_ARGB(25, 0, 0, 0)); hFont = CreateFont(20, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, "Verdana");
Hook::module("d3d8.dll","Direct3DCreate8", H_Direct3DCreate8); hBrush = CreateSolidBrush(D3DCOLOR_ARGB(25, 0, 0, 0));
Hook::module("d3d8.dll", "Direct3DCreate8", H_Direct3DCreate8);
} }

View file

@ -4,16 +4,16 @@ class Hook
{ {
private: private:
MEMORY_BASIC_INFORMATION mbi; MEMORY_BASIC_INFORMATION mbi;
void* orig; void *orig;
void* detour; void *detour;
bool enabled; bool enabled;
uint8_t orig_bytes[6]; uint8_t orig_bytes[6];
uint8_t jmp_bytes[6]; uint8_t jmp_bytes[6];
static map<uintptr_t, shared_ptr<Hook>> hooks; static map<uintptr_t, shared_ptr<Hook>> hooks;
public:
Hook(void* func, void* detour) { public:
Hook(void *func, void *detour)
{
uintptr_t dest = reinterpret_cast<uintptr_t>(detour); uintptr_t dest = reinterpret_cast<uintptr_t>(detour);
uintptr_t src = reinterpret_cast<uintptr_t>(func); uintptr_t src = reinterpret_cast<uintptr_t>(func);
this->orig = func; this->orig = func;
@ -31,57 +31,70 @@ public:
this->enabled = false; this->enabled = false;
} }
~Hook() { ~Hook()
{
cout << "Unhooking: [" << this->orig << " <- " << this->detour << "]" << endl; cout << "Unhooking: [" << this->orig << " <- " << this->detour << "]" << endl;
this->disable(); this->disable();
} }
static void addr(void* addr, void* detour) { static void addr(void *addr, void *detour)
cout << "Hooking: [" << addr << " -> " << detour <<"]" << endl; {
cout << "Hooking: [" << addr << " -> " << detour << "]" << endl;
uintptr_t key = reinterpret_cast<uintptr_t>(detour); uintptr_t key = reinterpret_cast<uintptr_t>(detour);
hooks[key] = make_shared<Hook>(addr,detour); hooks[key] = make_shared<Hook>(addr, detour);
hooks[key]->enable(); hooks[key]->enable();
} }
static void module(const char* mod, const char* func, void* detour) { static void module(const char *mod, const char *func, void *detour)
cout << "Hooking: [" << mod<<"]."<<func << " -> " << detour << endl; {
void* addr = GetProcAddress(GetModuleHandle(mod), func); cout << "Hooking: [" << mod << "]." << func << " -> " << detour << endl;
if (addr != NULL) { void *addr = GetProcAddress(GetModuleHandle(mod), func);
if (addr != NULL)
{
Hook::addr(addr, detour); Hook::addr(addr, detour);
} }
else { else
{
cerr << "[" << mod << "]." << func << " not found!" << endl; cerr << "[" << mod << "]." << func << " not found!" << endl;
}; };
} }
static shared_ptr<Hook> get(void* func) { static shared_ptr<Hook> get(void *func)
{
uintptr_t addr = reinterpret_cast<uintptr_t>(func); uintptr_t addr = reinterpret_cast<uintptr_t>(func);
return Hook::get(addr); return Hook::get(addr);
} }
static shared_ptr<Hook> get(uintptr_t addr) { static shared_ptr<Hook> get(uintptr_t addr)
{
return hooks.at(addr); return hooks.at(addr);
} }
static size_t drop(void* func) { static size_t drop(void *func)
{
uintptr_t addr = reinterpret_cast<uintptr_t>(func); uintptr_t addr = reinterpret_cast<uintptr_t>(func);
return Hook::drop(addr); return Hook::drop(addr);
} }
static size_t drop(uintptr_t addr) { static size_t drop(uintptr_t addr)
{
return hooks.erase(addr); return hooks.erase(addr);
} }
static void clear() { static void clear()
{
cout << "Clearing Hooks" << endl; cout << "Clearing Hooks" << endl;
for (pair<uintptr_t,shared_ptr<Hook>> h : hooks) { for (pair<uintptr_t, shared_ptr<Hook>> h : hooks)
{
h.second->disable(); h.second->disable();
} }
return hooks.clear(); return hooks.clear();
} }
void disable() { void disable()
if (enabled) { {
if (enabled)
{
//cout << "Disabling: [" << this->orig << " <- " << this->detour << "]" << endl; //cout << "Disabling: [" << this->orig << " <- " << this->detour << "]" << endl;
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL);
memcpy(this->orig, this->orig_bytes, 1 + 4 + 1); memcpy(this->orig, this->orig_bytes, 1 + 4 + 1);
@ -89,8 +102,10 @@ public:
enabled = false; enabled = false;
} }
} }
void enable() { void enable()
if (!enabled) { {
if (!enabled)
{
//cout << "Enabling: [" << this->orig << " -> " << this->detour << "]" << endl; //cout << "Enabling: [" << this->orig << " -> " << this->detour << "]" << endl;
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL);
memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1); memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1);
@ -99,14 +114,16 @@ public:
} }
} }
void* get_orig() { void *get_orig()
{
return this->orig; return this->orig;
} }
template<typename F,typename ...Args> template <typename F, typename... Args>
decltype(auto) func(Args... args) { decltype(auto) func(Args... args)
{
disable(); disable();
auto ret=reinterpret_cast<F>(this->orig)(args...); auto ret = reinterpret_cast<F>(this->orig)(args...);
enable(); enable();
return ret; return ret;
} }

View file

@ -8,12 +8,13 @@ PyMethodDef *find_method_table(uintptr_t base, uintptr_t needle)
for (ptrdiff_t offset = 0; offset < 64; ++offset) for (ptrdiff_t offset = 0; offset < 64; ++offset)
{ {
uintptr_t instr = reinterpret_cast<uintptr_t *>(base + offset)[0]; uintptr_t instr = reinterpret_cast<uintptr_t *>(base + offset)[0];
if (instr == needle) { if (instr == needle)
{
uintptr_t mod_addr = reinterpret_cast<uintptr_t *>(base + offset - (1 + 4))[0]; uintptr_t mod_addr = reinterpret_cast<uintptr_t *>(base + offset - (1 + 4))[0];
return reinterpret_cast<PyMethodDef*>(mod_addr); return reinterpret_cast<PyMethodDef *>(mod_addr);
} }
} }
return reinterpret_cast<PyMethodDef*>(0); return reinterpret_cast<PyMethodDef *>(0);
} }
map<string, Module> get_modules(uintptr_t base) map<string, Module> get_modules(uintptr_t base)

View file

@ -1,4 +1,3 @@
#include "stdafx.h"
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <vector> #include <vector>

View file

@ -16,8 +16,8 @@
#define P_SCRAP_EXIT 0x4010c0 #define P_SCRAP_EXIT 0x4010c0
//FUNCTION TYPES //FUNCTION TYPES
#define T_SCRAP_LOG int(_cdecl*)(unsigned int, const char*) #define T_SCRAP_LOG int(_cdecl *)(unsigned int, const char *)
#define T_SCRAP_EXEC int(_cdecl*)(const char*) #define T_SCRAP_EXEC int(_cdecl *)(const char *)
auto scrap_log = (T_SCRAP_LOG)P_SCRAP_LOG; auto scrap_log = (T_SCRAP_LOG)P_SCRAP_LOG;
auto scrap_exec = (T_SCRAP_EXEC)P_SCRAP_EXEC; auto scrap_exec = (T_SCRAP_EXEC)P_SCRAP_EXEC;

View file

@ -1,19 +1,20 @@
#pragma once #pragma once
template<typename T> template <typename T>
struct HashTableEntry; struct HashTableEntry;
struct Vector3 { struct Vector3
{
float x; float x;
float y; float y;
float z; float z;
}; };
struct Matrix3x3 { struct Matrix3x3
{
Vector3 a; Vector3 a;
Vector3 b; Vector3 b;
Vector3 c; Vector3 c;
}; };
struct PyMethodDef struct PyMethodDef
{ {
char *ml_name; char *ml_name;
@ -31,31 +32,35 @@ struct PyMod
struct Module struct Module
{ {
PyMod *mod; PyMod *mod;
map<string, PyMethodDef*> methods; map<string, PyMethodDef *> methods;
}; };
struct Entity { struct Entity
void* vmt; {
const char* name; void *vmt;
const char *name;
}; };
struct EntityList { struct EntityList
const char* name; {
void* unk_1; const char *name;
void* unk_2; void *unk_1;
const char* mod; void *unk_2;
const char* func; const char *mod;
const char *func;
}; };
template<typename T> template <typename T>
struct HashTable { struct HashTable
{
uint32_t size; uint32_t size;
HashTableEntry<T>** chains; HashTableEntry<T> **chains;
}; };
template<typename T> template <typename T>
struct HashTableEntry { struct HashTableEntry
T* data; {
const char* name; T *data;
HashTableEntry* next; const char *name;
HashTableEntry *next;
}; };

View file

@ -9,7 +9,7 @@ string GetLastErrorAsString()
return "No error"; return "No error";
LPSTR messageBuffer = NULL; LPSTR messageBuffer = NULL;
size_t m_size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 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); NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
string message(messageBuffer, m_size); string message(messageBuffer, m_size);
LocalFree(messageBuffer); LocalFree(messageBuffer);
if (!message.empty() && message[message.length() - 1] == '\n') if (!message.empty() && message[message.length() - 1] == '\n')
@ -62,7 +62,6 @@ void FreeConsole(bool wait)
FreeConsole(); FreeConsole();
} }
bool in_foreground = false; bool in_foreground = false;
BOOL CALLBACK EnumWindowsProcMy(HWND hwnd, LPARAM lParam) BOOL CALLBACK EnumWindowsProcMy(HWND hwnd, LPARAM lParam)
{ {
@ -109,7 +108,6 @@ bool key_down_norepeat(int keycode, int delay = 100)
return false; return false;
} }
void hexdump(void *addr, size_t count) void hexdump(void *addr, size_t count)
{ {
for (size_t i = 0; i < count; ++i) for (size_t i = 0; i < count; ++i)
@ -124,35 +122,35 @@ void hexdump(void *addr, size_t count)
cout << endl; cout << endl;
} }
template<typename T> template <typename T>
T* __ptr(uintptr_t addr) T *__ptr(uintptr_t addr)
{ {
return reinterpret_cast<T*>(addr); return reinterpret_cast<T *>(addr);
} }
template <typename T>
template<typename T> T *__ptr(uintptr_t addr, ptrdiff_t offset)
T* __ptr(uintptr_t addr, ptrdiff_t offset)
{ {
//cout << "[" << (void*)addr << "] + " << (void*)offset << " = "; //cout << "[" << (void*)addr << "] + " << (void*)offset << " = ";
addr = reinterpret_cast<uintptr_t*>(addr)[0] + offset; addr = reinterpret_cast<uintptr_t *>(addr)[0] + offset;
//cout << (void*)addr << endl;; //cout << (void*)addr << endl;;
auto ret = __ptr<T>(addr); auto ret = __ptr<T>(addr);
return ret; return ret;
} }
template <typename T, typename... Offsets>
template<typename T, typename... Offsets> T *__ptr(uintptr_t addr, ptrdiff_t offset, Offsets... offsets)
T* __ptr(uintptr_t addr, ptrdiff_t offset, Offsets... offsets) { {
//cout << "[" << (void*)addr << "] + " << (void*)offset << " = "; //cout << "[" << (void*)addr << "] + " << (void*)offset << " = ";
addr = reinterpret_cast<uintptr_t*>(addr)[0] + offset; addr = reinterpret_cast<uintptr_t *>(addr)[0] + offset;
//cout << (void*)addr << endl;; //cout << (void*)addr << endl;;
auto ret = __ptr<T>(addr, offsets...); auto ret = __ptr<T>(addr, offsets...);
return ret; return ret;
} }
template<typename T, typename... Offsets> template <typename T, typename... Offsets>
T* ptr(uintptr_t addr, Offsets... offsets) { T *ptr(uintptr_t addr, Offsets... offsets)
{
auto ret = __ptr<T>(addr, offsets...); auto ret = __ptr<T>(addr, offsets...);
return ret; return ret;
} }

View file

@ -4,23 +4,23 @@ class VMT_Hook
{ {
private: private:
MEMORY_BASIC_INFORMATION mbi; MEMORY_BASIC_INFORMATION mbi;
void* orig; void *orig;
void* detour; void *detour;
DWORD* vtable; DWORD *vtable;
size_t ord; size_t ord;
bool enabled; bool enabled;
static map<uintptr_t, shared_ptr<VMT_Hook>> hooks; static map<uintptr_t, shared_ptr<VMT_Hook>> hooks;
static DWORD* GetVTable(void* addr) { static DWORD *GetVTable(void *addr)
{
return (DWORD *)*(DWORD *)addr; return (DWORD *)*(DWORD *)addr;
}; };
public: public:
VMT_Hook(void *obj, size_t ord, void *detour)
VMT_Hook(void* obj, size_t ord, void* detour) { {
this->vtable = GetVTable(obj); this->vtable = GetVTable(obj);
this->detour = detour; this->detour = detour;
this->orig = reinterpret_cast<void*>(vtable[ord]); this->orig = reinterpret_cast<void *>(vtable[ord]);
this->ord = ord; this->ord = ord;
this->enabled = false; this->enabled = false;
@ -28,51 +28,62 @@ public:
cout << "Hooking: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour << ")" << endl; cout << "Hooking: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour << ")" << endl;
} }
~VMT_Hook() { ~VMT_Hook()
{
cout << "Unhooking: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour << ")" << endl; cout << "Unhooking: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour << ")" << endl;
this->disable(); this->disable();
} }
static void create(void* obj, size_t ord, void* detour) { static void create(void *obj, size_t ord, void *detour)
{
uintptr_t key = reinterpret_cast<uintptr_t>(detour); uintptr_t key = reinterpret_cast<uintptr_t>(detour);
hooks[key] = make_shared<VMT_Hook>(obj,ord, detour); hooks[key] = make_shared<VMT_Hook>(obj, ord, detour);
hooks[key]->enable(); hooks[key]->enable();
} }
static shared_ptr<VMT_Hook> get(void* func) { static shared_ptr<VMT_Hook> get(void *func)
{
uintptr_t addr = reinterpret_cast<uintptr_t>(func); uintptr_t addr = reinterpret_cast<uintptr_t>(func);
return VMT_Hook::get(addr); return VMT_Hook::get(addr);
} }
static shared_ptr<VMT_Hook> get(uintptr_t addr) { static shared_ptr<VMT_Hook> get(uintptr_t addr)
{
return hooks.at(addr); return hooks.at(addr);
} }
static size_t drop(void* func) { static size_t drop(void *func)
{
uintptr_t addr = reinterpret_cast<uintptr_t>(func); uintptr_t addr = reinterpret_cast<uintptr_t>(func);
return VMT_Hook::drop(addr); return VMT_Hook::drop(addr);
} }
static size_t drop(uintptr_t addr) { static size_t drop(uintptr_t addr)
{
return hooks.erase(addr); return hooks.erase(addr);
} }
static void clear() { static void clear()
{
return hooks.clear(); return hooks.clear();
} }
void disable() { void disable()
if (enabled) { {
cout << "Disabling: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour<<")" << endl; if (enabled)
{
cout << "Disabling: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour << ")" << endl;
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL);
this->vtable[ord] = reinterpret_cast<DWORD>(this->orig); this->vtable[ord] = reinterpret_cast<DWORD>(this->orig);
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL);
enabled = false; enabled = false;
} }
} }
void enable() { void enable()
if (!enabled) { {
cout << "Enabling: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour <<")" << endl; if (!enabled)
{
cout << "Enabling: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour << ")" << endl;
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL);
this->vtable[ord] = reinterpret_cast<DWORD>(this->detour); this->vtable[ord] = reinterpret_cast<DWORD>(this->detour);
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL);
@ -80,12 +91,11 @@ public:
} }
} }
template<typename T> template <typename T>
T func() { T func()
{
return reinterpret_cast<T>(this->orig); return reinterpret_cast<T>(this->orig);
} }
}; };
map<uintptr_t, shared_ptr<VMT_Hook>> VMT_Hook::hooks; map<uintptr_t, shared_ptr<VMT_Hook>> VMT_Hook::hooks;

View file

@ -1,4 +1,4 @@
#include "stdafx.h" #include <Windows.h>
#define DLL_EXPORT extern "C" __declspec(dllexport) #define DLL_EXPORT extern "C" __declspec(dllexport)
void DllInit(HMODULE); void DllInit(HMODULE);
void DllPreInit(HMODULE); void DllPreInit(HMODULE);

File diff suppressed because one or more lines are too long

View file

@ -1,18 +1,20 @@
from construct import * from construct import *
from pprint import pprint from pprint import pprint
ScrapSaveVar = Struct( ScrapSaveVar = Struct(
'name'/PascalString(Int32ul,encoding='utf-8'), "name" / PascalString(Int32ul, encoding="utf-8"),
'data'/PascalString(Int32ul,encoding='utf-8'), "data" / PascalString(Int32ul, encoding="utf-8"),
) )
ScrapSave = 'ScarpSaveGame'/Struct( ScrapSave = "ScarpSaveGame" / Struct(
'title'/PascalString(Int32ul,encoding='utf-8'), "title" / PascalString(Int32ul, encoding="utf-8"),
'id'/PascalString(Int32ul,encoding='utf-8'), "id" / PascalString(Int32ul, encoding="utf-8"),
'data'/PrefixedArray(Int32ul,ScrapSaveVar), "data" / PrefixedArray(Int32ul, ScrapSaveVar),
Terminated Terminated,
) )
with open("Save0.sav", 'rb') as sav_file: with open("Save0.sav", "rb") as sav_file:
save = ScrapSave.parse_stream(sav_file) save = ScrapSave.parse_stream(sav_file)
print("ID:",save.id) print("ID:", save.id)
print("Title:",save.title) print("Title:", save.title)
for var in save.data: for var in save.data:
print(" - {}: {}".format(var.name,var.data)) print(" - {}: {}".format(var.name, var.data))

View file

@ -5,131 +5,128 @@ import os
import shutil import shutil
from construct import * from construct import *
from tqdm import tqdm from tqdm import tqdm
setglobalstringencoding(None) setglobalstringencoding(None)
ScrapFile = Struct( ScrapFile = Struct(
'path'/PascalString(Int32ul), "path" / PascalString(Int32ul),
'size'/Int32ul, "size" / Int32ul,
'offset'/Int32ul, "offset" / Int32ul,
'data'/OnDemandPointer(this.offset,Bytes(this.size)), "data" / OnDemandPointer(this.offset, Bytes(this.size)),
) )
DummyFile = Struct( DummyFile = Struct("path" / PascalString(Int32ul), "size" / Int32ul, "offset" / Int32ul)
'path'/PascalString(Int32ul),
'size'/Int32ul,
'offset'/Int32ul,
)
PackedHeader = Struct( PackedHeader = Struct(
Const(b'BFPK'), Const(b"BFPK"), Const(b"\0\0\0\0"), "files" / PrefixedArray(Int32ul, ScrapFile)
Const(b'\0\0\0\0'), )
'files'/PrefixedArray(Int32ul,ScrapFile),
)
DummyHeader = Struct( DummyHeader = Struct(
Const(b'BFPK'), Const(b"BFPK"), Const(b"\0\0\0\0"), "files" / PrefixedArray(Int32ul, DummyFile)
Const(b'\0\0\0\0'), )
'files'/PrefixedArray(Int32ul,DummyFile), parser = argparse.ArgumentParser(description="Unpack and Repack .packed files")
) parser.add_argument(
parser = argparse.ArgumentParser(description='Unpack and Repack .packed files') "-u", "--unpack", action="store_true", help="unpack file to 'extracted' directory"
parser.add_argument('-u', '--unpack', action='store_true', )
help='unpack file to \'extracted\' directory') parser.add_argument(
parser.add_argument('-r', '--repack', action='store_true', "-r", "--repack", action="store_true", help="repack file from 'extracted' directory"
help='repack file from \'extracted\' directory') )
parser.add_argument( parser.add_argument(
'--reset', "--reset", action="store_true", default=False, help="restore backup"
action='store_true', )
default=False,
help='restore backup')
parser.add_argument( parser.add_argument(
'scrap_dir', "scrap_dir",
metavar='Scrapland Directory', metavar="Scrapland Directory",
type=str, type=str,
default=".", default=".",
help='Scrapland installation directory') help="Scrapland installation directory",
)
options = parser.parse_args() options = parser.parse_args()
scrap_dir = os.path.abspath(options.scrap_dir) scrap_dir = os.path.abspath(options.scrap_dir)
if options.reset: if options.reset:
print('Restoring Backups and removing extracted folder...') print("Restoring Backups and removing extracted folder...")
for packed_file in glob.glob(os.path.join(scrap_dir, '*.packed.bak')): for packed_file in glob.glob(os.path.join(scrap_dir, "*.packed.bak")):
outfile = os.path.basename(packed_file) outfile = os.path.basename(packed_file)
orig_filename = outfile[:-4] orig_filename = outfile[:-4]
if os.path.isfile(outfile): if os.path.isfile(outfile):
print('deleting', orig_filename) print("deleting", orig_filename)
os.remove(orig_filename) os.remove(orig_filename)
print('moving', outfile, '->', orig_filename) print("moving", outfile, "->", orig_filename)
shutil.move(outfile, orig_filename) shutil.move(outfile, orig_filename)
target_folder = os.path.join( target_folder = os.path.join("extracted", os.path.basename(orig_filename))
'extracted', os.path.basename(orig_filename)) print("deleting", target_folder)
print('deleting', target_folder)
shutil.rmtree(target_folder) shutil.rmtree(target_folder)
if os.path.isdir('extracted'): if os.path.isdir("extracted"):
input('Press enter to remove rest of extracted folder') input("Press enter to remove rest of extracted folder")
shutil.rmtree('extracted') shutil.rmtree("extracted")
exit('Done!') exit("Done!")
if not (options.unpack or options.repack): if not (options.unpack or options.repack):
parser.print_help() parser.print_help()
exit() exit()
pstatus = '' pstatus = ""
if options.unpack: if options.unpack:
if os.path.isdir('extracted'): if os.path.isdir("extracted"):
print("Removing extracted folder") print("Removing extracted folder")
shutil.rmtree('extracted') shutil.rmtree("extracted")
for packed_file in glob.glob(os.path.join(scrap_dir, '*.packed')): for packed_file in glob.glob(os.path.join(scrap_dir, "*.packed")):
os.chdir(scrap_dir) os.chdir(scrap_dir)
BN=os.path.basename(packed_file) BN = os.path.basename(packed_file)
target_folder = os.path.join( target_folder = os.path.join("extracted", os.path.basename(packed_file))
'extracted', os.path.basename(packed_file))
os.makedirs(target_folder, exist_ok=True) os.makedirs(target_folder, exist_ok=True)
os.chdir(target_folder) os.chdir(target_folder)
print('Unpacking {}'.format(os.path.basename(packed_file))) print("Unpacking {}".format(os.path.basename(packed_file)))
with open(packed_file, 'rb') as pkfile: with open(packed_file, "rb") as pkfile:
data = PackedHeader.parse_stream(pkfile) data = PackedHeader.parse_stream(pkfile)
print("Offset:",hex(pkfile.tell())) print("Offset:", hex(pkfile.tell()))
for file in tqdm(data.files,ascii=True): for file in tqdm(data.files, ascii=True):
folder, filename = os.path.split(file.path) folder, filename = os.path.split(file.path)
if folder: if folder:
os.makedirs(folder, exist_ok=True) os.makedirs(folder, exist_ok=True)
with open(file.path, 'wb') as outfile: with open(file.path, "wb") as outfile:
outfile.write(file.data()) outfile.write(file.data())
print('\r' + ' ' * len(pstatus) + '\r', end='', flush=True) print("\r" + " " * len(pstatus) + "\r", end="", flush=True)
os.chdir(scrap_dir) os.chdir(scrap_dir)
if (options.unpack and options.repack): if options.unpack and options.repack:
input('Press enter to rebuild *.packed files from folders in \'extracted\' dir...') # noqa input(
"Press enter to rebuild *.packed files from folders in 'extracted' dir..."
) # noqa
pass pass
def file_gen(files,offset=0):
for real_path,size,path in files:
file=dict(
path=path,
offset=offset,
size=size)
yield file
offset+=file['size']
def make_header(files,offset=0): def file_gen(files, offset=0):
files_list=list(file_gen(files,offset)) for real_path, size, path in files:
file = dict(path=path, offset=offset, size=size)
yield file
offset += file["size"]
def make_header(files, offset=0):
files_list = list(file_gen(files, offset))
return DummyHeader.build(dict(files=files_list)) return DummyHeader.build(dict(files=files_list))
if options.repack: if options.repack:
for folder in glob.glob(os.path.join(scrap_dir, 'extracted', '*.packed')): for folder in glob.glob(os.path.join(scrap_dir, "extracted", "*.packed")):
data=[] data = []
filename=os.path.join(scrap_dir,os.path.basename(folder)) filename = os.path.join(scrap_dir, os.path.basename(folder))
for root,folders,files in os.walk(folder): for root, folders, files in os.walk(folder):
for file in sorted(files): for file in sorted(files):
file=os.path.join(root,file) file = os.path.join(root, file)
rel_path=bytes(file.replace(folder, '').replace('\\', '/').lstrip('/'), 'windows-1252') rel_path = bytes(
size=os.stat(file).st_size file.replace(folder, "").replace("\\", "/").lstrip("/"),
data.append((file,size,rel_path)) "windows-1252",
print("Found {} files for {}".format(len(data),filename)) )
offset=len(make_header(data)) size = os.stat(file).st_size
print("Writing",filename) data.append((file, size, rel_path))
header=make_header(data,offset) print("Found {} files for {}".format(len(data), filename))
with open(filename,"wb") as outfile: offset = len(make_header(data))
print("Writing", filename)
header = make_header(data, offset)
with open(filename, "wb") as outfile:
outfile.write(header) outfile.write(header)
for file,size,rel_path in tqdm(data,ascii=True): for file, size, rel_path in tqdm(data, ascii=True):
outfile.write(open(file,"rb").read()) outfile.write(open(file, "rb").read())
print('Done!') print("Done!")