Added function hooking
Cleaned up the injector a bit and added launch-time injection
This commit is contained in:
		
							parent
							
								
									ffbcc30427
								
							
						
					
					
						commit
						7cf3ab8580
					
				
					 11 changed files with 166 additions and 36 deletions
				
			
		|  | @ -169,7 +169,6 @@ void InjectDll(DWORD PID, bool do_resume = false) | ||||||
| 	cout << "[*] Injecting DLL " << dll_name << " into PID " << PID << endl; | 	cout << "[*] Injecting DLL " << dll_name << " into PID " << PID << endl; | ||||||
| 	cout << "[*] Opening Process Handle" << endl; | 	cout << "[*] Opening Process Handle" << endl; | ||||||
| 	hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, PID); | 	hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, PID); | ||||||
| 	PID = GetProcessId(hProc); |  | ||||||
| 	GetFullPathNameA(dll_name, MAX_PATH, dll_full_path, 0); | 	GetFullPathNameA(dll_name, MAX_PATH, dll_full_path, 0); | ||||||
| 	cout << "[*] Adjusting Privileges of Process" << endl; | 	cout << "[*] Adjusting Privileges of Process" << endl; | ||||||
| 	adjustPrivs(hProc); | 	adjustPrivs(hProc); | ||||||
|  | @ -216,23 +215,53 @@ void InjectDll(DWORD PID, bool do_resume = false) | ||||||
| 	CloseHandle(hProc); | 	CloseHandle(hProc); | ||||||
| 	return; | 	return; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | vector<HANDLE> spawn(char* binary) { | ||||||
|  | 	STARTUPINFO startupinfo; | ||||||
|  | 	PROCESS_INFORMATION processinfo; | ||||||
|  | 	ZeroMemory(&startupinfo, sizeof(startupinfo)); | ||||||
|  | 	ZeroMemory(&processinfo, sizeof(processinfo)); | ||||||
|  | 	startupinfo.cb = sizeof(startupinfo); | ||||||
|  | 	if (!CreateProcessA(NULL, binary, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupinfo, &processinfo)) { | ||||||
|  | 		return {}; | ||||||
|  | 	} | ||||||
|  | 	return { processinfo.hProcess,processinfo.hThread }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||||||
| { | { | ||||||
| 	string prog; | 	string prog; | ||||||
| 	HANDLE hProc = INVALID_HANDLE_VALUE; | 	HANDLE hProc = INVALID_HANDLE_VALUE; | ||||||
|  | 	HANDLE hThread = INVALID_HANDLE_VALUE; | ||||||
| 	DWORD PID = 0; | 	DWORD PID = 0; | ||||||
| 	GetWindowThreadProcessId(FindWindowA("ScrapClass", NULL), &PID); | 	if ((argc>1)&&fexists(argv[1])) { | ||||||
| 	if (PID == 0) | 		cout << "[*] Spawning process for \"" << argv[1] << "\"" << endl; | ||||||
| 	{ | 		vector<HANDLE> handles = spawn(argv[1]); | ||||||
| 		cout << "[*] Waiting for Scrapland to Launch..." << endl; | 		if (handles.empty()) { | ||||||
| 	} | 			cout << "[!] Error: " << GetLastErrorAsString() << endl; | ||||||
| 	while (PID == 0) | 			return -1; | ||||||
| 	{ | 		} | ||||||
| 		Sleep(100); | 		hProc = handles[0]; | ||||||
|  | 		hThread = handles[1]; | ||||||
|  | 		PID = GetProcessId(hProc); | ||||||
|  | 		cout << "[+] Got PID: " << PID << endl; | ||||||
|  | 	} else { | ||||||
| 		GetWindowThreadProcessId(FindWindowA("ScrapClass", NULL), &PID); | 		GetWindowThreadProcessId(FindWindowA("ScrapClass", NULL), &PID); | ||||||
|  | 		if (PID == 0) | ||||||
|  | 		{ | ||||||
|  | 			cout << "[*] Waiting for Scrapland to Launch..." << endl; | ||||||
|  | 		} | ||||||
|  | 		while (PID == 0) | ||||||
|  | 		{ | ||||||
|  | 			Sleep(100); | ||||||
|  | 			GetWindowThreadProcessId(FindWindowA("ScrapClass", NULL), &PID); | ||||||
|  | 		} | ||||||
|  | 		cout << "[+] Found PID: " << PID << endl; | ||||||
| 	} | 	} | ||||||
| 	cout << "[+] Found PID: " << PID << endl; |  | ||||||
| 	InjectDll(PID); | 	InjectDll(PID); | ||||||
|  | 	if (hThread != INVALID_HANDLE_VALUE) { | ||||||
|  | 		while (ResumeThread(hThread)); | ||||||
|  | 	} | ||||||
| 	cout << "[*] Done!" << endl; | 	cout << "[*] Done!" << endl; | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -160,6 +160,5 @@ | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||||||
|   <ImportGroup Label="ExtensionTargets"> |   <ImportGroup Label="ExtensionTargets" /> | ||||||
|   </ImportGroup> |  | ||||||
| </Project> | </Project> | ||||||
							
								
								
									
										50
									
								
								ScrapHacks/ScrapHack/Hook.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								ScrapHacks/ScrapHack/Hook.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | ||||||
|  | #pragma once | ||||||
|  | #include <functional> | ||||||
|  | class Hook; | ||||||
|  | 
 | ||||||
|  | map<uintptr_t, shared_ptr<Hook>> hooks; | ||||||
|  | 
 | ||||||
|  | class Hook { | ||||||
|  | private: | ||||||
|  | 	DWORD protect; | ||||||
|  | 	void* orig; | ||||||
|  | 	void* detour; | ||||||
|  | 	uint8_t orig_bytes[6]; | ||||||
|  | 	uint8_t jmp_bytes[6]; | ||||||
|  | public: | ||||||
|  | 	Hook(void* func, void* detour) { | ||||||
|  | 		cout << "Hooking: " << func << " -> " << detour << endl; | ||||||
|  | 		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
 | ||||||
|  | 		VirtualProtect(func, 16, PAGE_EXECUTE_READWRITE, &(this->protect)); | ||||||
|  | 		memcpy(this->orig_bytes, this->orig, 1 + 4 + 1); | ||||||
|  | 		memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1); | ||||||
|  | 		hooks[src]=shared_ptr<Hook>(this); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	~Hook() { | ||||||
|  | 		cout << "Unhooking: " << this->detour << " -> " << this->orig << endl; | ||||||
|  | 		uintptr_t src = reinterpret_cast<uintptr_t>(this->orig); | ||||||
|  | 		memcpy(this->orig, this->orig_bytes, 1 + 4 + 1); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void disable() { | ||||||
|  | 		memcpy(this->orig, this->orig_bytes, 1 + 4 + 1); | ||||||
|  | 	} | ||||||
|  | 	void enable() { | ||||||
|  | 		memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	void* func() { | ||||||
|  | 		return this->orig; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | }; | ||||||
|  | @ -13,7 +13,7 @@ PyMethodDef *find_method_table(uintptr_t base, uintptr_t needle) | ||||||
| 			return reinterpret_cast<PyMethodDef*>(mod_addr); | 			return reinterpret_cast<PyMethodDef*>(mod_addr); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return reinterpret_cast<PyMethodDef *>(0); | 	return reinterpret_cast<PyMethodDef*>(0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| map<string, Module> get_modules(uintptr_t base) | map<string, Module> get_modules(uintptr_t base) | ||||||
|  | @ -27,7 +27,7 @@ map<string, Module> get_modules(uintptr_t base) | ||||||
| 		PyMethodDef *method_table = find_method_table((size_t)modules[i].init_func, reinterpret_cast<uintptr_t>(modules[i].name)); | 		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++) | 		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]; | 			mod.methods[method_table[j].ml_name] = &method_table[j]; | ||||||
| 		} | 		} | ||||||
| 		Py[mod.mod->name] = mod; | 		Py[mod.mod->name] = mod; | ||||||
| 	} | 	} | ||||||
|  | @ -38,7 +38,7 @@ void *get_py(const char *mod, const char *meth) | ||||||
| { | { | ||||||
| 	try | 	try | ||||||
| 	{ | 	{ | ||||||
| 		return Py.at(mod).methods.at(meth).ml_meth; | 		return Py.at(mod).methods.at(meth)->ml_meth; | ||||||
| 	} | 	} | ||||||
| 	catch (out_of_range) | 	catch (out_of_range) | ||||||
| 	{ | 	{ | ||||||
|  | @ -51,7 +51,7 @@ void inject(const char *mod, const char *meth, void *detour) | ||||||
| 	try | 	try | ||||||
| 	{ | 	{ | ||||||
| 		void *orig = get_py(mod, meth); | 		void *orig = get_py(mod, meth); | ||||||
| 		Py.at(mod).methods.at(meth).ml_meth = detour; | 		Py.at(mod).methods.at(meth)->ml_meth = detour; | ||||||
| 		cout << mod << "." << meth << ": " << orig << " -> " << detour << endl; | 		cout << mod << "." << meth << ": " << orig << " -> " << detour << endl; | ||||||
| 	} | 	} | ||||||
| 	catch (out_of_range) | 	catch (out_of_range) | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | #define WIN32_LEAN_AND_MEAN | ||||||
| #include "stdafx.h" | #include "stdafx.h" | ||||||
| #include <string> | #include <string> | ||||||
| #include <sstream> | #include <sstream> | ||||||
|  | @ -5,16 +6,19 @@ | ||||||
| #include <map> | #include <map> | ||||||
| #include <iomanip> | #include <iomanip> | ||||||
| #include <iostream> | #include <iostream> | ||||||
|  | #include <typeinfo> | ||||||
|  | #include <functional> | ||||||
| #include <Windows.h> | #include <Windows.h> | ||||||
| #include <TlHelp32.h> | #include <TlHelp32.h> | ||||||
| //#include <D3d8.h>
 |  | ||||||
| 
 |  | ||||||
| using namespace std; | using namespace std; | ||||||
| 
 | 
 | ||||||
| #include "Scrapland.h" | #include "Scrapland.h" | ||||||
| #include "Util.h" | #include "Util.h" | ||||||
| #include "Structures.h" | #include "Structures.h" | ||||||
| #include "Py_Utils.h" | #include "Py_Utils.h" | ||||||
|  | #include "Hook.h" | ||||||
|  | 
 | ||||||
|  | #define SIZE 6 | ||||||
| 
 | 
 | ||||||
| HMODULE hD3D8Dll = 0; | HMODULE hD3D8Dll = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -22,7 +26,6 @@ bool initialized = false; | ||||||
| bool running = true; | bool running = true; | ||||||
| HMODULE mod = 0; | HMODULE mod = 0; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| void MainLoop(HMODULE mod) | void MainLoop(HMODULE mod) | ||||||
| { | { | ||||||
| 	Sleep(100); | 	Sleep(100); | ||||||
|  | @ -67,7 +70,7 @@ void MainLoop(HMODULE mod) | ||||||
| 			{ | 			{ | ||||||
| 				for (auto meth : mod.second.methods) | 				for (auto meth : mod.second.methods) | ||||||
| 				{ | 				{ | ||||||
| 					cout << mod.first << "." << meth.first << " @ " << meth.second.ml_meth << endl; | 					cout << mod.first << "." << meth.first << " @ " << meth.second->ml_meth << endl; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -77,9 +80,11 @@ void MainLoop(HMODULE mod) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	SetConsoleCtrlHandler(NULL, false); | 	SetConsoleCtrlHandler(NULL, false); | ||||||
|  | 	hooks.clear(); | ||||||
|  | 	scrap_log(0xff0000, "ScrapHacks unloaded!\n"); | ||||||
| 	cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl; | 	cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl; | ||||||
| 	; |  | ||||||
| 	FreeConsole(); | 	FreeConsole(); | ||||||
|  | 	PostQuitMessage(0); | ||||||
| 	FreeLibraryAndExitThread(mod, 0); | 	FreeLibraryAndExitThread(mod, 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -90,21 +95,53 @@ void InitConsole() | ||||||
| 	SetupConsole(me); | 	SetupConsole(me); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void handle_command(const char* cmd) { | ||||||
|  | 	cout << "CMD: " << cmd << endl; | ||||||
|  | 	scrap_log(0x00ff00, "HAXX: "); | ||||||
|  | 	scrap_log(0x00ff00,cmd); | ||||||
|  | 	scrap_log(0x00ff00,"\n"); | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int my_console(const char* cmd) { | ||||||
|  | 	typedef int(_cdecl *t_func)(const char*); | ||||||
|  | 	shared_ptr<Hook> hook = hooks[P_CON_HANDLER]; | ||||||
|  | 	t_func func= reinterpret_cast<t_func>(hook->func()); | ||||||
|  | 	if (cmd[0] == '$') { | ||||||
|  | 		handle_command(++cmd); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	hook->disable(); | ||||||
|  | 	int ret=func(cmd); | ||||||
|  | 	hook->enable(); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void hook_console() { | ||||||
|  | 	new Hook(reinterpret_cast<void*>(P_CON_HANDLER) , my_console); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void DllPreInit(HMODULE _mod) { | ||||||
|  | 	char mfn[1024]; | ||||||
|  | 	InitConsole(); | ||||||
|  | 	GetModuleFileName(0, mfn, 1024); | ||||||
|  | 	Py = get_modules(P_PY_MODS); | ||||||
|  | 	hD3D8Dll = GetModuleHandle("d3d8.dll"); | ||||||
|  | 	cout << "[+] ScrapHacks v0.1 Loaded in " << mfn << endl; | ||||||
|  | 	cout << "[*] D3D8 DLL @0x" << hD3D8Dll << endl; | ||||||
|  | 	hook_console(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void DllInit(HMODULE _mod) | void DllInit(HMODULE _mod) | ||||||
| { | { | ||||||
| 	initialized = true; | 	initialized = true; | ||||||
| 	mod = _mod; | 	mod = _mod; | ||||||
| 	char mfn[1024]; |  | ||||||
| 	InitConsole(); |  | ||||||
| 	GetModuleFileName(0, mfn, 1024); |  | ||||||
| 	cout << "[+] ScrapHacks v0.1 Loaded in " << mfn << endl; |  | ||||||
| 	Sleep(3000); | 	Sleep(3000); | ||||||
| 	Py = get_modules(P_PY_MODS); | 	cout << "[*] World: " << ptr<void>(P_WORLD, 0) << endl; | ||||||
| 	cout << "[*] Importing python dbg module" << endl; | 	cout << "[*] Importing python dbg module" << endl; | ||||||
| 	scrap_exec("import dbg"); | 	scrap_exec("import dbg"); | ||||||
| 	cout << "[*] World: " << ptr<void>(P_WORLD,0) << endl; | 	scrap_log(0xff0000, "ScrapHacks loaded!\n"); | ||||||
| 	hD3D8Dll = GetModuleHandle("d3d8.dll"); |  | ||||||
| 	cout << "[*] D3D8 DLL @0x"<< hD3D8Dll << endl; |  | ||||||
| 	CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainLoop, mod, 0, 0); | 	CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainLoop, mod, 0, 0); | ||||||
| 	cout << "[*] Starting message pump" << endl; | 	cout << "[*] Starting message pump" << endl; | ||||||
| 	MSG msg; | 	MSG msg; | ||||||
|  |  | ||||||
|  | @ -150,6 +150,7 @@ | ||||||
|     </Link> |     </Link> | ||||||
|   </ItemDefinitionGroup> |   </ItemDefinitionGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|  |     <ClInclude Include="Hook.h" /> | ||||||
|     <ClInclude Include="Py_Utils.h" /> |     <ClInclude Include="Py_Utils.h" /> | ||||||
|     <ClInclude Include="Structures.h" /> |     <ClInclude Include="Structures.h" /> | ||||||
|     <ClInclude Include="Scrapland.h" /> |     <ClInclude Include="Scrapland.h" /> | ||||||
|  |  | ||||||
|  | @ -33,6 +33,9 @@ | ||||||
|     <ClInclude Include="Py_Utils.h"> |     <ClInclude Include="Py_Utils.h"> | ||||||
|       <Filter>Headerdateien</Filter> |       <Filter>Headerdateien</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="Hook.h"> | ||||||
|  |       <Filter>Headerdateien</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClCompile Include="stdafx.cpp"> |     <ClCompile Include="stdafx.cpp"> | ||||||
|  |  | ||||||
|  | @ -1,7 +1,17 @@ | ||||||
| #pragma once | #pragma once | ||||||
| #define P_WORLD 0x7FE944 | //OFFSETS
 | ||||||
| #define P_PY_MODS 0x79C698 |  | ||||||
| #define O_MONEY 0x2090 | #define O_MONEY 0x2090 | ||||||
| 
 | 
 | ||||||
| auto scrap_log = (int(_cdecl*)(int, const char*))0x4134C0; | //POINTERS
 | ||||||
| auto scrap_exec = (void(_cdecl*)(const char*))0x5a8390; | #define P_WORLD 0x7FE944 | ||||||
|  | #define P_PY_MODS 0x79C698 | ||||||
|  | #define P_CON_HANDLER 0x402190 | ||||||
|  | #define P_SCRAP_LOG 0x4134C0 | ||||||
|  | #define P_SCRAP_EXEC 0x5a8390 | ||||||
|  | 
 | ||||||
|  | //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; | ||||||
|  |  | ||||||
|  | @ -30,5 +30,5 @@ struct PyMod | ||||||
| struct Module | struct Module | ||||||
| { | { | ||||||
| 	PyMod *mod; | 	PyMod *mod; | ||||||
| 	map<string, PyMethodDef> methods; | 	map<string, PyMethodDef*> methods; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -124,7 +124,6 @@ void hexdump(void *addr, size_t count) | ||||||
| 	cout << endl; | 	cout << endl; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| template<typename T> | template<typename T> | ||||||
| T* __ptr(uintptr_t addr) | T* __ptr(uintptr_t addr) | ||||||
| { | { | ||||||
|  | @ -156,4 +155,4 @@ template<typename T, typename... Offsets> | ||||||
| T* ptr(uintptr_t addr, Offsets... offsets) { | T* ptr(uintptr_t addr, Offsets... offsets) { | ||||||
| 	auto ret = __ptr<T>(addr, offsets...); | 	auto ret = __ptr<T>(addr, offsets...); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include "stdafx.h" | #include "stdafx.h" | ||||||
| #define DLL_EXPORT extern "C" __declspec(dllexport) | #define DLL_EXPORT extern "C" __declspec(dllexport) | ||||||
| void DllInit(HMODULE); | void DllInit(HMODULE); | ||||||
|  | void DllPreInit(HMODULE); | ||||||
| 
 | 
 | ||||||
| BOOL APIENTRY DllMain(HMODULE hModule, | BOOL APIENTRY DllMain(HMODULE hModule, | ||||||
|                       DWORD ul_reason_for_call, |                       DWORD ul_reason_for_call, | ||||||
|  | @ -11,6 +12,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, | ||||||
|     { |     { | ||||||
|     case DLL_PROCESS_ATTACH: |     case DLL_PROCESS_ATTACH: | ||||||
| 		DisableThreadLibraryCalls(hModule); | 		DisableThreadLibraryCalls(hModule); | ||||||
|  | 		DllPreInit(hModule); | ||||||
|         hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DllInit, hModule, 0, 0); |         hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DllInit, hModule, 0, 0); | ||||||
|         break; |         break; | ||||||
|     case DLL_PROCESS_DETACH: |     case DLL_PROCESS_DETACH: | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue