⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protectdata.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
        return FALSE;
    }

    /* info1 */
    if (!unserialize_string(ptr,&index,size,16,sizeof(BYTE),FALSE,
                            &pInfo->info1.pbData, &pInfo->info1.cbData))
    {
        ERR("reading info1 failed!\n");
        return FALSE;
    }

    /* null0 */
    if (!unserialize_dword(ptr,&index,size,&pInfo->null0))
    {
        ERR("reading null0 failed!\n");
        return FALSE;
    }
    
    /* szDataDescr */
    if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE,
                            (BYTE**)&pInfo->szDataDescr, NULL))
    {
        ERR("reading szDataDescr failed!\n");
        return FALSE;
    }

    /* unknown0 */
    if (!unserialize_dword(ptr,&index,size,&pInfo->unknown0))
    {
        ERR("reading unknown0 failed!\n");
        return FALSE;
    }
    
    /* unknown1 */
    if (!unserialize_dword(ptr,&index,size,&pInfo->unknown1))
    {
        ERR("reading unknown1 failed!\n");
        return FALSE;
    }
    
    /* data0 */
    if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE,
                            &pInfo->data0.pbData, &pInfo->data0.cbData))
    {
        ERR("reading data0 failed!\n");
        return FALSE;
    }

    /* null1 */
    if (!unserialize_dword(ptr,&index,size,&pInfo->null1))
    {
        ERR("reading null1 failed!\n");
        return FALSE;
    }
    
    /* unknown2 */
    if (!unserialize_dword(ptr,&index,size,&pInfo->unknown2))
    {
        ERR("reading unknown2 failed!\n");
        return FALSE;
    }
    
    /* unknown3 */
    if (!unserialize_dword(ptr,&index,size,&pInfo->unknown3))
    {
        ERR("reading unknown3 failed!\n");
        return FALSE;
    }
    
    /* salt */
    if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE,
                            &pInfo->salt.pbData, &pInfo->salt.cbData))
    {
        ERR("reading salt failed!\n");
        return FALSE;
    }

    /* cipher */
    if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE,
                            &pInfo->cipher.pbData, &pInfo->cipher.cbData))
    {
        ERR("reading cipher failed!\n");
        return FALSE;
    }

    /* fingerprint */
    if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE,
                            &pInfo->fingerprint.pbData, &pInfo->fingerprint.cbData))
    {
        ERR("reading fingerprint failed!\n");
        return FALSE;
    }

    /* allow structure size to be too big (since some applications
     * will pad this up to 256 bytes, it seems) */
    if (index>size)
    {
        /* this is an impossible-to-reach test, but if the padding
         * issue is ever understood, this may become more useful */
        ERR("loaded corrupt structure! (used %u expected %u)\n",
                (unsigned int)index, (unsigned int)size);
        status=FALSE;
    }

    return status;
}

/* perform sanity checks */
static
BOOL valid_protect_data(const struct protect_data_t *pInfo)
{
    BOOL status=TRUE;

    TRACE("called\n");

    if (pInfo->count0 != 0x0001)
    {
        ERR("count0 != 0x0001 !\n");
        status=FALSE;
    }
    if (pInfo->count1 != 0x0001)
    {
        ERR("count0 != 0x0001 !\n");
        status=FALSE;
    }
    if (pInfo->null0 != 0x0000)
    {
        ERR("null0 != 0x0000 !\n");
        status=FALSE;
    }
    if (pInfo->null1 != 0x0000)
    {
        ERR("null1 != 0x0000 !\n");
        status=FALSE;
    }
    /* since we have no idea what info0 is used for, and it seems
     * rather constant, we can test for a Wine-specific magic string
     * there to be reasonably sure we're using data created by the Wine
     * implementation of CryptProtectData.
     */
    if (pInfo->info0.cbData!=strlen(crypt_magic_str)+1 ||
        strcmp( (LPCSTR)pInfo->info0.pbData,crypt_magic_str) != 0)
    {
        ERR("info0 magic value not matched !\n");
        status=FALSE;
    }

    if (!status)
    {
        ERR("unrecognized CryptProtectData block\n");
    }

    return status;
}

static
void free_protect_data(struct protect_data_t * pInfo)
{
    TRACE("called\n");

    if (!pInfo) return;

    CryptMemFree(pInfo->info0.pbData);
    CryptMemFree(pInfo->info1.pbData);
    CryptMemFree(pInfo->szDataDescr);
    CryptMemFree(pInfo->data0.pbData);
    CryptMemFree(pInfo->salt.pbData);
    CryptMemFree(pInfo->cipher.pbData);
    CryptMemFree(pInfo->fingerprint.pbData);
}

/* copies a string into a data blob */
static
BYTE *convert_str_to_blob(LPCSTR str, DATA_BLOB *blob)
{
    if (!str || !blob) return NULL;

    blob->cbData=strlen(str)+1;
    if (!(blob->pbData=CryptMemAlloc(blob->cbData)))
    {
        blob->cbData=0;
    }
    else {
        strcpy((LPSTR)blob->pbData, str);
    }

    return blob->pbData;
}

/*
 * Populates everything except "cipher" and "fingerprint".
 */
