📄 tnamebreakerdlg2.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 + -