首页
社区
课程
招聘
[分享&挑战]sekurlsa.dll逆向分析challenge(可能发现windows系统账号存储机制的小秘密)
发表于: 2012-2-23 20:55 59914

[分享&挑战]sekurlsa.dll逆向分析challenge(可能发现windows系统账号存储机制的小秘密)

2012-2-23 20:55
59914

声明:
本文作者是CasperKid,本文发表经过他本人授权!

昨天有朋友发了个法国佬写的神器叫 mimikatz (附件在3楼)让我们看下

神器下载地址:

http://blog.gentilkiwi.com/mimikatz
还有一篇用这个神器直接从 lsass.exe 里获取windows处于active状态账号明文密码的文章

http://pentestmonkey.net/blog/mimikatz-tool-to-recover-cleartext-passwords-from-lsass
自己尝试了下用 win2008 r2 x64 来测试



最后测试成功 wdigest 就是我的明文密码

我还测过密码复杂度在14位以上

包含数字 大小写字母 特殊字符的密码

一样能抓出明文密码来

以前用 wce.exe lslsass.exe 通常是只能从内存里顶多抓出active账号的 lm hash 和 ntlm hash

但用了这个神器抓出明文密码后

由此我们可以反推断 在 lsass.exe 里并不是只存有 lm hash ntlm hash 而已

应该还存在有你的明文密码经过某种加密算法 (注意: 是加密算法 而不是hash算法 加密算法是可逆的 hash算法是不可逆的)

这样这个加密算法是可逆的 能被解密出明文

所以进程注入 lsass.exe 时 所调用的 sekurlsa.dll 应该包含了对应的解密算法

逆向功底比较好的童鞋可以尝试去逆向分析一下

然后这个神器的功能肯定不仅仅如此 在我看来它更像一个轻量级调试器

可以提升进程权限 注入进程 读取进程内存等等

下面展示一个 读取扫雷游戏的内存的例子



我们还可以通过pause命令来挂起该进程 这个时候游戏的时间就静止了



总之这个神器相当华丽 还有更多能力有待各黑阔们挖掘 =..=~

(在文章最后 附加作者的回答)

在上篇文章中 我们看到了通过用 mimikatzlsass.exe 进行进程注入

再调用 sekurlsa.dll 去获取 wdigest
也写了下自己对加密解密这个问题的想法

现在在把这个给大家点明确一些~



在用这个神器获取密码的时候 命令分别如下

privilege::debug

inject::process lsass.exe sekurlsa.dll

@getLogonPasswords

可以推理出整个流程

先将进程提升到 debug 权限

然后将 sekurlsa.dll 注入到 lsass.exe 进程里

调用 sekurlsa.dll 里的 getLogonPasswords 这个函数获取出密码

结合上文我提到的废话

--------------------------------------------------------------------------------------

以前我们一般用 wce.exe lslsass.exe通常是只能从内存里顶多抓active账号的 lm hash 和 ntlm hash

但用了这个神器抓出明文密码后

由此我们可以反推断 在 lsass.exe 里并不是只存有 lm hash ntlm hash 而已

lsass.exe 里很可能是存在两个敏感信息

1. 明文密码经过加密算法的密文 (这个加密算法是可逆的 能被解密出明文)

2. 明文密码经过hash算法做数字摘要认证的hash

(注意: 是加密算法 而不是hash算法 加密算法是可逆的 hash算法是不可逆的)

所以进程注入 lsass.exe 时 所调用的 sekurlsa.dll 应该包含了对应的解密算法

--------------------------------------------------------------------------------------



逆向功底比较好的童鞋可以尝试去逆向分析一下

直接去逆向分析下 sekurlsa.dll getLogonPasswords 函数做了些什么

是直接从某处就取出了 wdigest
还是从某处先取出了 某些信息

然后有解密操作的过程

说不定能发现微软的一些小秘密哟 =..=~

比如 它的这个加密算法

---------------------------------------------- 作者回答 ----------------------------------------------

在作者blog里发现作者其实已经回答过这个问题了



没有明文存储 而是放在内存里 并且是可逆的 这样也就验证了我推测的第一种情况

1. 明文密码经过加密算法的密文 (这个加密算法是可逆的 能被解密出明文)


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 6
支持
分享
最新回复 (64)
雪    币: 2307
活跃值: (1018)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
强大,沙发
2012-2-23 21:19
0
雪    币: 2307
活跃值: (1018)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3
帮着上传下附件 mimikatz_trunk.zip
上传的附件:
2012-2-23 21:25
0
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
4
[QUOTE=非虫;1047297]帮着上传下附件 mimikatz_trunk.zip[/QUOTE]

