compressdlg.cpp

来自「一些初级的网络编程」· C++ 代码 · 共 1,352 行 · 第 1/3 页

CPP
1,352
字号
			pStubSecHdr++;
		}
		else
		{
			fGevFound = TRUE;
			break;
		}
	}

	if(fGevFound)
	{
		pgev = (GlobalExternalVars*)((DWORD)lpBuf + pStubSecHdr->PointerToRawData);
		
		pgev->dwOEP = dwOldOEP;
		pgev->dwRVAStubEntry = dwRvaStart + dwStubEntryPoint;
		pgev->dwIATAddress = dwOriginalIAT;
		pgev->dwRVACompressedResourceSize = dwNewResourceSize;

		// Copy icon count
		pgev->dwFirstGroupIconCount = gev.dwFirstGroupIconCount;

		// TLS directory stuff
		if(pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress != 0)
		{
			memcpy(&(pgev->tlsOriginal), &(gev.tlsOriginal), sizeof(IMAGE_TLS_DIRECTORY));

			// complicated TLS stuff to fix problems with Delphi 7 apps
			DWORD dwStubOffsetIndex = (DWORD)&pgev->dwAddressOfIndex - (DWORD)lpBuf;
			dwStubOffsetIndex -= dwPointerToStubRawData;
			dwStubOffsetIndex += dwPointerNew;
			dwStubOffsetIndex = OffsetToRVA(dwStubOffsetIndex, lpMapping);

			pgev->tlsOriginal.AddressOfIndex = (DWORD*)(dwStubOffsetIndex + pNtHdr->OptionalHeader.ImageBase);
			//pgev->tlsOriginal.AddressOfIndex = (dwStubOffsetIndex + pNtHdr->OptionalHeader.ImageBase);

			DWORD dwTlsOffset = (DWORD)(&(gev.tlsOriginal)) - (DWORD)(&(gev));
			pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = dwStubRvaStart + (pStubSecHdr->PointerToRawData - dwPointerToStubRawData) + dwTlsOffset;
			pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = sizeof(IMAGE_TLS_DIRECTORY);
		}

		// encrypt gev section
		BYTE* lpbUncompressedBuffer = 0;
		DWORD dwUncompressedSize = 0;
		BYTE* lpbCompressedBuffer = 0;
		DWORD dwCompressedSize = 0;

		lpbUncompressedBuffer = (BYTE*)pgev;
		dwUncompressedSize = (DWORD)&pgev->tlsOriginal - (DWORD)pgev;

		lpbCompressedBuffer = (BYTE*)Compress(lpbUncompressedBuffer, dwUncompressedSize, &dwCompressedSize, 0);

		// clear raw GEV and replace with compressed
		memset(pgev, 0, dwUncompressedSize);
		memcpy(pgev, lpbCompressedBuffer, dwCompressedSize);

		free(lpbCompressedBuffer);
		lpbCompressedBuffer = 0;
	}
	
	// end find gev

	// Write new section to disk
	SetFilePointer(hFile, dwPointerNew, NULL, FILE_BEGIN);
	WriteFile(hFile, ((char*)lpBuf + dwPointerToStubRawData), CalcStubSize(pStubDosHdr), &dwWritten, NULL);

	// truncation
	BYTE* lpbTruncateBuffer = 0;
	DWORD dwTruncateSize = ValidAlignment(CalcStubSize(pStubDosHdr), 0x200) - CalcStubSize(pStubDosHdr);

	lpbTruncateBuffer = (BYTE*)malloc(dwTruncateSize);
	memset(lpbTruncateBuffer, 0, dwTruncateSize);
	WriteFile(hFile, lpbTruncateBuffer, dwTruncateSize, &dwWritten, NULL);

	free(lpbTruncateBuffer);

	// unmap backup
	UnmapViewOfFile(lpBackupMapping);
	CloseHandle(hBackupMapping);	
	CloseHandle(hBackupFile);
	DeleteFile(szTempFile);

	// unmap target
	UnmapViewOfFile(lpMapping);
	CloseHandle(hMapping);	
	SetEndOfFile(hFile);

	//dwOrigSize = dwNewSize;
	dwNewSize = GetFileSize(hFile, 0);

	//printf(" Compressing shrunk from %dk to %dk\n", dwOrigSize/1024, dwNewSize/1024);

	CloseHandle(hFile);

	// Set compsize progress bar
	double fPercent = 0.0;
	fPercent = ((double)(dwNewSize)/(double)(dwOrigSize))*100;
	m_ctrlCompessedSize.SetPos((int)fPercent);	
	m_FileSize.Format("%.02f%%", fPercent);

	UpdateData(FALSE);

	return 0;
}

