Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
8.5 kB
0
Indexable
Never
#include <stdio.h>
#include <windows.h>
#include <psapi.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>
#include <dbghelp.h>

/*
					HMODULE moduleHandles[1024];
					DWORD cbNeeded;
					if (EnumProcessModules(processHandle, moduleHandles, sizeof(moduleHandles), &cbNeeded)) {
						for (DWORD i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
							TCHAR moduleName[MAX_PATH];
							if (GetModuleFileNameEx(processHandle, moduleHandles[i], moduleName, sizeof(moduleName) / sizeof(TCHAR))) {
								printf("%s address: %p difference address: %td\n", moduleName, (uintptr_t)moduleHandles[i], (ptrdiff_t)event.u.Exception.ExceptionRecord.ExceptionAddress - (ptrdiff_t)moduleHandles[i]);
							}
						}
					} else {
						printf("Failed to enumerate process modules.\n");
					}
*/
typedef NTSTATUS(NTAPI* pNtAllocateVirtualMemory)(
  HANDLE               ProcessHandle,
  PVOID                *BaseAddress,
  ULONG                ZeroBits,
  PULONG           	   RegionSize,
  ULONG                AllocationType,
  ULONG                Protect
);
//static __typeof__(NtAllocateVirtualMemory) *fnNtAllocateVirtualMemory;

//optimize(0)
#define PIC CALLBACK __attribute__((noclone,noinline,))

HMODULE RemoteAddressToModule( HANDLE hProcess , void* pAddress ) {
	
	//context for input/output from the remote function
	//must contain REMOTE PROCESS pointers to any function that will be called (kernel32/ntdll is free.)
	//so for other than kernel32 is better to import LoadLibraryA / GetProcAddressA // FreeLibraryA and use there
	typedef struct {		
		HMODULE hModuleOut;
		void    *pAddressIn;				
		__typeof__(GetModuleHandleExA) *fnGetModuleHandleExA;
	} RemoteFuncContext;
	
	//declaring functions before and after to serve as barriers, and to know the function size
	//the function must not use constant strings or any other constant that would be end being in .data .rodata etc... sections
	//those must reside on the context if required,  so no accessing global or TLS variables
  //no directly accessing any other functions except those that are forcefully inlined
	void PIC RemoteFuncA() {}	
	BOOL PIC RemoteFuncN( RemoteFuncContext *p ) { 		
		return p->fnGetModuleHandleExA( 0x6 , (LPCSTR)p->pAddressIn , &(p->hModuleOut) );
	}
	void PIC RemoteFuncZ() {}	
	
	assert( ((uintptr_t)RemoteFuncZ) > ((uintptr_t)RemoteFuncN) );
	assert( ((uintptr_t)RemoteFuncN) > ((uintptr_t)RemoteFuncA) );
	
	//RemoteFunctionN();
	//printf("%p %p %p\n",RemoteFuncA,RemoteFuncN,RemoteFuncZ);
	//printf("size = %i\n", ((uintptr_t)RemoteFuncZ)-((uintptr_t)RemoteFuncN));
	
	//module handles for import kernel32 import functions
	HMODULE hKernel32 = GetModuleHandle("kernel32.dll");
	
	//initialize context with function pointers and input parameter or constants that would not be inside code
	RemoteFuncContext tCtx = {
		.pAddressIn = pAddress, 
		.fnGetModuleHandleExA = (void*)GetProcAddress(hKernel32,"GetModuleHandleExA")
	};
	
	if (!tCtx.fnGetModuleHandleExA) { puts("failed to get import addresses"); }
	
	
	//load nt function
	
	HMODULE ntdll = GetModuleHandle("ntdll.dll");
	pNtAllocateVirtualMemory myNtAlloc = (pNtAllocateVirtualMemory)GetProcAddress(ntdll, "NtAllocateVirtualMemory");

	//allocate memory on the remote process and copy code/data to it
	int CodeSize = (((uintptr_t)RemoteFuncZ)-((uintptr_t)RemoteFuncN)) , DataSize = sizeof(tCtx);
	size_t thSize = CodeSize+DataSize;
	PVOID rb = 0;
	printf("NT allocated memory. StatusCode: 0x%08X\n", myNtAlloc( hProcess , &rb ,0 , &thSize , MEM_COMMIT , PAGE_EXECUTE_READWRITE));

	DWORD statusNtAlloc = 0;

	RemoteFuncContext *pCtx = rb;
	WriteProcessMemory( hProcess , pCtx , &tCtx , DataSize , NULL );
	WriteProcessMemory( hProcess , pCtx+1 , RemoteFuncN , CodeSize , NULL );
	printf("Last Error after WriteProcessMemory(hProcess ,pCtx , &tCtx, DataSize, NULL): %d\n", GetLastError());

	//create thread and wait for it to finish
	DWORD dwTID;
	HANDLE hThread = CreateRemoteThread( hProcess , NULL , 0 , (LPTHREAD_START_ROUTINE)(pCtx+1) , pCtx , 0 , &dwTID );
	if (!hThread) {
		puts("Failed to create remote thread");
	} else {
		WaitForSingleObject( hThread , INFINITE );
		CloseHandle(hThread);
	}
	
	//copy back structure data (output) so it can even do a partial copy of the structure with just OUTPUT elements
	ReadProcessMemory( hProcess , pCtx , &tCtx , sizeof(tCtx) , NULL );
	VirtualFreeEx( hProcess , pCtx , CodeSize+DataSize , MEM_RELEASE );
	
  //done 	
	return tCtx.hModuleOut;
	
}