校园网不给力啊,谢谢了!
2012-2-23 21:28
0
雪    币: 1370
活跃值: (2351)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
强大个毛,如下面,根本访问不了进程
上传的附件:
2012-2-23 21:30
0
雪    币: 53
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
多测试些环境和操作系统版本吧
目前和朋友他们一起测试过 xp win2003 win7 win2008 全部通杀
有时可能因为电脑上有杀软 会守护lsass.exe 所以最好关闭杀软
还有就是别选错是 x32 还是 x64
2012-2-23 21:39
0
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
7
dll路径里面不要包含中文噢.
2012-2-23 21:40
0
雪    币: 1847
活跃值: (1821)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
8
强大,前来围观
2012-2-23 21:50
0
雪    币: 2105
活跃值: (424)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
mark1111
2012-2-23 21:52
0
雪    币: 1370
活跃值: (2351)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
把杀毒软件删掉,没有中文路径,还是不行
上传的附件:
2012-2-23 21:53
0
雪    币: 53
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
你换个操作系统 或者 VM里试试 =..=~
成功的人很多的 =..=~
2012-2-23 22:02
0
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
12

我是在虚拟机XP SP3环境下测试的。
ntlm和lm的hash导出,管理员密码直接明文显示出来的!
重启试试吧,反正这个是能够成功的。关键是大家来试试逆向这个原理,估计收获会不小的。
上传的附件:
2012-2-23 22:03
0
雪    币: 1370
活跃值: (2351)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
我这电脑被一个SYS HOOK了NTCREATETHREAD。不让DLL注入LSASS.EXE
2012-2-23 22:25
0
雪    币: 8858
活跃值: (18510)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
14
这么有意思,要试下
2012-2-23 23:09
0
雪    币: 8858
活跃值: (18510)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
15
注入不了,拒绝访问,用其他工具注入也不行
2012-2-23 23:21
0
雪    币: 53
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
建议用VM 或 其他OS version测试
目前好像爆得不成功最多的是winxp
win7和win2008目前都测试正常
2012-2-23 23:40
0
雪    币: 105
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
17
简单分析了下,DLL本身没有解密代码,结合了两个DLL获取了密码的原文。
有兴趣的同学,可以继续深入分析。
这里给出我分析几个点

1 通过 LsaEnumerateLogonSessions() 获取活动Session的LUID

2 在模块 wdigest 中
.text:7EAC538A 008 8B 0D AC E2 AC 7E                       mov     ecx, ?l_LogSessList@@3U_LIST_ENTRY@@A ; _LIST_ENTRY l_LogSessList
.text:7EAC5390 008 8B 45 08                                mov     eax, [ebp+arg_0]
.text:7EAC5393 008 89 08                                   mov     [eax], ecx
.text:7EAC5395 008 C7 40 04 AC E2 AC 7E                    mov     dword ptr [eax+4], offset ?l_LogSessList@@3U_LIST_ENTRY@@A ; _LIST_ENTRY l_LogSessList

获取导出变量地址 ?l_LogSessList@@3U_LIST_ENTRY@@A ; _LIST_ENTRY l_LogSessList
l_LogSessList 变量地址 sekurlsa 10035868

3 遍历l_LogSessList 得到 指定LUID的密码密文。
枚举列表处理地址 sekurlsa 10014B80

4 调用在模块 lsasrv 中 内部函数LsaUnprotectMemory进行解密
LsaUnprotectMemory函数指针保存在 sekurlsa  10035870

佩服作者对系统安全机制的研究深度
PS: getWDigest导出函数也可以获取密码。

不早了,明天还要Working。
2012-2-24 01:09
0
雪    币: 602
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
关注一下.......
2012-2-24 06:09
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
win7下测试,工具使用成功与否貌似跟系统权限有关
2012-2-24 09:08
0
雪    币: 62
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
20
强人,下来试试
2012-2-24 09:45
0
雪    币: 238
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
m$又把可逆密文存内存里了?
2012-2-24 14:40
0
雪    币: 8230
活跃值: (2811)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
22
这个的确厉害哈.谢谢分享.
2012-2-24 15:46
0
雪    币: 8858
活跃值: (18510)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
23
haha,在办公室试验成功
2012-2-24 16:33
0
雪    币: 451
活跃值: (78)
能力值: ( LV12,RANK:470 )
在线值:
发帖
回帖
粉丝
24
下面来自http://64.4.30.156/en-us/library/windows/desktop/ff714510%28v=vs.85%29.aspx
由此可见,函数肯定不能支持2000,xp多半也不行的
void NTAPI LsaUnprotectMemory(
__inout PVOID Buffer,
__in ULONG BufferSize
);
Buffer [in, out]
On input, a pointer to the buffer to be decrypted. On output, a pointer to the decrypted buffer.
BufferSize [in]
The size, in bytes, of the Buffer buffer.
Remarks
A pointer to the LsaProtectMemory function is available in the LSA_SECPKG_FUNCTION_TABLE structure received by the SpInitialize function.
Requirements
Minimum supported client
Windows XP
Minimum supported server
Windows Server 2003
Header
Ntsecpkg.h


继续,贴点相关函数代码,转载到论坛保存下

