Exetools

Exetools (https://forum.exetools.com/index.php)
-   Source Code (https://forum.exetools.com/forumdisplay.php?f=46)
-   -   [C/C++] Memory patcher to deal with (ASLR) (https://forum.exetools.com/showthread.php?t=17195)

Insid3Code 10-17-2015 01:50

[C/C++] Memory patcher to deal with (ASLR)
 
1 Attachment(s)
Memory patcher (loader) to deal with Address Space Layout Randomization (ASLR)

PHP Code:

#include <windows.h>
#include <stdio.h>

#ifdef _WIN64
#define CAPTION "atomos - memory patcher for chimera #01 (64-bit)"
#define EXENAME "target64.exe"
#else
#define CAPTION "atomos - memory patcher for chimera #01 (32-bit)"
#define EXENAME "target32.exe"
#endif

int iWinMain() {
    
PROCESS_INFORMATION lpProcessInfo = {0};
    
CONTEXT lpContext = {0};
    
STARTUPINFO lpStartupInfo = {0};

    
printf("%s\nFilename: %s\n\n"CAPTIONEXENAME);

    if(
CreateProcessA(EXENAME,
                      
NULL,
                      
NULL,
                      
NULL,
                      
0,
                      
CREATE_SUSPENDED,
                      
NULL,
                      
NULL,
                      &
lpStartupInfo,
                      &
lpProcessInfo))    {

        
lpContext.ContextFlags CONTEXT_FULL;
        
GetThreadContext(lpProcessInfo.hThread, &lpContext);

#ifdef _WIN64
        
ULONG_PTRpeb = (ULONG_PTR*)lpContext.Rdx;
#else
        
ULONG_PTRpeb = (ULONG_PTR*)lpContext.Ebx;
#endif
        
ULONG_PTR ImageBaseAddress NULL;

        
ReadProcessMemory(lpProcessInfo.hProcess,
                          &
peb[2],
                          (
LPVOID)&ImageBaseAddress,
                          
sizeof(ULONG_PTR),
                          
NULL);
                  
        
printf("[-] ImageBase Address     = 0x%p\n"ImageBaseAddress);

#ifdef _WIN64
        
printf("[-] EntryPoint Address    = 0x%p\n"lpContext.Rcx);
        
printf("[-] Process (PEB Address) = 0x%p\n"lpContext.Rdx);

#else
        
printf("[-] EntryPoint Address    = 0x%p\n"lpContext.Eax);
        
printf("[-] Process (PEB Address) = 0x%p\n"lpContext.Ebx);
#endif



#ifdef _WIN64
        
ULONG_PTR uTargetAddress lpContext.Rcx 0x7E;
        const 
char newByte 0x75;
#else
        
ULONG_PTR uTargetAddress lpContext.Eax 0x64;
        const 
char newByte 0x74;
#endif
        
WriteProcessMemory(lpProcessInfo.hProcess,
                           (
LPVOID)uTargetAddress,
                           &
newByte,
                           
1,
                           
NULL);

        
ResumeThread(lpProcessInfo.hThread);
        
WaitForSingleObject(lpProcessInfo.hThreadINFINITE);
    }

    return 
0;


Attached file contains (source and binary (32bit/64bit) for testing purposes)

evlncrn8 10-19-2015 17:43

better way is to use the NtQueryInformationProcess - process_basic_information method to obtain the peb address for the process, its much more reliable than using register values which might change with a service pack / os update etc..

Insid3Code 10-19-2015 19:45

Yes, it's more safe to use Win/Native Api to get Base Address than using hard coded offsets (can be altered or modified between os version) especially if you plane to use it in production tools, MS recommendations.

bilbo 10-19-2015 23:55

Hi Insid3Code,

IMHO, your source code is very useful to find the image base address and the image entrypoint, but I really do not understand the use of patching one byte inside NTDLL.DLL, at EntryPoint+64/7E!

In my Window7-64, for a 32bit application, EntryPoint is at start of RtlUserThreadStart() (inside SysWOW64\ntdll.dll), and EntryPoint+0x64/0x7E are inside the exports table!

Best regards, bilbo

Insid3Code 10-20-2015 00:57

Hi bilbo,
To add support for WOW64 (32bit application on 64bit system) you need to use (Wow64GetThreadContext and WOW64_CONTEXT structure) and some system check to retrieve running environment info (32bit or 64bit).

bilbo 10-21-2015 00:12

Thanks for your answer, Insid3Code,
Quote:

To add support for WOW64 (32bit application on 64bit system) you need to use (Wow64GetThreadContext
Well, that's not true if I compile your code in 32bit mode and I take as target a 32bit app; from MSDN:
Quote:

A 32-bit application can call this function on a WOW64 thread; the result is the same as calling the GetThreadContext function
Anyway, the one-byte patch (either in 32 or in 64bit mode) is yet a mistery for me...
Best regards
bilbo

Insid3Code 10-21-2015 01:42

Quote:

Well, that's not true if I compile your code in 32bit mode and I take as target a 32bit app; from MSDN:
Yes, on 64bit system 32bit patcher to patch 32bit target: Wow64 support not needed. On 64bit system 64bit patcher to patch 32bit target: Wow64 support is needed.

Quote:

Anyway, the one-byte patch (either in 32 or in 64bit mode) is yet a mistery for me...
This code snippet is a demo for (chimera #01) challenge at AT4RE Forum, patching one byte to get (SUCCESS ICON ID instead of ERROR ICON ID of MessageBox)

Insid3Code 10-21-2015 02:20

1 Attachment(s)
Code snippet updated to support Wow64 for 64bit patcher to patch 32bit target...

PHP Code:

#include <windows.h>
#include <stdio.h>

#ifdef _WIN64
#define CAPTION "atomos - memory patcher for chimera #01 (64-bit)"
#define EXENAME "target64.exe" // change it to target "target32.exe" for Wow64 test.
#else
#define CAPTION "atomos - memory patcher for chimera #01 (32-bit)"
#define EXENAME "target32.exe"
#endif

int iWinMain() {
    
PROCESS_INFORMATION lpProcessInfo = {0};
    
STARTUPINFO lpStartupInfo = {0};

    
printf("%s\nFilename: %s\n\n"CAPTIONEXENAME);

    if(
CreateProcessA(EXENAME,
                      
NULL,
                      
NULL,
                      
NULL,
                      
0,
                      
CREATE_SUSPENDED,
                      
NULL,
                      
NULL,
                      &
lpStartupInfo,
                      &
lpProcessInfo))    {

#ifdef _WIN64  // 64bit Application
        
DWORD64peb64bit;
        
DWORD32wowPeb;

        
CONTEXT lpContext64bit = {0};
        
WOW64_CONTEXT lpWoWContext = {0};

        
DWORD64 uTargetAddress64bit;
        
char newByte64bit;

        
DWORD64 uTargetAddressWow64;
        
char newByteWow64;

        
BOOL  Wow64Process FALSE;

        
IsWow64Process(lpProcessInfo.hProcess, &Wow64Process);

        if (
Wow64Process) { // Wow64 Process
            
lpWoWContext.ContextFlags CONTEXT_FULL;
            
Wow64GetThreadContext(lpProcessInfo.hThread, &lpWoWContext);
            
wowPeb = (DWORD32*)lpWoWContext.Ebx;

            
DWORD32 ImageBaseAddress NULL;
            
ReadProcessMemory(lpProcessInfo.hProcess,
                              &
wowPeb[2],
                              (
LPVOID)&ImageBaseAddress,
                              
sizeof(DWORD32),
                              
NULL);

            
printf("[-] Wow64 ImageBase Address     = 0x%08X\n"ImageBaseAddress);
            
printf("[-] Wow64 EntryPoint Address    = 0x%08X\n"lpWoWContext.Eax);
            
printf("[-] Wow64 Process (PEB Address) = 0x%08X\n"lpWoWContext.Ebx);

            
uTargetAddressWow64 lpWoWContext.Eax 0x64;
            
newByteWow64 0x74;

            
WriteProcessMemory(lpProcessInfo.hProcess,
                               (
LPVOID)uTargetAddressWow64,
                               &
newByteWow64,
                               
1,
                               
NULL);
        } else { 
// 64bit Process

            
lpContext64bit.ContextFlags CONTEXT_FULL;
            
GetThreadContext(lpProcessInfo.hThread, &lpContext64bit);
            
peb64bit = (DWORD64*)lpContext64bit.Rdx;

            
DWORD64 ImageBaseAddress NULL;
            
ReadProcessMemory(lpProcessInfo.hProcess,
                              &
peb64bit[2],
                              (
LPVOID)&ImageBaseAddress,
                              
sizeof(DWORD64),
                              
NULL);

            
printf("[-] 64bit ImageBase Address     = 0x%p\n"ImageBaseAddress);
            
printf("[-] 64bit EntryPoint Address    = 0x%p\n"lpContext64bit.Rcx);
            
printf("[-] 64bit Process (PEB Address) = 0x%p\n"lpContext64bit.Rdx);

            
uTargetAddress64bit lpContext64bit.Rcx 0x7E;
            
newByte64bit 0x75;

            
WriteProcessMemory(lpProcessInfo.hProcess,
                               (
LPVOID)uTargetAddress64bit,
                               &
newByte64bit,
                               
1,
                               
NULL);

        }

        
ResumeThread(lpProcessInfo.hThread);
        
WaitForSingleObject(lpProcessInfo.hThreadINFINITE);

#else // 32bit Application
        
DWORD32peb32bit;
        
CONTEXT lpContext32bit = {0};

        
DWORD32 uTargetAddress32bit;
        
char newByte32bit;

        
lpContext32bit.ContextFlags CONTEXT_FULL;
        
GetThreadContext(lpProcessInfo.hThread, &lpContext32bit);
        
peb32bit = (DWORD32*)lpContext32bit.Ebx;

        
DWORD32 ImageBaseAddress NULL;
        
ReadProcessMemory(lpProcessInfo.hProcess,
                          &
peb32bit[2],
                          (
LPVOID)&ImageBaseAddress,
                          
sizeof(DWORD32),
                          
NULL);

        
printf("[-] 32bit ImageBase Address     = 0x%08X\n"ImageBaseAddress);
        
printf("[-] 32bit EntryPoint Address    = 0x%08X\n"lpContext32bit.Eax);
        
printf("[-] 32bit Process (PEB Address) = 0x%08X\n"lpContext32bit.Ebx);

        
uTargetAddress32bit lpContext32bit.Eax 0x64;
        
newByte32bit 0x74;

        
WriteProcessMemory(lpProcessInfo.hProcess,
                           (
LPVOID)uTargetAddress32bit,
                           &
newByte32bit,
                           
1,
                           
NULL);

        
ResumeThread(lpProcessInfo.hThread);
        
WaitForSingleObject(lpProcessInfo.hThreadINFINITE);
#endif

    
}

    return 
0;


Attached file contains (source and binary (32bit/64bit and Wow64) for testing purposes)


All times are GMT +8. The time now is 17:32.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2026, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX