Onaylı Üye
So this source has just been pasted on UC for a .stub bypass, I do not have the needed knowledge to go in depth about it but I guess it could probably help getting ensoulsharp etc back Undetected?
If someone wants to discuss here's the source
If someone wants to discuss here's the source
Kod:
#include <windows.h>
#include <stdio.h>
#include <cstdint>
#include <map>
#include <Psapi.h>
/* Our list of spoofed bytes and their original values */
std::map<std::uintptr_t, std::uint8_t> spoofed_bytes;
/* Addresses */
std::uintptr_t stub_check = 0x000A4C59;
std::uintptr_t league_check = 0x00976216;
/* Our naked stub check hook */
/* Original bytes: movzx esi, byte ptr [eax]; cmc; test ebp, edx */
__declspec(naked) void stub_check_hook()
{
/* Save all registers */
__asm pushad
__asm pushfd
/* Get the current address being checked */
std::uint32_t current_address = 0;
__asm mov current_address, eax
/* Check if the current address is in our map */
if ( spoofed_bytes.find( current_address ) != spoofed_bytes.end( ) )
{
/* Pop all registers, but reserve modified eax */
__asm popfd
__asm popad
/* If it is, set the byte to the original value */
__asm mov si, spoofed_bytes[current_address]
/* Call original instructions */
__asm cmc
__asm test ebp, edx
/* jmp to stub_check + hook size */
__asm jmp stub_check + 6
}
/* Pop all registers */
__asm popfd
__asm popad
/* Call replaced instructions */
__asm cmc
__asm test ebp, edx
/* If it isn’t, jmp to stub_check + hook size */
__asm jmp stub_check + 6
}
/* Our naked league integrity check hook */
/* Original bytes: movzx ecx, byte ptr [ecx+ebx]; jmp next_block */
__declspec(naked) void league_check_hook()
{
/* Save all registers */
__asm pushad
__asm pushfd
/* TODO: Reader exercise :D */
/* Pop all registers */
__asm popfd
__asm popad
/* Call replaced instructions */
__asm jmp league_check + 6
}
/* Patch a single byte */
void patch_byte( std::uintptr_t address, std::uint8_t value )
{
/* Save the original value */
spoofed_bytes[address] = *(std::uint8_t*)address;
/* Patch the byte */
DWORD old_protect;
VirtualProtect( reinterpret_cast<void*>(address), 1, PAGE_EXECUTE_READWRITE, &old_protect );
*reinterpret_cast<std::uint8_t*>( address ) = value;
VirtualProtect( reinterpret_cast<void*>(address), 1, old_protect, &old_protect) ;
}
bool write_jmp( std::uintptr_t address, std::uintptr_t destination, std::size_t size )
{
/* Check if the size is valid */
if ( size < 5 )
return false;
/* Calculate the relative address */
std::uintptr_t relative_address = destination - address - 5;
/* Write the opcode */
*reinterpret_cast<std::uint8_t*>( address ) = 0xE9;
/* Write the relative address */
*reinterpret_cast<std::uintptr_t*>( address + 1 ) = relative_address;
/* Nop the rest of the bytes */
for ( std::size_t i = 5; i < size; i++ )
*reinterpret_cast<std::uint8_t*>( address + i ) = 0x90;
return true;
}
bool get_shadow_module( std::uintptr_t& base_address )
{
/* The `shadow module` has the same size as the `league` module, but has a different base */
/* Get base address of `League of Legends.exe` */
std::uintptr_t league_base = (std::uintptr_t)GetModuleHandleA( “League of Legends.exe” );
/* Check if `League of Legends.exe` is loaded */
if ( !league_base )
return false;
/* Get Module information */
MODULEINFO module_info = { 0 };
if( !GetModuleInformation( GetCurrentProcess( ), (HMODULE)league_base, &module_info, sizeof( MODULEINFO ) ) )
return false;
/* Get module size */
std::uintptr_t module_size = (std::uintptr_t)module_info.SizeOfImage;
MEMORY_BASIC_INFORMATION memory_info = { 0 };
/* Start at end of league base */
std::uintptr_t current_address = league_base + module_size;
/* Loop until we find the shadow module */
while ( VirtualQuery( (LPCVOID)current_address, &memory_info, sizeof( MEMORY_BASIC_INFORMATION32 ) ) )
{
/* Check if the size is the same as the league module */
if ( memory_info.RegionSize == module_size && memory_info.BaseAddress != (LPVOID)league_base )
{
/* Set the base address */
base_address = current_address;
return true;
}
/* Move to the next region */
current_address += memory_info.RegionSize;
}
}
bool hook_stub_check( )
{
/* Get address of stub.dll */
std::uintptr_t stub_dll = (std::uintptr_t)GetModuleHandleA( “stub.dll” );
/* Check if stub.dll is loaded */
if ( !stub_dll )
return false;
/* Write jmp at stub_check */
if ( !write_jmp( stub_check, (std::uintptr_t)stub_check_hook, 6 ) )
return false;
/* Write jmp at league_check */
if ( !write_jmp( league_check, (std::uintptr_t)league_check_hook, 6 ) )
return false;
return true;
}
bool hook_league( std::uintptr_t address, std::uintptr_t destination, std::size_t length )
{
/* Get the shadow module */
std::uintptr_t shadow_module = 0;
if ( !get_shadow_module( shadow_module ) )
return false;
/* Get base league module */
std::uintptr_t league_base = (std::uintptr_t)GetModuleHandleA( “League of Legends.exe” );
/* Subtract address from league base */
std::uintptr_t offset = address - league_base;
/* Write jmp at shadow address */
if ( !write_jmp( shadow_module + offset, destination, length ) )
return false;
return true;
}
/* DllMain */
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
/* Ensure we are attaching */
if ( fdwReason != DLL_PROCESS_ATTACH )
return FALSE;
/* Remove overhead calls */
DisableThreadLibraryCalls( hinstDLL );
/* Patch the stub check */
if ( !hook_stub_check( ) )
{
MessageBoxA( NULL, “Failed to hook stub.dll”, “Error”, MB_OK );
return FALSE;
}
return TRUE;
}