int CCompressDlg::TranslateAddresses(BYTE* pBuffer, DWORD dwLength, DWORD dwSourceVA, DWORD dwDestinationVA, DWORD dwRVAPage)
{
	// == 0x3F Warning: you should avoid to use this byte in patterns
	#define _XX_  '?' 

	unsigned char PAT_Address[] = { _XX_, _XX_, _XX_, _XX_ };

	DWORD dwAddress = 0;
	BYTE* pOrigBuffer = pBuffer;
	DWORD dwDelta = dwSourceVA - dwDestinationVA;
	DWORD dwMask = 0xffffff00;
	DWORD dwDontCare = 0x0000003f;
	DWORD* pAddress;
	DWORD* pPattern;

	// Setup search pattern
	pPattern = (DWORD*)&PAT_Address;

	// masking need to be figured out more
	*pPattern = ((dwSourceVA & 0xffff0000) | dwRVAPage ) & dwMask;
	*pPattern = *pPattern | (~*pPattern & dwDontCare);

	// Search and replace all addresses in range
	dwAddress = PatternSearch(PAT_Address, sizeof(PAT_Address), pBuffer, dwLength);
				
	while(((int)dwAddress >= 0) && (pBuffer < (pOrigBuffer + dwLength)))
	{
		pAddress = (DWORD*)((DWORD)pBuffer + dwAddress);		
		*pAddress -= dwDelta;

		pBuffer = pBuffer + dwAddress + sizeof(PAT_Address);
		dwAddress = PatternSearch(PAT_Address, sizeof(PAT_Address), pBuffer, dwLength);
	}

	return 0;
}

int CCompressDlg::PatternSearch(unsigned char *SearchString, int StringLen, unsigned char *SearchBuff, int BuffSize)
{
    int i,j;

    if (BuffSize < StringLen) return -64;

    for(i=0;i<(BuffSize-StringLen);i++)
    {
        for(j=0;j<StringLen;j++)
        {
            if (
                 (SearchString[j] != _XX_) &&
                 (SearchString[j] != SearchBuff[i+j])
               )
            break;
        }
        if (j==StringLen) return i;
    }

    return -100;
}

int CCompressDlg::CalcStubSize(PIMAGE_DOS_HEADER pDosHdr)
{
	PIMAGE_NT_HEADERS pNtHdr = 0;
	PIMAGE_SECTION_HEADER pSecHdr = 0;
	LONG lJmp = 0;
	DWORD dwSecStart = 0;
	DWORD dwResult = 0;
	DWORD dwKatSup = 0;
	WORD wNumSections = 0;
	WORD wSizeO = 0;

	lJmp = pDosHdr->e_lfanew;
	dwKatSup = (DWORD)pDosHdr;
	dwKatSup += lJmp;

	pNtHdr = (PIMAGE_NT_HEADERS)dwKatSup;

	wNumSections = pNtHdr->FileHeader.NumberOfSections;
	wSizeO = pNtHdr->FileHeader.SizeOfOptionalHeader;
	
	dwSecStart = (DWORD)pNtHdr;
	dwSecStart += 24;
	dwSecStart += wSizeO;
	
	pSecHdr = (PIMAGE_SECTION_HEADER)dwSecStart;

	dwResult = pSecHdr->SizeOfRawData;
	pSecHdr++;
	dwResult += pSecHdr->SizeOfRawData;
	pSecHdr++;
	dwResult += pSecHdr->SizeOfRawData;

	return dwResult;
}