LsaEnumerateLogonSessions函数可以获取已经存在的logon session identifiers (LUIDs) 和session的总数。
NTSTATUS NTAPI LsaEnumerateLogonSessions(
PULONG LogonSessionCount,
PLUID* LogonSessionList
);

获取的LogonSessionList,数据类型为LUID。

typedef struct _LUID {
DWORD LowPart;
LONG HighPart;
} LUID, *PLUID;

通过LUID来获取详细的logon session信息,需要调用函数LsaGetLogonSessionData,调用者必须是拥有该session或者是本地的系统管理员。

NTSTATUS NTAPI LsaGetLogonSessionData(
PLUID LogonId,
PSECURITY_LOGON_SESSION_DATA* ppLogonSessionData
);

LsaGetLogonSessionData函数返回一个PSECURITY_LOGON_SESSION_DATA结构体。

typedef struct _SECURITY_LOGON_SESSION_DATA {
ULONG Size;
LUID LogonId;
LSA_UNICODE_STRING UserName;
LSA_UNICODE_STRING LogonDomain;
LSA_UNICODE_STRING AuthenticationPackage;
ULONG LogonType;
ULONG Session;
PSID Sid;
LARGE_INTEGER LogonTime;
LSA_UNICODE_STRING LogonServer;
LSA_UNICODE_STRING DnsDomainName;
LSA_UNICODE_STRING Upn;
} SECURITY_LOGON_SESSION_DATA, *PSECURITY_LOGON_SESSION_DATA;

其中包含了登陆标识(LogonId)、登陆的账号(UserName)、域(LogonDomain)、认证方式(AuthenticationPackage)、登陆类型(LogonType)、会话ID(Session)、用户的Sid(Sid)、用户登陆时间(LogonTime)等信息。

登陆类型(LogonType)是个枚举类型。

typedef enum _SECURITY_LOGON_TYPE {
Interactive = 2, // Interactively logged on (locally or remotely)
Network, // Accessing system via network
Batch, // Started via a batch queue
Service, // Service started by service controller
Proxy, // Proxy logon
Unlock, // Unlock workstation
NetworkCleartext, // Network logon with cleartext credentials
NewCredentials, // Clone caller, new default credentials
RemoteInteractive, // Remote, yet interactive. Terminal server
CachedInteractive, // Try cached credentials without hitting the net.
CachedRemoteInteractive, // Same as RemoteInteractive, this is used internally for auditing purpose
CachedUnlock // Cached Unlock workstation
} SECURITY_LOGON_TYPE, *PSECURITY_LOGON_TYPE;

用户的Sid(Sid)可以用ConvertSidToStringSid来转换成常见的SID格式字符串。

BOOL ConvertSidToStringSid(
PSID Sid,
LPTSTR* StringSid
);

这样,所有logon session的信息就获取到了。
最后调用LSAFreeReturnBuffer函数来释放所占用的内存。


更进一步的,用EnumProcesses函数枚举进程ID,OpenProcess获取每一个进程的句柄。在分别通过OpenProcessToken和GetTokenInformation打开并获取进程的访问令牌信息。

BOOL OpenProcessToken(
HANDLE ProcessHandle,
DWORD DesiredAccess,
PHANDLE TokenHandle
);

BOOL GetTokenInformation(
HANDLE TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
LPVOID TokenInformation,
DWORD TokenInformationLength,
PDWORD ReturnLength
);

TokenInformationClass是个枚举类型,用来指明要获取的信息类型,这里用TokenStatistics即可。获取的信息在TokenInformation中,数据类型为TOKEN_STATISTICS的结构体。

typedef struct _TOKEN_STATISTICS {
LUID TokenId;
LUID AuthenticationId;
LARGE_INTEGER ExpirationTime;
TOKEN_TYPE TokenType;
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
DWORD DynamicCharged;
DWORD DynamicAvailable;
DWORD GroupCount;
DWORD PrivilegeCount;
LUID ModifiedId;
} TOKEN_STATISTICS, *PTOKEN_STATISTICS;

其中LUID AuthenticationId如果和前面logon session的LUID一致,说明该进程的拥有者是相应的logon session。
2012-2-24 18:16
0
雪    币: 451
活跃值: (78)
能力值: ( LV12,RANK:470 )
在线值:
发帖
回帖
粉丝
25
作者这么说的
Correct, crypted in memory but in reversible way (LsaProtectMemory/LsaUnprotectMemory, see : http://blog.gentilkiwi.com/mimikatz/sekurlsa/wdigest#getWDigestFunctions & http://blog.gentilkiwi.com/mimikatz/sekurlsa/tspkg#getTsPkgFunctions), msv1_0 also use subcalls too for pass the hash.

Usualy, debug privilege is needed, but you can use system account too, (psexec -s or other tricks) and with it : no need of privilege :)

I disagree vulnerability, it's a weakness (but big fail ;))
2012-2-24 18:36
0
游客
登录 | 注册 方可回帖
返回
//