static
BOOL fill_protect_data(struct protect_data_t * pInfo, LPCWSTR szDataDescr,
                       HCRYPTPROV hProv)
{
    DWORD dwStrLen;

    TRACE("called\n");

    if (!pInfo) return FALSE;

    dwStrLen=lstrlenW(szDataDescr);

    memset(pInfo,0,sizeof(*pInfo));

    pInfo->count0=0x0001;

    convert_str_to_blob(crypt_magic_str, &pInfo->info0);

    pInfo->count1=0x0001;

    convert_str_to_blob(crypt_magic_str, &pInfo->info1);

    pInfo->null0=0x0000;

    if ((pInfo->szDataDescr=CryptMemAlloc((dwStrLen+1)*sizeof(WCHAR))))
    {
        memcpy(pInfo->szDataDescr,szDataDescr,(dwStrLen+1)*sizeof(WCHAR));
    }

    pInfo->unknown0=0x0000;
    pInfo->unknown1=0x0000;

    convert_str_to_blob(crypt_magic_str, &pInfo->data0);

    pInfo->null1=0x0000;
    pInfo->unknown2=0x0000;
    pInfo->unknown3=0x0000;

    /* allocate memory to hold a salt */
    pInfo->salt.cbData=CRYPT32_PROTECTDATA_SALT_LEN;
    if ((pInfo->salt.pbData=CryptMemAlloc(pInfo->salt.cbData)))
    {
        /* generate random salt */
        if (!CryptGenRandom(hProv, pInfo->salt.cbData, pInfo->salt.pbData))
        {
            ERR("CryptGenRandom\n");
            free_protect_data(pInfo);
            return FALSE;
        }
    }

    /* debug: show our salt */
    TRACE_DATA_BLOB(&pInfo->salt);

    pInfo->cipher.cbData=0;
    pInfo->cipher.pbData=NULL;

    pInfo->fingerprint.cbData=0;
    pInfo->fingerprint.pbData=NULL;

    /* check all the allocations at once */
    if (!pInfo->info0.pbData ||
        !pInfo->info1.pbData ||
        !pInfo->szDataDescr  ||
        !pInfo->data0.pbData ||
        !pInfo->salt.pbData
        )
    {
        ERR("could not allocate protect_data structures\n");
        free_protect_data(pInfo);
        return FALSE;
    }

    return TRUE;
}

static
BOOL convert_hash_to_blob(HCRYPTHASH hHash, DATA_BLOB * blob)
{
    DWORD dwSize;

    TRACE("called\n");

    if (!blob) return FALSE;

    dwSize=sizeof(DWORD);
    if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&blob->cbData,
                           &dwSize, 0))
    {
        ERR("failed to get hash size\n");
        return FALSE;
    }

    if (!(blob->pbData=CryptMemAlloc(blob->cbData)))
    {
        ERR("failed to allocate blob memory\n");
        return FALSE;
    }

    dwSize=blob->cbData;
    if (!CryptGetHashParam(hHash, HP_HASHVAL, blob->pbData, &dwSize, 0))
    {
        ERR("failed to get hash value\n");
        CryptMemFree(blob->pbData);
        blob->pbData=NULL;
        blob->cbData=0;
        return FALSE;
    }

    return TRUE;
}

/* test that a given hash matches an exported-to-blob hash value */
static
BOOL hash_matches_blob(HCRYPTHASH hHash, const DATA_BLOB *two)
{
    BOOL rc = FALSE;
    DATA_BLOB one;

    if (!two || !two->pbData) return FALSE;

    if (!convert_hash_to_blob(hHash,&one)) {
        return FALSE;
    }

    if ( one.cbData == two->cbData &&
         memcmp( one.pbData, two->pbData, one.cbData ) == 0 )
    {
        rc = TRUE;
    }

    CryptMemFree(one.pbData);
    return rc;
}

/* create an encryption key from a given salt and optional entropy */
static
BOOL load_encryption_key(HCRYPTPROV hProv, const DATA_BLOB *salt,
                         const DATA_BLOB *pOptionalEntropy, HCRYPTKEY *phKey)
{
    BOOL rc = TRUE;
    HCRYPTHASH hSaltHash;
    char * szUsername = NULL;
    DWORD dwUsernameLen;
    DWORD dwError;

    /* create hash for salt */
    if (!salt || !phKey ||
        !CryptCreateHash(hProv,CRYPT32_PROTECTDATA_HASH_CALG,0,0,&hSaltHash))
    {
        ERR("CryptCreateHash\n");
        return FALSE;
    }

    /* This should be the "logon credentials" instead of username */
    dwError=GetLastError();
    dwUsernameLen = 0;
    if (!GetUserNameA(NULL,&dwUsernameLen) &&
        GetLastError()==ERROR_MORE_DATA && dwUsernameLen &&
        (szUsername = CryptMemAlloc(dwUsernameLen)))
    {
        szUsername[0]='\0';
        GetUserNameA( szUsername, &dwUsernameLen );
    }
    SetLastError(dwError);

    /* salt the hash with:
     * - the user id
     * - an "internal secret"
     * - randomness (from the salt)
     * - user-supplied entropy
     */
    if ((szUsername && !CryptHashData(hSaltHash,(LPBYTE)szUsername,dwUsernameLen,0)) ||
        !CryptHashData(hSaltHash,crypt32_protectdata_secret,
                                 sizeof(crypt32_protectdata_secret)-1,0) ||
        !CryptHashData(hSaltHash,salt->pbData,salt->cbData,0) ||
        (pOptionalEntropy && !CryptHashData(hSaltHash,
                                            pOptionalEntropy->pbData,
                                            pOptionalEntropy->cbData,0)))
    {
        ERR("CryptHashData\n");
        rc = FALSE;
    }

    /* produce a symmetric key */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -