Auto format everything
This commit is contained in:
parent
e21faa76a1
commit
a920c63d41
16 changed files with 1165 additions and 5336 deletions
|
@ -1,17 +1,17 @@
|
||||||
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)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#include "stdafx.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <TlHelp32.h>
|
#include <TlHelp32.h>
|
||||||
|
@ -27,7 +26,8 @@ string GetLastErrorAsString()
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fail(char* msg) {
|
void fail(char *msg)
|
||||||
|
{
|
||||||
cerr << "[!] " << msg << ": " << GetLastErrorAsString() << endl;
|
cerr << "[!] " << msg << ": " << GetLastErrorAsString() << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -211,13 +211,15 @@ void InjectDll(DWORD PID)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<HANDLE> spawn(char* binary) {
|
vector<HANDLE> spawn(char *binary)
|
||||||
|
{
|
||||||
STARTUPINFO startupinfo;
|
STARTUPINFO startupinfo;
|
||||||
PROCESS_INFORMATION processinfo;
|
PROCESS_INFORMATION processinfo;
|
||||||
ZeroMemory(&startupinfo, sizeof(startupinfo));
|
ZeroMemory(&startupinfo, sizeof(startupinfo));
|
||||||
ZeroMemory(&processinfo, sizeof(processinfo));
|
ZeroMemory(&processinfo, sizeof(processinfo));
|
||||||
startupinfo.cb = sizeof(startupinfo);
|
startupinfo.cb = sizeof(startupinfo);
|
||||||
if (!CreateProcessA(NULL, binary, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupinfo, &processinfo)) {
|
if (!CreateProcessA(NULL, binary, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupinfo, &processinfo))
|
||||||
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return {processinfo.hProcess, processinfo.hThread};
|
return {processinfo.hProcess, processinfo.hThread};
|
||||||
|
@ -232,23 +234,29 @@ int main(int argc, char *argv[])
|
||||||
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 << "[*] Injector PID: " << GetCurrentProcessId() << endl;
|
||||||
cout << "[*] Spawning process for \"" << argv[1] << "\"" << endl;
|
cout << "[*] Spawning process for \"" << argv[1] << "\"" << endl;
|
||||||
vector<HANDLE> handles = spawn(argv[1]);
|
vector<HANDLE> handles = spawn(argv[1]);
|
||||||
if (handles.empty()) {
|
if (handles.empty())
|
||||||
|
{
|
||||||
fail("Failed to spawn process");
|
fail("Failed to spawn process");
|
||||||
}
|
}
|
||||||
hProc = handles[0];
|
hProc = handles[0];
|
||||||
hThread = handles[1];
|
hThread = handles[1];
|
||||||
PID = GetProcessId(hProc);
|
PID = GetProcessId(hProc);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
cerr << "Usage: " << argv[0] << " <Path to Scrap.exe>" << endl;
|
cerr << "Usage: " << argv[0] << " <Path to Scrap.exe>" << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
InjectDll(PID);
|
InjectDll(PID);
|
||||||
if (hThread != INVALID_HANDLE_VALUE) {
|
if (hThread != INVALID_HANDLE_VALUE)
|
||||||
while (ResumeThread(hThread));
|
{
|
||||||
|
while (ResumeThread(hThread))
|
||||||
|
;
|
||||||
}
|
}
|
||||||
SetEnvironmentVariableA("Inj_PID", NULL);
|
SetEnvironmentVariableA("Inj_PID", NULL);
|
||||||
cout << "[*] Done!" << endl;
|
cout << "[*] Done!" << endl;
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
ExternalProject_Add(DirectX
|
ExternalProject_Add(
|
||||||
|
DirectX
|
||||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}
|
PREFIX ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
URL https://archive.org/download/DirectX.8.0a.SDK_includes_libs_only/DirectX.8.0a.SDK.zip
|
URL
|
||||||
URL_HASH SHA1=39f168336d0df92ff14d62d5e3aef1b9e3191312
|
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)
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
#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;
|
||||||
|
@ -16,21 +17,25 @@ 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) {
|
{
|
||||||
|
if (!overlay)
|
||||||
|
{
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
char text[4096];
|
char text[4096];
|
||||||
int32_t money = 0;
|
int32_t money = 0;
|
||||||
size_t num_ents = 0;
|
size_t num_ents = 0;
|
||||||
size_t num_ent_lst = 0;
|
size_t num_ent_lst = 0;
|
||||||
if (ptr<void>(P_WORLD, 0)!=nullptr) {
|
if (ptr<void>(P_WORLD, 0) != nullptr)
|
||||||
|
{
|
||||||
money = ptr<int32_t>(P_WORLD, O_MONEY)[0];
|
money = ptr<int32_t>(P_WORLD, O_MONEY)[0];
|
||||||
num_ents = size_ht(ptr<HashTable<Entity>>(P_WORLD, O_ENTS));
|
num_ents = size_ht(ptr<HashTable<Entity>>(P_WORLD, O_ENTS));
|
||||||
num_ent_lst = size_ht(ptr<HashTable<EntityList>>(P_WORLD, O_ENTLISTS));
|
num_ent_lst = size_ht(ptr<HashTable<EntityList>>(P_WORLD, O_ENTLISTS));
|
||||||
}
|
}
|
||||||
snprintf(text, 4096, "ScrapHack v0.1\nFrame: [%lld]\nMoney: [%d]\nEntities: [%ld]\nEntity Lists: [%ld]", ++frame, money, num_ents, num_ent_lst);
|
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) {
|
if (m_pFont == nullptr)
|
||||||
|
{
|
||||||
D3DXCreateFont(dev, hFont, &m_pFont);
|
D3DXCreateFont(dev, hFont, &m_pFont);
|
||||||
CloseHandle(hFont);
|
CloseHandle(hFont);
|
||||||
}
|
}
|
||||||
|
@ -41,7 +46,8 @@ LPDIRECT3DDEVICE8 Render(LPDIRECT3DDEVICE8 dev) {
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI H_EndScene(LPDIRECT3DDEVICE8 dev) {
|
HRESULT WINAPI H_EndScene(LPDIRECT3DDEVICE8 dev)
|
||||||
|
{
|
||||||
typedef HRESULT(WINAPI * t_func)(LPDIRECT3DDEVICE8);
|
typedef HRESULT(WINAPI * t_func)(LPDIRECT3DDEVICE8);
|
||||||
shared_ptr<Hook> hook = Hook::get(H_EndScene);
|
shared_ptr<Hook> hook = Hook::get(H_EndScene);
|
||||||
return hook->func<t_func>(Render(dev));
|
return hook->func<t_func>(Render(dev));
|
||||||
|
@ -49,7 +55,8 @@ HRESULT WINAPI H_EndScene(LPDIRECT3DDEVICE8 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 *);
|
typedef HRESULT(WINAPI * t_func)(void *, unsigned int, D3DDEVTYPE, HWND, unsigned long, D3DPRESENT_PARAMETERS *, LPDIRECT3DDEVICE8 *);
|
||||||
shared_ptr<Hook> hook = Hook::get(H_CreateDevice);
|
shared_ptr<Hook> hook = Hook::get(H_CreateDevice);
|
||||||
HRESULT ret = hook->func<t_func>(pDirect3D, uiAdapter, pDeviceType, hFocusWindow, ulBehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
|
HRESULT ret = hook->func<t_func>(pDirect3D, uiAdapter, pDeviceType, hFocusWindow, ulBehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
|
||||||
|
@ -61,7 +68,8 @@ HRESULT WINAPI H_CreateDevice(void* pDirect3D, unsigned int uiAdapter, D3DDEVTYP
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPDIRECT3D8 WINAPI H_Direct3DCreate8(unsigned int SDKVersion) {
|
LPDIRECT3D8 WINAPI H_Direct3DCreate8(unsigned int SDKVersion)
|
||||||
|
{
|
||||||
typedef LPDIRECT3D8(_stdcall * t_func)(unsigned int);
|
typedef LPDIRECT3D8(_stdcall * t_func)(unsigned int);
|
||||||
shared_ptr<Hook> hook = Hook::get(H_Direct3DCreate8);
|
shared_ptr<Hook> hook = Hook::get(H_Direct3DCreate8);
|
||||||
|
|
||||||
|
@ -76,17 +84,21 @@ LPDIRECT3D8 WINAPI H_Direct3DCreate8(unsigned int SDKVersion) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unhook_d3d8() {
|
void unhook_d3d8()
|
||||||
if (hFont != INVALID_HANDLE_VALUE) {
|
{
|
||||||
|
if (hFont != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
CloseHandle(hFont);
|
CloseHandle(hFont);
|
||||||
}
|
}
|
||||||
if (m_pFont != nullptr) {
|
if (m_pFont != nullptr)
|
||||||
|
{
|
||||||
m_pFont->Release();
|
m_pFont->Release();
|
||||||
}
|
}
|
||||||
Hook::drop(H_EndScene);
|
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");
|
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));
|
hBrush = CreateSolidBrush(D3DCOLOR_ARGB(25, 0, 0, 0));
|
||||||
Hook::module("d3d8.dll", "Direct3DCreate8", H_Direct3DCreate8);
|
Hook::module("d3d8.dll", "Direct3DCreate8", H_Direct3DCreate8);
|
||||||
|
|
|
@ -12,8 +12,8 @@ private:
|
||||||
static map<uintptr_t, shared_ptr<Hook>> hooks;
|
static map<uintptr_t, shared_ptr<Hook>> hooks;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Hook(void *func, void *detour)
|
||||||
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;
|
cout << "Hooking: [" << mod << "]." << func << " -> " << detour << endl;
|
||||||
void *addr = GetProcAddress(GetModuleHandle(mod), func);
|
void *addr = GetProcAddress(GetModuleHandle(mod), func);
|
||||||
if (addr != NULL) {
|
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,12 +114,14 @@ 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();
|
||||||
|
|
|
@ -8,7 +8,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#include "stdafx.h"
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -34,12 +35,14 @@ struct Module
|
||||||
map<string, PyMethodDef *> methods;
|
map<string, PyMethodDef *> methods;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Entity {
|
struct Entity
|
||||||
|
{
|
||||||
void *vmt;
|
void *vmt;
|
||||||
const char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EntityList {
|
struct EntityList
|
||||||
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
void *unk_1;
|
void *unk_1;
|
||||||
void *unk_2;
|
void *unk_2;
|
||||||
|
@ -48,13 +51,15 @@ struct EntityList {
|
||||||
};
|
};
|
||||||
|
|
||||||
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;
|
T *data;
|
||||||
const char *name;
|
const char *name;
|
||||||
HashTableEntry *next;
|
HashTableEntry *next;
|
||||||
|
|
|
@ -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)
|
||||||
|
@ -130,7 +128,6 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -141,9 +138,9 @@ T* __ptr(uintptr_t addr, ptrdiff_t offset)
|
||||||
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;;
|
||||||
|
@ -152,7 +149,8 @@ T* __ptr(uintptr_t addr, ptrdiff_t offset, Offsets... offsets) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,14 +10,14 @@ private:
|
||||||
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]);
|
||||||
|
@ -28,41 +28,50 @@ 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) {
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
cout << "Disabling: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour << ")" << endl;
|
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);
|
||||||
|
@ -70,8 +79,10 @@ public:
|
||||||
enabled = false;
|
enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void enable() {
|
void enable()
|
||||||
if (!enabled) {
|
{
|
||||||
|
if (!enabled)
|
||||||
|
{
|
||||||
cout << "Enabling: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour << ")" << endl;
|
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);
|
||||||
|
@ -81,11 +92,10 @@ 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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
5470
helplib.txt
5470
helplib.txt
File diff suppressed because one or more lines are too long
|
@ -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))
|
||||||
|
|
||||||
|
|
113
scrapper.py
113
scrapper.py
|
@ -5,123 +5,120 @@ 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(
|
|
||||||
'path'/PascalString(Int32ul),
|
|
||||||
'size'/Int32ul,
|
|
||||||
'offset'/Int32ul,
|
|
||||||
)
|
)
|
||||||
|
DummyFile = Struct("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(
|
||||||
|
"-u", "--unpack", action="store_true", help="unpack file to 'extracted' directory"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-r", "--repack", action="store_true", help="repack file from 'extracted' directory"
|
||||||
)
|
)
|
||||||
parser = argparse.ArgumentParser(description='Unpack and Repack .packed files')
|
|
||||||
parser.add_argument('-u', '--unpack', action='store_true',
|
|
||||||
help='unpack file to \'extracted\' directory')
|
|
||||||
parser.add_argument('-r', '--repack', action='store_true',
|
|
||||||
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):
|
def file_gen(files, offset=0):
|
||||||
for real_path, size, path in files:
|
for real_path, size, path in files:
|
||||||
file=dict(
|
file = dict(path=path, offset=offset, size=size)
|
||||||
path=path,
|
|
||||||
offset=offset,
|
|
||||||
size=size)
|
|
||||||
yield file
|
yield file
|
||||||
offset+=file['size']
|
offset += file["size"]
|
||||||
|
|
||||||
|
|
||||||
def make_header(files, offset=0):
|
def make_header(files, offset=0):
|
||||||
files_list = list(file_gen(files, offset))
|
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(
|
||||||
|
file.replace(folder, "").replace("\\", "/").lstrip("/"),
|
||||||
|
"windows-1252",
|
||||||
|
)
|
||||||
size = os.stat(file).st_size
|
size = os.stat(file).st_size
|
||||||
data.append((file, size, rel_path))
|
data.append((file, size, rel_path))
|
||||||
print("Found {} files for {}".format(len(data), filename))
|
print("Found {} files for {}".format(len(data), filename))
|
||||||
|
@ -132,4 +129,4 @@ if options.repack:
|
||||||
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!")
|
||||||
|
|
Loading…
Reference in a new issue