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

📄 tnamebreakerdlg2.cpp

📁 mpq文件的格式就是一种压缩格式
💻 CPP
字号:
/*****************************************************************************/
/* TNameBreakerDlg2.cpp                   Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Dialog for brute-force name detecting - Working thread part               */
/*---------------------------------------------------------------------------*/
/*   Date    Ver   Who  Comment                                              */
/* --------  ----  ---  -------                                              */
/* 12.04.03  1.00  Lad  The first version of TNameBreakerDlg.cpp             */
/*****************************************************************************/

#include "stdafx.h"
#include "TNameBreakerDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//-----------------------------------------------------------------------------
// Defines

#define FIRST_TRIED_CHAR '0'
//#define FIRST_TRIED_CHAR 'A'
#define LAST_TRIED_CHAR  '_'

//-----------------------------------------------------------------------------
// Name breaking functions

DWORD TNameBreakerDlg::StormBuffer[STORM_BUFFER_SIZE];
BOOL  TNameBreakerDlg::m_bInitialized = FALSE;

// This table contains the increments for each character
BYTE IncChar[256] = 
{
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0x00 - 0x0F */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0x10 - 0x1F */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,     /* 0x20 - 0x2F */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1,     /* 0x30 - 0x3F */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0x40 - 0x4F */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1,     /* 0x50 - 0x5F */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0x60 - 0x6F */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0x70 - 0x7F */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0x80 - 0x8F */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0x90 - 0x9F */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0xA0 - 0xAF */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0xB0 - 0xBF */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0xC0 - 0xCF */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0xD0 - 0xDF */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 0xE0 - 0xEF */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1      /* 0xF0 - 0xFF */
};
/*
// This table contains the assignment for each character
BYTE NextChar[256] = 
{
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  // 0x00 - 0x0F
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,  // 0x10 - 0x1F
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,  // 0x20 - 0x2F
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,  // 0x30 - 0x3F
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,  // 0x40 - 0x4F
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,  // 0x50 - 0x5F
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,  // 0x60 - 0x6F
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,  // 0x70 - 0x7F
    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,  // 0x80 - 0x8F
    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,  // 0x90 - 0x9F
    0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,  // 0xA0 - 0xAF
    0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,  // 0xB0 - 0xBF
    0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,  // 0xC0 - 0xCF
    0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,  // 0xD0 - 0xDF
    0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,  // 0xE0 - 0xEF
    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,  // 0xF0 - 0xFF
};
*/
#define DECRYPT_SEEDS(szText, seed1, seed2, SB)             \
dwSeed1 = seed1;                                            \
dwSeed2 = seed2;                                            \
pbKey   = (BYTE *)szText;                                   \
                                                            \
while(*pbKey != 0)                                          \
{                                                           \
    ch = *pbKey++;                                          \
                                                            \
    dwSeed1 = SB[ch] ^ (dwSeed1 + dwSeed2);                 \
    dwSeed2 = ch + dwSeed1 + dwSeed2 + (dwSeed2 << 5) + 3;  \
}

int TNameBreakerDlg::PrepareStormBuffer()
{
    DWORD dwSeed = 0x00100001;
    DWORD index1 = 0;
    DWORD index2 = 0;
    int   i;

    // If already prepared, do nothing
    if(m_bInitialized == FALSE)
    {
        // Initialize the decryption buffer
        for(index1 = 0; index1 < 0x100; index1++)
        {
            for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
            {
                DWORD temp1, temp2;

                dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB;
                temp1  = (dwSeed & 0xFFFF) << 0x10;

                dwSeed = (dwSeed * 125 + 3) % 0x2AAAAB;
                temp2  = (dwSeed & 0xFFFF);

                StormBuffer[index2] = (temp1 | temp2);
            }
        }
        m_bInitialized = TRUE;
    }
    return ERROR_SUCCESS;
}


