mirror of
https://github.com/dashr9230/SA-MP.git
synced 2024-12-22 14:37:29 +08:00
[arctool2] Add archive tool
This commit is contained in:
parent
16f92725a7
commit
a630a523e1
454
arctool2/ArchiveBuilder.cpp
Normal file
454
arctool2/ArchiveBuilder.cpp
Normal file
@ -0,0 +1,454 @@
|
|||||||
|
|
||||||
|
#include "ArchiveBuilder.h"
|
||||||
|
|
||||||
|
#include "../saco/archive/CryptoContext.h"
|
||||||
|
#include "../saco/archive/KeyPair.h"
|
||||||
|
#include "../saco/archive/Signer.h"
|
||||||
|
#include "../saco/archive/Hasher.h"
|
||||||
|
#include "../saco/archive/TinyEncrypt.h"
|
||||||
|
#include "../saco/archive/Obfuscator.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define DO_ENCRYPT
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
DWORD CArchiveBuilder::ms_dwHashInit = OBFUSCATE_DATA(0x9E3779B9);
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
CArchiveBuilder::CArchiveBuilder(void)
|
||||||
|
{
|
||||||
|
m_dwNumEntries = SAA_MAX_ENTRIES;
|
||||||
|
m_dwFDSize = SAA_MAX_FAKEDATA;
|
||||||
|
m_bProperHeader = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
CArchiveBuilder::CArchiveBuilder(DWORD dwNumEntries, DWORD dwFDSize, BOOL bProperHeader)
|
||||||
|
{
|
||||||
|
m_dwNumEntries = dwNumEntries;
|
||||||
|
m_dwFDSize = dwFDSize;
|
||||||
|
m_bProperHeader = bProperHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
CArchiveBuilder::~CArchiveBuilder(void)
|
||||||
|
{
|
||||||
|
if (!m_vecEntries.empty()) {
|
||||||
|
EntryMemStateVector_t::iterator it = m_vecEntries.begin();
|
||||||
|
while(it != m_vecEntries.end()) {
|
||||||
|
AB_ENTRY_MEMSTATE* pEntry = (*it);
|
||||||
|
fclose(pEntry->fiFile);
|
||||||
|
delete pEntry;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
DWORD CArchiveBuilder::HashString(PCHAR szString)
|
||||||
|
{
|
||||||
|
// This is an implementation of the Jenkins hash
|
||||||
|
|
||||||
|
# define mix(a,b,c) \
|
||||||
|
{ \
|
||||||
|
a -= b; a -= c; a ^= (c>>13); \
|
||||||
|
b -= c; b -= a; b ^= (a<<8); \
|
||||||
|
c -= a; c -= b; c ^= (b>>13); \
|
||||||
|
a -= b; a -= c; a ^= (c>>12); \
|
||||||
|
b -= c; b -= a; b ^= (a<<16); \
|
||||||
|
c -= a; c -= b; c ^= (b>>5); \
|
||||||
|
a -= b; a -= c; a ^= (c>>3); \
|
||||||
|
b -= c; b -= a; b ^= (a<<10); \
|
||||||
|
c -= a; c -= b; c ^= (b>>15); \
|
||||||
|
}
|
||||||
|
|
||||||
|
register BYTE* k = (BYTE*)szString;
|
||||||
|
register DWORD initval = 0x12345678;
|
||||||
|
register DWORD length;
|
||||||
|
|
||||||
|
length = (DWORD)strlen(szString);
|
||||||
|
|
||||||
|
register DWORD a,b,c,len;
|
||||||
|
|
||||||
|
/* Set up the internal state */
|
||||||
|
len = length;
|
||||||
|
a = b = UNOBFUSCATE_DATA(ms_dwHashInit); /* the golden ratio; an arbitrary value */
|
||||||
|
c = initval; /* the previous hash value */
|
||||||
|
|
||||||
|
/*---------------------------------------- handle most of the key */
|
||||||
|
while (len >= 12)
|
||||||
|
{
|
||||||
|
a += (k[0] +((DWORD)k[1]<<8) +((DWORD)k[2]<<16) +((DWORD)k[3]<<24));
|
||||||
|
b += (k[4] +((DWORD)k[5]<<8) +((DWORD)k[6]<<16) +((DWORD)k[7]<<24));
|
||||||
|
c += (k[8] +((DWORD)k[9]<<8) +((DWORD)k[10]<<16)+((DWORD)k[11]<<24));
|
||||||
|
mix(a,b,c);
|
||||||
|
k += 12; len -= 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------- handle the last 11 bytes */
|
||||||
|
c += length;
|
||||||
|
switch(len) /* all the case statements fall through */
|
||||||
|
{
|
||||||
|
case 11: c+=((DWORD)k[10]<<24);
|
||||||
|
case 10: c+=((DWORD)k[9]<<16);
|
||||||
|
case 9 : c+=((DWORD)k[8]<<8);
|
||||||
|
/* the first byte of c is reserved for the length */
|
||||||
|
case 8 : b+=((DWORD)k[7]<<24);
|
||||||
|
case 7 : b+=((DWORD)k[6]<<16);
|
||||||
|
case 6 : b+=((DWORD)k[5]<<8);
|
||||||
|
case 5 : b+=k[4];
|
||||||
|
case 4 : a+=((DWORD)k[3]<<24);
|
||||||
|
case 3 : a+=((DWORD)k[2]<<16);
|
||||||
|
case 2 : a+=((DWORD)k[1]<<8);
|
||||||
|
case 1 : a+=k[0];
|
||||||
|
/* case 0: nothing left to add */
|
||||||
|
}
|
||||||
|
mix(a,b,c);
|
||||||
|
/*-------------------------------------------- report the result */
|
||||||
|
return c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
PCHAR CArchiveBuilder::ExtractFileName(PCHAR szString)
|
||||||
|
{
|
||||||
|
DWORD dwOffset = (DWORD)strlen(szString);
|
||||||
|
while((dwOffset > 0) && (szString[dwOffset] != '\\'))
|
||||||
|
dwOffset--;
|
||||||
|
if (dwOffset == 0)
|
||||||
|
return szString;
|
||||||
|
else
|
||||||
|
return szString+dwOffset+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
DWORD CArchiveBuilder::AddFile(PCHAR szFileName)
|
||||||
|
{
|
||||||
|
|
||||||
|
AB_ENTRY_MEMSTATE* pEntry = new AB_ENTRY_MEMSTATE();
|
||||||
|
|
||||||
|
PCHAR szNameOnly = ExtractFileName(szFileName);
|
||||||
|
if ((strlen(szNameOnly)+1) > sizeof(pEntry->szFileName))
|
||||||
|
throw "Internal Error: Not enough memory allocated for the length of the filename.";
|
||||||
|
|
||||||
|
strcpy(pEntry->szFileName, szNameOnly);
|
||||||
|
_strlwr(pEntry->szFileName);
|
||||||
|
pEntry->dwFileNameHash = HashString(pEntry->szFileName);
|
||||||
|
|
||||||
|
FILE* fiFile;
|
||||||
|
fiFile = fopen(szFileName, "rb");
|
||||||
|
if (!fiFile)
|
||||||
|
throw "Could not load archive data file.";
|
||||||
|
|
||||||
|
pEntry->fiFile = fiFile;
|
||||||
|
|
||||||
|
fseek(fiFile, 0, SEEK_END);
|
||||||
|
pEntry->dwFileSize = (DWORD)ftell(fiFile);
|
||||||
|
|
||||||
|
fseek(fiFile, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (pEntry->dwFileSize > 16*1024*1024)
|
||||||
|
throw "Archive data file is greater than 16MB.";
|
||||||
|
|
||||||
|
m_vecEntries.push_back(pEntry);
|
||||||
|
|
||||||
|
return pEntry->dwFileNameHash;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
void CArchiveBuilder::BuildEntryTable(SAA_ENTRY *pEntryTable, DWORD dwInvalidIndex)
|
||||||
|
{
|
||||||
|
CCryptoContext context;
|
||||||
|
BOOL* pbEntryUsed;
|
||||||
|
|
||||||
|
EntryMemStateVector_t::iterator it;
|
||||||
|
DWORD dwIndex;
|
||||||
|
AB_ENTRY_MEMSTATE* pEntry;
|
||||||
|
|
||||||
|
// Create some stuff to make things simple
|
||||||
|
pbEntryUsed = new BOOL[m_dwNumEntries];
|
||||||
|
memset(pbEntryUsed, 0, sizeof(BOOL)*m_dwNumEntries);
|
||||||
|
|
||||||
|
// Make the entire table's data random
|
||||||
|
context.GenerateRandom(m_dwNumEntries*sizeof(SAA_ENTRY), reinterpret_cast<BYTE*>(pEntryTable));
|
||||||
|
|
||||||
|
// Ensure that there are no hash collisions between whats in the entry table and our files
|
||||||
|
BOOL bCollision = FALSE;
|
||||||
|
for(DWORD i=0; i<m_dwNumEntries; i++) {
|
||||||
|
|
||||||
|
it = m_vecEntries.begin();
|
||||||
|
while(it != m_vecEntries.end()) {
|
||||||
|
pEntry = (*it);
|
||||||
|
|
||||||
|
if (pEntryTable[i].dwFileNameHash == pEntry->dwFileNameHash) {
|
||||||
|
pEntryTable[i].dwFileNameHash = GetRandom();
|
||||||
|
bCollision = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bCollision) {
|
||||||
|
bCollision = FALSE;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Ver1: Set all the invalid entries to the invalid index
|
||||||
|
for(DWORD i=0; i<m_dwNumEntries; i++) {
|
||||||
|
pEntryTable[i].dwPrevEntry = dwInvalidIndex;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Ver2: Set all the invalid entries to itself, use the invalid index for the first entry instead
|
||||||
|
for(DWORD i=0; i<m_dwNumEntries; i++) {
|
||||||
|
pEntryTable[i].dwPrevEntry = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Randomly place our loaded entries into the entry table
|
||||||
|
it = m_vecEntries.begin();
|
||||||
|
while(it != m_vecEntries.end()) {
|
||||||
|
pEntry = (*it);
|
||||||
|
|
||||||
|
// Generate a random value that works for us
|
||||||
|
while(1) {
|
||||||
|
dwIndex = (GetRandom() >> 5) & 0xFF; // Take it from the middle!
|
||||||
|
dwIndex %= m_dwNumEntries;
|
||||||
|
|
||||||
|
// Check if it matches our reserved index for invalid files
|
||||||
|
if (dwIndex == dwInvalidIndex)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check to see if any existing entries have this index
|
||||||
|
if (pbEntryUsed[dwIndex])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pbEntryUsed[dwIndex] = true;
|
||||||
|
|
||||||
|
pEntry->pEntry = &(pEntryTable[dwIndex]);
|
||||||
|
pEntry->dwEntryTableOffset = dwIndex;
|
||||||
|
pEntry->pbTEAKey = reinterpret_cast<BYTE*>(pEntryTable) +
|
||||||
|
(pEntry->dwFileNameHash % (sizeof(SAA_ENTRY)*m_dwNumEntries-TEA_KEY_SIZE));
|
||||||
|
|
||||||
|
pEntry->pEntry->dwFileNameHash = pEntry->dwFileNameHash;
|
||||||
|
pEntry->pEntry->dwFileSize = pEntry->dwFileSize;
|
||||||
|
|
||||||
|
if (it == m_vecEntries.begin()) {
|
||||||
|
// Ver2: Set the first index to the invalid index
|
||||||
|
pEntry->pEntry->dwPrevEntry = dwInvalidIndex;
|
||||||
|
} else {
|
||||||
|
pEntry->pEntry->dwPrevEntry = (*(it-1))->dwEntryTableOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Ver1:
|
||||||
|
// Process the first entry finally and set its previous index to
|
||||||
|
// an invalid entry, but not to our invalid index
|
||||||
|
it = m_vecEntries.begin();
|
||||||
|
while(1) {
|
||||||
|
dwIndex = (GetRandom() >> 5) & 0xFF; // Take it from the middle!
|
||||||
|
|
||||||
|
// Check if it matches our reserved index for invalid files
|
||||||
|
if (dwIndex == dwInvalidIndex)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check to see if any existing entries have this index
|
||||||
|
if (pbEntryUsed[dwIndex])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(*it)->pEntry->dwPrevEntry = dwIndex;
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Now obfuscate the non-hash part of all our entries
|
||||||
|
// XOR it with the hash for good measure.
|
||||||
|
for(DWORD i=0; i<m_dwNumEntries; i++) {
|
||||||
|
pEntryTable[i].dwDataBlock ^= pEntryTable[i].dwFileNameHash;
|
||||||
|
pEntryTable[i].dwDataBlock = OBFUSCATE_DATA(pEntryTable[i].dwDataBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
DWORD CArchiveBuilder::GetRandom()
|
||||||
|
{
|
||||||
|
static BOOL bSeeded = FALSE;
|
||||||
|
if (!bSeeded) {
|
||||||
|
srand((DWORD)time(NULL));
|
||||||
|
bSeeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD dwRandom;
|
||||||
|
|
||||||
|
dwRandom = rand();
|
||||||
|
dwRandom <<= 15;
|
||||||
|
dwRandom ^= rand();
|
||||||
|
dwRandom <<= 15;
|
||||||
|
dwRandom ^= rand();
|
||||||
|
|
||||||
|
return dwRandom;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
void CArchiveBuilder::BuildHeader(SAA_FILE_HEADER* pFileHeader)
|
||||||
|
{
|
||||||
|
CCryptoContext context;
|
||||||
|
|
||||||
|
context.GenerateRandom(pFileHeader->SizeOf(), reinterpret_cast<BYTE*>(pFileHeader));
|
||||||
|
|
||||||
|
pFileHeader->dwFakeDataSize = this->m_dwFDSize;
|
||||||
|
|
||||||
|
if (this->m_bProperHeader)
|
||||||
|
pFileHeader->InitializeDataV1();
|
||||||
|
|
||||||
|
pFileHeader->InitializeDataV2();
|
||||||
|
|
||||||
|
pFileHeader->headerV2.dwInvalidIndex %= m_dwNumEntries;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
void CArchiveBuilder::BuildEntryData(FILE *fiArchive)
|
||||||
|
{
|
||||||
|
CCryptoContext context;
|
||||||
|
EntryMemStateVector_t::iterator it;
|
||||||
|
const DWORD dwReadBlockSize = SAA_BLOCK_SIZE;
|
||||||
|
CTinyEncrypt tinyEncrypt;
|
||||||
|
|
||||||
|
BYTE *pbReadData = new BYTE[dwReadBlockSize];
|
||||||
|
|
||||||
|
it = m_vecEntries.begin();
|
||||||
|
while(it != m_vecEntries.end()) {
|
||||||
|
|
||||||
|
AB_ENTRY_MEMSTATE* pEntry = (*it);
|
||||||
|
|
||||||
|
tinyEncrypt.SetKey(pEntry->pbTEAKey, 0);
|
||||||
|
|
||||||
|
DWORD dwReadSize;
|
||||||
|
for(DWORD i=0; i<pEntry->dwFileSize; i+=dwReadBlockSize) {
|
||||||
|
dwReadSize = (DWORD)fread(pbReadData, 1, dwReadBlockSize, pEntry->fiFile);
|
||||||
|
if (dwReadSize < dwReadBlockSize) {
|
||||||
|
context.GenerateRandom(dwReadBlockSize-dwReadSize, pbReadData+dwReadSize);
|
||||||
|
}
|
||||||
|
#ifdef DO_ENCRYPT
|
||||||
|
tinyEncrypt.EncryptData(dwReadBlockSize, pbReadData);
|
||||||
|
#endif
|
||||||
|
fwrite(pbReadData, 1, dwReadBlockSize, fiArchive);
|
||||||
|
}
|
||||||
|
|
||||||
|
it++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] pbReadData;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
void CArchiveBuilder::SignArchive(FILE *fiArchive, DWORD dwSignatureOffset, SAA_FILE_HEADER *pHeader)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Sign the archive file
|
||||||
|
|
||||||
|
CCryptoContext context;
|
||||||
|
CKeyPair keyPair(&context);
|
||||||
|
CHasher hasher(&context);
|
||||||
|
CSigner signer;
|
||||||
|
|
||||||
|
// 1. Hash the stuff
|
||||||
|
fseek(fiArchive, pHeader->SizeOf(), SEEK_SET); // start from the actual data section
|
||||||
|
const DWORD dwReadBlockSize = 10 * 1024; // 10kb
|
||||||
|
BYTE *pbReadData = new BYTE[dwReadBlockSize];
|
||||||
|
DWORD dwReadSize;
|
||||||
|
DWORD dwPos = ftell(fiArchive);
|
||||||
|
while(!feof(fiArchive)) {
|
||||||
|
dwReadSize = (DWORD)fread(pbReadData, 1, dwReadBlockSize, fiArchive);
|
||||||
|
hasher.AddData(dwReadSize, pbReadData);
|
||||||
|
dwPos = ftell(fiArchive);
|
||||||
|
}
|
||||||
|
delete[] pbReadData;
|
||||||
|
|
||||||
|
// 2. Load the key, and sign the hash
|
||||||
|
keyPair.LoadFromFile("pkey.bin");
|
||||||
|
signer.SignHash(&hasher);
|
||||||
|
keyPair.ReleaseKey();
|
||||||
|
|
||||||
|
// 3. Write the signature
|
||||||
|
pHeader->headerV2.dwSignSize = signer.GetSignatureLength();
|
||||||
|
fseek(fiArchive, dwSignatureOffset, SEEK_SET);
|
||||||
|
fwrite(signer.GetSignature(), 1, pHeader->headerV2.dwSignSize, fiArchive);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
void CArchiveBuilder::WriteArchive(PCHAR szFileName)
|
||||||
|
{
|
||||||
|
SAA_FILE_HEADER header;
|
||||||
|
SAA_ENTRY *pEntryTable;
|
||||||
|
FILE* fiArchive;
|
||||||
|
|
||||||
|
fiArchive = fopen(szFileName, "w+b");
|
||||||
|
|
||||||
|
pEntryTable = new SAA_ENTRY[m_dwNumEntries];
|
||||||
|
|
||||||
|
// 1. Build the header
|
||||||
|
BuildHeader(&header);
|
||||||
|
|
||||||
|
// 2. Build the entry table
|
||||||
|
BuildEntryTable(pEntryTable, header.headerV2.dwInvalidIndex);
|
||||||
|
|
||||||
|
// 3. Encode and write the file data
|
||||||
|
fseek(fiArchive, header.SizeOf(), SEEK_SET);
|
||||||
|
BuildEntryData(fiArchive);
|
||||||
|
|
||||||
|
// 4. Encrypt and write the entry table
|
||||||
|
// (Note that the file data decryption must be done with decrypted entry table used for keys)
|
||||||
|
CTinyEncrypt tinyEnc;
|
||||||
|
tinyEnc.LoadKey("skey.bin");
|
||||||
|
#ifdef DO_ENCRYPT
|
||||||
|
tinyEnc.EncryptData(sizeof(SAA_ENTRY)*m_dwNumEntries, reinterpret_cast<BYTE*>(pEntryTable));
|
||||||
|
#endif
|
||||||
|
fwrite(pEntryTable, sizeof(SAA_ENTRY), m_dwNumEntries, fiArchive);
|
||||||
|
|
||||||
|
// 5. Sign the data (excluding the header)
|
||||||
|
fflush(fiArchive);
|
||||||
|
SignArchive(fiArchive, (DWORD)ftell(fiArchive), &header);
|
||||||
|
|
||||||
|
// 6. Finish the header and write it
|
||||||
|
#ifdef DO_ENCRYPT
|
||||||
|
header.XorV2Identifier();
|
||||||
|
#endif
|
||||||
|
header.Write(fiArchive);
|
||||||
|
|
||||||
|
// And we're done.
|
||||||
|
fclose(fiArchive);
|
||||||
|
|
||||||
|
delete[] pEntryTable;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
66
arctool2/ArchiveBuilder.h
Normal file
66
arctool2/ArchiveBuilder.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../saco/archive/ArchiveCommon.h"
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
typedef struct _AB_ENTRY_MEMSTATE
|
||||||
|
{
|
||||||
|
SAA_ENTRY* pEntry;
|
||||||
|
|
||||||
|
DWORD dwEntryTableOffset;
|
||||||
|
BYTE* pbTEAKey;
|
||||||
|
|
||||||
|
CHAR szFileName[32];
|
||||||
|
DWORD dwFileNameHash;
|
||||||
|
DWORD dwFileSize;
|
||||||
|
FILE* fiFile;
|
||||||
|
|
||||||
|
_AB_ENTRY_MEMSTATE()
|
||||||
|
{
|
||||||
|
dwEntryTableOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} AB_ENTRY_MEMSTATE;
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
typedef std::vector<AB_ENTRY_MEMSTATE*> EntryMemStateVector_t;
|
||||||
|
|
||||||
|
class CArchiveBuilder
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
DWORD m_dwNumEntries;
|
||||||
|
DWORD m_dwFDSize;
|
||||||
|
BOOL m_bProperHeader;
|
||||||
|
|
||||||
|
EntryMemStateVector_t m_vecEntries;
|
||||||
|
|
||||||
|
PCHAR m_szPrivKeyFile;
|
||||||
|
PCHAR m_szTEAKeyFile;
|
||||||
|
|
||||||
|
static DWORD ms_dwHashInit;
|
||||||
|
DWORD HashString(PCHAR szString);
|
||||||
|
PCHAR ExtractFileName(PCHAR szString);
|
||||||
|
DWORD GetRandom();
|
||||||
|
|
||||||
|
void BuildHeader(SAA_FILE_HEADER* pFileHeader);
|
||||||
|
void BuildEntryTable(SAA_ENTRY* pEntryTable, DWORD dwInvalidIndex);
|
||||||
|
void BuildEntryData(FILE* fiArchive);
|
||||||
|
void SignArchive(FILE *fiArchive, DWORD dwSignatureOffset, SAA_FILE_HEADER *pHeader);
|
||||||
|
|
||||||
|
public:
|
||||||
|
CArchiveBuilder(void);
|
||||||
|
CArchiveBuilder(DWORD dwNumEntries, DWORD dwFDSize, BOOL bProperHeader);
|
||||||
|
~CArchiveBuilder(void);
|
||||||
|
|
||||||
|
void SetKeyFile(PCHAR szPrivKeyFile, PCHAR szTEAKeyFile);
|
||||||
|
|
||||||
|
DWORD AddFile(PCHAR szFileName);
|
||||||
|
void WriteArchive(PCHAR szFileName);
|
||||||
|
};
|
340
arctool2/arctool2.cpp
Normal file
340
arctool2/arctool2.cpp
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../saco/archive/CryptoContext.h"
|
||||||
|
#include "../saco/archive/KeyPair.h"
|
||||||
|
#include "../saco/archive/TinyEncrypt.h"
|
||||||
|
#include "../saco/archive/ArchiveFS.h"
|
||||||
|
#include "ArchiveBuilder.h"
|
||||||
|
|
||||||
|
void CreateArchive(PCHAR szFileList, PCHAR szArchive)
|
||||||
|
{
|
||||||
|
|
||||||
|
CArchiveBuilder archiveBuilder;
|
||||||
|
|
||||||
|
// Load the file list
|
||||||
|
FILE* fiList;
|
||||||
|
fiList = fopen(szFileList, "rb");
|
||||||
|
if (!fiList)
|
||||||
|
throw "Could not find file list.";
|
||||||
|
fseek(fiList, 0, SEEK_END);
|
||||||
|
DWORD dwFileListSize = ftell(fiList);
|
||||||
|
CHAR* szFiles = new CHAR[dwFileListSize+1];
|
||||||
|
fseek(fiList, 0, SEEK_SET);
|
||||||
|
fread(szFiles, 1, dwFileListSize, fiList);
|
||||||
|
szFiles[dwFileListSize] = 0;
|
||||||
|
fclose(fiList);
|
||||||
|
|
||||||
|
// Load the files and stuff
|
||||||
|
CHAR* szToken;
|
||||||
|
szToken = strtok(szFiles, "\r\n");
|
||||||
|
while(szToken != NULL) {
|
||||||
|
if (szToken[0] != 0 && szToken[0] != '#') {
|
||||||
|
printf("Adding file: %s...\t", szToken);
|
||||||
|
DWORD hash = archiveBuilder.AddFile(szToken);
|
||||||
|
printf(" Added, file hash=0x%x\n", hash);
|
||||||
|
}
|
||||||
|
szToken = strtok(NULL, "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the archive
|
||||||
|
printf("Writing archive...\n");
|
||||||
|
archiveBuilder.WriteArchive(szArchive);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
delete[] szFiles;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CreateArchiveSingle(PCHAR szFile, PCHAR szArchive)
|
||||||
|
{
|
||||||
|
|
||||||
|
CArchiveBuilder archiveBuilder(4, 0, FALSE);
|
||||||
|
|
||||||
|
// Load the file
|
||||||
|
printf("Adding file: %s...\t", szFile);
|
||||||
|
DWORD hash = archiveBuilder.AddFile(szFile);
|
||||||
|
printf(" Added, file hash=0x%x\n", hash);
|
||||||
|
|
||||||
|
// Write the archive
|
||||||
|
printf("Writing archive...\n");
|
||||||
|
archiveBuilder.WriteArchive(szArchive);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper for test routine
|
||||||
|
PCHAR ExtractFileName(PCHAR szString)
|
||||||
|
{
|
||||||
|
DWORD dwOffset = (DWORD)strlen(szString);
|
||||||
|
while((dwOffset > 0) && (szString[dwOffset] != '\\'))
|
||||||
|
dwOffset--;
|
||||||
|
if (dwOffset == 0)
|
||||||
|
return szString;
|
||||||
|
else
|
||||||
|
return szString+dwOffset+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test routine to see if the archive making works properly...
|
||||||
|
// And for archive verification!
|
||||||
|
void VerifyArchive(PCHAR szFileList, PCHAR szArchive)
|
||||||
|
{
|
||||||
|
|
||||||
|
CArchiveFS fs;
|
||||||
|
|
||||||
|
const DWORD BUFFER_SIZE = 1024;
|
||||||
|
BYTE* pbBuffer[BUFFER_SIZE];
|
||||||
|
|
||||||
|
// Load the file list
|
||||||
|
FILE* fiList;
|
||||||
|
fiList = fopen(szFileList, "rb");
|
||||||
|
if (!fiList)
|
||||||
|
throw "Could not find file list.";
|
||||||
|
fseek(fiList, 0, SEEK_END);
|
||||||
|
DWORD dwFileListSize = ftell(fiList);
|
||||||
|
CHAR* szFiles = new CHAR[dwFileListSize+1];
|
||||||
|
fseek(fiList, 0, SEEK_SET);
|
||||||
|
fread(szFiles, 1, dwFileListSize, fiList);
|
||||||
|
szFiles[dwFileListSize] = 0;
|
||||||
|
fclose(fiList);
|
||||||
|
|
||||||
|
// Load the archive
|
||||||
|
if (!fs.Load(szArchive))
|
||||||
|
throw "Failed to load archive.";
|
||||||
|
|
||||||
|
// Load the files and stuff
|
||||||
|
CHAR* szToken;
|
||||||
|
FILE* fiData;
|
||||||
|
|
||||||
|
szToken = strtok(szFiles, "\r\n");
|
||||||
|
while(szToken != NULL) {
|
||||||
|
if (szToken[0] != 0 && szToken[0] != '#') {
|
||||||
|
|
||||||
|
// Get the file data
|
||||||
|
DWORD dwFileIndex = fs.GetFileIndex(ExtractFileName(szToken));
|
||||||
|
|
||||||
|
if (dwFileIndex != FS_INVALID_FILE) {
|
||||||
|
|
||||||
|
DWORD dwFileSize = fs.GetFileSize(dwFileIndex);
|
||||||
|
BYTE* pbFileData = fs.GetFileData(dwFileIndex);
|
||||||
|
|
||||||
|
printf("Verifying file: %s...\t", szToken);
|
||||||
|
|
||||||
|
// Load the actual file and verify the data
|
||||||
|
fiData = fopen(szToken, "rb");
|
||||||
|
|
||||||
|
if (dwFileSize == 0)
|
||||||
|
printf(" Warning: 0 byte file.\n");
|
||||||
|
|
||||||
|
for(DWORD i=0; i<dwFileSize; i+=BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
DWORD dwReadBytes;
|
||||||
|
if ((i + BUFFER_SIZE) >= dwFileSize) {
|
||||||
|
// The last block, read using our real size
|
||||||
|
dwReadBytes = dwFileSize % BUFFER_SIZE;
|
||||||
|
} else {
|
||||||
|
dwReadBytes = BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
dwReadBytes = (DWORD)fread(pbBuffer, 1, dwReadBytes, fiData);
|
||||||
|
if (memcmp(pbBuffer, pbFileData+i, dwReadBytes) != 0) {
|
||||||
|
throw " Failed to verify file.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fiData);
|
||||||
|
|
||||||
|
printf(" Verified.\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf(" Warning: File ""%s"" not found in archive.\n", szToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
szToken = strtok(NULL, "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the archive
|
||||||
|
fs.Unload();
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
delete[] szFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerifyArchiveSingle(PCHAR szFile, PCHAR szArchive)
|
||||||
|
{
|
||||||
|
const DWORD BUFFER_SIZE = 1024;
|
||||||
|
BYTE* pbBuffer[BUFFER_SIZE];
|
||||||
|
|
||||||
|
CArchiveFS fs(4, 0);
|
||||||
|
|
||||||
|
// Load the archive
|
||||||
|
if (!fs.Load(szArchive))
|
||||||
|
throw "Failed to load archive.";
|
||||||
|
|
||||||
|
// Load the files and stuff
|
||||||
|
FILE* fiData;
|
||||||
|
|
||||||
|
// Get the file data
|
||||||
|
DWORD dwFileIndex = fs.GetFileIndex(ExtractFileName(szFile));
|
||||||
|
|
||||||
|
if (dwFileIndex != FS_INVALID_FILE) {
|
||||||
|
|
||||||
|
DWORD dwFileSize = fs.GetFileSize(dwFileIndex);
|
||||||
|
BYTE* pbFileData = fs.GetFileData(dwFileIndex);
|
||||||
|
|
||||||
|
printf("Verifying file: %s...\t", szFile);
|
||||||
|
|
||||||
|
// Load the actual file and verify the data
|
||||||
|
fiData = fopen(szFile, "rb");
|
||||||
|
|
||||||
|
if (dwFileSize == 0)
|
||||||
|
printf(" Warning: 0 byte file.\n");
|
||||||
|
|
||||||
|
for(DWORD i=0; i<dwFileSize; i+=BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
DWORD dwReadBytes;
|
||||||
|
if ((i + BUFFER_SIZE) >= dwFileSize) {
|
||||||
|
// The last block, read using our real size
|
||||||
|
dwReadBytes = dwFileSize % BUFFER_SIZE;
|
||||||
|
} else {
|
||||||
|
dwReadBytes = BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
dwReadBytes = (DWORD)fread(pbBuffer, 1, dwReadBytes, fiData);
|
||||||
|
if (memcmp(pbBuffer, pbFileData+i, dwReadBytes) != 0) {
|
||||||
|
throw " Failed to verify file.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fiData);
|
||||||
|
|
||||||
|
printf(" Verified.\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf(" Warning: File ""%s"" not found in archive.\n", szFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Close the archive
|
||||||
|
fs.Unload();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenerateKeys()
|
||||||
|
{
|
||||||
|
CCryptoContext context;
|
||||||
|
CKeyPair keyPair(&context);
|
||||||
|
CTinyEncrypt tinyEncrypt;
|
||||||
|
BYTE pbTEAKey[TEA_KEY_SIZE];
|
||||||
|
|
||||||
|
keyPair.GenerateKey();
|
||||||
|
keyPair.WriteToFile("pkey.bin");
|
||||||
|
keyPair.WriteCHeaderFile("pkey.h");
|
||||||
|
keyPair.ReleaseKey();
|
||||||
|
|
||||||
|
context.GenerateRandom(TEA_KEY_SIZE, pbTEAKey);
|
||||||
|
tinyEncrypt.SetKey(pbTEAKey, 0);
|
||||||
|
tinyEncrypt.WriteKey("skey.bin");
|
||||||
|
tinyEncrypt.WriteCHeaderFile("skey.h");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintBanner()
|
||||||
|
{
|
||||||
|
printf("SA:MP Archive 2 Tool\n");
|
||||||
|
printf("Copyright(C) 2006, SA:MP Team\n");
|
||||||
|
printf("Built on " __DATE__ " at " __TIME__ ".\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintUsage()
|
||||||
|
{
|
||||||
|
printf("Usage:\n");
|
||||||
|
printf(" -c [filelist.txt] [samp.saa]\n \tGenerates samp.saa from filelist.txt\n");
|
||||||
|
printf(" -v [filelist.txt] [samp.saa]\n \tVerifies samp.saa using filelist.txt\n");
|
||||||
|
printf(" -sc file.dat file.saa\n \tGenerates single file SAA\n");
|
||||||
|
printf(" -sv file.dat file.saa\n \tVerifies single file SAA\n");
|
||||||
|
printf(" -gk\tGenerates a new set of TEA and RSA keys\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD main(DWORD argc, CHAR** argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
PrintBanner();
|
||||||
|
|
||||||
|
if (argc == 1) {
|
||||||
|
PrintUsage();
|
||||||
|
} else {
|
||||||
|
if (strcmp(argv[1], "-c")==0) {
|
||||||
|
// generate file
|
||||||
|
PCHAR szFileList = "filelist.txt";
|
||||||
|
PCHAR szArchive = "samp.saa";
|
||||||
|
if (argc > 2)
|
||||||
|
szFileList = argv[2];
|
||||||
|
if (argc > 3)
|
||||||
|
szArchive = argv[3];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
printf("Creating archive...\n");
|
||||||
|
CreateArchive(szFileList, szArchive);
|
||||||
|
printf("Archive generated successfully.\n");
|
||||||
|
}
|
||||||
|
catch (PCHAR error)
|
||||||
|
{
|
||||||
|
printf("Error: %s\n", error);
|
||||||
|
}
|
||||||
|
} else if (strcmp(argv[1], "-v")==0) {
|
||||||
|
// verify file
|
||||||
|
PCHAR szFileList = "filelist.txt";
|
||||||
|
PCHAR szArchive = "samp.saa";
|
||||||
|
if (argc > 2)
|
||||||
|
szFileList = argv[2];
|
||||||
|
if (argc > 3)
|
||||||
|
szArchive = argv[3];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
printf("Verifying archive...\n");
|
||||||
|
VerifyArchive(szFileList, szArchive);
|
||||||
|
printf("Archive verification complete.\n");
|
||||||
|
}
|
||||||
|
catch (PCHAR error)
|
||||||
|
{
|
||||||
|
printf("Error: %s\n", error);
|
||||||
|
}
|
||||||
|
} else if (strcmp(argv[1], "-gk")==0) {
|
||||||
|
GenerateKeys();
|
||||||
|
printf("Generated keys successfully.\n");
|
||||||
|
} else if (argc > 3 && strcmp(argv[1], "-sc")==0) {
|
||||||
|
// generate file
|
||||||
|
PCHAR szFile = argv[2];
|
||||||
|
PCHAR szArchive = argv[3];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
printf("Creating archive...\n");
|
||||||
|
CreateArchiveSingle(szFile, szArchive);
|
||||||
|
printf("Archive generated successfully.\n");
|
||||||
|
}
|
||||||
|
catch (PCHAR error)
|
||||||
|
{
|
||||||
|
printf("Error: %s\n", error);
|
||||||
|
}
|
||||||
|
} else if (argc > 3 && strcmp(argv[1], "-sv")==0) {
|
||||||
|
// generate file
|
||||||
|
PCHAR szFile = argv[2];
|
||||||
|
PCHAR szArchive = argv[3];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
printf("Verifying archive...\n");
|
||||||
|
VerifyArchiveSingle(szFile, szArchive);
|
||||||
|
printf("Archive verification complete.\n");
|
||||||
|
}
|
||||||
|
catch (PCHAR error)
|
||||||
|
{
|
||||||
|
printf("Error: %s\n", error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PrintUsage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
getchar();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
}
|
21
arctool2/arctool2.sln
Normal file
21
arctool2/arctool2.sln
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "arctool2", "arctool2.vcproj", "{15D9069D-0365-4493-A00F-9B2478884489}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfiguration) = preSolution
|
||||||
|
Debug = Debug
|
||||||
|
Release = Release
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfiguration) = postSolution
|
||||||
|
{15D9069D-0365-4493-A00F-9B2478884489}.Debug.ActiveCfg = Debug|Win32
|
||||||
|
{15D9069D-0365-4493-A00F-9B2478884489}.Debug.Build.0 = Debug|Win32
|
||||||
|
{15D9069D-0365-4493-A00F-9B2478884489}.Release.ActiveCfg = Release|Win32
|
||||||
|
{15D9069D-0365-4493-A00F-9B2478884489}.Release.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
169
arctool2/arctool2.vcproj
Normal file
169
arctool2/arctool2.vcproj
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.10"
|
||||||
|
Name="arctool2"
|
||||||
|
ProjectGUID="{15D9069D-0365-4493-A00F-9B2478884489}"
|
||||||
|
Keyword="Win32Proj">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="Debug"
|
||||||
|
IntermediateDirectory="Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;ARCTOOL"
|
||||||
|
MinimalRebuild="TRUE"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="5"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="TRUE"
|
||||||
|
DebugInformationFormat="4"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
OutputFile="$(OutDir)/arctool2.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
ProgramDatabaseFile="$(OutDir)/arctool2.pdb"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedWrapperGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="Release"
|
||||||
|
IntermediateDirectory="Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;ARCTOOL"
|
||||||
|
RuntimeLibrary="4"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="TRUE"
|
||||||
|
DebugInformationFormat="3"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
OutputFile="$(OutDir)/arctool2.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedWrapperGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Archive"
|
||||||
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\ArchiveCommon.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\ArchiveFS.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\ArchiveFS.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\CryptoContext.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\CryptoContext.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\Hasher.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\Hasher.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\KeyPair.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\KeyPair.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\Obfuscator.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\Signer.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\Signer.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\TinyEncrypt.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\saco\archive\TinyEncrypt.h">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<File
|
||||||
|
RelativePath=".\ArchiveBuilder.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\ArchiveBuilder.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\arctool2.cpp">
|
||||||
|
</File>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
@ -75,6 +75,28 @@ typedef struct _SAA_FILE_HEADER
|
|||||||
return(sizeof(DWORD)*2 + sizeof(WORD)*dwFakeDataSize + sizeof(VER2_HEADER));
|
return(sizeof(DWORD)*2 + sizeof(WORD)*dwFakeDataSize + sizeof(VER2_HEADER));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void InitializeDataV1()
|
||||||
|
{
|
||||||
|
headerV1.dwSAAV = 0x32414153; // "SAA2"
|
||||||
|
headerV1.dwFileCount = 0x16;
|
||||||
|
// All other data should be random, or predefined outside.
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeDataV2()
|
||||||
|
{
|
||||||
|
headerV2.dwSAMPID = SAA_FILE_ID;
|
||||||
|
headerV2.dwVersion = SAA_FILE_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(FILE *f)
|
||||||
|
{
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
fwrite(&headerV1, 1, sizeof(DWORD)*2 + sizeof(WORD)*dwFakeDataSize, f);
|
||||||
|
fwrite(&headerV2, 1, sizeof(VER2_HEADER), f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool VerifyIdentifier()
|
bool VerifyIdentifier()
|
||||||
{
|
{
|
||||||
return ((headerV2.dwSAMPID == SAA_FILE_ID) &&
|
return ((headerV2.dwSAMPID == SAA_FILE_ID) &&
|
||||||
|
@ -9,8 +9,13 @@
|
|||||||
|
|
||||||
#include "../mod.h"
|
#include "../mod.h"
|
||||||
|
|
||||||
|
#ifndef ARCTOOL
|
||||||
|
|
||||||
|
// Load the original CFileSystem class
|
||||||
#include "../filesystem.h"
|
#include "../filesystem.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FS_INVALID_FILE 0xFFFFFFFF
|
#define FS_INVALID_FILE 0xFFFFFFFF
|
||||||
|
|
||||||
typedef struct _AFS_ENTRYBT_NODE
|
typedef struct _AFS_ENTRYBT_NODE
|
||||||
@ -86,8 +91,10 @@ typedef struct _AFS_ENTRYBT_NODE
|
|||||||
|
|
||||||
} AFS_ENTRYBT_NODE;
|
} AFS_ENTRYBT_NODE;
|
||||||
|
|
||||||
class CArchiveFS // size: 2357
|
class CArchiveFS
|
||||||
|
#ifndef ARCTOOL
|
||||||
: public CFileSystem
|
: public CFileSystem
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool m_bLoaded;
|
bool m_bLoaded;
|
||||||
|
@ -60,3 +60,10 @@ HCRYPTPROV CCryptoContext::GetProvider()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void CCryptoContext::GenerateRandom(DWORD dwLength, BYTE* pbBuffer)
|
||||||
|
{
|
||||||
|
CryptGenRandom(m_hCryptProv, dwLength, pbBuffer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -20,4 +20,9 @@ public:
|
|||||||
~CCryptoContext(void);
|
~CCryptoContext(void);
|
||||||
|
|
||||||
HCRYPTPROV GetProvider();
|
HCRYPTPROV GetProvider();
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void GenerateRandom(DWORD dwLength, BYTE* pbBuffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include "KeyPair.h"
|
#include "KeyPair.h"
|
||||||
#include "CryptoFns.h"
|
#include "CryptoFns.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
@ -24,6 +25,17 @@ CKeyPair::~CKeyPair(void)
|
|||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void CKeyPair::GenerateKey()
|
||||||
|
{
|
||||||
|
// Generate a key pair
|
||||||
|
HCRYPTPROV hCryptProv = m_pContext->GetProvider();
|
||||||
|
CryptGenKey(hCryptProv, AT_SIGNATURE, (ms_dwRSAKeySize << 16) | CRYPT_EXPORTABLE, &m_hCryptKey);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
void CKeyPair::ReleaseKey()
|
void CKeyPair::ReleaseKey()
|
||||||
{
|
{
|
||||||
// Destroy the key pair
|
// Destroy the key pair
|
||||||
@ -33,6 +45,99 @@ void CKeyPair::ReleaseKey()
|
|||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void CKeyPair::LoadFromFile(PCHAR szFileName)
|
||||||
|
{
|
||||||
|
DWORD dwKeySize;
|
||||||
|
BYTE *pbKeyBlob;
|
||||||
|
FILE *fiKey;
|
||||||
|
|
||||||
|
// Load the private key from a file
|
||||||
|
fiKey = fopen((CHAR*)szFileName, "rb");
|
||||||
|
fread(&dwKeySize, sizeof(dwKeySize), 1, fiKey);
|
||||||
|
pbKeyBlob = new BYTE[dwKeySize];
|
||||||
|
fread(pbKeyBlob, 1, dwKeySize, fiKey);
|
||||||
|
fclose(fiKey);
|
||||||
|
|
||||||
|
// Load the key pair
|
||||||
|
HCRYPTPROV hCryptProv = m_pContext->GetProvider();
|
||||||
|
CryptImportKey(hCryptProv, pbKeyBlob, dwKeySize, NULL, CRYPT_EXPORTABLE, &m_hCryptKey);
|
||||||
|
|
||||||
|
// Clean up memory
|
||||||
|
delete[] pbKeyBlob;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void CKeyPair::WriteToFile(PCHAR szFileName)
|
||||||
|
{
|
||||||
|
DWORD dwKeySize;
|
||||||
|
BYTE *pbKeyBlob;
|
||||||
|
FILE *fiKey;
|
||||||
|
|
||||||
|
// Export the private key
|
||||||
|
CryptExportKey(m_hCryptKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwKeySize);
|
||||||
|
pbKeyBlob = new BYTE[dwKeySize];
|
||||||
|
CryptExportKey(m_hCryptKey, NULL, PRIVATEKEYBLOB, 0, pbKeyBlob, &dwKeySize);
|
||||||
|
|
||||||
|
// Write the private key to a file
|
||||||
|
fiKey = fopen((CHAR*)szFileName, "wb");
|
||||||
|
fwrite(&dwKeySize, sizeof(dwKeySize), 1, fiKey);
|
||||||
|
fwrite(pbKeyBlob, 1, dwKeySize, fiKey);
|
||||||
|
fclose(fiKey);
|
||||||
|
|
||||||
|
// Clean up memory
|
||||||
|
delete[] pbKeyBlob;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void CKeyPair::WriteCHeaderFile(PSTR szFileName)
|
||||||
|
{
|
||||||
|
const BYTE bytXORKey = 0xAA;
|
||||||
|
DWORD dwKeySize;
|
||||||
|
BYTE *pbKeyBlob;
|
||||||
|
FILE *fiHeader;
|
||||||
|
|
||||||
|
// Export the public key
|
||||||
|
CryptExportKey(m_hCryptKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwKeySize);
|
||||||
|
pbKeyBlob = new BYTE[dwKeySize];
|
||||||
|
CryptExportKey(m_hCryptKey, NULL, PUBLICKEYBLOB, 0, pbKeyBlob, &dwKeySize);
|
||||||
|
|
||||||
|
// Generate the header file
|
||||||
|
fiHeader = fopen(szFileName, "wt");
|
||||||
|
fprintf(fiHeader, "//-----------------------------------------\n" );
|
||||||
|
fprintf(fiHeader, "// SAMP Archive 2 Tool - Public Keys\n" );
|
||||||
|
fprintf(fiHeader, "//\n" );
|
||||||
|
fprintf(fiHeader, "// This file was automatically generated.\n" );
|
||||||
|
fprintf(fiHeader, "// Do not modify this file!\n" );
|
||||||
|
fprintf(fiHeader, "//-----------------------------------------\n" );
|
||||||
|
fprintf(fiHeader, "\n" );
|
||||||
|
fprintf(fiHeader, "#pragma once\n" );
|
||||||
|
fprintf(fiHeader, "\n" );
|
||||||
|
fprintf(fiHeader, "#define RSA_XOR_KEY %d\n", bytXORKey );
|
||||||
|
fprintf(fiHeader, "\n" );
|
||||||
|
fprintf(fiHeader, "#define RSA_PUB_KEY_SIZE %d\n", dwKeySize );
|
||||||
|
fprintf(fiHeader, "const BYTE RSA_PUB_KEY[] = \n\t{" );
|
||||||
|
for(DWORD i=0; i<dwKeySize; i++) {
|
||||||
|
fprintf(fiHeader, "0x%x%s", (pbKeyBlob[i] ^ bytXORKey), (i==(dwKeySize-1)?"};":",\t"));
|
||||||
|
if (((i+1) % 8) == 0) {
|
||||||
|
fprintf(fiHeader, "\n\t ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fiHeader);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
delete[] pbKeyBlob;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
void CKeyPair::LoadFromMemory(DWORD dwPubKeySize, BYTE* pbPubKeyBlob, BYTE bytXORKey)
|
void CKeyPair::LoadFromMemory(DWORD dwPubKeySize, BYTE* pbPubKeyBlob, BYTE bytXORKey)
|
||||||
{
|
{
|
||||||
BYTE *pbKeyBlob;
|
BYTE *pbKeyBlob;
|
||||||
|
@ -16,6 +16,13 @@ public:
|
|||||||
CKeyPair(CCryptoContext* pContext);
|
CKeyPair(CCryptoContext* pContext);
|
||||||
~CKeyPair(void);
|
~CKeyPair(void);
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void GenerateKey();
|
||||||
|
void LoadFromFile(PCHAR szFileName);
|
||||||
|
void WriteToFile(PCHAR szFileName);
|
||||||
|
void WriteCHeaderFile(PCHAR szFileName);
|
||||||
|
#endif
|
||||||
|
|
||||||
void LoadFromMemory(DWORD dwPubKeySize, BYTE* pbPubKeyBlob, BYTE bytXORKey);
|
void LoadFromMemory(DWORD dwPubKeySize, BYTE* pbPubKeyBlob, BYTE bytXORKey);
|
||||||
void ReleaseKey();
|
void ReleaseKey();
|
||||||
|
|
||||||
|
@ -20,6 +20,39 @@ CSigner::~CSigner(void)
|
|||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void CSigner::SignHash(CHasher *pHasher)
|
||||||
|
{
|
||||||
|
if (m_pbSignature != NULL)
|
||||||
|
delete[] m_pbSignature;
|
||||||
|
|
||||||
|
HCRYPTHASH hCryptHash = pHasher->GetContainer();
|
||||||
|
CryptSignHash(hCryptHash, AT_SIGNATURE, NULL, CRYPT_NOHASHOID, NULL, &m_dwLength);
|
||||||
|
m_pbSignature = new BYTE[m_dwLength];
|
||||||
|
CryptSignHash(hCryptHash, AT_SIGNATURE, NULL, CRYPT_NOHASHOID, m_pbSignature, &m_dwLength);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
BYTE* CSigner::GetSignature()
|
||||||
|
{
|
||||||
|
return m_pbSignature;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
DWORD CSigner::GetSignatureLength()
|
||||||
|
{
|
||||||
|
return m_dwLength;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
void CSigner::SetSignature(DWORD dwLength, BYTE *pbSignature)
|
void CSigner::SetSignature(DWORD dwLength, BYTE *pbSignature)
|
||||||
{
|
{
|
||||||
if (m_pbSignature != NULL)
|
if (m_pbSignature != NULL)
|
||||||
|
@ -15,6 +15,12 @@ public:
|
|||||||
CSigner(void);
|
CSigner(void);
|
||||||
~CSigner(void);
|
~CSigner(void);
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void SignHash(CHasher* pHasher);
|
||||||
|
BYTE* GetSignature();
|
||||||
|
DWORD GetSignatureLength();
|
||||||
|
#endif
|
||||||
|
|
||||||
void SetSignature(DWORD dwLength, BYTE* pbSignature);
|
void SetSignature(DWORD dwLength, BYTE* pbSignature);
|
||||||
BOOL VerifySignature(CHasher* pHasher, CKeyPair* pKeyPair);
|
BOOL VerifySignature(CHasher* pHasher, CKeyPair* pKeyPair);
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include "TinyEncrypt.h"
|
#include "TinyEncrypt.h"
|
||||||
#include "Obfuscator.h"
|
#include "Obfuscator.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
@ -42,6 +43,27 @@ void CTinyEncrypt::SetKey(BYTE *pbKey, BYTE bytXORKey)
|
|||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
|
||||||
|
void CTinyEncrypt::EncryptBlock(DWORD &dwV0, DWORD &dwV1)
|
||||||
|
{
|
||||||
|
DWORD dwSum = 0;
|
||||||
|
|
||||||
|
for(DWORD i=0; i<ms_dwRounds; i++) {
|
||||||
|
dwV0 += ((dwV1 << 4 ^ dwV1 >> 5) + dwV1) ^ (dwSum + m_pdwKey[dwSum & 3]);
|
||||||
|
dwSum += ms_dwInitDelta;
|
||||||
|
dwV1 += ((dwV0 << 4 ^ dwV0 >> 5) + dwV0) ^ (dwSum + m_pdwKey[dwSum>>11 & 3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pdwKey[0] ^= dwV0;
|
||||||
|
m_pdwKey[1] ^= dwV1;
|
||||||
|
m_pdwKey[2] ^= dwV0;
|
||||||
|
m_pdwKey[3] ^= dwV1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
void CTinyEncrypt::DecryptBlock(DWORD &dwV0, DWORD &dwV1)
|
void CTinyEncrypt::DecryptBlock(DWORD &dwV0, DWORD &dwV1)
|
||||||
{
|
{
|
||||||
DWORD dwSum = ms_dwInitSum;
|
DWORD dwSum = ms_dwInitSum;
|
||||||
@ -63,6 +85,19 @@ void CTinyEncrypt::DecryptBlock(DWORD &dwV0, DWORD &dwV1)
|
|||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void CTinyEncrypt::EncryptData(DWORD dwLength, BYTE *pbData)
|
||||||
|
{
|
||||||
|
DWORD dwBlocks = dwLength / 4;
|
||||||
|
DWORD *pdwData = reinterpret_cast<DWORD*>(pbData);
|
||||||
|
for(DWORD i=0; i<dwBlocks; i+=2) {
|
||||||
|
EncryptBlock(pdwData[i+0], pdwData[i+1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
void CTinyEncrypt::DecryptData(DWORD dwLength, BYTE *pbData)
|
void CTinyEncrypt::DecryptData(DWORD dwLength, BYTE *pbData)
|
||||||
{
|
{
|
||||||
DWORD dwBlocks = dwLength / 4;
|
DWORD dwBlocks = dwLength / 4;
|
||||||
@ -73,3 +108,61 @@ void CTinyEncrypt::DecryptData(DWORD dwLength, BYTE *pbData)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void CTinyEncrypt::LoadKey(PCHAR szFileName)
|
||||||
|
{
|
||||||
|
FILE* fiKey;
|
||||||
|
|
||||||
|
fiKey = fopen((CHAR*)szFileName, "rb");
|
||||||
|
fread(m_pdwKey, 1, TEA_KEY_SIZE, fiKey);
|
||||||
|
fclose(fiKey);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void CTinyEncrypt::WriteKey(PCHAR szFileName)
|
||||||
|
{
|
||||||
|
FILE* fiKey;
|
||||||
|
|
||||||
|
fiKey = fopen((CHAR*)szFileName, "wb");
|
||||||
|
fwrite(m_pdwKey, 1, TEA_KEY_SIZE, fiKey);
|
||||||
|
fclose(fiKey);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void CTinyEncrypt::WriteCHeaderFile(PSTR szFileName)
|
||||||
|
{
|
||||||
|
const BYTE bytXORKey = 0xAA;
|
||||||
|
BYTE* pbKey = reinterpret_cast<BYTE*>(m_pdwKey);
|
||||||
|
FILE *fiHeader;
|
||||||
|
|
||||||
|
// Generate the header file
|
||||||
|
fiHeader = fopen(szFileName, "wt");
|
||||||
|
fprintf(fiHeader, "//-----------------------------------------\n" );
|
||||||
|
fprintf(fiHeader, "// SAMP Archive 2 Tool - TEA Keys\n" );
|
||||||
|
fprintf(fiHeader, "//\n" );
|
||||||
|
fprintf(fiHeader, "// This file was automatically generated.\n" );
|
||||||
|
fprintf(fiHeader, "// Do not modify this file!\n" );
|
||||||
|
fprintf(fiHeader, "//-----------------------------------------\n" );
|
||||||
|
fprintf(fiHeader, "\n" );
|
||||||
|
fprintf(fiHeader, "#pragma once\n" );
|
||||||
|
fprintf(fiHeader, "\n" );
|
||||||
|
fprintf(fiHeader, "#define TEA_XOR_KEY %d\n", bytXORKey );
|
||||||
|
fprintf(fiHeader, "\n" );
|
||||||
|
fprintf(fiHeader, "#define TEA_KEY_SIZE %d\n", TEA_KEY_SIZE );
|
||||||
|
fprintf(fiHeader, "const BYTE TEA_KEY[] = \n\t{" );
|
||||||
|
for(DWORD i=0; i<TEA_KEY_SIZE; i++) {
|
||||||
|
fprintf(fiHeader, "0x%x%s", (pbKey[i] ^ bytXORKey), (i==(TEA_KEY_SIZE-1)?"};":",\t"));
|
||||||
|
if (((i+1) % 8) == 0) {
|
||||||
|
fprintf(fiHeader, "\n\t ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fiHeader);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -15,6 +15,10 @@ private:
|
|||||||
|
|
||||||
DWORD m_pdwKey[TEA_KEY_SIZE/sizeof(DWORD)];
|
DWORD m_pdwKey[TEA_KEY_SIZE/sizeof(DWORD)];
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void EncryptBlock(DWORD &dwV0, DWORD &dwV1);
|
||||||
|
#endif
|
||||||
|
|
||||||
void DecryptBlock(DWORD &dwV0, DWORD &dwV1);
|
void DecryptBlock(DWORD &dwV0, DWORD &dwV1);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -23,5 +27,13 @@ public:
|
|||||||
|
|
||||||
void SetKey(BYTE* pbKey, BYTE bytXORKey);
|
void SetKey(BYTE* pbKey, BYTE bytXORKey);
|
||||||
|
|
||||||
|
#ifdef ARCTOOL
|
||||||
|
void LoadKey(PCHAR szFileName);
|
||||||
|
void WriteKey(PCHAR szFileName);
|
||||||
|
void WriteCHeaderFile(PCHAR szFileName);
|
||||||
|
|
||||||
|
void EncryptData(DWORD dwLength, BYTE* pbData);
|
||||||
|
#endif
|
||||||
|
|
||||||
void DecryptData(DWORD dwLength, BYTE* pbData);
|
void DecryptData(DWORD dwLength, BYTE* pbData);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user