int main() 
{
    char buf[1024];
    char c;
    int i;
	printf("请输入字符串:\n");
    gets(buf);
    for(i = 0;i < strlen(buf);i++) 
	{
		if(!isupper(buf[i]) && !islower(buf[i])) 
		{
			perror("字符串只可以包含大小写字母!\n");
			exit(1);
		}
    }
    LoadHashTable(buf);
    if(Locate(buf, c)) 
	{
		printf("第一个只出现一次的字符为:");
		putchar(c);
	}
	else 
		perror("没有出现一次的字母!");
    printf("\n");
	return 0;
}
示例#2
0
static int MD5MatchTest01(void)
{
    ROHashTable *hash = ROHashInit(4, 16);
    if (hash == NULL) {
        return 0;
    }
    if (LoadHashTable(hash, "d80f93a93dc5f3ee945704754d6e0a36", "file", 1, DETECT_FILEMD5) != 1)
        return 0;
    if (LoadHashTable(hash, "92a49985b384f0d993a36e4c2d45e206", "file", 2, DETECT_FILEMD5) != 1)
        return 0;
    if (LoadHashTable(hash, "11adeaacc8c309815f7bc3e33888f281", "file", 3, DETECT_FILEMD5) != 1)
        return 0;
    if (LoadHashTable(hash, "22e10a8fe02344ade0bea8836a1714af", "file", 4, DETECT_FILEMD5) != 1)
        return 0;
    if (LoadHashTable(hash, "c3db2cbf02c68f073afcaee5634677bc", "file", 5, DETECT_FILEMD5) != 1)
        return 0;
    if (LoadHashTable(hash, "7ed095da259638f42402fb9e74287a17", "file", 6, DETECT_FILEMD5) != 1)
        return 0;

    if (ROHashInitFinalize(hash) != 1) {
        return 0;
    }

    if (MD5MatchLookupString(hash, "d80f93a93dc5f3ee945704754d6e0a36") != 1)
        return 0;
    if (MD5MatchLookupString(hash, "92a49985b384f0d993a36e4c2d45e206") != 1)
        return 0;
    if (MD5MatchLookupString(hash, "11adeaacc8c309815f7bc3e33888f281") != 1)
        return 0;
    if (MD5MatchLookupString(hash, "22e10a8fe02344ade0bea8836a1714af") != 1)
        return 0;
    if (MD5MatchLookupString(hash, "c3db2cbf02c68f073afcaee5634677bc") != 1)
        return 0;
    if (MD5MatchLookupString(hash, "7ed095da259638f42402fb9e74287a17") != 1)
        return 0;
    /* shouldn't match */
    if (MD5MatchLookupString(hash, "33333333333333333333333333333333") == 1)
        return 0;

    ROHashFree(hash);
    return 1;
}
示例#3
0
bool WINAPI SFileOpenArchive(
    const char * szMpqName, 
    DWORD dwPriority, 
    DWORD dwFlags, 
    HANDLE * phMpq)
{
    TFileStream * pStream = NULL;       // Open file stream
    TMPQArchive * ha = NULL;            // Archive handle
    ULONGLONG FileSize = 0;             // Size of the file
    int nError = ERROR_SUCCESS;

    // Verify the parameters
    if (szMpqName == NULL || *szMpqName == 0 || phMpq == NULL)
        nError = ERROR_INVALID_PARAMETER;

    // One time initialization of MPQ cryptography
    InitializeMpqCryptography();
    dwPriority = dwPriority;

    // Open the MPQ archive file
    if (nError == ERROR_SUCCESS)
    {
        if (!(dwFlags & MPQ_OPEN_ENCRYPTED))
        {
            pStream = FileStream_OpenFile(szMpqName, (dwFlags & MPQ_OPEN_READ_ONLY) ? false : true);
            if (pStream == NULL)
                nError = GetLastError();
        }
        else
        {
            pStream = FileStream_OpenEncrypted(szMpqName);
            if (pStream == NULL)
                nError = GetLastError();
        }
    }

    // Allocate the MPQhandle
    if (nError == ERROR_SUCCESS)
    {
        FileStream_GetSize(pStream, FileSize);
        if ((ha = ALLOCMEM(TMPQArchive, 1)) == NULL)
            nError = ERROR_NOT_ENOUGH_MEMORY;
    }

    // Initialize handle structure and allocate structure for MPQ header
    if (nError == ERROR_SUCCESS)
    {
        memset(ha, 0, sizeof(TMPQArchive));
        ha->pStream = pStream;
        pStream = NULL;

        // Remember if the archive is open for write
        if (ha->pStream->StreamFlags & (STREAM_FLAG_READ_ONLY | STREAM_FLAG_ENCRYPTED_FILE))
            ha->dwFlags |= MPQ_FLAG_READ_ONLY;

        // Also remember if we shall check sector CRCs when reading file
        if (dwFlags & MPQ_OPEN_CHECK_SECTOR_CRC)
            ha->dwFlags |= MPQ_FLAG_CHECK_SECTOR_CRC;
    }

    // Find the offset of MPQ header within the file
    if (nError == ERROR_SUCCESS)
    {
        ULONGLONG SearchPos = 0;
        DWORD dwHeaderID;

        while (SearchPos < FileSize)
        {
            DWORD dwBytesAvailable = MPQ_HEADER_SIZE_V4;

            // Cut the bytes available, if needed
            if ((FileSize - SearchPos) < MPQ_HEADER_SIZE_V4)
                dwBytesAvailable = (DWORD)(FileSize - SearchPos);

            // Read the eventual MPQ header
            if (!FileStream_Read(ha->pStream, &SearchPos, ha->HeaderData, dwBytesAvailable))
            {
                nError = GetLastError();
                break;
            }

            // There are AVI files from Warcraft III with 'MPQ' extension.
            if (SearchPos == 0 && IsAviFile(ha->HeaderData))
            {
                nError = ERROR_AVI_FILE;
                break;
            }

            // If there is the MPQ user data signature, process it
            dwHeaderID = BSWAP_INT32_UNSIGNED(*(LPDWORD)ha->HeaderData);
            if (dwHeaderID == ID_MPQ_USERDATA && ha->pUserData == NULL)
            {
                // Ignore the MPQ user data completely if the caller wants to open the MPQ as V1.0
                if ((dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0)
                {
                    // Fill the user data header
                    ha->pUserData = &ha->UserData;
                    memcpy(ha->pUserData, ha->HeaderData, sizeof(TMPQUserData));
                    BSWAP_TMPQUSERDATA(ha->pUserData);

                    // Remember the position of the user data and continue search
                    ha->UserDataPos = SearchPos;
                    SearchPos += ha->pUserData->dwHeaderOffs;
                    continue;
                }
            }

            // There must be MPQ header signature
            if (dwHeaderID == ID_MPQ)
            {
                // Save the position where the MPQ header has been found
                if (ha->pUserData == NULL)
                    ha->UserDataPos = SearchPos;
                ha->pHeader = (TMPQHeader *)ha->HeaderData;
                ha->MpqPos = SearchPos;

                // Now convert the header to version 4
                BSWAP_TMPQHEADER(ha->pHeader);
                ConvertMpqHeaderToFormat4(ha, FileSize, dwFlags);
                break;
            }

            // Move to the next possible offset
            SearchPos += 0x200;
        }

        // If we haven't found MPQ header in the file, it's an error
        if (ha->pHeader == NULL)
            nError = ERROR_BAD_FORMAT;
    }

    // Fix table positions according to format
    if (nError == ERROR_SUCCESS)
    {
        // W3x Map Protectors use the fact that War3's Storm.dll ignores the MPQ user data, 
        // and probably ignores the MPQ format version as well. The trick is to
        // fake MPQ format 2, with an improper hi-word position of hash table and block table
        // We can overcome such protectors by forcing opening the archive as MPQ v 1.0
        if (dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
        {
            ha->pHeader->wFormatVersion = MPQ_FORMAT_VERSION_1;
            ha->pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V1;
            ha->dwFlags |= MPQ_FLAG_READ_ONLY;
            ha->pUserData = NULL;
        }

        // Both MPQ_OPEN_NO_LISTFILE or MPQ_OPEN_NO_ATTRIBUTES trigger read only mode
        if (dwFlags & (MPQ_OPEN_NO_LISTFILE | MPQ_OPEN_NO_ATTRIBUTES))
            ha->dwFlags |= MPQ_FLAG_READ_ONLY;

        // Set the size of file sector
        ha->dwSectorSize = (0x200 << ha->pHeader->wSectorSize);

        // Verify if any of the tables doesn't start beyond the end of the file
        nError = VerifyMpqTablePositions(ha, FileSize);
    }

    // Read the hash table.
    // "interface.MPQ.part" in trial version of World of Warcraft
    // has compressed block table and hash table.
    if (nError == ERROR_SUCCESS)
    {
        //
        // Note: We will not check if the hash table is properly decrypted.
        // Some MPQ protectors corrupt the hash table by rewriting part of it.
        // Hash table, the way how it works, allows arbitrary values for unused entries.
        //

        nError = LoadHashTable(ha);
    }

    // Read Het and Bet tables, if they are present
    if (nError == ERROR_SUCCESS)
    {
        nError = LoadHetAndBetTable(ha);
        if (ha->pHetTable || ha->pBetTable)
            ha->dwFlags |= MPQ_FLAG_READ_ONLY;
    }

    // Now, build the file table. It will be built by combining
    // the block table, hi-block table, (attributes) and (listfile).
    if (nError == ERROR_SUCCESS)
    {
        nError = BuildFileTable(ha, FileSize);
    }

    // Verify the block table, if no kind of protection was detected
    if (nError == ERROR_SUCCESS && (ha->dwFlags & MPQ_FLAG_PROTECTED) == 0)
    {
        TFileEntry * pFileTableEnd = ha->pFileTable + ha->pHeader->dwBlockTableSize;
        TFileEntry * pFileEntry = ha->pFileTable;
//      ULONGLONG ArchiveSize = 0;
        ULONGLONG RawFilePos;

        // Parse all file entries
        for (pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
        {
            // If that file entry is valid, check the file position
            if (pFileEntry->dwFlags & MPQ_FILE_EXISTS)
            {
                // Get the 64-bit file position, 
                // relative to the begin of the file
                RawFilePos = ha->MpqPos + pFileEntry->ByteOffset;

                // Begin of the file must be within range
                if (RawFilePos > FileSize)
                {
                    nError = ERROR_FILE_CORRUPT;
                    break;
                }

                // End of the file must be within range
                RawFilePos += pFileEntry->dwCmpSize;
                if (RawFilePos > FileSize)
                {
                    nError = ERROR_FILE_CORRUPT;
                    break;
                }

                // Also, we remember end of the file
//              if (RawFilePos > ArchiveSize)
//                  ArchiveSize = RawFilePos;
            }
        }
    }

    // Load the "(attributes)" file and merge it to the file table
    if (nError == ERROR_SUCCESS && (dwFlags & MPQ_OPEN_NO_ATTRIBUTES) == 0)
    {
        // Ignore result of the operation. (attributes) is optional.
        SAttrLoadAttributes(ha);
    }

    // Load the internal listfile and include it to the file table
    if (nError == ERROR_SUCCESS && (dwFlags & MPQ_OPEN_NO_LISTFILE) == 0)
    {
        // Ignore result of the operation. (listfile) is optional.
        SFileAddListFile((HANDLE)ha, NULL);
    }

    // Test the indexes from BET and BET table
#ifdef __STORMLIB_TEST__
    if (nError == ERROR_SUCCESS)
    {
        TestNewHashBlockTables(ha);
    }
#endif

    // Cleanup and exit
    if (nError != ERROR_SUCCESS)
    {
        FileStream_Close(pStream);
        FreeMPQArchive(ha);
        SetLastError(nError);
        ha = NULL;
    }

    *phMpq = ha;
    return (nError == ERROR_SUCCESS);
}
示例#4
0
/**
 * \brief Parse the filemd5, filesha1 or filesha256 keyword
 *
 * \param det_ctx pattern matcher thread local data
 * \param str Pointer to the user provided option
 * \param type the hash algorithm
 *
 * \retval hash pointer to DetectFileHashData on success
 * \retval NULL on failure
 */
static DetectFileHashData *DetectFileHashParse (const DetectEngineCtx *de_ctx,
        char *str, uint32_t type)
{
    DetectFileHashData *filehash = NULL;
    FILE *fp = NULL;
    char *filename = NULL;

    /* We have a correct hash algorithm option */
    filehash = SCMalloc(sizeof(DetectFileHashData));
    if (unlikely(filehash == NULL))
        goto error;

    memset(filehash, 0x00, sizeof(DetectFileHashData));

    if (strlen(str) && str[0] == '!') {
        filehash->negated = 1;
        str++;
    }

    if (type == DETECT_FILEMD5) {
        filehash->hash = ROHashInit(18, 16);
    }
    else if (type == DETECT_FILESHA1) {
        filehash->hash = ROHashInit(18, 20);
    }
    else if (type == DETECT_FILESHA256) {
        filehash->hash = ROHashInit(18, 32);
    }

    if (filehash->hash == NULL) {
        goto error;
    }

    /* get full filename */
    filename = DetectLoadCompleteSigPath(de_ctx, str);
    if (filename == NULL) {
        goto error;
    }

    char line[8192] = "";
    fp = fopen(filename, "r");
    if (fp == NULL) {
        SCLogError(SC_ERR_OPENING_RULE_FILE, "opening hash file %s: %s", filename, strerror(errno));
        goto error;
    }

    int line_no = 0;
    while(fgets(line, (int)sizeof(line), fp) != NULL) {
        size_t valid = 0, len = strlen(line);
        line_no++;

        while (strchr(hexcodes, line[valid]) != NULL && valid++ < len);

        /* lines that do not contain sequentially any valid character are ignored */
        if (valid == 0)
            continue;

        /* ignore anything after the sequence of valid characters */
        line[valid] = '\0';

        if (LoadHashTable(filehash->hash, line, filename, line_no, type) != 1) {
            goto error;
        }
    }
    fclose(fp);
    fp = NULL;

    if (ROHashInitFinalize(filehash->hash) != 1) {
        goto error;
    }
    SCLogInfo("Hash hash table size %u bytes%s", ROHashMemorySize(filehash->hash), filehash->negated ? ", negated match" : "");

    SCFree(filename);
    return filehash;

error:
    if (filehash != NULL)
        DetectFileHashFree(filehash);
    if (fp != NULL)
        fclose(fp);
    if (filename != NULL)
        SCFree(filename);
    return NULL;
}