// Brute-force algorithm for decrypting the file names
int TNameBreakerDlg::DecryptFileName(char * szFileName,
        char * pchFirstNameChar, int nNameLength, int nMaxNameLength,
        char * szExts, int nExts)
{
    TMPQHash * pHash = NULL;
    DWORD * pdwStormBuffer000 = StormBuffer + 0x000;
    DWORD * pdwStormBuffer100 = StormBuffer + 0x100;
    DWORD * pdwStormBuffer200 = StormBuffer + 0x200;
    char * pchLastNameChar = pchFirstNameChar;
    DWORD dwHashIndexMask = m_dwHashIndexMask;
    DWORD dwSeed1HTI = 0x7FED7FED;  // Seed 1 for the hash index
    DWORD dwSeed2HTI = 0xEEEEEEEE;  // Seed 2 for the hash index
    DWORD dwSeed1CN1 = 0x7FED7FED;  // Seed 1 for the CodeName1
    DWORD dwSeed2CN1 = 0xEEEEEEEE;  // Seed 2 for the CodeName1
    DWORD dwSeed1CN2 = 0x7FED7FED;  // Seed 1 for the CodeName2
    DWORD dwSeed2CN2 = 0xEEEEEEEE;  // Seed 2 for the CodeName2
    DWORD dwSeed1;
    DWORD dwSeed2;
    BYTE * pbKey;
    int    chSaveChar;
    int    ch;

    // Initial prepare the file name and add table
    IncChar[LAST_TRIED_CHAR] = (BYTE)(FIRST_TRIED_CHAR - LAST_TRIED_CHAR);
    IncChar[0]   = FIRST_TRIED_CHAR;
    IncChar['.'] = FIRST_TRIED_CHAR - '.';

    // Skip '4', '5', '6', '7', '8', '9'.
//  IncChar['3'] = 'A' - '3';

    // If no name entered, initialize it to the first tried char
    if(nNameLength <= 1 || *pchFirstNameChar == 0)
    {
        *pchFirstNameChar = FIRST_TRIED_CHAR;
        nNameLength = 1;
    }

    // Temporarily cut the file name
    chSaveChar = *pchFirstNameChar;
    *pchFirstNameChar = 0;

    // Pre-decrypt the hash index
    DECRYPT_SEEDS(szFileName, dwSeed1HTI, dwSeed2HTI, pdwStormBuffer000);
    dwSeed1HTI = dwSeed1;
    dwSeed2HTI = dwSeed2;

    // Pre-decrypt the first codename
    DECRYPT_SEEDS(szFileName, dwSeed1CN1, dwSeed2CN1, pdwStormBuffer100);
    dwSeed1CN1 = dwSeed1;
    dwSeed2CN1 = dwSeed2;

    // Pre-decrypt the second codename
    DECRYPT_SEEDS(szFileName, dwSeed1CN2, dwSeed2CN2, pdwStormBuffer200);
    dwSeed1CN2 = dwSeed1;
    dwSeed2CN2 = dwSeed2;

    // Return the file name back
    *pchFirstNameChar = (char)chSaveChar;
    pchLastNameChar = pchFirstNameChar + nNameLength;

    // For all name combinations. Do at least one test
    do
    {
        char * pchHelper;
        char * szExt = szExts;
        char * pchExt;
        int    nExt;

        // Do for all extensions
        for(nExt = 0, pchExt = szExt; nExt < nExts; nExt++, pchExt += 8)
        {
            pchHelper = pchLastNameChar;
            *pchHelper++ = (char)((*pchExt != 0) ? '.' : 0);
            *(DWORD *)pchHelper = *(DWORD *)pchExt;

            // Decode hash index. Then test the dwName1 and dwName2
            DECRYPT_SEEDS(pchFirstNameChar, dwSeed1HTI, dwSeed2HTI, pdwStormBuffer000);

            // Get the first hash entry which can hold the name
            pHash = m_pHashTable + (dwSeed1 & dwHashIndexMask);
            if(pHash->dwName1 != 0xFFFFFFFF)
            {
                DWORD dwCodeName1;

                // Decrypt the first name seed and compare it to the CodeName1
                DECRYPT_SEEDS(pchFirstNameChar, dwSeed1CN1, dwSeed2CN1, pdwStormBuffer100);
                dwCodeName1 = dwSeed1;

                while(pHash->dwName1 != 0xFFFFFFFF)
                {
                    if(pHash->dwName1 == dwCodeName1)
                    {
                        DECRYPT_SEEDS(pchFirstNameChar, dwSeed1CN2, dwSeed2CN2, pdwStormBuffer200);
                        if(dwSeed1 == pHash->dwName2)
                        {
                            DWORD dwName1 = pHash->dwName1;
                            DWORD dwName2 = pHash->dwName2;

                            // Do for all language versions of the file
                            while(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2)
                            {
                                if(pHash->dwBlockIndex != 0xFFFFFFFE)
                                    SendMessage(WM_NAMEFOUND, pHash->dwBlockIndex, (LPARAM)szFileName);
                                
                                pHash++;
                                if(pHash >= m_pHashEnd)
                                    pHash = m_pHashTable;
                            }
                            break;
                        }
                    }

                    // Move to the next hash table entry
                    pHash++;
                    if(pHash >= m_pHashEnd)
                        pHash = m_pHashTable;
                }
            }
        }

        // If one name only, break the loop
        if(m_dto.bThisOnly)
            break;

        // Move to the next file name
        _asm
        {
            // Prepare registers
            mov     ecx, pchLastNameChar;   // ECX contains the address of the current char
            xor     eax, eax;               // EAX contains one character
        __IncName:
            dec     ecx;                    // Move one byte back
            mov     al, byte ptr [ecx];     // Get the character from there
            add     al, [IncChar + EAX];    // Move to the nect character
            mov     byte ptr [ecx], al;     // Store the character to the text
            jnc     __EndIncName            // If no overflow, get out of the loop

            // Increment previous character
            cmp     ecx, pchFirstNameChar;  // Are we BEFORE begin ?
            ja      __IncName;              // Not yet => just go to prev character

            // Now we have to increment the name length ...
            inc     dword ptr pchLastNameChar;
            inc     dword ptr nNameLength;
            
            // ... and fill the new name with the first tried char
            mov     al, FIRST_TRIED_CHAR;   // Init the name with first tried chars
        __FillName:
            mov     byte ptr [ecx], al;     // Store one char
            inc     ecx;                    // Move to the next char
            cmp     ecx, pchLastNameChar;   // Are we at the end ?
            jb      __FillName;             // Not yet => continue

        __EndIncName:
        }
/*
        *pchLastNameChar = 0;
        
        _asm
        {
            // Increment the name
            xor   eax, eax;
            mov   ecx, pchFirstNameChar
        __IncNextChar:
            mov   al, byte ptr [ecx];           // Current character
            add   al, byte ptr [IncChar + eax]; // Increment character
            mov   byte ptr [ecx], al            // Store the character back
            jnc   __EndLoop;                    // If no shift to net char, end loop
            inc   ecx;                          // Increment the current character    
            jmp   __IncNextChar;                // Do again
        __EndLoop:

            // Increment the name length, if necessary
            cmp   eax, 1;                       // If we have increased the name length
            mov   al, byte ptr [NextChar + eax];// Will change 0x01 to FIRST_TRIED_CHAR, other unchanged
            mov   byte ptr [ecx], al            // Store the character
            sete  al;                           // If there was 0x01, set EAX to 1, otherwise to 0
            add   pchLastNameChar, eax          // Add to last name char
            add   nNameLength, eax              // Add to name length
        }
*/
    }
    while(nNameLength <= nMaxNameLength);

    return ERROR_SUCCESS;
}

