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
					
				
					 26 changed files with 1894 additions and 973 deletions
				
			
		
							
								
								
									
										127
									
								
								ScrapHacks/.clang-format
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								ScrapHacks/.clang-format
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||||
|  | ... | ||||||
|  | 
 | ||||||
							
								
								
									
										82
									
								
								ScrapHacks/.vscode/settings.json
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								ScrapHacks/.vscode/settings.json
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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; |  | ||||||
| } |  | ||||||
							
								
								
									
										136
									
								
								ScrapHacks/src/D3D8_Hook.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								ScrapHacks/src/D3D8_Hook.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										274
									
								
								ScrapHacks/src/D3D8_VMT.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								ScrapHacks/src/D3D8_VMT.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										124
									
								
								ScrapHacks/src/Hook.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								ScrapHacks/src/Hook.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
							
								
								
									
										58
									
								
								ScrapHacks/src/Py_Utils.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								ScrapHacks/src/Py_Utils.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										259
									
								
								ScrapHacks/src/REPL.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								ScrapHacks/src/REPL.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										177
									
								
								ScrapHacks/src/ScrapHack.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								ScrapHacks/src/ScrapHack.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								ScrapHacks/src/Scrapland.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								ScrapHacks/src/Scrapland.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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); | ||||||
|  | } | ||||||
							
								
								
									
										54
									
								
								ScrapHacks/src/Structures.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								ScrapHacks/src/Structures.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
|  | }; | ||||||
							
								
								
									
										375
									
								
								ScrapHacks/src/Util.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										375
									
								
								ScrapHacks/src/Util.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								ScrapHacks/src/dllmain.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								ScrapHacks/src/dllmain.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								ScrapHacks/src/make_D3D8_VMT.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								ScrapHacks/src/make_D3D8_VMT.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue