Windows 2000で IIS EXPRESS 7.5 が動くと言ったが…あれは嘘だ

Iexpress.exe が Windows 2000が謎のクラッシュ起こすので解析したら、未初期化のバッファーにアクセスしてる|・ω・) 。o ( … )

CLSID clsid;
CoInitialize(NULL);
HRESULT hr = CLSIDFromProgID(L"Microsoft.ApplicationHost.WritableAdminManager", &clsid);

どうも上記のコードに失敗してるのが原因なんですが、失敗した場合の処理(NULL)ならば、エラーという処理があるのに、そこをNULLでクリアする処理が無い…どうなってるのさ・ω・!

          lea    eax,[ebp-00000084h]
          push    eax
          push    SWC01001648_Microsoft_ApplicationHost_Writab
          call    [ole32.dll!CLSIDFromProgID]
          mov    esi,eax
          cmp    esi,ebx
          jl     L010056BD <-ここで失敗する
          lea    eax,[ebp-00000090h]
          push    eax
          push    L01001638
          push    00000001h
          push    ebx
          lea    eax,[ebp-00000084h]
          push    eax
          call    [ole32.dll!CoCreateInstance]
          mov    esi,eax
          cmp    esi,ebx
          jl     L010056BD
          push    00000210h
          call    SUB_L01006807
          pop    ecx
          cmp    eax,ebx
          jz     L01004F01
          mov    edx,[ebp-00000094h]
          cmp    edx,ebx
          jnz    L01004EF5
          mov    edx,L01001300
 L01004EF5:
          push    edx
          mov    ecx,eax
          call    SUB_L010037C8
          mov    edi,eax
          jmp    L01004F03
 L01004F01:
          xor    edi,edi
 L01004F03:
          mov    [ebp-00000108h],edi

   :

 L010056BD:
          push    [ebp-00000104h]
          mov    edi,[OLEAUT32.dll!OLEAUT32.6]
          call    edi
          xor    ebx,ebx
          cmp    [ebp-000000C4h],ebx
          jz     L010056DD
          push    [ebp-000000C4h]
          call    edi
 L010056DD:
          mov    eax,[ebp-000000ACh]
          cmp    eax,ebx
          jz     L010056F3
          mov    ecx,[eax]
          push    eax
          call    [ecx+08h]
          mov    [ebp-000000ACh],ebx
 L010056F3:
          mov    eax,[ebp-000000A4h]
          cmp    eax,ebx
          jz     L01005709
          mov    ecx,[eax]
          push    eax
          call    [ecx+08h]
          mov    [ebp-000000A4h],ebx
 L01005709:
          mov    eax,[ebp-00000108h] <-失敗後、ここが初期化されてないのでクラッシュ
          cmp    eax,ebx
          jz     L01005719
          mov    ecx,[eax]
          push    eax
          call    [ecx+08h]

さすがにおかしいので調べてみた所…
lsa
Windows 2000の非対応関数実装してた!
というわけで、LogonUserExW を実装してみることに


高度なログオン

参考にしたサイト・ω・