// Exception handler function
void checkBits(DWORD pid) {
    /* check the bits of the process */
	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
    if (hProcess == NULL) {
        printf("Error: OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid) failed with error code %d\n", GetLastError());
        return;
    }

	BOOL isWow64 = FALSE;
    if (!IsWow64Process(hProcess, &isWow64)) {
        printf("Error: !IsWow64Process(hProcess, &isWow64) failed with error code %d\n", GetLastError());
        CloseHandle(hProcess);
        return;
    }

    if (isWow64) {
        printf("Process %d is running as a 32-bit process on a 64-bit system.\n", pid);
    } else {
        printf("Process %d is running as a 64-bit process.\n", pid);
    }

    CloseHandle(hProcess);
}

// Main function
int main(int argc, char *argv[]) {
    // Check if target process ID was provided as argument
    if (argc < 2) {
        printf("Usage: %s <Process ID>\n", argv[0]);
        return 1;
    }

    // Convert target process ID from string to integer
    DWORD processId = atoi(argv[1]);

	checkBits(processId);

    // Attach to target process
    if (!DebugActiveProcess(processId)) {
        printf("Error attaching to process (error code %d)\n", GetLastError());
        return 1;
    }
	
	DebugSetProcessKillOnExit(FALSE);

	
    // Loop indefinitel
    DEBUG_EVENT event;
	while (1) {
		if (!WaitForDebugEvent(&event, 50)) {
			if ( (GetLastError() == WAIT_TIMEOUT) && (!(GetKeyState( VK_ESCAPE ) >> 1)) ) { continue; }
			break;
		}
		switch (event.dwDebugEventCode) {
            case EXCEPTION_DEBUG_EVENT:
                printf("Exception occurred with code 0x%08X at address 0x%p ", event.u.Exception.ExceptionRecord.ExceptionCode, event.u.Exception.ExceptionRecord.ExceptionAddress);
				HMODULE moduleToTheAddress;
				if (!GetModuleHandleEx(0x00000004, (LPCSTR)event.u.Exception.ExceptionRecord.ExceptionAddress, &moduleToTheAddress)) {
										
					printf("Error GetModuleHandleEx(0x00000004, ptr, &moduleToTheAddress) (error code %d)\n", GetLastError());
					
					/* Enumerating Modules Loaded */
					HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
					if (processHandle == NULL) {
						printf("Failed to open process handle.\n");
						return 0;
					}
			
					HMODULE moduleTaken = RemoteAddressToModule( processHandle, (void*) event.u.Exception.ExceptionRecord.ExceptionAddress );
					
					char moduleName[MAX_PATH];
					GetModuleFileNameEx(processHandle, moduleTaken, moduleName, MAX_PATH);
					printf(" Module Name: %s", moduleName);
					
					CloseHandle(processHandle);
				}else{
					char moduleName[MAX_PATH];
					GetModuleFileName(moduleToTheAddress, moduleName, MAX_PATH);
					printf(" Module Name: %s", moduleName);
					
					
					/* Enumerating Modules Loaded */
					HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
					if (processHandle == NULL) {
						printf("Failed to open process handle.\n");
						return 0;
					}
			
					HMODULE moduleTaken = RemoteAddressToModule( processHandle, (void*) event.u.Exception.ExceptionRecord.ExceptionAddress );
					
					char moduleName2[MAX_PATH];
					GetModuleFileNameEx(processHandle, moduleTaken, moduleName2, MAX_PATH);
					printf(" Module Name: %s", moduleName2);
					
					CloseHandle(processHandle);
				}
				printf("\n");
				ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
                break;
            default:
                ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
                break;
        }
    }
	

    // Detach from target process
    DebugActiveProcessStop(processId);

    return 0;
}