void CCompressDlg::PerformStubRelocations(LPVOID lpMapping, DWORD dwStubVA)
{
	PIMAGE_DOS_HEADER pDosHdr = 0;
	PIMAGE_NT_HEADERS pNtHdr = 0;
	PIMAGE_BASE_RELOCATION pIBRCurrent = 0;
	PIMAGE_BASE_RELOCATION pIBREnd = 0;
	DWORD dwKatSup = 0;
	LONG lJmp = 0;
	DWORD* pAddress = 0;
	DWORD dwDelta = 0;

	pDosHdr = (PIMAGE_DOS_HEADER) lpMapping;
	lJmp = pDosHdr->e_lfanew;
	dwKatSup = (DWORD)pDosHdr;
	dwKatSup += lJmp;

	pNtHdr = (PIMAGE_NT_HEADERS)dwKatSup;

	if(pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0)
	{
		pIBRCurrent = (PIMAGE_BASE_RELOCATION)RVAToMappedOffset((DWORD)pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, lpMapping);
		pIBREnd = (PIMAGE_BASE_RELOCATION)&((BYTE*)pIBRCurrent)[pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size];

		while((pIBRCurrent<pIBREnd) && (pIBRCurrent->VirtualAddress != 0))
		{
			DWORD dwRVAPage = pIBRCurrent->VirtualAddress;
			DWORD dwRelocation = 0;
			DWORD dwSectionOffset = 0;
			DWORD dwVirtualAddress = 0; 
			DWORD dwRelocationCount = (pIBRCurrent->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / sizeof(WORD);
			WORD* awRelType = (WORD*)((BYTE*)pIBRCurrent + IMAGE_SIZEOF_BASE_RELOCATION);

			for(DWORD dw=0; dw<dwRelocationCount; ++dw)
			{
				WORD wType = awRelType[dw] >> 12;
				WORD wValue = awRelType[dw] & 0x0fff;

				if(wType == IMAGE_REL_BASED_HIGHLOW)
				{
					dwRelocation = dwRVAPage + wValue;
					pAddress = (DWORD*)RVAToMappedOffset(dwRelocation, lpMapping);

					DWORD dwTempAddress = (*pAddress) & 0x0000ffff;
					dwSectionOffset = RVAToSectionRawDataSize(dwTempAddress, lpMapping);
					dwVirtualAddress = RVAToSectionVirtualAddress(dwTempAddress, lpMapping);
					dwDelta = (dwStubVA + dwSectionOffset) - (pNtHdr->OptionalHeader.ImageBase + dwVirtualAddress);
					
					*pAddress = *pAddress + dwDelta;
				}

				pIBRCurrent = (PIMAGE_BASE_RELOCATION)&((BYTE*)pIBRCurrent)[pIBRCurrent->SizeOfBlock];
			}
		}
	}
}

void CCompressDlg::CompressSections(LPVOID lpMapping, LPVOID lpBackup)
{
	PIMAGE_DOS_HEADER pDosHdr = 0;
	PIMAGE_NT_HEADERS pNtHdr = 0;
	PIMAGE_SECTION_HEADER pSecHdr = 0;
	DWORD dwSecStart = 0;
	DWORD dwKatSup = 0;
	DWORD dwBytesWritten = 0;
	LONG lJmp = 0;
	WORD wNumSections = 0;
	WORD wSizeO = 0;

	PIMAGE_DOS_HEADER pBackupDosHdr = 0;
	PIMAGE_NT_HEADERS pBackupNtHdr = 0;
	PIMAGE_SECTION_HEADER pBackupSecHdr = 0;
	DWORD dwBackupSecStart = 0;
	DWORD dwBackupKatSup = 0;
	LONG lBackupJmp = 0;
	WORD wBackupNumSections = 0;
	WORD wBackupSizeO = 0;

	BYTE* lpbBuffer = 0;
	DWORD dwBufferSize = 0;
	DWORD dwBufferPos = 0;
	int i = 0;

	DWORD dwTempPointerToRawData = 0;
	bool bResource;
	BYTE* lpbNewResourceSection = 0;

	bool bSkipedZeroSizeSection;
	bool bBigger = false;

	pDosHdr = (PIMAGE_DOS_HEADER) lpMapping;
	lJmp = pDosHdr->e_lfanew;
	dwKatSup = (DWORD)pDosHdr;
	dwKatSup += lJmp;

	pNtHdr = (PIMAGE_NT_HEADERS)dwKatSup;

	wNumSections = pNtHdr->FileHeader.NumberOfSections;
	wSizeO = pNtHdr->FileHeader.SizeOfOptionalHeader;

	dwSecStart = (DWORD)pNtHdr;
	dwSecStart += 24;
	dwSecStart += wSizeO;

	pBackupDosHdr = (PIMAGE_DOS_HEADER) lpBackup;
	lBackupJmp = pBackupDosHdr->e_lfanew;
	dwBackupKatSup = (DWORD)pBackupDosHdr;
	dwBackupKatSup += lBackupJmp;

	pBackupNtHdr = (PIMAGE_NT_HEADERS)dwBackupKatSup;

	wBackupNumSections = pBackupNtHdr->FileHeader.NumberOfSections;
	wBackupSizeO = pBackupNtHdr->FileHeader.SizeOfOptionalHeader;

	dwBackupSecStart = (DWORD)pBackupNtHdr;
	dwBackupSecStart += 24;
	dwBackupSecStart += wBackupSizeO;

	// TLS directory stuff
	
	if(pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress != 0)
	{
		PIMAGE_TLS_DIRECTORY tlsOriginal = 0;
		tlsOriginal = (PIMAGE_TLS_DIRECTORY)RVAToMappedOffset((DWORD)pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress, lpMapping);

		// Copy original and blank original
		memcpy(&(gev.tlsOriginal), tlsOriginal, sizeof(IMAGE_TLS_DIRECTORY));
		memset(tlsOriginal, 0, sizeof(IMAGE_TLS_DIRECTORY));
	}

	DWORD dwTempSize = 0;
	
	m_ProgressFileSize = 0;
	m_ProgressOffset = 0;

	for(i = 0; i < wNumSections-1; i++)
	{
		pSecHdr = (PIMAGE_SECTION_HEADER)dwSecStart;

		m_ProgressFileSize += pSecHdr->Misc.VirtualSize;

		// move to next section header
		dwSecStart += sizeof(IMAGE_SECTION_HEADER);
	}

	dwSecStart = (DWORD)pNtHdr;
	dwSecStart += 24;
	dwSecStart += wSizeO;

	for(i = 0; i < wNumSections; i++)
	{
		// Reset resource flag
		bResource = false;

		pSecHdr = (PIMAGE_SECTION_HEADER)dwSecStart;
		pBackupSecHdr = (PIMAGE_SECTION_HEADER)dwBackupSecStart;

		if(strcmp((char*)pBackupSecHdr->Name, ".rsrc") == 0)
		{
			// we are at resource section
			bResource = true;
		}

		// skip sections with raw size = 0
		if(pBackupSecHdr->SizeOfRawData == 0)
		{		
			// move to next section header
			dwSecStart += sizeof(IMAGE_SECTION_HEADER);
			pBackupSecHdr += sizeof(IMAGE_SECTION_HEADER);
			bSkipedZeroSizeSection = true;
			continue;
		}

		BYTE* lpbUncompressedBuffer = 0;
		DWORD dwUncompressedSize = 0;
		BYTE* lpbCompressedBuffer = 0;
		DWORD dwCompressedSize = 0;

		lpbUncompressedBuffer = (BYTE*)((DWORD)lpBackup + pBackupSecHdr->PointerToRawData);
		dwUncompressedSize = pBackupSecHdr->SizeOfRawData;

		if(bResource)
		{
			lpbNewResourceSection = (BYTE*)BuildNewResourceSection(lpBackup, &dwNewResourceSize);

			// This is the resource section, so skip the directory and only compress the data afterwards
			lpbUncompressedBuffer = (BYTE*)((DWORD)lpBackup + pBackupSecHdr->PointerToRawData);
			dwUncompressedSize = pBackupSecHdr->SizeOfRawData;
		}

		lpbCompressedBuffer = (BYTE*)Compress(lpbUncompressedBuffer, dwUncompressedSize, &dwCompressedSize, &CallbackFunc);

		double fPercent = ((double)dwCompressedSize/(double)dwUncompressedSize) * 100;

		//printf("\r %s %.1f%% (comp: %d, uncomp: %d)\n", pSecHdr->Name, fPercent, dwCompressedSize, pSecHdr->SizeOfRawData);
		
		// copy compressed buffer into original mapped file
		DWORD dwNewAlignedSectionSize = ValidAlignment(dwCompressedSize, 0x200);
		BYTE* lpbNewSectionBuffer = (BYTE*)malloc(dwNewAlignedSectionSize);
		memset(lpbNewSectionBuffer, 0, dwNewAlignedSectionSize);
		memcpy(lpbNewSectionBuffer, lpbCompressedBuffer, dwCompressedSize);


		if(i==0)
		{
			memcpy((LPVOID)((DWORD)lpMapping + pBackupSecHdr->PointerToRawData), lpbNewSectionBuffer, dwNewAlignedSectionSize);
			pSecHdr->SizeOfRawData = dwNewAlignedSectionSize;
		}
		else
		{
			if(bResource && lpbNewResourceSection)
			{
				memcpy((LPVOID)((DWORD)lpMapping + dwTempPointerToRawData), lpbNewResourceSection, dwNewResourceSize);
				pSecHdr->PointerToRawData = dwTempPointerToRawData;
				
				dwTempPointerToRawData += dwNewResourceSize;
				memcpy((LPVOID)((DWORD)lpMapping + dwTempPointerToRawData), lpbNewSectionBuffer, dwNewAlignedSectionSize);

				pSecHdr->SizeOfRawData = dwNewResourceSize + dwNewAlignedSectionSize;

				free(lpbNewResourceSection);
			}
			else
			{
				memcpy((LPVOID)((DWORD)lpMapping + dwTempPointerToRawData), lpbNewSectionBuffer, dwNewAlignedSectionSize);
				//pSecHdr->PointerToRawData = dwTempPointerToRawData;
				pSecHdr->PointerToRawData = dwTempPointerToRawData;

				// correct pointer to raw data if we skipped a zero size section
				if(bSkipedZeroSizeSection == true)
				{
					PIMAGE_SECTION_HEADER pLastSecHdr = pSecHdr;
					pLastSecHdr--;

					pLastSecHdr->PointerToRawData = dwTempPointerToRawData;

					bSkipedZeroSizeSection = false;
				}

				pSecHdr->SizeOfRawData = dwNewAlignedSectionSize;
			}
		}

		dwTempPointerToRawData = pSecHdr->PointerToRawData + pSecHdr->SizeOfRawData;

		free(lpbNewSectionBuffer);
		free(lpbCompressedBuffer);

		// Set VSize = RSize
		pSecHdr->Misc.VirtualSize = ValidAlignment(pSecHdr->Misc.VirtualSize, 0x1000);

		m_ProgressOffset += pSecHdr->Misc.VirtualSize;

		// move to next section header

⌨️ 快捷键说明

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