BOOL MyLogonUser(HANDLE hLsa, ULONG uPackageId, LPWSTR lpszUserName, LPWSTR lpszPassword, LPWSTR lpszDomainName, HANDLE *phToken,MSV1_0_INTERACTIVE_PROFILE *pmsvProfile,ULONG *uProfileLength,QUOTA_LIMITS *limits)
{
    LUID                        luid;
    ULONG                       uBufferLength;
    //ULONG                       uProfileLength;
    LPBYTE                      lp;
    NTSTATUS                    ns;
    NTSTATUS                    nsSub;
    LSA_STRING                  lsaOriginal;
    TOKEN_SOURCE                tokenSource;
    MSV1_0_INTERACTIVE_LOGON    msvLogon;
    PMSV1_0_INTERACTIVE_LOGON   pmsvLogon;
    
    InitString(&lsaOriginal, "origial");

    uBufferLength  =  sizeof(MSV1_0_INTERACTIVE_LOGON);
    uBufferLength += InitUnicodeString(&msvLogon.UserName, lpszUserName);
    uBufferLength += InitUnicodeString(&msvLogon.Password, lpszPassword);
    uBufferLength += InitUnicodeString(&msvLogon.LogonDomainName, lpszDomainName);
    msvLogon.MessageType = MsV1_0InteractiveLogon;

    lp = (LPBYTE)LocalAlloc(LPTR, uBufferLength);
    CopyMemory(lp, (PVOID)&msvLogon, sizeof(MSV1_0_INTERACTIVE_LOGON));

    pmsvLogon = (PMSV1_0_INTERACTIVE_LOGON)lp;
    lp += sizeof(MSV1_0_INTERACTIVE_LOGON);

    FormatBuffer(&lp, &pmsvLogon->UserName);
    lp += pmsvLogon->UserName.Length;

    FormatBuffer(&lp, &pmsvLogon->Password);
    lp += pmsvLogon->Password.Length;
    
    FormatBuffer(&lp, &pmsvLogon->LogonDomainName);
    lstrcpyA(tokenSource.SourceName, "sample");

    AllocateLocallyUniqueId(&tokenSource.SourceIdentifier);

    ns = LsaLogonUser(hLsa, &lsaOriginal, Interactive, uPackageId,
        (PVOID)pmsvLogon, uBufferLength, NULL, &tokenSource, (PVOID *)pmsvProfile,
        uProfileLength, &luid, phToken, limits, &nsSub);
    if (LsaNtStatusToWinError(ns) != ERROR_SUCCESS) {
        LocalFree(pmsvLogon);
        return FALSE;
    }

    LocalFree(pmsvLogon);   
    return TRUE;
}
void FormatBuffer(LPBYTE *lp, PUNICODE_STRING pString)
{
    if (pString->Buffer != NULL) {
        CopyMemory(*lp, pString->Buffer, pString->Length);
        pString->Buffer = (LPWSTR)*lp;
    }
}
ULONG InitString(PLSA_STRING plsaString, LPSTR lpszString)
{
    if (lpszString == NULL) {
        plsaString->Length        = 0;
        plsaString->MaximumLength = 0;
        plsaString->Buffer        = NULL;
    }
    else {
        plsaString->Length        = (USHORT)(lstrlenA(lpszString) * sizeof(CHAR));
        plsaString->MaximumLength = plsaString->Length + sizeof(CHAR);
        plsaString->Buffer        = lpszString;
    }   
    return plsaString->Length;
}
ULONG InitUnicodeString(PLSA_UNICODE_STRING plsaString, LPWSTR lpszString)
{
    if (lpszString == NULL) {
        plsaString->Length        = 0;
        plsaString->MaximumLength = 0;
        plsaString->Buffer        = NULL;
    }
    else {
        plsaString->Length        = (USHORT)(lstrlenW(lpszString) * sizeof(WCHAR));
        plsaString->MaximumLength = plsaString->Length + sizeof(WCHAR);
        plsaString->Buffer        = lpszString;
    }
    return plsaString->Length;
}
BOOL EnablePrivilege(LPTSTR lpszPrivilege, BOOL bEnable)
{
    BOOL             bResult;
    LUID             luid;
    HANDLE           hToken;
    TOKEN_PRIVILEGES tokenPrivileges;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
        return FALSE;
    if (!LookupPrivilegeValue(NULL, lpszPrivilege, &luid)) {
        CloseHandle(hToken);
        return FALSE;
    }
    tokenPrivileges.PrivilegeCount           = 1;
    tokenPrivileges.Privileges[0].Luid       = luid;
    tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
    bResult = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
        CloseHandle(hToken);
    return bResult && GetLastError() == ERROR_SUCCESS;
}
__declspec(dllexport) BOOL WINAPI LogonUserExW(
  wchar_t* lpszUsername,
  wchar_t* lpszDomain,
  wchar_t* lpszPassword,
  DWORD dwLogonType,
  DWORD dwLogonProvider,
  PHANDLE phToken,
  PSID *ppLogonSid,
  PVOID ppProfileBuffer,
  PULONG pdwProfileLength,
  PQUOTA_LIMITS pQuotaLimits
  ){
    ULONG      uPackageId;
    HANDLE     hLsa;    NTSTATUS   ns;
    LSA_STRING lsaString;
    HTOKEN hToken;

    ns = LsaConnectUntrusted(&hLsa);
    if (LsaNtStatusToWinError(ns) != ERROR_SUCCESS) {
        return 0;
    }
    InitString(&lsaString, MSV1_0_PACKAGE_NAME);
    ns = LsaLookupAuthenticationPackage(hLsa, &lsaString, &uPackageId);
    if (LsaNtStatusToWinError(ns) != ERROR_SUCCESS) {
        LsaDeregisterLogonProcess(hLsa);
        return 0;
    }
    if (! MyLogonUser(hLsa, uPackageId, lpszUsername,lpszPassword, lpszDomain, &hToken, (struct _MSV1_0_INTERACTIVE_PROFILE *)ppProfileBuffer,pdwProfileLength,pQuotaLimits)) {
        LsaDeregisterLogonProcess(hLsa);
        return 0;
    }

    if(ppLogonSid) {
        DWORD req;
        TOKEN_USER *sid;
        SID *sid2;
        req=0;
        GetTokenInformation(hToken,TokenUser,0,0,&req);
        if(req){
            sid=(TOKEN_USER*)LocalAlloc(0x40,req);
            GetTokenInformation(hToken,TokenUser,sid,req,&req);
            DWORD zz=GetLengthSid(sid->User.Sid);
            sid2=(SID*)LocalAlloc(0x40,zz);
            memcpy(sid2,sid->User.Sid,zz);
            LocalFree(sid);
            *ppLogonSid=sid2;
        }
    }
    if(phToken) {
        *phToken = hToken;
    }

    LsaDeregisterLogonProcess(hLsa);    
    return 1;
}

これでいけるはず。

dwLogonType, dwLogonProvider は無視

おすすめ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です