code cleanup, expand REPL, Automatically generate D3D8-VMT header file from include file, made ScrapHacks importable as python module
This commit is contained in:
parent
37c64ea9ce
commit
493b10e78b
|
@ -0,0 +1,127 @@
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveMacros: false
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowAllConstructorInitializersOnNextLine: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: MultiLine
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 80
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||||
|
Priority: 3
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 1
|
||||||
|
IncludeIsMainRegex: '(Test)?$'
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 4
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: All
|
||||||
|
ObjCBinPackProtocolList: Auto
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PointerAlignment: Right
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: true
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Cpp11
|
||||||
|
StatementMacros:
|
||||||
|
- Q_UNUSED
|
||||||
|
- QT_REQUIRE_VERSION
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Never
|
||||||
|
...
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"xlocale": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bitset": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"codecvt": "cpp",
|
||||||
|
"complex": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"csignal": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"future": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"ios": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"locale": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"regex": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"shared_mutex": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"strstream": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"typeindex": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"variant": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"xfacet": "cpp",
|
||||||
|
"xhash": "cpp",
|
||||||
|
"xiosbase": "cpp",
|
||||||
|
"xlocbuf": "cpp",
|
||||||
|
"xlocinfo": "cpp",
|
||||||
|
"xlocmes": "cpp",
|
||||||
|
"xlocmon": "cpp",
|
||||||
|
"xlocnum": "cpp",
|
||||||
|
"xloctime": "cpp",
|
||||||
|
"xmemory": "cpp",
|
||||||
|
"xstddef": "cpp",
|
||||||
|
"xstring": "cpp",
|
||||||
|
"xtr1common": "cpp",
|
||||||
|
"xtree": "cpp",
|
||||||
|
"xutility": "cpp"
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,5 +19,71 @@ if(WIN32)
|
||||||
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(ScrapHack)
|
include(ExternalProject)
|
||||||
|
|
||||||
|
ExternalProject_Add(
|
||||||
|
DirectX
|
||||||
|
PREFIX ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
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)
|
||||||
|
include_directories(AFTER ${SOURCE_DIR}/8.0/include/)
|
||||||
|
link_directories(AFTER ${SOURCE_DIR}/8.0/lib/)
|
||||||
|
|
||||||
|
add_custom_target(
|
||||||
|
MAKE_D3D8_VMT python ${CMAKE_CURRENT_SOURCE_DIR}/src/make_D3D8_VMT.py ${CMAKE_CURRENT_SOURCE_DIR}/src/D3D8_VMT.hpp ${SOURCE_DIR}/8.0/include/d3d8.h
|
||||||
|
DEPENDS DirectX
|
||||||
|
)
|
||||||
|
|
||||||
|
# ExternalProject_Add(
|
||||||
|
# Python152
|
||||||
|
# PREFIX ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
# CONFIGURE_COMMAND ""
|
||||||
|
# BUILD_COMMAND ""
|
||||||
|
# INSTALL_COMMAND ""
|
||||||
|
# URL
|
||||||
|
# https://www.python.org/ftp/python/src/py152.tgz
|
||||||
|
# URL_HASH SHA1=2d648d07b1aa1aab32a3a24851c33715141779b9
|
||||||
|
# )
|
||||||
|
# ExternalProject_Get_Property(Python152 SOURCE_DIR)
|
||||||
|
# include_directories(AFTER ${SOURCE_DIR}/Include/)
|
||||||
|
|
||||||
|
|
||||||
|
# ExternalProject_Add(
|
||||||
|
# Python152_Bin
|
||||||
|
# PREFIX ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
# CONFIGURE_COMMAND ""
|
||||||
|
# BUILD_COMMAND ""
|
||||||
|
# INSTALL_COMMAND ""
|
||||||
|
# URL
|
||||||
|
# https://www.python.org/ftp/python/win32/py152.exe
|
||||||
|
# URL_HASH SHA1=dfaf2dcc3704fb1bbc339db4f33ff94bd61c74c6
|
||||||
|
# )
|
||||||
|
# ExternalProject_Get_Property(Python152 SOURCE_DIR)
|
||||||
|
# link_directories(AFTER ${SOURCE_DIR}/)
|
||||||
|
|
||||||
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
add_compile_definitions(POINTER_64=__ptr64)
|
||||||
|
add_library(ScrapHack SHARED
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/dllmain.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/ScrapHack.cpp
|
||||||
|
)
|
||||||
|
set_target_properties(ScrapHack PROPERTIES SUFFIX ".pyd")
|
||||||
|
add_dependencies(ScrapHack DirectX)
|
||||||
|
add_dependencies(ScrapHack MAKE_D3D8_VMT)
|
||||||
|
add_dependencies(MAKE_D3D8_VMT DirectX)
|
||||||
|
# add_dependencies(ScrapHack Python152)
|
||||||
|
# add_dependencies(ScrapHack Python152_Bin)
|
||||||
|
target_link_libraries(ScrapHack
|
||||||
|
d3d8
|
||||||
|
d3dx8
|
||||||
|
dxerr8
|
||||||
|
# PYTHON15
|
||||||
|
legacy_stdio_definitions)
|
||||||
|
target_compile_features(ScrapHack PUBLIC cxx_std_11)
|
||||||
|
install(TARGETS ScrapHack DESTINATION bin)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
- Visual Studio 2017/2019 (others might work)
|
- Visual Studio 2017/2019 (others might work)
|
||||||
- CMake
|
- CMake
|
||||||
|
- Python 3.6 or newer
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
|
@ -11,13 +12,22 @@ Open VS 32-bit command prompt (`vcvars32.bat`)
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake -G"NMake Makefiles" ..
|
cmake -G"NMake Makefiles" ..
|
||||||
cmake --build . --target install
|
mkdir bin
|
||||||
|
cd bin
|
||||||
|
cmake --build .. --target install
|
||||||
```
|
```
|
||||||
|
|
||||||
this will drop the compiled files into `./build/bin`
|
this will drop the compiled files into `./build/bin`
|
||||||
|
|
||||||
(this has only been tested with a (cracked/deobfuscated) `Scrap.exe` v1.0 with a SHA1 checksum of `d2dde960e8eca69d60c2e39a439088b75f0c89fa`, other version might crash if the memory offsets don't match)
|
## Usage
|
||||||
|
|
||||||
## TODO
|
- create a `lib` folder next to `Scrapland.exe`
|
||||||
|
- copy `ScrapHack.pyd` into said folder
|
||||||
|
- open the ingame console (Ctrl+^)
|
||||||
|
- type `import ScrapHack`
|
||||||
|
- Done!
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
(this has only been tested with a (cracked/de-obfuscated) `Scrap.exe` v1.0 with a SHA1 checksum of `d2dde960e8eca69d60c2e39a439088b75f0c89fa`, other version might crash if the memory offsets don't match)
|
||||||
|
|
||||||
- Injector-less version (patch Scrap.exe to load DLL)
|
|
|
@ -1,24 +0,0 @@
|
||||||
include(ExternalProject)
|
|
||||||
ExternalProject_Add(
|
|
||||||
DirectX
|
|
||||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
CONFIGURE_COMMAND ""
|
|
||||||
BUILD_COMMAND ""
|
|
||||||
INSTALL_COMMAND ""
|
|
||||||
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)
|
|
||||||
include_directories(AFTER ${SOURCE_DIR}/8.0/include/)
|
|
||||||
link_directories(AFTER ${SOURCE_DIR}/8.0/lib/)
|
|
||||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
|
||||||
add_compile_definitions(POINTER_64=__ptr64)
|
|
||||||
add_library(ScrapHack SHARED ScrapHack.cpp dllmain.cpp)
|
|
||||||
add_dependencies(ScrapHack DirectX)
|
|
||||||
target_link_libraries(ScrapHack
|
|
||||||
d3d8
|
|
||||||
d3dx8
|
|
||||||
dxerr8
|
|
||||||
legacy_stdio_definitions)
|
|
||||||
target_compile_features(ScrapHack PUBLIC cxx_std_11)
|
|
||||||
install(TARGETS ScrapHack DESTINATION bin)
|
|
|
@ -1,82 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <d3d8.h>
|
|
||||||
#include <d3dx8.h>
|
|
||||||
#include <dxerr8.h>
|
|
||||||
uintmax_t frame = 0;
|
|
||||||
DWORD *GetVTable(void *addr)
|
|
||||||
{
|
|
||||||
return (DWORD *)(*(DWORD *)addr);
|
|
||||||
}
|
|
||||||
bool overlay = false;
|
|
||||||
LPD3DXFONT m_pFont;
|
|
||||||
HFONT hFont;
|
|
||||||
HBRUSH hBrush;
|
|
||||||
D3DCOLOR color = D3DCOLOR_ARGB(255, 255, 0, 0);
|
|
||||||
RECT Rect = {0, 0, 0, 0};
|
|
||||||
D3DRECT panel;
|
|
||||||
|
|
||||||
size_t size_ht(HashTable<EntityList> *ht);
|
|
||||||
size_t size_ht(HashTable<Entity> *ht);
|
|
||||||
|
|
||||||
LPDIRECT3DDEVICE8 Render(LPDIRECT3DDEVICE8 dev)
|
|
||||||
{
|
|
||||||
if (!overlay)
|
|
||||||
{
|
|
||||||
return dev;
|
|
||||||
}
|
|
||||||
char text[4096];
|
|
||||||
int32_t money = 0;
|
|
||||||
size_t num_ents = 0;
|
|
||||||
size_t num_ent_lst = 0;
|
|
||||||
if (ptr<void>(P_WORLD, 0) != nullptr)
|
|
||||||
{
|
|
||||||
money = ptr<int32_t>(P_WORLD, O_MONEY)[0];
|
|
||||||
num_ents = size_ht(ptr<HashTable<Entity>>(P_WORLD, O_ENTS));
|
|
||||||
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);
|
|
||||||
if (m_pFont == nullptr)
|
|
||||||
{
|
|
||||||
D3DXCreateFont(dev, hFont, &m_pFont);
|
|
||||||
CloseHandle(hFont);
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
typedef HRESULT(WINAPI * t_func)(LPDIRECT3DDEVICE8);
|
|
||||||
shared_ptr<Hook> hook = Hook::get(H_EndScene);
|
|
||||||
return hook->func<t_func>(Render(dev));
|
|
||||||
}
|
|
||||||
|
|
||||||
void unhook_d3d8()
|
|
||||||
{
|
|
||||||
if (hFont != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
CloseHandle(hFont);
|
|
||||||
}
|
|
||||||
if (m_pFont != nullptr)
|
|
||||||
{
|
|
||||||
m_pFont->Release();
|
|
||||||
}
|
|
||||||
Hook::drop(H_EndScene);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hook_d3d8()
|
|
||||||
{
|
|
||||||
typedef void(_cdecl * t_func)();
|
|
||||||
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));
|
|
||||||
Hook::addr(ptr<void>(0x853954,0x2a3d8,0,4*35,0),H_EndScene);
|
|
||||||
shared_ptr<Hook> hook = Hook::get(hook_d3d8);
|
|
||||||
hook->func_void<t_func>();
|
|
||||||
hook->disable();
|
|
||||||
Hook::drop(hook_d3d8);
|
|
||||||
return;
|
|
||||||
}
|
|
|
@ -1,141 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <functional>
|
|
||||||
class Hook
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
|
||||||
void *orig;
|
|
||||||
void *detour;
|
|
||||||
bool enabled;
|
|
||||||
uint8_t orig_bytes[6];
|
|
||||||
uint8_t jmp_bytes[6];
|
|
||||||
static map<uintptr_t, shared_ptr<Hook>> hooks;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Hook(void *func, void *detour)
|
|
||||||
{
|
|
||||||
uintptr_t dest = reinterpret_cast<uintptr_t>(detour);
|
|
||||||
uintptr_t src = reinterpret_cast<uintptr_t>(func);
|
|
||||||
this->orig = func;
|
|
||||||
this->detour = detour;
|
|
||||||
this->jmp_bytes[0] = 0x68; // push
|
|
||||||
this->jmp_bytes[1] = (dest >> 0) & 0xff;
|
|
||||||
this->jmp_bytes[2] = (dest >> 8) & 0xff;
|
|
||||||
this->jmp_bytes[3] = (dest >> 16) & 0xff;
|
|
||||||
this->jmp_bytes[4] = (dest >> 24) & 0xff;
|
|
||||||
this->jmp_bytes[5] = 0xC3; // ret
|
|
||||||
VirtualQuery(func, &mbi, sizeof(mbi));
|
|
||||||
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect);
|
|
||||||
memcpy(this->orig_bytes, this->orig, 1 + 4 + 1);
|
|
||||||
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL);
|
|
||||||
this->enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Hook()
|
|
||||||
{
|
|
||||||
cout << "Unhooking: [" << this->orig << " <- " << this->detour << "]" << endl;
|
|
||||||
this->disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addr(void *addr, void *detour)
|
|
||||||
{
|
|
||||||
cout << "Hooking: [" << addr << " -> " << detour << "]" << endl;
|
|
||||||
uintptr_t key = reinterpret_cast<uintptr_t>(detour);
|
|
||||||
hooks[key] = make_shared<Hook>(addr, detour);
|
|
||||||
hooks[key]->enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void module(const char *mod, const char *func, void *detour)
|
|
||||||
{
|
|
||||||
cout << "Hooking: [" << mod << "]." << func << " -> " << detour << endl;
|
|
||||||
void *addr = GetProcAddress(GetModuleHandle(mod), func);
|
|
||||||
if (addr != NULL)
|
|
||||||
{
|
|
||||||
Hook::addr(addr, detour);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cerr << "[" << mod << "]." << func << " not found!" << endl;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static shared_ptr<Hook> get(void *func)
|
|
||||||
{
|
|
||||||
uintptr_t addr = reinterpret_cast<uintptr_t>(func);
|
|
||||||
return Hook::get(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static shared_ptr<Hook> get(uintptr_t addr)
|
|
||||||
{
|
|
||||||
return hooks.at(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t drop(void *func)
|
|
||||||
{
|
|
||||||
uintptr_t addr = reinterpret_cast<uintptr_t>(func);
|
|
||||||
return Hook::drop(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t drop(uintptr_t addr)
|
|
||||||
{
|
|
||||||
return hooks.erase(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear()
|
|
||||||
{
|
|
||||||
cout << "Clearing Hooks" << endl;
|
|
||||||
for (pair<uintptr_t, shared_ptr<Hook>> h : hooks)
|
|
||||||
{
|
|
||||||
h.second->disable();
|
|
||||||
}
|
|
||||||
return hooks.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void disable()
|
|
||||||
{
|
|
||||||
if (enabled)
|
|
||||||
{
|
|
||||||
//cout << "Disabling: [" << this->orig << " <- " << this->detour << "]" << endl;
|
|
||||||
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL);
|
|
||||||
memcpy(this->orig, this->orig_bytes, 1 + 4 + 1);
|
|
||||||
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL);
|
|
||||||
enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void enable()
|
|
||||||
{
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
//cout << "Enabling: [" << this->orig << " -> " << this->detour << "]" << endl;
|
|
||||||
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL);
|
|
||||||
memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1);
|
|
||||||
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL);
|
|
||||||
enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *get_orig()
|
|
||||||
{
|
|
||||||
return this->orig;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename F, typename... Args>
|
|
||||||
void func_void(Args... args)
|
|
||||||
{
|
|
||||||
disable();
|
|
||||||
reinterpret_cast<F>(this->orig)(args...);
|
|
||||||
enable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename F, typename... Args>
|
|
||||||
decltype(auto) func(Args... args)
|
|
||||||
{
|
|
||||||
disable();
|
|
||||||
auto ret = reinterpret_cast<F>(this->orig)(args...);
|
|
||||||
enable();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
map<uintptr_t, shared_ptr<Hook>> Hook::hooks;
|
|
|
@ -1,62 +0,0 @@
|
||||||
#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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
#include <sstream>
|
|
||||||
#include <regex>
|
|
||||||
#include <Windows.h>
|
|
||||||
#include "Util.h"
|
|
||||||
|
|
||||||
DWORD get_protection(void *addr)
|
|
||||||
{
|
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
|
||||||
VirtualQuery(addr, &mbi, sizeof(mbi));
|
|
||||||
return mbi.Protect;
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle_command(const char *_cmd)
|
|
||||||
{
|
|
||||||
cout<<"CMD: '"<<_cmd<<"'"<<endl;
|
|
||||||
vector<string> cmd = split(string(_cmd), ' ');
|
|
||||||
cout<<"PARTS: ";
|
|
||||||
for (string c:cmd) {
|
|
||||||
cout<<"'"<<c<<"' ";
|
|
||||||
}
|
|
||||||
cout<<endl;
|
|
||||||
if (cmd.size() == 0)
|
|
||||||
{
|
|
||||||
cout<<"EMPTY!"<<endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
scrap_log(0x00ff00,_cmd);
|
|
||||||
scrap_log(0x00ff00,"\n");
|
|
||||||
if (cmd[0] == "r")
|
|
||||||
{
|
|
||||||
if (cmd.size()!=2) {
|
|
||||||
scrap_log(0xff0000, "Usage: $r <addr> [size]\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
scrap_log(0xff0000, "READ!\n");
|
|
||||||
cout<<"READ!"<<endl;
|
|
||||||
}
|
|
||||||
else if (cmd[0] == "w")
|
|
||||||
{
|
|
||||||
if (cmd.size()!=2) {
|
|
||||||
scrap_log(0xff0000, "Usage: $w <addr> <hex_data>\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
scrap_log(0xff0000, "WRITE!\n");
|
|
||||||
cout<<"WRITE!"<<endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scrap_log(0xff0000, "Unknown command!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
scrap_log(0x00ff00, "HAXX\n");
|
|
||||||
return;
|
|
||||||
}
|
|
|
@ -1,266 +0,0 @@
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#include <typeinfo>
|
|
||||||
#include <functional>
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <TlHelp32.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "Scrapland.h"
|
|
||||||
#include "Util.h"
|
|
||||||
#include "Structures.h"
|
|
||||||
#include "Py_Utils.h"
|
|
||||||
#include "Hook.h"
|
|
||||||
#include "D3D8_Hook.h"
|
|
||||||
#include "REPL.h"
|
|
||||||
HMODULE hD3D8Dll = 0;
|
|
||||||
|
|
||||||
bool initialized = false;
|
|
||||||
bool running = true;
|
|
||||||
bool redirect_console = false;
|
|
||||||
HMODULE mod = 0;
|
|
||||||
|
|
||||||
void DllUnload(HMODULE);
|
|
||||||
int hooked_console(const char *);
|
|
||||||
void H_Exit();
|
|
||||||
|
|
||||||
size_t size_ht(HashTable<EntityList> *ht)
|
|
||||||
{
|
|
||||||
size_t cnt = 0;
|
|
||||||
for (size_t i = 0; i < ht->size; ++i)
|
|
||||||
{
|
|
||||||
HashTableEntry<EntityList> *ent = ht->chains[i];
|
|
||||||
if (ent)
|
|
||||||
{
|
|
||||||
while (ent)
|
|
||||||
{
|
|
||||||
++cnt;
|
|
||||||
ent = ent->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size_ht(HashTable<Entity> *ht)
|
|
||||||
{
|
|
||||||
size_t cnt = 0;
|
|
||||||
for (size_t i = 0; i < ht->size; ++i)
|
|
||||||
{
|
|
||||||
HashTableEntry<Entity> *ent = ht->chains[i];
|
|
||||||
if (ent)
|
|
||||||
{
|
|
||||||
while (ent)
|
|
||||||
{
|
|
||||||
++cnt;
|
|
||||||
ent = ent->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t dump_ht(HashTable<EntityList> *ht)
|
|
||||||
{
|
|
||||||
size_t cnt = 0;
|
|
||||||
for (size_t i = 0; i < ht->size; ++i)
|
|
||||||
{
|
|
||||||
HashTableEntry<EntityList> *ent = ht->chains[i];
|
|
||||||
if (ent)
|
|
||||||
{
|
|
||||||
cout << i << ": ";
|
|
||||||
while (ent)
|
|
||||||
{
|
|
||||||
++cnt;
|
|
||||||
cout << "[ " << ent->name << ": " << ent->data << "]";
|
|
||||||
if (ent->next)
|
|
||||||
{
|
|
||||||
cout << " -> ";
|
|
||||||
};
|
|
||||||
ent = ent->next;
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cout << cnt << " Entries" << endl;
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t dump_ht(HashTable<Entity> *ht)
|
|
||||||
{
|
|
||||||
size_t cnt = 0;
|
|
||||||
for (size_t i = 0; i < ht->size; ++i)
|
|
||||||
{
|
|
||||||
HashTableEntry<Entity> *ent = ht->chains[i];
|
|
||||||
if (ent)
|
|
||||||
{
|
|
||||||
cout << i << ": ";
|
|
||||||
while (ent)
|
|
||||||
{
|
|
||||||
++cnt;
|
|
||||||
cout << "[ " << ent->name << ": " << ent->data << "]";
|
|
||||||
if (ent->next)
|
|
||||||
{
|
|
||||||
cout << " -> ";
|
|
||||||
};
|
|
||||||
ent = ent->next;
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cout << cnt << " Entries" << endl;
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainLoop(HMODULE mod)
|
|
||||||
{
|
|
||||||
Sleep(100);
|
|
||||||
Hook::addr(reinterpret_cast<void *>(P_SCRAP_EXIT), H_Exit);
|
|
||||||
Hook::addr(reinterpret_cast<void *>(P_D3DCHECK),hook_d3d8);
|
|
||||||
Hook::addr(reinterpret_cast<void *>(P_CON_HANDLER), hooked_console);
|
|
||||||
overlay=true;
|
|
||||||
cout << "[*] Starting main Loop" << endl;
|
|
||||||
cout << endl;
|
|
||||||
cout << "[F2 ] Redirect game console to ScapHacks console" << endl;
|
|
||||||
cout << "[F3 ] Unload ScrapHacks" << endl;
|
|
||||||
cout << "[F5 ] Show Overlay" << endl;
|
|
||||||
cout << "[F6 ] Show Alarm status" << endl;
|
|
||||||
cout << "[F7 ] Set Money to 0x7fffffff" << endl;
|
|
||||||
cout << "[F8 ] Dump python modules" << endl;
|
|
||||||
cout << "[F9 ] Dump Entity hashtable" << endl;
|
|
||||||
cout << "[F10] Enable python tracing" << endl;
|
|
||||||
cout << "[ F ] \"Handbrake\" (*Will* crash the game after some time!)" << endl;
|
|
||||||
|
|
||||||
while (running)
|
|
||||||
{
|
|
||||||
Sleep(100);
|
|
||||||
while (key_down('F'))
|
|
||||||
{
|
|
||||||
scrap_exec("dbg.brake()");
|
|
||||||
}
|
|
||||||
if (key_down_norepeat(VK_F2))
|
|
||||||
{
|
|
||||||
redirect_console = !redirect_console;
|
|
||||||
}
|
|
||||||
if (key_down_norepeat(VK_F3))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key_down_norepeat(VK_F5))
|
|
||||||
{
|
|
||||||
overlay = !overlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key_down_norepeat(VK_F6))
|
|
||||||
{
|
|
||||||
|
|
||||||
float *alarm = ptr<float>(P_WORLD, O_ALARM);
|
|
||||||
float *alarm_grow = ptr<float>(P_WORLD, O_ALARM_GROW);
|
|
||||||
cout << "Alarm: " << alarm[0] << " + " << alarm_grow[0] << endl;
|
|
||||||
}
|
|
||||||
if (key_down_norepeat(VK_F7))
|
|
||||||
{
|
|
||||||
int32_t *money = ptr<int32_t>(P_WORLD, O_MONEY);
|
|
||||||
*money = 0x7fffffff;
|
|
||||||
}
|
|
||||||
if (key_down_norepeat(VK_F8))
|
|
||||||
{
|
|
||||||
for (auto mod : Py)
|
|
||||||
{
|
|
||||||
for (auto meth : mod.second.methods)
|
|
||||||
{
|
|
||||||
cout << mod.first << "." << meth.first << " @ " << meth.second->ml_meth << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key_down_norepeat(VK_F9))
|
|
||||||
{
|
|
||||||
cout << "Entities:" << endl;
|
|
||||||
dump_ht(ptr<HashTable<Entity>>(P_WORLD, O_ENTS));
|
|
||||||
cout << "Entity Lists:" << endl;
|
|
||||||
dump_ht(ptr<HashTable<EntityList>>(P_WORLD, O_ENTLISTS));
|
|
||||||
}
|
|
||||||
if (key_down_norepeat(VK_F10))
|
|
||||||
{
|
|
||||||
scrap_exec("dbg.settrace()");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FreeLibraryAndExitThread(mod, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitConsole()
|
|
||||||
{
|
|
||||||
char me[1024];
|
|
||||||
GetModuleFileName(mod, me, 1024);
|
|
||||||
SetupConsole(me);
|
|
||||||
}
|
|
||||||
|
|
||||||
int hooked_console(const char *cmd)
|
|
||||||
{
|
|
||||||
typedef int(_cdecl * t_func)(const char *);
|
|
||||||
if (cmd[0] == '$')
|
|
||||||
{
|
|
||||||
handle_command(++cmd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
shared_ptr<Hook> hook = Hook::get(hooked_console);
|
|
||||||
int ret = hook->func<t_func>(cmd);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void H_Exit()
|
|
||||||
{
|
|
||||||
typedef void(_cdecl * t_func)(void);
|
|
||||||
shared_ptr<Hook> hook = Hook::get(H_Exit);
|
|
||||||
DllUnload(mod);
|
|
||||||
HWND hMainWindow = ptr<HWND>(0x7FA830, 0x7c)[0];
|
|
||||||
SendMessage(hMainWindow, WM_CLOSE, 0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DllPreInit(HMODULE _mod)
|
|
||||||
{
|
|
||||||
char mfn[1024];
|
|
||||||
InitConsole();
|
|
||||||
GetModuleFileNameA(0, mfn, 1024);
|
|
||||||
Py = get_modules(P_PY_MODS);
|
|
||||||
cout << "[+] ScrapHacks v0.1 Loaded in " << mfn << " (PID: " << std::hex << GetCurrentProcessId() << std::dec << ")" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DllInit(HMODULE _mod)
|
|
||||||
{
|
|
||||||
initialized = true;
|
|
||||||
mod = _mod;
|
|
||||||
cout << "[*] World: " << ptr<void>(P_WORLD, 0) << endl;
|
|
||||||
cout << "[*] Importing python dbg module" << endl;
|
|
||||||
scrap_exec("import dbg");
|
|
||||||
scrap_log(0xff0000, "ScrapHacks loaded!\n");
|
|
||||||
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainLoop, mod, 0, 0);
|
|
||||||
cout << "[*] Starting message pump" << endl;
|
|
||||||
MSG msg;
|
|
||||||
while (GetMessage(&msg, NULL, 0, 0))
|
|
||||||
{
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DllUnload(HMODULE _mod)
|
|
||||||
{
|
|
||||||
SetConsoleCtrlHandler(NULL, false);
|
|
||||||
unhook_d3d8();
|
|
||||||
Hook::clear();
|
|
||||||
scrap_log(0xff0000, "ScrapHacks unloaded!\n");
|
|
||||||
cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl;
|
|
||||||
FreeConsole();
|
|
||||||
DestroyWindow(GetConsoleWindow());
|
|
||||||
return;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
//OFFSETS
|
|
||||||
#define O_MONEY 0x2090
|
|
||||||
#define O_ALARM 0x1C6C
|
|
||||||
#define O_ALARM_GROW 0x1C68
|
|
||||||
#define O_ENTS 0x4
|
|
||||||
#define O_ENTLISTS 0x2b8
|
|
||||||
|
|
||||||
//POINTERS
|
|
||||||
#define P_WORLD 0x7FE944
|
|
||||||
#define P_PY_MODS 0x79C698
|
|
||||||
|
|
||||||
//FUNCTIONS
|
|
||||||
#define P_CON_HANDLER 0x402190
|
|
||||||
#define P_SCRAP_LOG 0x4134C0
|
|
||||||
#define P_SCRAP_EXEC 0x5a8390
|
|
||||||
#define P_SCRAP_EXIT 0x4010c0
|
|
||||||
#define P_D3DCHECK 0x602a70
|
|
||||||
|
|
||||||
//FUNCTION TYPES
|
|
||||||
#define T_SCRAP_LOG int(_cdecl *)(unsigned int, const char *)
|
|
||||||
#define T_SCRAP_EXEC int(_cdecl *)(const char *)
|
|
||||||
|
|
||||||
auto scrap_log = (T_SCRAP_LOG)P_SCRAP_LOG;
|
|
||||||
auto scrap_exec = (T_SCRAP_EXEC)P_SCRAP_EXEC;
|
|
|
@ -1,66 +0,0 @@
|
||||||
#pragma once
|
|
||||||
template <typename T>
|
|
||||||
struct HashTableEntry;
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Entity
|
|
||||||
{
|
|
||||||
void *vmt;
|
|
||||||
const char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EntityList
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
void *unk_1;
|
|
||||||
void *unk_2;
|
|
||||||
const char *mod;
|
|
||||||
const char *func;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct HashTable
|
|
||||||
{
|
|
||||||
uint32_t size;
|
|
||||||
HashTableEntry<T> **chains;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct HashTableEntry
|
|
||||||
{
|
|
||||||
T *data;
|
|
||||||
const char *name;
|
|
||||||
HashTableEntry *next;
|
|
||||||
};
|
|
|
@ -1,206 +0,0 @@
|
||||||
#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 (!AttachConsole(-1)) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DWORD PPID()
|
|
||||||
{
|
|
||||||
DWORD PID = GetCurrentProcessId();
|
|
||||||
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
||||||
PROCESSENTRY32 procentry;
|
|
||||||
if (hSnapShot == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
cout << GetLastErrorAsString() << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (Process32First(hSnapShot, &procentry))
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (procentry.th32ProcessID == PID)
|
|
||||||
{
|
|
||||||
CloseHandle(hSnapShot);
|
|
||||||
return procentry.th32ParentProcessID;
|
|
||||||
}
|
|
||||||
procentry.dwSize = sizeof(PROCESSENTRY32);
|
|
||||||
} while (Process32Next(hSnapShot, &procentry));
|
|
||||||
}
|
|
||||||
CloseHandle(hSnapShot);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<string> split(string str, char sep)
|
|
||||||
{
|
|
||||||
vector<string> ret;
|
|
||||||
string part;
|
|
||||||
for (auto n : str)
|
|
||||||
{
|
|
||||||
if (n == sep)
|
|
||||||
{
|
|
||||||
ret.push_back(part);
|
|
||||||
part.clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
part = part + n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (part != "")
|
|
||||||
ret.push_back(part);
|
|
||||||
return ret;
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
#include <Windows.h>
|
|
||||||
#define DLL_EXPORT extern "C" __declspec(dllexport)
|
|
||||||
void DllInit(HMODULE);
|
|
||||||
void DllPreInit(HMODULE);
|
|
||||||
void DllUnload(HMODULE);
|
|
||||||
|
|
||||||
BOOL APIENTRY DllMain(HMODULE hModule,
|
|
||||||
DWORD ul_reason_for_call,
|
|
||||||
LPVOID lpReserved)
|
|
||||||
{
|
|
||||||
HANDLE hThread = INVALID_HANDLE_VALUE;
|
|
||||||
switch (ul_reason_for_call)
|
|
||||||
{
|
|
||||||
case DLL_PROCESS_ATTACH:
|
|
||||||
DisableThreadLibraryCalls(hModule);
|
|
||||||
DllPreInit(hModule);
|
|
||||||
hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DllInit, hModule, 0, 0);
|
|
||||||
if (hThread) {
|
|
||||||
CloseHandle(hThread);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DLL_PROCESS_DETACH:
|
|
||||||
DllUnload(hModule);
|
|
||||||
break;
|
|
||||||
case DLL_THREAD_ATTACH:
|
|
||||||
case DLL_THREAD_DETACH:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
#pragma once
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <d3d8.h>
|
||||||
|
#include <d3dx8.h>
|
||||||
|
#include <dxerr8.h>
|
||||||
|
|
||||||
|
#include "D3D8_VMT.hpp"
|
||||||
|
#include "Hook.hpp"
|
||||||
|
#include "Scrapland.hpp"
|
||||||
|
#include "Structures.hpp"
|
||||||
|
#include "Util.hpp"
|
||||||
|
|
||||||
|
uintmax_t frame = 0;
|
||||||
|
bool hooked=false;
|
||||||
|
bool overlay = false;
|
||||||
|
LPD3DXFONT m_pFont;
|
||||||
|
HFONT hFont;
|
||||||
|
HBRUSH hBrush;
|
||||||
|
D3DCOLOR color = D3DCOLOR_ARGB(255, 255, 0, 0);
|
||||||
|
RECT Rect = {0, 0, 0, 0};
|
||||||
|
D3DRECT panel;
|
||||||
|
|
||||||
|
size_t size_ht(HashTable<EntityList> *ht);
|
||||||
|
size_t size_ht(HashTable<Entity> *ht);
|
||||||
|
|
||||||
|
LPDIRECT3DDEVICE8
|
||||||
|
Render(LPDIRECT3DDEVICE8 dev) {
|
||||||
|
if (!overlay) {
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
char text[4096];
|
||||||
|
int32_t money = 0;
|
||||||
|
size_t num_ents = 0;
|
||||||
|
size_t num_ent_lst = 0;
|
||||||
|
if (ptr<void>(P_WORLD, 0) != nullptr) {
|
||||||
|
money = ptr<int32_t>(P_WORLD, O_MONEY)[0];
|
||||||
|
num_ents = size_ht(ptr<HashTable<Entity>>(P_WORLD, O_ENTS));
|
||||||
|
num_ent_lst = size_ht(ptr<HashTable<EntityList>>(P_WORLD, O_ENTLISTS));
|
||||||
|
}
|
||||||
|
snprintf(text, 4096,
|
||||||
|
R"(ScrapHack v0.1
|
||||||
|
Frame: [%lld]
|
||||||
|
Money: [%d]
|
||||||
|
Entities: [%ld]
|
||||||
|
Entity Lists: [%ld])",
|
||||||
|
++frame, money, num_ents, num_ent_lst);
|
||||||
|
if (m_pFont == nullptr) {
|
||||||
|
D3DXCreateFont(dev, hFont, &m_pFont);
|
||||||
|
hFont = nullptr;
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
typedef decltype(&H_EndScene) t_func;
|
||||||
|
shared_ptr<Hook> hook = Hook::get(H_EndScene);
|
||||||
|
return hook->func<t_func>(Render(dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI H_SetLight(LPDIRECT3DDEVICE8 dev, DWORD index,
|
||||||
|
D3DLIGHT8 *light) {
|
||||||
|
typedef decltype(&H_SetLight) t_func;
|
||||||
|
shared_ptr<Hook> hook = Hook::get(H_SetLight);
|
||||||
|
light->Diffuse.r = ((float)rand() / (float)RAND_MAX);
|
||||||
|
light->Diffuse.g = ((float)rand() / (float)RAND_MAX);
|
||||||
|
light->Diffuse.b = ((float)rand() / (float)RAND_MAX);
|
||||||
|
light->Diffuse.a = 1.0;
|
||||||
|
light->Specular.r = ((float)rand() / (float)RAND_MAX);
|
||||||
|
light->Specular.g = ((float)rand() / (float)RAND_MAX);
|
||||||
|
light->Specular.b = ((float)rand() / (float)RAND_MAX);
|
||||||
|
light->Specular.r = 1.0;
|
||||||
|
light->Ambient.r = ((float)rand() / (float)RAND_MAX);
|
||||||
|
light->Ambient.g = ((float)rand() / (float)RAND_MAX);
|
||||||
|
light->Ambient.b = ((float)rand() / (float)RAND_MAX);
|
||||||
|
light->Ambient.a = 1.0;
|
||||||
|
return hook->func<t_func>(dev, index, light);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI H_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 dev,
|
||||||
|
D3DPRIMITIVETYPE Type, UINT minIndex,
|
||||||
|
UINT NumVertices, UINT startIndex,
|
||||||
|
UINT primCount) {
|
||||||
|
typedef decltype(&H_DrawIndexedPrimitive) t_func;
|
||||||
|
DWORD AMBIENT;
|
||||||
|
shared_ptr<Hook> hook = Hook::get(H_DrawIndexedPrimitive);
|
||||||
|
dev->GetRenderState(D3DRS_AMBIENT, &AMBIENT);
|
||||||
|
dev->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(255, 255, 255));
|
||||||
|
dev->SetRenderState(D3DRS_FILLMODE, D3DFILLMODE::D3DFILL_SOLID);
|
||||||
|
dev->SetRenderState(D3DRS_ZENABLE, 0);
|
||||||
|
auto ret = hook->func<t_func>(dev, Type, minIndex, NumVertices, startIndex,
|
||||||
|
primCount);
|
||||||
|
dev->SetRenderState(D3DRS_AMBIENT, AMBIENT);
|
||||||
|
dev->SetRenderState(D3DRS_ZENABLE, 1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unhook_d3d8() {
|
||||||
|
if (!hooked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_pFont != nullptr) {
|
||||||
|
m_pFont->Release();
|
||||||
|
m_pFont = nullptr;
|
||||||
|
}
|
||||||
|
Hook::drop(H_EndScene);
|
||||||
|
Hook::drop(H_DrawIndexedPrimitive);
|
||||||
|
Hook::drop(H_SetLight);
|
||||||
|
hooked=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hook_d3d8() {
|
||||||
|
if (hooked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hFont = CreateFontA(15, 0, 0, 0, FW_EXTRABOLD, 0, 0, 0, ANSI_CHARSET, 0, 0,
|
||||||
|
0, 0, "Lucida Console");
|
||||||
|
hBrush = CreateSolidBrush(D3DCOLOR_ARGB(25, 0, 0, 0));
|
||||||
|
void *dev = nullptr;
|
||||||
|
while (true) {
|
||||||
|
dev = ptr<void>(P_D3DDEV);
|
||||||
|
if (dev) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Sleep(100);
|
||||||
|
};
|
||||||
|
Hook::addr(GetVTable(dev)[VMT_IDirect3DDevice8::m_EndScene], H_EndScene);
|
||||||
|
Hook::addr(GetVTable(dev)[VMT_IDirect3DDevice8::m_DrawIndexedPrimitive],
|
||||||
|
H_DrawIndexedPrimitive);
|
||||||
|
Hook::addr(GetVTable(dev)[VMT_IDirect3DDevice8::m_SetLight], H_SetLight);
|
||||||
|
hooked=true;
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,274 @@
|
||||||
|
namespace VMT_IDirect3D8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_RegisterSoftwareDevice = 3;
|
||||||
|
const size_t m_GetAdapterCount = 4;
|
||||||
|
const size_t m_GetAdapterIdentifier = 5;
|
||||||
|
const size_t m_GetAdapterModeCount = 6;
|
||||||
|
const size_t m_EnumAdapterModes = 7;
|
||||||
|
const size_t m_GetAdapterDisplayMode = 8;
|
||||||
|
const size_t m_CheckDeviceType = 9;
|
||||||
|
const size_t m_CheckDeviceFormat = 10;
|
||||||
|
const size_t m_CheckDeviceMultiSampleType = 11;
|
||||||
|
const size_t m_CheckDepthStencilMatch = 12;
|
||||||
|
const size_t m_GetDeviceCaps = 13;
|
||||||
|
const size_t m_GetAdapterMonitor = 14;
|
||||||
|
const size_t m_CreateDevice = 15;
|
||||||
|
}
|
||||||
|
namespace VMT_IDirect3DBaseTexture8_IDirect3DResource8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_GetDevice = 3;
|
||||||
|
const size_t m_SetPrivateData = 4;
|
||||||
|
const size_t m_GetPrivateData = 5;
|
||||||
|
const size_t m_FreePrivateData = 6;
|
||||||
|
const size_t m_SetPriority = 7;
|
||||||
|
const size_t m_GetPriority = 8;
|
||||||
|
const size_t m_PreLoad = 9;
|
||||||
|
const size_t m_GetType = 10;
|
||||||
|
const size_t m_SetLOD = 11;
|
||||||
|
const size_t m_GetLOD = 12;
|
||||||
|
const size_t m_GetLevelCount = 13;
|
||||||
|
}
|
||||||
|
namespace VMT_IDirect3DCubeTexture8_IDirect3DBaseTexture8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_GetDevice = 3;
|
||||||
|
const size_t m_SetPrivateData = 4;
|
||||||
|
const size_t m_GetPrivateData = 5;
|
||||||
|
const size_t m_FreePrivateData = 6;
|
||||||
|
const size_t m_SetPriority = 7;
|
||||||
|
const size_t m_GetPriority = 8;
|
||||||
|
const size_t m_PreLoad = 9;
|
||||||
|
const size_t m_GetType = 10;
|
||||||
|
const size_t m_SetLOD = 11;
|
||||||
|
const size_t m_GetLOD = 12;
|
||||||
|
const size_t m_GetLevelCount = 13;
|
||||||
|
const size_t m_GetLevelDesc = 14;
|
||||||
|
const size_t m_GetCubeMapSurface = 15;
|
||||||
|
const size_t m_LockRect = 16;
|
||||||
|
const size_t m_UnlockRect = 17;
|
||||||
|
const size_t m_AddDirtyRect = 18;
|
||||||
|
}
|
||||||
|
namespace VMT_IDirect3DDevice8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_TestCooperativeLevel = 3;
|
||||||
|
const size_t m_GetAvailableTextureMem = 4;
|
||||||
|
const size_t m_ResourceManagerDiscardBytes = 5;
|
||||||
|
const size_t m_GetDirect3D = 6;
|
||||||
|
const size_t m_GetDeviceCaps = 7;
|
||||||
|
const size_t m_GetDisplayMode = 8;
|
||||||
|
const size_t m_GetCreationParameters = 9;
|
||||||
|
const size_t m_SetCursorProperties = 10;
|
||||||
|
const size_t m_SetCursorPosition = 11;
|
||||||
|
const size_t m_ShowCursor = 12;
|
||||||
|
const size_t m_CreateAdditionalSwapChain = 13;
|
||||||
|
const size_t m_Reset = 14;
|
||||||
|
const size_t m_Present = 15;
|
||||||
|
const size_t m_GetBackBuffer = 16;
|
||||||
|
const size_t m_GetRasterStatus = 17;
|
||||||
|
const size_t m_SetGammaRamp = 18;
|
||||||
|
const size_t m_GetGammaRamp = 19;
|
||||||
|
const size_t m_CreateTexture = 20;
|
||||||
|
const size_t m_CreateVolumeTexture = 21;
|
||||||
|
const size_t m_CreateCubeTexture = 22;
|
||||||
|
const size_t m_CreateVertexBuffer = 23;
|
||||||
|
const size_t m_CreateIndexBuffer = 24;
|
||||||
|
const size_t m_CreateRenderTarget = 25;
|
||||||
|
const size_t m_CreateDepthStencilSurface = 26;
|
||||||
|
const size_t m_CreateImageSurface = 27;
|
||||||
|
const size_t m_CopyRects = 28;
|
||||||
|
const size_t m_UpdateTexture = 29;
|
||||||
|
const size_t m_GetFrontBuffer = 30;
|
||||||
|
const size_t m_SetRenderTarget = 31;
|
||||||
|
const size_t m_GetRenderTarget = 32;
|
||||||
|
const size_t m_GetDepthStencilSurface = 33;
|
||||||
|
const size_t m_BeginScene = 34;
|
||||||
|
const size_t m_EndScene = 35;
|
||||||
|
const size_t m_Clear = 36;
|
||||||
|
const size_t m_SetTransform = 37;
|
||||||
|
const size_t m_GetTransform = 38;
|
||||||
|
const size_t m_MultiplyTransform = 39;
|
||||||
|
const size_t m_SetViewport = 40;
|
||||||
|
const size_t m_GetViewport = 41;
|
||||||
|
const size_t m_SetMaterial = 42;
|
||||||
|
const size_t m_GetMaterial = 43;
|
||||||
|
const size_t m_SetLight = 44;
|
||||||
|
const size_t m_GetLight = 45;
|
||||||
|
const size_t m_LightEnable = 46;
|
||||||
|
const size_t m_GetLightEnable = 47;
|
||||||
|
const size_t m_SetClipPlane = 48;
|
||||||
|
const size_t m_GetClipPlane = 49;
|
||||||
|
const size_t m_SetRenderState = 50;
|
||||||
|
const size_t m_GetRenderState = 51;
|
||||||
|
const size_t m_BeginStateBlock = 52;
|
||||||
|
const size_t m_EndStateBlock = 53;
|
||||||
|
const size_t m_ApplyStateBlock = 54;
|
||||||
|
const size_t m_CaptureStateBlock = 55;
|
||||||
|
const size_t m_DeleteStateBlock = 56;
|
||||||
|
const size_t m_CreateStateBlock = 57;
|
||||||
|
const size_t m_SetClipStatus = 58;
|
||||||
|
const size_t m_GetClipStatus = 59;
|
||||||
|
const size_t m_GetTexture = 60;
|
||||||
|
const size_t m_SetTexture = 61;
|
||||||
|
const size_t m_GetTextureStageState = 62;
|
||||||
|
const size_t m_SetTextureStageState = 63;
|
||||||
|
const size_t m_ValidateDevice = 64;
|
||||||
|
const size_t m_GetInfo = 65;
|
||||||
|
const size_t m_SetPaletteEntries = 66;
|
||||||
|
const size_t m_GetPaletteEntries = 67;
|
||||||
|
const size_t m_SetCurrentTexturePalette = 68;
|
||||||
|
const size_t m_GetCurrentTexturePalette = 69;
|
||||||
|
const size_t m_DrawPrimitive = 70;
|
||||||
|
const size_t m_DrawIndexedPrimitive = 71;
|
||||||
|
const size_t m_DrawPrimitiveUP = 72;
|
||||||
|
const size_t m_DrawIndexedPrimitiveUP = 73;
|
||||||
|
const size_t m_ProcessVertices = 74;
|
||||||
|
const size_t m_CreateVertexShader = 75;
|
||||||
|
const size_t m_SetVertexShader = 76;
|
||||||
|
const size_t m_GetVertexShader = 77;
|
||||||
|
const size_t m_DeleteVertexShader = 78;
|
||||||
|
const size_t m_SetVertexShaderConstant = 79;
|
||||||
|
const size_t m_GetVertexShaderConstant = 80;
|
||||||
|
const size_t m_GetVertexShaderDeclaration = 81;
|
||||||
|
const size_t m_GetVertexShaderFunction = 82;
|
||||||
|
const size_t m_SetStreamSource = 83;
|
||||||
|
const size_t m_GetStreamSource = 84;
|
||||||
|
const size_t m_SetIndices = 85;
|
||||||
|
const size_t m_GetIndices = 86;
|
||||||
|
const size_t m_CreatePixelShader = 87;
|
||||||
|
const size_t m_SetPixelShader = 88;
|
||||||
|
const size_t m_GetPixelShader = 89;
|
||||||
|
const size_t m_DeletePixelShader = 90;
|
||||||
|
const size_t m_SetPixelShaderConstant = 91;
|
||||||
|
const size_t m_GetPixelShaderConstant = 92;
|
||||||
|
const size_t m_GetPixelShaderFunction = 93;
|
||||||
|
const size_t m_DrawRectPatch = 94;
|
||||||
|
const size_t m_DrawTriPatch = 95;
|
||||||
|
const size_t m_DeletePatch = 96;
|
||||||
|
}
|
||||||
|
namespace VMT_IDirect3DIndexBuffer8_IDirect3DResource8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_GetDevice = 3;
|
||||||
|
const size_t m_SetPrivateData = 4;
|
||||||
|
const size_t m_GetPrivateData = 5;
|
||||||
|
const size_t m_FreePrivateData = 6;
|
||||||
|
const size_t m_SetPriority = 7;
|
||||||
|
const size_t m_GetPriority = 8;
|
||||||
|
const size_t m_PreLoad = 9;
|
||||||
|
const size_t m_GetType = 10;
|
||||||
|
const size_t m_Lock = 11;
|
||||||
|
const size_t m_Unlock = 12;
|
||||||
|
const size_t m_GetDesc = 13;
|
||||||
|
}
|
||||||
|
namespace VMT_IDirect3DResource8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_GetDevice = 3;
|
||||||
|
const size_t m_SetPrivateData = 4;
|
||||||
|
const size_t m_GetPrivateData = 5;
|
||||||
|
const size_t m_FreePrivateData = 6;
|
||||||
|
const size_t m_SetPriority = 7;
|
||||||
|
const size_t m_GetPriority = 8;
|
||||||
|
const size_t m_PreLoad = 9;
|
||||||
|
const size_t m_GetType = 10;
|
||||||
|
}
|
||||||
|
namespace VMT_IDirect3DSurface8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_GetDevice = 3;
|
||||||
|
const size_t m_SetPrivateData = 4;
|
||||||
|
const size_t m_GetPrivateData = 5;
|
||||||
|
const size_t m_FreePrivateData = 6;
|
||||||
|
const size_t m_GetContainer = 7;
|
||||||
|
const size_t m_GetDesc = 8;
|
||||||
|
const size_t m_LockRect = 9;
|
||||||
|
const size_t m_UnlockRect = 10;
|
||||||
|
}
|
||||||
|
namespace VMT_IDirect3DSwapChain8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_Present = 3;
|
||||||
|
const size_t m_GetBackBuffer = 4;
|
||||||
|
}
|
||||||
|
namespace VMT_IDirect3DTexture8_IDirect3DBaseTexture8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_GetDevice = 3;
|
||||||
|
const size_t m_SetPrivateData = 4;
|
||||||
|
const size_t m_GetPrivateData = 5;
|
||||||
|
const size_t m_FreePrivateData = 6;
|
||||||
|
const size_t m_SetPriority = 7;
|
||||||
|
const size_t m_GetPriority = 8;
|
||||||
|
const size_t m_PreLoad = 9;
|
||||||
|
const size_t m_GetType = 10;
|
||||||
|
const size_t m_SetLOD = 11;
|
||||||
|
const size_t m_GetLOD = 12;
|
||||||
|
const size_t m_GetLevelCount = 13;
|
||||||
|
const size_t m_GetLevelDesc = 14;
|
||||||
|
const size_t m_GetSurfaceLevel = 15;
|
||||||
|
const size_t m_LockRect = 16;
|
||||||
|
const size_t m_UnlockRect = 17;
|
||||||
|
const size_t m_AddDirtyRect = 18;
|
||||||
|
}
|
||||||
|
namespace VMT_IDirect3DVertexBuffer8_IDirect3DResource8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_GetDevice = 3;
|
||||||
|
const size_t m_SetPrivateData = 4;
|
||||||
|
const size_t m_GetPrivateData = 5;
|
||||||
|
const size_t m_FreePrivateData = 6;
|
||||||
|
const size_t m_SetPriority = 7;
|
||||||
|
const size_t m_GetPriority = 8;
|
||||||
|
const size_t m_PreLoad = 9;
|
||||||
|
const size_t m_GetType = 10;
|
||||||
|
const size_t m_Lock = 11;
|
||||||
|
const size_t m_Unlock = 12;
|
||||||
|
const size_t m_GetDesc = 13;
|
||||||
|
}
|
||||||
|
namespace VMT_IDirect3DVolume8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_GetDevice = 3;
|
||||||
|
const size_t m_SetPrivateData = 4;
|
||||||
|
const size_t m_GetPrivateData = 5;
|
||||||
|
const size_t m_FreePrivateData = 6;
|
||||||
|
const size_t m_GetContainer = 7;
|
||||||
|
const size_t m_GetDesc = 8;
|
||||||
|
const size_t m_LockBox = 9;
|
||||||
|
const size_t m_UnlockBox = 10;
|
||||||
|
}
|
||||||
|
namespace VMT_IDirect3DVolumeTexture8_IDirect3DBaseTexture8 {
|
||||||
|
const size_t m_QueryInterface = 0;
|
||||||
|
const size_t m_AddRef = 1;
|
||||||
|
const size_t m_Release = 2;
|
||||||
|
const size_t m_GetDevice = 3;
|
||||||
|
const size_t m_SetPrivateData = 4;
|
||||||
|
const size_t m_GetPrivateData = 5;
|
||||||
|
const size_t m_FreePrivateData = 6;
|
||||||
|
const size_t m_SetPriority = 7;
|
||||||
|
const size_t m_GetPriority = 8;
|
||||||
|
const size_t m_PreLoad = 9;
|
||||||
|
const size_t m_GetType = 10;
|
||||||
|
const size_t m_SetLOD = 11;
|
||||||
|
const size_t m_GetLOD = 12;
|
||||||
|
const size_t m_GetLevelCount = 13;
|
||||||
|
const size_t m_GetLevelDesc = 14;
|
||||||
|
const size_t m_GetVolumeLevel = 15;
|
||||||
|
const size_t m_LockBox = 16;
|
||||||
|
const size_t m_UnlockBox = 17;
|
||||||
|
const size_t m_AddDirtyBox = 18;
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
#pragma once
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Hook {
|
||||||
|
private:
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
void *orig;
|
||||||
|
void *detour;
|
||||||
|
bool enabled;
|
||||||
|
uint8_t orig_bytes[6];
|
||||||
|
uint8_t jmp_bytes[6];
|
||||||
|
static map<uintptr_t, shared_ptr<Hook>> hooks;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Hook(void *func, void *detour) {
|
||||||
|
uintptr_t dest = reinterpret_cast<uintptr_t>(detour);
|
||||||
|
uintptr_t src = reinterpret_cast<uintptr_t>(func);
|
||||||
|
this->orig = func;
|
||||||
|
this->detour = detour;
|
||||||
|
this->jmp_bytes[0] = 0x68; // push
|
||||||
|
this->jmp_bytes[1] = (dest >> 0) & 0xff;
|
||||||
|
this->jmp_bytes[2] = (dest >> 8) & 0xff;
|
||||||
|
this->jmp_bytes[3] = (dest >> 16) & 0xff;
|
||||||
|
this->jmp_bytes[4] = (dest >> 24) & 0xff;
|
||||||
|
this->jmp_bytes[5] = 0xC3; // ret
|
||||||
|
VirtualQuery(func, &mbi, sizeof(mbi));
|
||||||
|
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE,
|
||||||
|
&mbi.Protect);
|
||||||
|
memcpy(this->orig_bytes, this->orig, 1 + 4 + 1);
|
||||||
|
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL);
|
||||||
|
this->enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Hook() {
|
||||||
|
cout << "Unhooking: [" << this->orig << " <- " << this->detour << "]"
|
||||||
|
<< endl;
|
||||||
|
this->disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addr(void *addr, void *detour) {
|
||||||
|
cout << "Hooking: [" << addr << " -> " << detour << "]" << endl;
|
||||||
|
uintptr_t key = reinterpret_cast<uintptr_t>(detour);
|
||||||
|
hooks[key] = make_shared<Hook>(addr, detour);
|
||||||
|
hooks[key]->enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void module(const char *mod, const char *func, void *detour) {
|
||||||
|
cout << "Hooking: [" << mod << "]." << func << " -> " << detour << endl;
|
||||||
|
void *addr = GetProcAddress(GetModuleHandle(mod), func);
|
||||||
|
if (addr != NULL) {
|
||||||
|
Hook::addr(addr, detour);
|
||||||
|
} else {
|
||||||
|
cerr << "[" << mod << "]." << func << " not found!" << endl;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static shared_ptr<Hook> get(void *func) {
|
||||||
|
uintptr_t addr = reinterpret_cast<uintptr_t>(func);
|
||||||
|
return Hook::get(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static shared_ptr<Hook> get(uintptr_t addr) { return hooks.at(addr); }
|
||||||
|
|
||||||
|
static size_t drop(void *func) {
|
||||||
|
uintptr_t addr = reinterpret_cast<uintptr_t>(func);
|
||||||
|
return Hook::drop(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t drop(uintptr_t addr) { return hooks.erase(addr); }
|
||||||
|
|
||||||
|
static void clear() {
|
||||||
|
cout << "Clearing Hooks" << endl;
|
||||||
|
for (pair<uintptr_t, shared_ptr<Hook>> h : hooks) {
|
||||||
|
h.second->disable();
|
||||||
|
}
|
||||||
|
return hooks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void disable() {
|
||||||
|
if (enabled) {
|
||||||
|
// cout << "Disabling: [" << this->orig << " <- " << this->detour <<
|
||||||
|
// "]"
|
||||||
|
// << endl;
|
||||||
|
VirtualProtect(mbi.BaseAddress, mbi.RegionSize,
|
||||||
|
PAGE_EXECUTE_READWRITE, NULL);
|
||||||
|
memcpy(this->orig, this->orig_bytes, 1 + 4 + 1);
|
||||||
|
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL);
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void enable() {
|
||||||
|
if (!this->enabled) {
|
||||||
|
// cout << "Enabling: [" << this->orig << " -> " << this->detour <<
|
||||||
|
// "]" << endl;
|
||||||
|
VirtualProtect(mbi.BaseAddress, mbi.RegionSize,
|
||||||
|
PAGE_EXECUTE_READWRITE, NULL);
|
||||||
|
memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1);
|
||||||
|
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL);
|
||||||
|
this->enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F, typename... Args> void func_void(Args... args) {
|
||||||
|
this->disable();
|
||||||
|
reinterpret_cast<F>(this->orig)(args...);
|
||||||
|
this->enable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F, typename... Args> auto func(Args... args) {
|
||||||
|
this->disable();
|
||||||
|
auto ret = reinterpret_cast<F>(this->orig)(args...);
|
||||||
|
this->enable();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
map<uintptr_t, shared_ptr<Hook>> Hook::hooks;
|
|
@ -0,0 +1,58 @@
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Structures.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,259 @@
|
||||||
|
#pragma once
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "Scrapland.hpp"
|
||||||
|
#include "Util.hpp"
|
||||||
|
|
||||||
|
void DllUnload();
|
||||||
|
|
||||||
|
|
||||||
|
void unhook_d3d8();
|
||||||
|
void hook_d3d8();
|
||||||
|
|
||||||
|
typedef void(_cdecl *t_cmd_func)(vector<string>);
|
||||||
|
|
||||||
|
struct t_cmd {
|
||||||
|
t_cmd_func func;
|
||||||
|
const char* usage;
|
||||||
|
const char* doc;
|
||||||
|
};
|
||||||
|
|
||||||
|
void cmd_help(vector<string>);
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
get_protection(void *addr) {
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
VirtualQuery(addr, &mbi, sizeof(mbi));
|
||||||
|
return mbi.Protect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_write(vector<string> args) {
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
if (args.size() != 2) {
|
||||||
|
scrap_log(ERR_COLOR, "Usage: $w <addr> <data(hex)>\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void *addr = 0;
|
||||||
|
vector<uint8_t> data;
|
||||||
|
try {
|
||||||
|
addr = (void *)stoull(args[0], 0, 16);
|
||||||
|
data = fromhex(args[1]);
|
||||||
|
} catch (exception e) {
|
||||||
|
scrap_log(ERR_COLOR, "ERROR!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t *buffer = new uint8_t[data.size()];
|
||||||
|
size_t idx = 0;
|
||||||
|
for (uint8_t v : data) {
|
||||||
|
buffer[idx++] = v;
|
||||||
|
}
|
||||||
|
cout << "W:" << (void *)addr << endl;
|
||||||
|
cout << buffer << endl;
|
||||||
|
if (VirtualQuery(addr, &mbi, sizeof(mbi)) == 0) {
|
||||||
|
scrap_log(ERR_COLOR, "ERROR!\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE,
|
||||||
|
&mbi.Protect);
|
||||||
|
memcpy(addr, buffer, data.size());
|
||||||
|
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL);
|
||||||
|
if (buffer) {
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_read(vector<string> args) {
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
if (args.size() != 2) {
|
||||||
|
scrap_log(ERR_COLOR, "Usage: $r <addr> <size>\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uintptr_t addr = UINTPTR_MAX;
|
||||||
|
size_t size = 0;
|
||||||
|
unsigned char *buffer;
|
||||||
|
try {
|
||||||
|
addr = stoull(args[0], 0, 16);
|
||||||
|
size = stoull(args[1]);
|
||||||
|
buffer = new unsigned char[size];
|
||||||
|
} catch (exception e) {
|
||||||
|
scrap_log(ERR_COLOR, "ERROR!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void *mptr = reinterpret_cast<void *>(addr);
|
||||||
|
if (VirtualQuery(mptr, &mbi, sizeof(mbi)) == 0) {
|
||||||
|
scrap_log(ERR_COLOR, "ERROR!\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE,
|
||||||
|
&mbi.Protect);
|
||||||
|
string hxd = hexdump_s(mptr, size);
|
||||||
|
scrap_log(INFO_COLOR, hxd.c_str());
|
||||||
|
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL);
|
||||||
|
if (buffer) {
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_dx8(vector<string> args) {
|
||||||
|
if (args.size()!=1) {
|
||||||
|
scrap_log(ERR_COLOR, "Usage: $dx8 (hook|unhook)\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args[0]=="hook") {
|
||||||
|
hook_d3d8();
|
||||||
|
scrap_log(INFO_COLOR,"DX8 hooked!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args[0]=="unhook") {
|
||||||
|
unhook_d3d8();
|
||||||
|
scrap_log(INFO_COLOR,"DX8 unhooked!\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
scrap_log(ERR_COLOR,"Invalid argument!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_dump_py(vector<string> args) {
|
||||||
|
stringstream out;
|
||||||
|
for (auto mod : Py) {
|
||||||
|
for (auto meth : mod.second.methods) {
|
||||||
|
out << mod.first << "." << meth.first << " @ "
|
||||||
|
<< meth.second->ml_meth << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scrap_log(INFO_COLOR,out.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_dump_ents(vector<string> args) {
|
||||||
|
stringstream out;
|
||||||
|
out << "Entities:" << endl;
|
||||||
|
dump_ht(ptr<HashTable<Entity>>(P_WORLD, O_ENTS), &out);
|
||||||
|
out << "Entity Lists:" << endl;
|
||||||
|
dump_ht(ptr<HashTable<EntityList>>(P_WORLD, O_ENTLISTS), &out);
|
||||||
|
scrap_log(INFO_COLOR,out.str().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_toggle_overlay(vector<string> args) {
|
||||||
|
overlay=!overlay;
|
||||||
|
if (overlay) {
|
||||||
|
scrap_log(INFO_COLOR,"Overlay enabled!\n");
|
||||||
|
} else {
|
||||||
|
scrap_log(INFO_COLOR,"Overlay disabled!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_print_alarm(vector<string> args) {
|
||||||
|
stringstream out;
|
||||||
|
float *alarm = ptr<float>(P_WORLD, O_ALARM);
|
||||||
|
float *alarm_grow = ptr<float>(P_WORLD, O_ALARM_GROW);
|
||||||
|
out << "Alarm: " << alarm[0] << " + " << alarm_grow[0] << endl;
|
||||||
|
scrap_log(INFO_COLOR,out.str().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_unload(vector<string> args) {
|
||||||
|
scrap_log(INFO_COLOR,"Unloading ScrapHacks... bye!\n");
|
||||||
|
DllUnload();
|
||||||
|
}
|
||||||
|
|
||||||
|
static map<string, t_cmd> commands = {
|
||||||
|
{"w", {
|
||||||
|
cmd_write,
|
||||||
|
"Usage: $w <addr> <data(hex)>",
|
||||||
|
"Write memory"
|
||||||
|
}},
|
||||||
|
{"r", {
|
||||||
|
cmd_read,
|
||||||
|
"Usage: $r <addr> <num_bytes>",
|
||||||
|
"Read memory"
|
||||||
|
}},
|
||||||
|
{"unload", {
|
||||||
|
cmd_unload,
|
||||||
|
"Usage: $unload",
|
||||||
|
"Unload ScrapHacks"
|
||||||
|
}},
|
||||||
|
{"dx8", {
|
||||||
|
cmd_dx8,
|
||||||
|
"Usage: $dx8 (hook|unhook)",
|
||||||
|
"Hook/Unhook DirectX 8 functions"
|
||||||
|
}},
|
||||||
|
{"dump_py",{
|
||||||
|
cmd_dump_py,
|
||||||
|
"Usage: $dump_py",
|
||||||
|
"Dump python modules to console"
|
||||||
|
}},
|
||||||
|
{"overlay",{
|
||||||
|
cmd_toggle_overlay,
|
||||||
|
"Usage: $overlay",
|
||||||
|
"Toggle DX8 Overlay"
|
||||||
|
}},
|
||||||
|
{"alarm",{
|
||||||
|
cmd_print_alarm,
|
||||||
|
"Usage: $alarm",
|
||||||
|
"Print alarm status"
|
||||||
|
}},
|
||||||
|
{"ents",{
|
||||||
|
cmd_dump_ents,
|
||||||
|
"Usage: $ents",
|
||||||
|
"Dump entity information"
|
||||||
|
}},
|
||||||
|
{"help", {
|
||||||
|
cmd_help,
|
||||||
|
"Usage: $help [command]",
|
||||||
|
"Print help for ScrapHacks command"}},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void cmd_help(vector<string> args) {
|
||||||
|
if (args.size()!=1) {
|
||||||
|
for (auto cmd: commands) {
|
||||||
|
scrap_log(INFO_COLOR,cmd.first.c_str());
|
||||||
|
scrap_log(INFO_COLOR,": ");
|
||||||
|
scrap_log(INFO_COLOR,cmd.second.doc);
|
||||||
|
scrap_log(INFO_COLOR,"\n");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!commands.count(args[0])) {
|
||||||
|
scrap_log(ERR_COLOR, "Unknown command '");
|
||||||
|
scrap_log(ERR_COLOR, args[0].c_str());
|
||||||
|
scrap_log(ERR_COLOR, "'!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t_cmd cmd=commands[args[0]];
|
||||||
|
scrap_log(INFO_COLOR,args[0].c_str());
|
||||||
|
scrap_log(INFO_COLOR,": ");
|
||||||
|
scrap_log(INFO_COLOR,cmd.usage);
|
||||||
|
scrap_log(INFO_COLOR,"\n\t");
|
||||||
|
scrap_log(INFO_COLOR,cmd.doc);
|
||||||
|
scrap_log(INFO_COLOR,"\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handle_command(const char *_cmd) {
|
||||||
|
scrap_log(ERR_COLOR, "$");
|
||||||
|
scrap_log(ERR_COLOR, _cmd);
|
||||||
|
scrap_log(ERR_COLOR, "\n");
|
||||||
|
cout << "CMD: '" << _cmd << "'" << endl;
|
||||||
|
vector<string> cmd = split(string(_cmd), ' ');
|
||||||
|
if (cmd.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (commands.count(cmd[0])) {
|
||||||
|
string command = cmd[0];
|
||||||
|
cmd.erase(cmd.begin());
|
||||||
|
commands[command].func(cmd);
|
||||||
|
} else {
|
||||||
|
scrap_log(ERR_COLOR, "Unknown command '");
|
||||||
|
scrap_log(ERR_COLOR, cmd[0].c_str());
|
||||||
|
scrap_log(ERR_COLOR, "'!\n");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
// Socket stuff
|
||||||
|
|
||||||
|
#include <Ws2tcpip.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#include "D3D8_Hook.hpp"
|
||||||
|
#include "Hook.hpp"
|
||||||
|
#include "Py_Utils.hpp"
|
||||||
|
#include "REPL.hpp"
|
||||||
|
#include "Scrapland.hpp"
|
||||||
|
#include "Structures.hpp"
|
||||||
|
#include "Util.hpp"
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
bool running = true;
|
||||||
|
|
||||||
|
HMODULE hMod = nullptr;
|
||||||
|
|
||||||
|
void DllUnload();
|
||||||
|
int hooked_console(const char *);
|
||||||
|
void hook_exit();
|
||||||
|
|
||||||
|
int hook_recvfrom(SOCKET s, char *buf, int len, int flags, sockaddr *from,
|
||||||
|
int *fromlen) {
|
||||||
|
typedef decltype(&hook_recvfrom) t_func;
|
||||||
|
shared_ptr<Hook> hook = Hook::get(hook_recvfrom);
|
||||||
|
int ret = hook->func<t_func>(s, buf, len, flags, from, fromlen);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
int hook_sendto(SOCKET s, const char *buf, int len, int flags,
|
||||||
|
const sockaddr *to, int tolen) {
|
||||||
|
typedef decltype(&hook_sendto) t_func;
|
||||||
|
shared_ptr<Hook> hook = Hook::get(hook_sendto);
|
||||||
|
int ret = hook->func<t_func>(s, buf, len, flags, to, tolen);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup_hooks() {
|
||||||
|
Hook::addr(reinterpret_cast<void *>(P_SCRAP_EXIT), hook_exit);
|
||||||
|
Hook::addr(reinterpret_cast<void *>(P_CON_HANDLER), hooked_console);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainLoop() {
|
||||||
|
setup_hooks();
|
||||||
|
overlay = true;
|
||||||
|
cout << "[*] Starting main Loop" << endl;
|
||||||
|
cout << endl;
|
||||||
|
cout << "[F2 ] Redirect game console to ScapHacks console" << endl;
|
||||||
|
cout << "[F3 ] Unload ScrapHacks" << endl;
|
||||||
|
cout << "[F5 ] Show Overlay" << endl;
|
||||||
|
cout << "[F6 ] Show Alarm status" << endl;
|
||||||
|
cout << "[F7 ] Set Money to 0x7fffffff" << endl;
|
||||||
|
cout << "[F8 ] Dump python modules" << endl;
|
||||||
|
cout << "[F9 ] Dump Entity hashtable" << endl;
|
||||||
|
cout << "[F10] Enable python tracing" << endl;
|
||||||
|
cout << "[ F ] \"Handbrake\" (*Will* crash the game after some time!)"
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
Sleep(100);
|
||||||
|
while (key_down('F')) {
|
||||||
|
scrap_exec("dbg.brake()");
|
||||||
|
}
|
||||||
|
if (key_down_norepeat(VK_F3)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_down_norepeat(VK_F7)) {
|
||||||
|
int32_t *money = ptr<int32_t>(P_WORLD, O_MONEY);
|
||||||
|
money[0] = 0x7fffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_down_norepeat(VK_F9)) {
|
||||||
|
cout << "Entities:" << endl;
|
||||||
|
dump_ht(ptr<HashTable<Entity>>(P_WORLD, O_ENTS));
|
||||||
|
cout << "Entity Lists:" << endl;
|
||||||
|
dump_ht(ptr<HashTable<EntityList>>(P_WORLD, O_ENTLISTS));
|
||||||
|
}
|
||||||
|
if (key_down_norepeat(VK_F10)) {
|
||||||
|
scrap_exec("dbg.settrace()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeLibraryAndExitThread(hMod, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitConsole() {
|
||||||
|
char me[1024];
|
||||||
|
GetModuleFileName(hMod, me, 1024);
|
||||||
|
SetupConsole(me);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hooked_console(const char *cmd) {
|
||||||
|
typedef decltype(&hooked_console) t_func;
|
||||||
|
if (cmd[0] == '$') {
|
||||||
|
handle_command(++cmd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
shared_ptr<Hook> hook = Hook::get(hooked_console);
|
||||||
|
int ret = hook->func<t_func>(cmd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hook_exit() {
|
||||||
|
typedef decltype(&hook_exit) t_func;
|
||||||
|
shared_ptr<Hook> hook = Hook::get(hook_exit);
|
||||||
|
DllUnload();
|
||||||
|
HWND hMainWindow = ptr<HWND>(0x7FA830, 0x7c)[0];
|
||||||
|
SendMessage(hMainWindow, WM_CLOSE, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DllInit(HMODULE mod) {
|
||||||
|
hMod = mod;
|
||||||
|
char mfn[1024];
|
||||||
|
InitConsole();
|
||||||
|
GetModuleFileNameA(0, mfn, 1024);
|
||||||
|
Py = get_modules(P_PY_MODS);
|
||||||
|
cout << "[+] ScrapHacks v0.1 Loaded in " << mfn << " (PID: " << std::hex
|
||||||
|
<< GetCurrentProcessId() << std::dec << ")" << endl;
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
cout << "[*] World: " << ptr<void>(P_WORLD, 0) << endl;
|
||||||
|
cout << "[*] Importing python dbg module" << endl;
|
||||||
|
scrap_exec("import dbg");
|
||||||
|
scrap_log(INFO_COLOR, "=== ScrapHacks loaded! ===\n");
|
||||||
|
scrap_log(INFO_COLOR, "=== Use '$help' for help! ===\n");
|
||||||
|
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainLoop, NULL, 0, 0);
|
||||||
|
cout << "[*] Starting message pump" << endl;
|
||||||
|
MSG msg;
|
||||||
|
while (GetMessage(&msg, NULL, 0, 0)) {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *H_port_FixupExtension(char *name, char *filename) {
|
||||||
|
Hook::drop(H_port_FixupExtension);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *H_PyEval_CallObjectWithKeywords(void *func, void *arg, void *kwarg) {
|
||||||
|
Hook::drop(H_PyEval_CallObjectWithKeywords);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DllPreInit() {
|
||||||
|
Hook::addr(reinterpret_cast<void *>(0x5a9ca0), H_port_FixupExtension);
|
||||||
|
Hook::addr(reinterpret_cast<void *>(0x5cdb00),
|
||||||
|
H_PyEval_CallObjectWithKeywords);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DllUnload() {
|
||||||
|
SetConsoleCtrlHandler(NULL, false);
|
||||||
|
unhook_d3d8();
|
||||||
|
Hook::clear();
|
||||||
|
scrap_log(0xff0000, "ScrapHacks unloaded!\n");
|
||||||
|
cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl;
|
||||||
|
FreeConsole();
|
||||||
|
DestroyWindow(GetConsoleWindow());
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// OFFSETS
|
||||||
|
#define O_MONEY 0x2090
|
||||||
|
#define O_ALARM 0x1C6C
|
||||||
|
#define O_ALARM_GROW 0x1C68
|
||||||
|
#define O_ENTS 0x4
|
||||||
|
#define O_ENTLISTS 0x2b8
|
||||||
|
|
||||||
|
// POINTERS
|
||||||
|
#define P_WORLD 0x7FE944
|
||||||
|
#define P_PY_MODS 0x79C698
|
||||||
|
|
||||||
|
// FUNCTION ADDRESSES
|
||||||
|
#define P_CON_HANDLER 0x402190
|
||||||
|
#define P_SCRAP_LOG 0x4134C0
|
||||||
|
#define P_SCRAP_EXEC 0x5a8390
|
||||||
|
#define P_SCRAP_EXIT 0x4010c0
|
||||||
|
#define P_D3DCHECK 0x602a70
|
||||||
|
#define P_D3DDEV 0x852914
|
||||||
|
#define P_Py_InitModule 0x5A8FB0
|
||||||
|
#define P_PyArg_ParseTuple 0x5bb9d0
|
||||||
|
|
||||||
|
|
||||||
|
#define MSG_COLOR scrap_RGB(255,128,0)
|
||||||
|
#define ERR_COLOR scrap_RGB(255,0,0)
|
||||||
|
#define INFO_COLOR scrap_RGB(0,0,255)
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t scrap_RGB(uint8_t r,uint8_t g,uint8_t b) {
|
||||||
|
return r|g<<8|b<<16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION TYPES
|
||||||
|
typedef int(_cdecl *t_scrap_log)(unsigned int color, const char *message);
|
||||||
|
typedef int(_cdecl *t_scrap_exec)(const char *code);
|
||||||
|
typedef int(_cdecl *t_PyArg_ParseTuple)(void *PyObj, char *format, ...);
|
||||||
|
typedef int(_cdecl *t_Py_InitModule)(const char *name, void *methods,
|
||||||
|
const char *doc, void *passthrough,
|
||||||
|
int module_api_version);
|
||||||
|
|
||||||
|
// GLOBAL FUNCTIONS
|
||||||
|
auto scrap_exec = (t_scrap_exec)P_SCRAP_EXEC;
|
||||||
|
auto pyarg_parsetuple = (t_PyArg_ParseTuple)P_PyArg_ParseTuple;
|
||||||
|
auto py_initmodule = (t_Py_InitModule)P_Py_InitModule;
|
||||||
|
|
||||||
|
int scrap_log(unsigned int color,const char* msg) {
|
||||||
|
return ((t_scrap_log)P_SCRAP_LOG)(color,msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int scrap_log(uint8_t r,uint8_t g,uint8_t b,const char* msg) {
|
||||||
|
return ((t_scrap_log)P_SCRAP_LOG)(scrap_RGB(r,g,b),msg);
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
#pragma once
|
||||||
|
template <typename T> struct HashTableEntry;
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Entity {
|
||||||
|
void *vmt;
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EntityList {
|
||||||
|
const char *name;
|
||||||
|
void *unk_1;
|
||||||
|
void *unk_2;
|
||||||
|
const char *mod;
|
||||||
|
const char *func;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> struct HashTable {
|
||||||
|
uint32_t size;
|
||||||
|
HashTableEntry<T> **chains;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> struct HashTableEntry {
|
||||||
|
T *data;
|
||||||
|
const char *name;
|
||||||
|
HashTableEntry *next;
|
||||||
|
};
|
|
@ -0,0 +1,375 @@
|
||||||
|
#pragma once
|
||||||
|
#include <TlHelp32.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Structures.hpp"
|
||||||
|
#include "Py_Utils.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#define DLL_EXPORT extern "C" __declspec(dllexport)
|
||||||
|
|
||||||
|
template <typename T> void **GetVTable(T *obj) {
|
||||||
|
void *addr = reinterpret_cast<void **>(obj)[0];
|
||||||
|
return (void **)(*(void **)addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (!AttachConsole(-1)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
string hexdump_s(void *addr, size_t count=0xff) {
|
||||||
|
ostringstream out;
|
||||||
|
uintptr_t offset=reinterpret_cast<uintptr_t>(addr);
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
unsigned int val = (unsigned int)(((unsigned char *)(offset+i))[0]);
|
||||||
|
if ((i % 16) == 0) {
|
||||||
|
out << endl;
|
||||||
|
out << setfill('0') << setw(8) << std::hex << std::uppercase << (offset+i) << ": ";
|
||||||
|
}
|
||||||
|
out << setfill('0') << setw(2) << std::hex << val << " ";
|
||||||
|
}
|
||||||
|
out << endl;
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hexdump(void *addr, size_t count=0xff) {
|
||||||
|
uintptr_t offset=reinterpret_cast<uintptr_t>(addr);
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
unsigned int val = (unsigned int)(((unsigned char *)(offset+i))[0]);
|
||||||
|
if ((i % 16) == 0) {
|
||||||
|
cout << endl;
|
||||||
|
cout << setfill('0') << setw(8) << std::hex << std::uppercase << (offset+i) << ": ";
|
||||||
|
}
|
||||||
|
cout << setfill('0') << setw(2) << std::hex << val << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void __to_str(ostream& o, T t)
|
||||||
|
{
|
||||||
|
o << t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
void __to_str(ostream& o, T t, Args... args) // recursive variadic function
|
||||||
|
{
|
||||||
|
__to_str(o, t);
|
||||||
|
__to_str(o, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
const char* to_str(Args... args)
|
||||||
|
{
|
||||||
|
ostringstream oss;
|
||||||
|
__to_str(oss, args...);
|
||||||
|
return oss.str().c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
PPID() {
|
||||||
|
DWORD PID = GetCurrentProcessId();
|
||||||
|
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
|
PROCESSENTRY32 procentry;
|
||||||
|
if (hSnapShot == INVALID_HANDLE_VALUE) {
|
||||||
|
cout << GetLastErrorAsString() << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (Process32First(hSnapShot, &procentry)) {
|
||||||
|
do {
|
||||||
|
if (procentry.th32ProcessID == PID) {
|
||||||
|
CloseHandle(hSnapShot);
|
||||||
|
return procentry.th32ParentProcessID;
|
||||||
|
}
|
||||||
|
procentry.dwSize = sizeof(PROCESSENTRY32);
|
||||||
|
} while (Process32Next(hSnapShot, &procentry));
|
||||||
|
}
|
||||||
|
CloseHandle(hSnapShot);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<uint8_t> fromhex(string input) {
|
||||||
|
vector<uint8_t> ret = {};
|
||||||
|
if (input.size() % 2) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
transform(input.begin(), input.end(), input.begin(), ::toupper);
|
||||||
|
string hc = "0123456789ABCDEF";
|
||||||
|
int v = 0;
|
||||||
|
size_t n = 0;
|
||||||
|
size_t idx;
|
||||||
|
for (unsigned char c : input) {
|
||||||
|
idx = hc.find(c);
|
||||||
|
if (idx != size_t(-1)) {
|
||||||
|
if ((n++) % 2 == 0) {
|
||||||
|
v = hc.find(c) << 4;
|
||||||
|
} else {
|
||||||
|
v |= hc.find(c);
|
||||||
|
ret.push_back(v);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cout << "Invalid Character in hex string" << endl;
|
||||||
|
ret.clear();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> split(string str, char sep) {
|
||||||
|
vector<string> ret;
|
||||||
|
string part;
|
||||||
|
for (auto n : str) {
|
||||||
|
if (n == sep) {
|
||||||
|
ret.push_back(part);
|
||||||
|
part.clear();
|
||||||
|
} else {
|
||||||
|
part = part + n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (part != "")
|
||||||
|
ret.push_back(part);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t size_ht(HashTable<EntityList> *ht) {
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (size_t i = 0; i < ht->size; ++i) {
|
||||||
|
HashTableEntry<EntityList> *ent = ht->chains[i];
|
||||||
|
if (ent) {
|
||||||
|
while (ent) {
|
||||||
|
++cnt;
|
||||||
|
ent = ent->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size_ht(HashTable<Entity> *ht) {
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (size_t i = 0; i < ht->size; ++i) {
|
||||||
|
HashTableEntry<Entity> *ent = ht->chains[i];
|
||||||
|
if (ent) {
|
||||||
|
while (ent) {
|
||||||
|
++cnt;
|
||||||
|
ent = ent->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t dump_ht(HashTable<EntityList> *ht) {
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (size_t i = 0; i < ht->size; ++i) {
|
||||||
|
HashTableEntry<EntityList> *ent = ht->chains[i];
|
||||||
|
if (ent) {
|
||||||
|
cout << i << ": ";
|
||||||
|
while (ent) {
|
||||||
|
++cnt;
|
||||||
|
cout << "[ " << ent->name << ": " << ent->data << "]";
|
||||||
|
if (ent->next) {
|
||||||
|
cout << " -> ";
|
||||||
|
};
|
||||||
|
ent = ent->next;
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cout << cnt << " Entries" << endl;
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t dump_ht(HashTable<Entity> *ht) {
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (size_t i = 0; i < ht->size; ++i) {
|
||||||
|
HashTableEntry<Entity> *ent = ht->chains[i];
|
||||||
|
if (ent) {
|
||||||
|
cout << i << ": ";
|
||||||
|
while (ent) {
|
||||||
|
++cnt;
|
||||||
|
cout << "[ " << ent->name << ": " << ent->data << "]";
|
||||||
|
if (ent->next) {
|
||||||
|
cout << " -> ";
|
||||||
|
};
|
||||||
|
ent = ent->next;
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cout << cnt << " Entries" << endl;
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t dump_ht(HashTable<EntityList> *ht,stringstream *out) {
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (size_t i = 0; i < ht->size; ++i) {
|
||||||
|
HashTableEntry<EntityList> *ent = ht->chains[i];
|
||||||
|
if (ent) {
|
||||||
|
*out << i << ": ";
|
||||||
|
while (ent) {
|
||||||
|
++cnt;
|
||||||
|
*out << "[ " << ent->name << ": " << ent->data << "]";
|
||||||
|
if (ent->next) {
|
||||||
|
*out << " -> ";
|
||||||
|
};
|
||||||
|
ent = ent->next;
|
||||||
|
}
|
||||||
|
*out << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out << cnt << " Entries" << endl;
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t dump_ht(HashTable<Entity> *ht,stringstream *out) {
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (size_t i = 0; i < ht->size; ++i) {
|
||||||
|
HashTableEntry<Entity> *ent = ht->chains[i];
|
||||||
|
if (ent) {
|
||||||
|
*out << i << ": ";
|
||||||
|
while (ent) {
|
||||||
|
++cnt;
|
||||||
|
*out << "[ " << ent->name << ": " << ent->data << "]";
|
||||||
|
if (ent->next) {
|
||||||
|
*out << " -> ";
|
||||||
|
};
|
||||||
|
ent = ent->next;
|
||||||
|
}
|
||||||
|
*out << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out << cnt << " Entries" << endl;
|
||||||
|
return cnt;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define DLL_EXPORT extern "C" __declspec(dllexport)
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void DllInit(HMODULE);
|
||||||
|
void DllUnload();
|
||||||
|
void DllPreInit();
|
||||||
|
|
||||||
|
HANDLE hThread = INVALID_HANDLE_VALUE;
|
||||||
|
bool loaded = false;
|
||||||
|
HMODULE mod = nullptr;
|
||||||
|
|
||||||
|
DLL_EXPORT void initScrapHack() {
|
||||||
|
DllPreInit();
|
||||||
|
if (!loaded) {
|
||||||
|
hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DllInit, mod,
|
||||||
|
0, 0);
|
||||||
|
CloseHandle(hThread);
|
||||||
|
loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
|
||||||
|
LPVOID lpReserved) {
|
||||||
|
mod = hModule;
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
outfile,infile=sys.argv[1:]
|
||||||
|
|
||||||
|
re_interface=re.compile(r"^DECLARE_INTERFACE_{0,1}\((.*?)\)$")
|
||||||
|
re_method=re.compile(r"^\w*STDMETHOD_{0,1}\((.*?)\)\((.*?)\).*;")
|
||||||
|
name=None
|
||||||
|
idx=0
|
||||||
|
VMTs={}
|
||||||
|
with open(infile,"r") as infh:
|
||||||
|
for line in infh:
|
||||||
|
line=line.strip()
|
||||||
|
interf=re_interface.match(line)
|
||||||
|
meth=re_method.match(line)
|
||||||
|
if interf:
|
||||||
|
idx=0
|
||||||
|
name="VMT_"+"_".join([name for name in interf.groups()[0].split(", ") if name!="IUnknown"])
|
||||||
|
VMTs[name]={}
|
||||||
|
if meth:
|
||||||
|
meth_name,meth_args=meth.groups()
|
||||||
|
meth_name=meth_name.split(",")[-1].strip()
|
||||||
|
VMTs[name][meth_name]=idx
|
||||||
|
idx+=1
|
||||||
|
print(f"Generating: {outfile} from {infile} ...")
|
||||||
|
with open(outfile,"w") as ofh:
|
||||||
|
for name in sorted(VMTs.keys()):
|
||||||
|
print(f"namespace {name} {{",file=ofh)
|
||||||
|
for method,idx in sorted(VMTs[name].items(),key=lambda v:v[1]):
|
||||||
|
print(f"\tconst size_t m_{method} = {idx};",file=ofh)
|
||||||
|
print("}",file=ofh)
|
|
@ -52,7 +52,7 @@ r2_cmd("aaaaa")
|
||||||
#0x413ee0
|
#0x413ee0
|
||||||
|
|
||||||
#0x7d2094 refcnt
|
#0x7d2094 refcnt
|
||||||
flags = {0x7FE944: ("World_Ptr", 4), 0x79C698: ("Py_Mods", 4)}
|
flags = {0x7FE944: ("P_World", 4), 0x79C698: ("Py_Mods", 4),0x852914: ("P_D3D8_Dev",4)}
|
||||||
|
|
||||||
types = ["struct PyMethodDef {char *ml_name; void *ml_meth; int ml_flags; char *ml_doc;};"]
|
types = ["struct PyMethodDef {char *ml_name; void *ml_meth; int ml_flags; char *ml_doc;};"]
|
||||||
|
|
||||||
|
@ -70,6 +70,9 @@ func_sigs = {
|
||||||
0x419950: "int fopen_2(const char* filename);",
|
0x419950: "int fopen_2(const char* filename);",
|
||||||
0x41AB50: "int open_pak(const char* filename, int unk_1,void* unk_ptr);",
|
0x41AB50: "int open_pak(const char* filename, int unk_1,void* unk_ptr);",
|
||||||
0x404460: "int register_c_callback(const char* name,void* func);"
|
0x404460: "int register_c_callback(const char* name,void* func);"
|
||||||
|
0x414070: "void throw_assertion_2(const char* check,const char* file, unsigned int line);"
|
||||||
|
0x5FBC50: "void throw_assertion_1(const char* check,const char* file,const char* date, unsigned int line);",
|
||||||
|
0x5bc140: "static char* convertsimple1(void *arg, char **p_format, void *p_va);"
|
||||||
}
|
}
|
||||||
|
|
||||||
functions = {
|
functions = {
|
||||||
|
@ -154,30 +157,38 @@ def c_callbacks():
|
||||||
|
|
||||||
def assertions():
|
def assertions():
|
||||||
assertions = {}
|
assertions = {}
|
||||||
for a_addr in ["fcn.throw_assertion_1", "fcn.throw_assertion_2"]:
|
for (n_args,a_addr) in [(4,"fcn.throw_assertion_1"), (3,"fcn.throw_assertion_2")]:
|
||||||
print(f"[*] Parsing C assertions for {a_addr}")
|
print(f"[*] Parsing C assertions for {a_addr}")
|
||||||
res = r2_cmd(f"/r {a_addr} ~CALL[1]").splitlines()
|
res = r2_cmd(f"/r {a_addr} ~CALL[1]").splitlines()
|
||||||
print()
|
print()
|
||||||
for line in tqdm(res, ascii=True):
|
for line in tqdm(res, ascii=True):
|
||||||
addr = line.strip()
|
addr = line.strip()
|
||||||
file, msg = r2_cmdJ(f"s {addr};so -2;pij 2") # seek and print disassembly
|
dis=r2_cmdJ(f"s {addr};so -{n_args};pij {n_args}") # seek and print disassembly
|
||||||
|
if n_args==4:
|
||||||
|
file, msg, date, line = dis
|
||||||
|
elif n_args==3:
|
||||||
|
date=None
|
||||||
|
file, msg, line = dis
|
||||||
try:
|
try:
|
||||||
file = r2_cmd(f"psz @{file.refs[0].addr}").strip()
|
file = r2_cmd(f"psz @{file.refs[0].addr}").strip()
|
||||||
msg = r2_cmd(f"psz @{msg.refs[0].addr}").strip()
|
msg = r2_cmd(f"psz @{msg.refs[0].addr}").strip()
|
||||||
path = os.path.abspath(file.replace("\\\\", "\\"))
|
if date:
|
||||||
|
r2_cmd(f"psz @{date.refs[0].addr}").strip()
|
||||||
|
line=line.val
|
||||||
|
file=file.replace("\\\\", "\\")
|
||||||
|
os.path.isabs(file):
|
||||||
|
file = os.path.abspath(file)
|
||||||
assertions.setdefault(path, [])
|
assertions.setdefault(path, [])
|
||||||
assertions[path].append([addr, msg])
|
assertions[path].append({'line':line,'date':date,'addr':addr,'msg': msg})
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
for path in assertions:
|
for path in assertions:
|
||||||
assertions[path].sort(key=lambda v:int(v[0],16))
|
assertions[path].sort(key=lambda v:v['line'])
|
||||||
return assertions
|
return assertions
|
||||||
|
|
||||||
|
def bb_refs(addr):
|
||||||
def world():
|
|
||||||
ret={}
|
ret={}
|
||||||
print("[*] Parsing World offsets")
|
res = r2_cmd(f"/r {addr} ~fcn[0,1]").splitlines()
|
||||||
res = r2_cmd("/r loc.World_Ptr ~fcn[0,1]").splitlines()
|
|
||||||
print()
|
print()
|
||||||
for ent in res:
|
for ent in res:
|
||||||
func,hit=ent.split()
|
func,hit=ent.split()
|
||||||
|
@ -186,6 +197,15 @@ def world():
|
||||||
ret[hit]['asm'].append(ins.disasm)
|
ret[hit]['asm'].append(ins.disasm)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def world():
|
||||||
|
print("[*] Parsing World offsets")
|
||||||
|
return bb_refs("loc.P_World")
|
||||||
|
|
||||||
|
def render():
|
||||||
|
print("[*] Parsing D3D_Device offsets")
|
||||||
|
return bb_refs("loc.P_D3D8_Dev")
|
||||||
|
|
||||||
|
|
||||||
def py_mods():
|
def py_mods():
|
||||||
print("[*] Parsing Python modules")
|
print("[*] Parsing Python modules")
|
||||||
res = r2_cmd("/r fcn.Py_InitModule ~CALL[1]").splitlines()
|
res = r2_cmd("/r fcn.Py_InitModule ~CALL[1]").splitlines()
|
||||||
|
@ -260,6 +280,7 @@ ret = dict(
|
||||||
assertions=assertions(),
|
assertions=assertions(),
|
||||||
vtables=vtables(),
|
vtables=vtables(),
|
||||||
world=world(),
|
world=world(),
|
||||||
|
render=render(),
|
||||||
)
|
)
|
||||||
|
|
||||||
r2_cmd("aaaaa") # Propagate type infos
|
r2_cmd("aaaaa") # Propagate type infos
|
||||||
|
|
Loading…
Reference in New Issue