关于定位lsass内存中的明文密码
;90 nop
766258ff 90 nop
76625900 90 nop
76625901 90 nop
76625902 90 nop
76625903 90 nop
76625904 90 nop 再看md4Initialize:
kd> u cryptdll!md4Initialize L10
cryptdll!md4Initialize:
76624cf0 56 push esi
76624cf1 6a68 push 0x68
76624cf3 ff156c106276 call dword ptr [cryptdll!_imp__malloc (7662106c)]
76624cf9 8bf0 mov esi,eax ;pMD4=malloc(0x68)
76624cfb 85f6 test esi,esi
76624cfd 59 pop ecx
76624cfe 7507 jnz cryptdll!md4Initialize+0x17 (76624d07)
76624d00 b8170000c0 mov eax,0xc0000017
76624d05 eb0e jmp cryptdll!md4Initialize+0x25 (76624d15)
76624d07 56 push esi
76624d08 e8d3100000 call cryptdll!MD4Init (76625de0) ;MD4Init(pMD4)
76624d0d 8b44240c mov eax,[esp+0xc]
76624d11 8930 mov [eax],esi
76624d13 33c0 xor eax,eax
76624d15 5e pop esi
76624d16 c20800 ret 0x8
搞了半天,pMD4(包括其中的密码缓存)是由malloc分配的。这下没戏了,根本无法确定它的位置。
这一点其实用脚趾头想想也知道,但非要亲眼所见才死心。 ^_^
还有最后一线“希望”——希望lsass把密码留着别释放。
md4Initialize(0,&pMD4);
md4Sum(pMD4,PassLeng,pPassword);
之后是
md4Finalize(pMD4,pHash);
kd> u cryptdll!md4Finalize L10
cryptdll!md4Finalize:
76624d80 56 push esi
76624d81 8b742408 mov esi,[esp+0x8]
76624d85 57 push edi
76624d86 56 push esi
76624d87 e894100000 call cryptdll!MD4Final (76625e20) ;MD4Final(pMD4)
76624d8c 8b7c2410 mov edi,[esp+0x10]
76624d90 83c658 add esi,0x58 ;esi=pMD4->Hash
76624d93 a5 movsd ;memcpy(pHash,pMD4->Hash,16)
76624d94 a5 movsd
76624d95 a5 movsd
76624d96 a5 movsd
76624d97 5f pop edi
76624d98 33c0 xor eax,eax
76624d9a 5e pop esi
76624d9b c20800 ret 0x8
cryptdll!md4Finish:
76624d9e 90 nop
md4Finalize调用MD4Final:
kd> u cryptdll!MD4Final
cryptdll!MD4Final:
76625e20 ff2550106276 jmp dword ptr [cryptdll!_imp__MD4Final (76621050)]
转到_imp__MD4Final:
kd> dd cryptdll!_imp__MD4Final L1
76621050 77d7d3f3
kd> u 77d7d3f3 L35
ADVAPI32!MD4Final:
77d7d3f3 83ec48 sub esp,0x48
77d7d3f6 53 push ebx
77d7d3f7 55 push ebp
77d7d3f8 56 push esi
77d7d3f9 8b742458 mov esi,[esp+0x58] ;esi=pMD4
77d7d3fd 8b4610 mov eax,[esi+0x10] ;eax=pMD4->Count.LowPart
77d7d400 8b4e14 mov ecx,[esi+0x14] ;ecx=pMD4->Count.HighPart
77d7d403 8d5e58 lea ebx,[esi+0x58] ;ebx=pMD4->Hash
77d7d406 8903 mov [ebx],eax ;下面是一些算法的操作,不关心
77d7d408 c1e803 shr eax,0x3 ;盯紧esi(=pMD4)就是了
77d7d40b 83e03f and eax,0x3f
77d7d40e 83f838 cmp eax,0x38
77d7d411 57 push edi
77d7d412 894e5c mov [esi+0x5c],ecx
77d7d415 ba38000000 mov edx,0x38
77d7d41a 0f83d3830100 jnb ADVAPI32!MD4Final+0x29 (77d957f3)
77d7d420 2bd0 sub edx,eax
77d7d422 8bca mov ecx,edx
77d7d424 8be9 mov ebp,ecx
77d7d426 c1e902 shr ecx,0x2
77d7d429 33c0 xor eax,eax
77d7d42b 8d7c2410 lea edi,[esp+0x10]
77d7d42f f3ab rep stosd
77d7d431 52 push edx
77d7d432 8d542414 lea edx,[esp+0x14]
77d7d436 8bcd mov ecx,ebp
77d7d438 83e103 and ecx,0x3
77d7d43b 52 push edx
77d7d43c f3aa rep stosb
77d7d43e 56 push esi
77d7d43f c644241c80 mov byte ptr [esp+0x1c],0x80
77d7d444 e8f1040000 call ADVAPI32!MD4Update (77d7d93a)
77d7d449 6a08 push 0x8
77d7d44b 53 push ebx
77d7d44c 56 push esi
77d7d44d e8e8040000 call ADVAPI32!MD4Update (77d7d93a)
77d7d452 8b06 mov eax,[esi]
77d7d454 8b4e04 mov ecx,[esi+0x4]
77d7d457 8b5608 mov edx,[esi+0x8]
77d7d45a 8903 mov [ebx],eax
77d7d45c 8b460c mov eax,[esi+0xc]
77d7d45f 5f pop edi
77d7d460 894e5c mov [esi+0x5c],ecx
77d7d463 895660 mov [esi+0x60],edx
77d7d466 894664 mov [esi+0x64],eax
77d7d469 5e pop esi
77d7d46a 5d pop ebp
77d7d46b 5b pop ebx
77d7d46c 83c448 add esp,0x48
77d7d46f c20400 ret 0x4
ADVAPI32!MD5Init:
77d7d472 90 nop
77d7d473 90 nop
77d7d474 90 nop
咦,怎么没释放?别高兴的太早,下面还有md4Finish呢!
md4Finish(&pMD4);
kd> u cryptdll!md4Finish L10
cryptdll!md4Finish:
766211f0 56 push esi
766211f1 8b742408 mov esi,[esp+0x8]
766211f5 ff36 push dword ptr [esi]
766211f7 ff1570106276 call dword ptr [cryptdll!_imp__free (76621070)] ;free(pMD4)
766211fd 832600 and dword ptr [esi],0x0 ;pMD4=NULL
76621200 59 pop ecx
76621201 33c0 xor eax,eax
76621203 5e pop esi
76621204 c20400 ret 0x4
cryptdll!md5Initialize:
76621207 90 nop
76621208 90 nop
76621209 90 nop
7662120a 90 nop
7662120b 90 nop
7662120c 90 nop
7662120d 90 nop
彻底没戏啦。pMD4连同里面的明文密码被free了。
我不知道关于lsass留着明文密码备用的说法究竟是不是可靠的,至少我们看到的那个确实被free了。
如果说,前面提到的多个“源密码”中的某一个被lsass留着,那就不应该搜索不到。要么密码不是明文的。
结论很明显,在lsass里找明文密码属于RP问题。如果它已经被覆盖,就算你用什么模拟登陆的方法确定它的位置,也是回天乏术。如果没有被覆盖,用WinEggDrop的办法找密码已经足够了。
我再加一个判断条件:密码前面的2个ULONG总是0x00000200和0x00000000。它们就是pMD4->Count的LowPart和HighPart,用于保存被加密数据的bit数。MD4加密以64字节(0x200 bit)为最小单位,密码不超过32个字符的话,一轮加密就完了,所以它们总是0x200和0x0。这个条件可以在密码被覆盖时减少误报。