int TNameBreakerDlg::DecryptThread()
{
    POSITION pos;
    int nError = ERROR_CAN_NOT_COMPLETE;

    // Initialize storm buffer
    PrepareStormBuffer();

    // Go through all folders
    for(pos = m_dto.pFolderList->GetHeadPosition(); pos != NULL; )
    {
        char * szFolder = (char *)m_dto.pFolderList->GetNext(pos);

        strcpy(m_dto.szFileName, szFolder);
        strcat(m_dto.szFileName, m_dto.szStartName);
        strupr(m_dto.szFileName);

        m_dto.pchFilePos = m_dto.szFileName + strlen(szFolder);
        nError = DecryptFileName(m_dto.szFileName, m_dto.pchFilePos, m_dto.nNameLength, m_dto.nMaxNameLength, m_dto.szExts, m_dto.nExts);

        // Reset the start name
        if(m_dto.bThisOnly == FALSE)
        {
            memset(m_dto.szStartName, 0, sizeof(m_dto.szStartName));
            m_dto.szStartName[0] = FIRST_TRIED_CHAR;
            m_dto.nNameLength = 1;
        }
    }

    // Notify the UI thread about finished work
    ::PostMessage(m_hWnd, WM_WORKCOMPLETE, m_dto.nIndex, ERROR_SUCCESS);
    return 0;
}


DWORD WINAPI TNameBreakerDlg::DecryptThread(LPVOID lpParam)
{
    TNameBreakerDlg * pThis = (TNameBreakerDlg *)lpParam;
    return pThis->DecryptThread();
}

⌨️ 快捷键说明

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