mirror of
https://github.com/dashr9230/SA-MP.git
synced 2024-12-22 22:47:29 +08:00
[saco] Implement archive functions
This commit is contained in:
parent
916d4d02f2
commit
8defa849b9
85
saco/archive/ArchiveCommon.h
Normal file
85
saco/archive/ArchiveCommon.h
Normal file
@ -0,0 +1,85 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include "Stream.h"
|
||||
|
||||
// SAA_FILE_ID := {'S', 'A', 'M', 'P'} ignoring first 3 bits of each char
|
||||
// first 3 bits are 010 anyhow :)
|
||||
#define SAA_FILE_ID 0x83433
|
||||
#define SAA_FILE_VERSION 2
|
||||
|
||||
#define SAA_MAX_ENTRIES 256
|
||||
|
||||
#define SAA_MAX_FAKEDATA 120
|
||||
|
||||
typedef struct _SAA_ENTRY
|
||||
{
|
||||
DWORD dwFileNameHash;
|
||||
int field_4;
|
||||
} SAA_ENTRY;
|
||||
|
||||
typedef struct _SAA_FILE_HEADER
|
||||
{
|
||||
// This is a fake header
|
||||
struct VER1_HEADER
|
||||
{
|
||||
DWORD dwSAAV;
|
||||
DWORD dwFileCount;
|
||||
WORD wFakeData[SAA_MAX_FAKEDATA];
|
||||
} headerV1; /* 248 bytes */
|
||||
|
||||
struct VER2_HEADER
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD dwSAMPID : 20;
|
||||
DWORD dwVersion : 3;
|
||||
DWORD dwSignSize : 8;
|
||||
DWORD dwPadding1 : 1;
|
||||
};
|
||||
DWORD dwCompleteID;
|
||||
};
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD dwPadding2 : 5;
|
||||
DWORD dwInvalidIndex : 8;
|
||||
DWORD dwPadding3 : 19;
|
||||
};
|
||||
DWORD dwXORKey;
|
||||
};
|
||||
} headerV2; /* 8 bytes */
|
||||
|
||||
DWORD dwFakeDataSize;
|
||||
|
||||
_SAA_FILE_HEADER()
|
||||
{
|
||||
dwFakeDataSize = SAA_MAX_FAKEDATA;
|
||||
}
|
||||
|
||||
DWORD SizeOf()
|
||||
{
|
||||
return(sizeof(DWORD)*2 + sizeof(WORD)*dwFakeDataSize + sizeof(VER2_HEADER));
|
||||
}
|
||||
|
||||
bool VerifyIdentifier()
|
||||
{
|
||||
return ((headerV2.dwSAMPID == SAA_FILE_ID) &&
|
||||
(headerV2.dwVersion == SAA_FILE_VERSION));
|
||||
}
|
||||
|
||||
void XorV2Identifier() {
|
||||
this->headerV2.dwCompleteID ^= this->headerV2.dwXORKey;
|
||||
}
|
||||
|
||||
void Read(CAbstractStream *pStream)
|
||||
{
|
||||
pStream->Read(&headerV1, sizeof(DWORD)*2 + sizeof(WORD)*dwFakeDataSize);
|
||||
pStream->Read(&headerV2, sizeof(VER2_HEADER));
|
||||
}
|
||||
|
||||
} SAA_FILE_HEADER;
|
128
saco/archive/ArchiveFS.cpp
Normal file
128
saco/archive/ArchiveFS.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
|
||||
#include "ArchiveFS.h"
|
||||
|
||||
#include "CryptoContext.h"
|
||||
#include "KeyPair.h"
|
||||
#include "Signer.h"
|
||||
#include "Hasher.h"
|
||||
#include "TinyEncrypt.h"
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CArchiveFS::CArchiveFS(void)
|
||||
{
|
||||
m_dwNumEntries = SAA_MAX_ENTRIES;
|
||||
m_bLoaded = false;
|
||||
m_bEntriesLoaded = false;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CArchiveFS::CArchiveFS(DWORD dwNumEntries, DWORD dwFDSize)
|
||||
{
|
||||
m_dwNumEntries = dwNumEntries;
|
||||
m_bLoaded = false;
|
||||
m_bEntriesLoaded = false;
|
||||
|
||||
m_Header.dwFakeDataSize = dwFDSize;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
void CArchiveFS::LoadEntries()
|
||||
{
|
||||
// Get the file signature, verify it... use the result to decode the entries table
|
||||
|
||||
// Verify the Archive Signature, and decode the Entry block
|
||||
CCryptoContext context;
|
||||
CKeyPair keyPair(&context);
|
||||
CHasher hasher(&context);
|
||||
CSigner signer;
|
||||
CTinyEncrypt tinyEnc;
|
||||
DWORD i;
|
||||
|
||||
// 1. Load the signature from the file
|
||||
DWORD dwSignSize = 128; //m_Header.headerV2.dwSignSize;
|
||||
BYTE *pbSignature;
|
||||
DWORD dwSignDataEnd;
|
||||
|
||||
pbSignature = new BYTE[dwSignSize];
|
||||
m_pStream->Seek(-(INT)dwSignSize, CAbstractStream::SeekEnd);
|
||||
dwSignDataEnd = m_pStream->Tell();
|
||||
m_pStream->Read(pbSignature, dwSignSize);
|
||||
|
||||
// 2. Hash the stuff (excluding the header and signature!)
|
||||
BYTE *pbReadData;
|
||||
DWORD dwReadSize;
|
||||
const DWORD dwReadBlockSize = 10 * 1024; // 10kb
|
||||
|
||||
m_pStream->Seek(m_Header.SizeOf()); // start from the actual data section
|
||||
pbReadData = new BYTE[dwReadBlockSize];
|
||||
for(i=m_Header.SizeOf(); i<dwSignDataEnd; ) {
|
||||
dwReadSize = m_pStream->Read(pbReadData, dwReadBlockSize);
|
||||
if (i+dwReadSize > dwSignDataEnd)
|
||||
hasher.AddData(dwSignDataEnd - i, pbReadData);
|
||||
else
|
||||
hasher.AddData(dwReadSize, pbReadData);
|
||||
i += dwReadSize;
|
||||
}
|
||||
delete[] pbReadData;
|
||||
|
||||
// 3. Load the key and verify the signature
|
||||
BOOL bVerified;
|
||||
|
||||
keyPair.LoadFromMemory(RSA_PUB_KEY_SIZE, (BYTE*)RSA_PUB_KEY, RSA_XOR_KEY);
|
||||
signer.SetSignature(dwSignSize, pbSignature);
|
||||
bVerified = signer.VerifySignature(&hasher, &keyPair);
|
||||
|
||||
delete[] pbSignature;
|
||||
|
||||
// Set the obfuscation decoding mask based on the bVerified value
|
||||
m_dwObfsMask = -((INT)bVerified); // if its 1 (true), then 0xffffffff, else 0.
|
||||
|
||||
// 4. Decode the TEA encrypted archive entry
|
||||
|
||||
m_pStream->Seek((dwSignDataEnd - m_dwNumEntries*sizeof(SAA_ENTRY)));
|
||||
DWORD dwFilePos = m_pStream->Tell();
|
||||
m_pStream->Read(m_pEntries, sizeof(SAA_ENTRY), m_dwNumEntries);
|
||||
dwFilePos = m_pStream->Tell();
|
||||
|
||||
tinyEnc.SetKey((BYTE*)TEA_KEY, TEA_XOR_KEY);
|
||||
tinyEnc.DecryptData(sizeof(SAA_ENTRY)*m_dwNumEntries, reinterpret_cast<BYTE*>(m_pEntries));
|
||||
|
||||
// 5. Build a binary tree of the entries.. it makes searching for files faster (since we have a
|
||||
// huge index with fake entries)
|
||||
for(i=0; i<m_dwNumEntries; i++) {
|
||||
m_EntryBTreeRoot.AddEntry(&m_pEntries[i]);
|
||||
}
|
||||
|
||||
// Done.
|
||||
|
||||
m_bEntriesLoaded = true;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
bool CArchiveFS::Load(char* szFileName)
|
||||
{
|
||||
if (m_bLoaded)
|
||||
Unload();
|
||||
|
||||
m_pStream = new CFileStream(szFileName, CFileStream::TypeBinary, CFileStream::ModeRead);
|
||||
|
||||
m_Header.Read(m_pStream);
|
||||
|
||||
m_Header.XorV2Identifier();
|
||||
|
||||
m_bLoaded = true;
|
||||
|
||||
if (!m_Header.VerifyIdentifier()) {
|
||||
Unload();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
88
saco/archive/ArchiveFS.h
Normal file
88
saco/archive/ArchiveFS.h
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "ArchiveCommon.h"
|
||||
#include "Stream.h"
|
||||
|
||||
#include "../mod.h"
|
||||
|
||||
#include "../filesystem.h"
|
||||
|
||||
typedef struct _AFS_ENTRYBT_NODE
|
||||
{
|
||||
SAA_ENTRY* pEntry;
|
||||
_AFS_ENTRYBT_NODE* pLNode;
|
||||
_AFS_ENTRYBT_NODE* pRNode;
|
||||
BYTE* pbData;
|
||||
|
||||
_AFS_ENTRYBT_NODE()
|
||||
{
|
||||
this->pEntry = NULL;
|
||||
this->pLNode = NULL;
|
||||
this->pRNode = NULL;
|
||||
this->pbData = NULL;
|
||||
}
|
||||
|
||||
_AFS_ENTRYBT_NODE(SAA_ENTRY* pSAAEntry)
|
||||
{
|
||||
this->pEntry = pSAAEntry;
|
||||
this->pLNode = NULL;
|
||||
this->pRNode = NULL;
|
||||
this->pbData = NULL;
|
||||
}
|
||||
|
||||
void AddEntry(SAA_ENTRY* pSAAEntry)
|
||||
{
|
||||
if (this->pEntry == NULL) {
|
||||
this->pEntry = pSAAEntry;
|
||||
} else {
|
||||
if (pSAAEntry->dwFileNameHash < this->pEntry->dwFileNameHash) {
|
||||
if (this->pLNode == NULL)
|
||||
this->pLNode = new _AFS_ENTRYBT_NODE(pSAAEntry);
|
||||
else
|
||||
this->pLNode->AddEntry(pSAAEntry);
|
||||
} else {
|
||||
if (this->pRNode == NULL)
|
||||
this->pRNode = new _AFS_ENTRYBT_NODE(pSAAEntry);
|
||||
else
|
||||
this->pRNode->AddEntry(pSAAEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} AFS_ENTRYBT_NODE;
|
||||
|
||||
class CArchiveFS // size: 2357
|
||||
: public CFileSystem
|
||||
{
|
||||
private:
|
||||
bool m_bLoaded;
|
||||
CAbstractStream *m_pStream;
|
||||
bool m_bEntriesLoaded;
|
||||
SAA_FILE_HEADER m_Header;
|
||||
SAA_ENTRY m_pEntries[SAA_MAX_ENTRIES];
|
||||
AFS_ENTRYBT_NODE m_EntryBTreeRoot;
|
||||
DWORD m_dwObfsMask;
|
||||
DWORD m_dwNumEntries;
|
||||
|
||||
void LoadEntries();
|
||||
|
||||
public:
|
||||
CArchiveFS(void);
|
||||
CArchiveFS(DWORD dwNumEntries, DWORD dwFDSize);
|
||||
|
||||
virtual bool Load(char* szFileName);
|
||||
|
||||
// TODO: CArchiveFS vftable 100E9AA8
|
||||
void CArchiveFS__sub_10065590() {};
|
||||
void CArchiveFS__sub_100654A0() {};
|
||||
void CArchiveFS__sub_10064E10() {};
|
||||
void CArchiveFS__sub_10064EC0() {};
|
||||
void CArchiveFS__sub_10064F20() {};
|
||||
void CArchiveFS__sub_10064F60() {};
|
||||
void CArchiveFS__sub_10064D30() {};
|
||||
void CArchiveFS__sub_10064E40() {};
|
||||
void CArchiveFS__sub_10065150() {};
|
||||
};
|
61
saco/archive/CryptoContext.cpp
Normal file
61
saco/archive/CryptoContext.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
#include "CryptoContext.h"
|
||||
#include "CryptoFns.h"
|
||||
|
||||
//------------------------------------
|
||||
|
||||
DWORD CCryptoContext::ms_dwRefCount = 0;
|
||||
DWORD CCryptoContext::ms_dwProviderType = PROV_RSA_FULL;
|
||||
LPTSTR CCryptoContext::ms_szProviderName = NULL;
|
||||
LPTSTR CCryptoContext::ms_szContainerName = (LPTSTR)"SAMP";
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CCryptoContext::CCryptoContext(void)
|
||||
{
|
||||
/*
|
||||
if (!ms_hAdvApi32)
|
||||
{
|
||||
ms_hAdvApi32 = LoadLibrary("advapi32.dll");
|
||||
}
|
||||
*/
|
||||
|
||||
// Open existing context, if not found, create one!
|
||||
if ( !CRYPT(AcquireContext)(&m_hCryptProv, ms_szContainerName, ms_szProviderName, ms_dwProviderType, 0) ) {
|
||||
if( !CRYPT(AcquireContext)(&m_hCryptProv, ms_szContainerName, ms_szProviderName, ms_dwProviderType, CRYPT_NEWKEYSET) ) {
|
||||
throw(1);
|
||||
}
|
||||
}
|
||||
|
||||
ms_dwRefCount++;
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CCryptoContext::~CCryptoContext(void)
|
||||
{
|
||||
// Release the context
|
||||
CRYPT(ReleaseContext)(m_hCryptProv, 0);
|
||||
ms_dwRefCount--;
|
||||
|
||||
if (ms_dwRefCount == 0) {
|
||||
/*
|
||||
// Free the library
|
||||
if (ms_hAdvApi32)
|
||||
FreeLibrary(ms_hAdvApi32);
|
||||
*/
|
||||
|
||||
// Delete the context
|
||||
CRYPT(AcquireContext)(&m_hCryptProv, ms_szContainerName, ms_szProviderName, ms_dwProviderType, CRYPT_DELETEKEYSET);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
HCRYPTPROV CCryptoContext::GetProvider()
|
||||
{
|
||||
return m_hCryptProv;
|
||||
}
|
||||
|
||||
//------------------------------------
|
21
saco/archive/CryptoContext.h
Normal file
21
saco/archive/CryptoContext.h
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
class CCryptoContext
|
||||
{
|
||||
private:
|
||||
static DWORD ms_dwRefCount;
|
||||
static DWORD ms_dwProviderType;
|
||||
static LPTSTR ms_szProviderName;
|
||||
static LPTSTR ms_szContainerName;
|
||||
|
||||
HCRYPTPROV m_hCryptProv;
|
||||
|
||||
public:
|
||||
CCryptoContext(void);
|
||||
~CCryptoContext(void);
|
||||
|
||||
HCRYPTPROV GetProvider();
|
||||
};
|
3
saco/archive/CryptoFns.cpp
Normal file
3
saco/archive/CryptoFns.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
#define CRYPT_FN_CPP
|
||||
#include "CryptoFns.h"
|
112
saco/archive/CryptoFns.h
Normal file
112
saco/archive/CryptoFns.h
Normal file
@ -0,0 +1,112 @@
|
||||
|
||||
// This is intended to be a wrapper for Obfuscating calls
|
||||
// to CryptoAPI. Make sure that LoadLibrary("ADVAPI32.DLL") is
|
||||
// somewhere (i.e. access some random reg key), otherwise this
|
||||
// will fail.. miserably.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef ARCTOOL
|
||||
|
||||
/*
|
||||
const CHAR* CRYPT_MODULE = "advapi32";
|
||||
const CHAR* CRYPT_FN_AcquireContext = "CryptAcquireContextA";
|
||||
const CHAR* CRYPT_FN_ReleaseContext = "CryptReleaseContext";
|
||||
const CHAR* CRYPT_FN_GenRandom = "CryptGenRandom";
|
||||
const CHAR* CRYPT_FN_CreateHash = "CryptCreateHash";
|
||||
const CHAR* CRYPT_FN_DestroyHash = "CryptDestroyHash";
|
||||
const CHAR* CRYPT_FN_HashData = "CryptHashData";
|
||||
const CHAR* CRYPT_FN_DestroyKey = "CryptDestroyKey";
|
||||
const CHAR* CRYPT_FN_ImportKey = "CryptImportKey";
|
||||
const CHAR* CRYPT_FN_VerifySignature = "CryptVerifySignatureA";
|
||||
*/
|
||||
|
||||
const CHAR CRYPT_MODULE[] = "41#4%<fgU";
|
||||
const CHAR CRYPT_FN_AcquireContext[] = {0x16,0x27,0x2C,0x25,0x21,0x14,0x36,0x24,
|
||||
0x20,0x3C,0x27,0x30,0x16,0x3A,0x3B,0x21,
|
||||
0x30,0x2D,0x21,0x14,0x55,0x00,0x00,0x00};
|
||||
const CHAR CRYPT_FN_ReleaseContext[] = {0x16,0x27,0x2C,0x25,0x21,0x07,0x30,0x39,
|
||||
0x30,0x34,0x26,0x30,0x16,0x3A,0x3B,0x21,
|
||||
0x30,0x2D,0x21,0x55,0x00,0x00,0x00,0x00,};
|
||||
const CHAR CRYPT_FN_CreateHash[] = {0x16,0x27,0x2C,0x25,0x21,0x16,0x27,0x30,
|
||||
0x34,0x21,0x30,0x1D,0x34,0x26,0x3D,0x55};
|
||||
const CHAR CRYPT_FN_DestroyHash[] = {0x16,0x27,0x2C,0x25,0x21,0x11,0x30,0x26,
|
||||
0x21,0x27,0x3A,0x2C,0x1D,0x34,0x26,0x3D,
|
||||
0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||
const CHAR CRYPT_FN_HashData[] = {0x16,0x27,0x2C,0x25,0x21,0x1D,0x34,0x26,
|
||||
0x3D,0x11,0x34,0x21,0x34,0x55,0x00,0x00};
|
||||
const CHAR CRYPT_FN_DestroyKey[] = {0x16,0x27,0x2C,0x25,0x21,0x11,0x30,0x26,
|
||||
0x21,0x27,0x3A,0x2C,0x1E,0x30,0x2C,0x55};
|
||||
const CHAR CRYPT_FN_ImportKey[] = {0x16,0x27,0x2C,0x25,0x21,0x1C,0x38,0x25,
|
||||
0x3A,0x27,0x21,0x1E,0x30,0x2C,0x55,0x00};
|
||||
const CHAR CRYPT_FN_VerifySignature[] = {0x16,0x27,0x2C,0x25,0x21,0x03,0x30,0x27,
|
||||
0x3C,0x33,0x2C,0x06,0x3C,0x32,0x3B,0x34,
|
||||
0x21,0x20,0x27,0x30,0x14,0x55,0x00,0x00};
|
||||
|
||||
#define CRYPT_GET_NAME(a,b) \
|
||||
CHAR* a = NULL; \
|
||||
{ \
|
||||
DWORD dwFnLen = strlen(b); \
|
||||
a = new CHAR[dwFnLen]; \
|
||||
for(DWORD i=0; i<dwFnLen; i++) \
|
||||
##a[i] = (CHAR)(##b[i] ^ 0x55); \
|
||||
}
|
||||
|
||||
#ifndef CRYPT_FN_CPP
|
||||
|
||||
#define CRYPT_IMPL_FN(n,r,p) \
|
||||
r WINAPI xCryptCall##n##p;
|
||||
|
||||
#else
|
||||
|
||||
// This is for the actual function when in the .CPP
|
||||
#define CRYPT_IMPL_FN(n,r,p) \
|
||||
DWORD xCryptOffs##n = NULL; \
|
||||
__declspec(naked) r WINAPI xCryptCall##n##p \
|
||||
{ \
|
||||
if (xCryptOffs##n == NULL) { \
|
||||
_asm { lea eax, CRYPT_FN_##n }; \
|
||||
_asm { push eax }; \
|
||||
_asm { call xCryptGetFunction }; \
|
||||
_asm { add esp, 4 }; \
|
||||
_asm { mov dword ptr xCryptOffs##n, eax }; \
|
||||
} \
|
||||
_asm { mov eax, dword ptr xCryptOffs##n }; \
|
||||
_asm { jmp eax }; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CRYPT_FN_CPP
|
||||
|
||||
FARPROC xCryptGetFunction(CHAR* name, DWORD len)
|
||||
{
|
||||
CRYPT_GET_NAME(szModName, CRYPT_MODULE);
|
||||
CRYPT_GET_NAME(szProcName, name);
|
||||
HMODULE hMod = GetModuleHandle(szModName);
|
||||
FARPROC fpProc = GetProcAddress(hMod, szProcName);
|
||||
return fpProc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define CRYPT(n) \
|
||||
xCryptCall##n
|
||||
|
||||
CRYPT_IMPL_FN(AcquireContext, BOOL, (HCRYPTPROV* phProv, LPCTSTR pszContainer, LPCTSTR pszProvider, DWORD dwProvType, DWORD dwFlags))
|
||||
CRYPT_IMPL_FN(ReleaseContext, BOOL, (HCRYPTPROV hProv, DWORD dwFlags))
|
||||
CRYPT_IMPL_FN(CreateHash, BOOL, (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH* phHash))
|
||||
CRYPT_IMPL_FN(DestroyHash, BOOL, (HCRYPTHASH hHash))
|
||||
CRYPT_IMPL_FN(HashData, BOOL, (HCRYPTHASH hHash, BYTE* pbData, DWORD dwDataLen, DWORD dwFlags))
|
||||
CRYPT_IMPL_FN(DestroyKey, BOOL, (HCRYPTKEY hKey))
|
||||
CRYPT_IMPL_FN(ImportKey, BOOL, (HCRYPTPROV hProv, BYTE* pbData, DWORD dwDataLen, HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY* phKey))
|
||||
CRYPT_IMPL_FN(VerifySignature, BOOL, (HCRYPTHASH hHash, BYTE* pbSignature, DWORD dwSigLen, HCRYPTKEY hPubKey, LPCTSTR sDescription, DWORD dwFlags))
|
||||
|
||||
#else
|
||||
|
||||
#define CRYPT(n) \
|
||||
Crypt##n
|
||||
|
||||
#endif
|
44
saco/archive/Hasher.cpp
Normal file
44
saco/archive/Hasher.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
#include "Hasher.h"
|
||||
#include "CryptoFns.h"
|
||||
|
||||
//------------------------------------
|
||||
|
||||
DWORD CHasher::ms_dwHashAlgorithm = CALG_SHA1;
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CHasher::CHasher(CCryptoContext* pContext)
|
||||
{
|
||||
// Save context for later
|
||||
m_pContext = pContext;
|
||||
|
||||
// Generate a hash container
|
||||
HCRYPTPROV hCryptProv = pContext->GetProvider();
|
||||
CRYPT(CreateHash)(hCryptProv, ms_dwHashAlgorithm, NULL, NULL, &m_hCryptHash);
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CHasher::~CHasher(void)
|
||||
{
|
||||
// Destory the hash container
|
||||
CRYPT(DestroyHash)(m_hCryptHash);
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
void CHasher::AddData(DWORD dwDataLength, BYTE *pbData)
|
||||
{
|
||||
// Add the data to be hashed
|
||||
CRYPT(HashData)(m_hCryptHash, pbData, dwDataLength, 0);
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
HCRYPTKEY CHasher::GetContainer()
|
||||
{
|
||||
return m_hCryptHash;
|
||||
}
|
||||
|
||||
//------------------------------------
|
22
saco/archive/Hasher.h
Normal file
22
saco/archive/Hasher.h
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include "CryptoContext.h"
|
||||
|
||||
class CHasher
|
||||
{
|
||||
private:
|
||||
static DWORD ms_dwHashAlgorithm;
|
||||
|
||||
HCRYPTHASH m_hCryptHash;
|
||||
CCryptoContext* m_pContext;
|
||||
|
||||
public:
|
||||
CHasher(CCryptoContext* pContext);
|
||||
~CHasher(void);
|
||||
|
||||
void AddData(DWORD dwDataLength, BYTE* pbData);
|
||||
HCRYPTHASH GetContainer();
|
||||
|
||||
};
|
62
saco/archive/KeyPair.cpp
Normal file
62
saco/archive/KeyPair.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
|
||||
#include "KeyPair.h"
|
||||
#include "CryptoFns.h"
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CKeyPair::CKeyPair(CCryptoContext* pContext)
|
||||
{
|
||||
m_pContext = pContext;
|
||||
m_hCryptKey = NULL;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CKeyPair::~CKeyPair(void)
|
||||
{
|
||||
if (m_hCryptKey != NULL)
|
||||
ReleaseKey();
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
void CKeyPair::ReleaseKey()
|
||||
{
|
||||
// Destroy the key pair
|
||||
CRYPT(DestroyKey)(m_hCryptKey);
|
||||
m_hCryptKey = NULL;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
void CKeyPair::LoadFromMemory(DWORD dwPubKeySize, BYTE* pbPubKeyBlob, BYTE bytXORKey)
|
||||
{
|
||||
BYTE *pbKeyBlob;
|
||||
|
||||
// Un-XOR keys from memory
|
||||
if (bytXORKey != 0) {
|
||||
pbKeyBlob = new BYTE[dwPubKeySize];
|
||||
for(DWORD i=0; i<dwPubKeySize; i++)
|
||||
pbKeyBlob[i] = pbPubKeyBlob[i] ^ bytXORKey;
|
||||
} else {
|
||||
pbKeyBlob = pbPubKeyBlob;
|
||||
}
|
||||
|
||||
// Import the key
|
||||
HCRYPTPROV hCryptProv = m_pContext->GetProvider();
|
||||
CRYPT(ImportKey)(hCryptProv, pbKeyBlob, dwPubKeySize, NULL, NULL, &m_hCryptKey);
|
||||
|
||||
// Clean up
|
||||
if (bytXORKey != 0) {
|
||||
delete[] pbKeyBlob;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
HCRYPTKEY CKeyPair::GetContainer()
|
||||
{
|
||||
return m_hCryptKey;
|
||||
}
|
||||
|
||||
//------------------------------------
|
21
saco/archive/KeyPair.h
Normal file
21
saco/archive/KeyPair.h
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include "CryptoContext.h"
|
||||
|
||||
class CKeyPair
|
||||
{
|
||||
private:
|
||||
HCRYPTKEY m_hCryptKey;
|
||||
CCryptoContext* m_pContext;
|
||||
|
||||
public:
|
||||
CKeyPair(CCryptoContext* pContext);
|
||||
~CKeyPair(void);
|
||||
|
||||
void LoadFromMemory(DWORD dwPubKeySize, BYTE* pbPubKeyBlob, BYTE bytXORKey);
|
||||
void ReleaseKey();
|
||||
|
||||
HCRYPTKEY GetContainer();
|
||||
};
|
6
saco/archive/Obfuscator.h
Normal file
6
saco/archive/Obfuscator.h
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define OBFUSCATE_KEY 0xC103D3E7
|
||||
#define OBFUSCATE_DATA(a) ((((a) << 19) | ((a) >> 13)) ^ OBFUSCATE_KEY)
|
||||
#define UNOBFUSCATE_DATA(a) ((((a) ^ OBFUSCATE_KEY) >> 19) | (((a) ^ OBFUSCATE_KEY) << 13))
|
46
saco/archive/Signer.cpp
Normal file
46
saco/archive/Signer.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
#include "Signer.h"
|
||||
#include "CryptoFns.h"
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CSigner::CSigner(void)
|
||||
{
|
||||
m_dwLength = 0;
|
||||
m_pbSignature = NULL;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CSigner::~CSigner(void)
|
||||
{
|
||||
if (m_pbSignature != NULL)
|
||||
delete[] m_pbSignature;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
void CSigner::SetSignature(DWORD dwLength, BYTE *pbSignature)
|
||||
{
|
||||
if (m_pbSignature != NULL)
|
||||
delete[] m_pbSignature;
|
||||
|
||||
m_dwLength = dwLength;
|
||||
m_pbSignature = new BYTE[dwLength];
|
||||
memcpy(m_pbSignature, pbSignature, m_dwLength);
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
BOOL CSigner::VerifySignature(CHasher *pHasher, CKeyPair *pKeyPair)
|
||||
{
|
||||
HCRYPTHASH hCryptHash = pHasher->GetContainer();
|
||||
HCRYPTKEY hCryptKey = pKeyPair->GetContainer();
|
||||
BOOL bVerify;
|
||||
|
||||
bVerify = CRYPT(VerifySignature)(hCryptHash, m_pbSignature, m_dwLength, hCryptKey, NULL, CRYPT_NOHASHOID);
|
||||
|
||||
return bVerify;
|
||||
}
|
||||
|
||||
//------------------------------------
|
21
saco/archive/Signer.h
Normal file
21
saco/archive/Signer.h
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include "Hasher.h"
|
||||
#include "KeyPair.h"
|
||||
|
||||
class CSigner
|
||||
{
|
||||
private:
|
||||
BYTE* m_pbSignature;
|
||||
DWORD m_dwLength;
|
||||
|
||||
public:
|
||||
CSigner(void);
|
||||
~CSigner(void);
|
||||
|
||||
void SetSignature(DWORD dwLength, BYTE* pbSignature);
|
||||
BOOL VerifySignature(CHasher* pHasher, CKeyPair* pKeyPair);
|
||||
|
||||
};
|
248
saco/archive/Stream.h
Normal file
248
saco/archive/Stream.h
Normal file
@ -0,0 +1,248 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class CAbstractStream
|
||||
{
|
||||
public:
|
||||
enum eSeek
|
||||
{
|
||||
SeekStart,
|
||||
SeekCurrent,
|
||||
SeekEnd,
|
||||
};
|
||||
|
||||
CAbstractStream() {}
|
||||
|
||||
virtual ~CAbstractStream() {}
|
||||
|
||||
virtual unsigned int Read(void *pbBuffer, int nNumberOfBytes) = 0;
|
||||
|
||||
virtual unsigned int Read(void *pbBuffer, int nElementSize, int nNumberOfElements)
|
||||
{
|
||||
return Read(pbBuffer, nNumberOfElements * nElementSize);
|
||||
}
|
||||
|
||||
virtual unsigned int Write(const void *pbBuffer, int nNumberOfBytes) = 0;
|
||||
|
||||
virtual unsigned int Write(const void *pbBuffer, int nElementSize, int nNumberOfElements)
|
||||
{
|
||||
return Write(pbBuffer, nNumberOfElements * nElementSize);
|
||||
}
|
||||
|
||||
virtual void Seek(int nOffset, eSeek seekMode) = 0;
|
||||
|
||||
virtual void Seek(int nOffset)
|
||||
{
|
||||
Seek(nOffset, SeekStart);
|
||||
}
|
||||
|
||||
virtual unsigned int Tell() = 0;
|
||||
};
|
||||
|
||||
class CFileStream :
|
||||
public CAbstractStream
|
||||
{
|
||||
protected:
|
||||
FILE *m_fiFile;
|
||||
|
||||
public:
|
||||
enum eMode
|
||||
{
|
||||
ModeRead,
|
||||
ModeReadWrite,
|
||||
ModeAppend,
|
||||
ModeWrite,
|
||||
};
|
||||
|
||||
enum eType
|
||||
{
|
||||
TypeText,
|
||||
TypeBinary,
|
||||
};
|
||||
|
||||
CFileStream(const char *szFilename, eType type, eMode mode)
|
||||
{
|
||||
m_fiFile = NULL;
|
||||
Open(szFilename, type, mode);
|
||||
}
|
||||
|
||||
virtual ~CFileStream()
|
||||
{
|
||||
if (m_fiFile)
|
||||
Close();
|
||||
}
|
||||
|
||||
virtual bool Open(const char *szFilename, eType type, eMode mode)
|
||||
{
|
||||
if (m_fiFile)
|
||||
Close();
|
||||
|
||||
char szMode[4];
|
||||
int nPos = 0;
|
||||
szMode[0] = szMode[1] = szMode[2] = szMode[3] = 0;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case ModeRead:
|
||||
szMode[nPos++] = 'r'; break;
|
||||
case ModeWrite:
|
||||
szMode[nPos++] = 'w'; break;
|
||||
case ModeReadWrite:
|
||||
szMode[nPos++] = 'r'; szMode[nPos++] = '+'; break;
|
||||
case ModeAppend:
|
||||
szMode[nPos++] = 'a'; break;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case TypeText:
|
||||
szMode[nPos++] = 't'; break;
|
||||
case TypeBinary:
|
||||
szMode[nPos++] = 'b'; break;
|
||||
}
|
||||
|
||||
m_fiFile = fopen(szFilename, szMode);
|
||||
if (!m_fiFile)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool IsOpen()
|
||||
{
|
||||
return (m_fiFile != NULL);
|
||||
}
|
||||
|
||||
virtual void Close()
|
||||
{
|
||||
if (m_fiFile)
|
||||
{
|
||||
fclose(m_fiFile);
|
||||
m_fiFile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned int Read(void *pbBuffer, int nNumberOfBytes)
|
||||
{
|
||||
return (unsigned int)fread(pbBuffer, 1, nNumberOfBytes, m_fiFile);
|
||||
}
|
||||
|
||||
virtual unsigned int Read(void *pbBuffer, int nElementSize, int nNumberOfElements)
|
||||
{
|
||||
return (unsigned int)fread(pbBuffer, nElementSize, nNumberOfElements, m_fiFile);
|
||||
}
|
||||
|
||||
virtual unsigned int Write(const void *pbBuffer, int nNumberOfBytes)
|
||||
{
|
||||
return (unsigned int)fwrite(pbBuffer, 1, nNumberOfBytes, m_fiFile);
|
||||
}
|
||||
|
||||
virtual unsigned int Write(const void *pbBuffer, int nElementSize, int nNumberOfElements)
|
||||
{
|
||||
return (unsigned int)fwrite(pbBuffer, nElementSize, nNumberOfElements, m_fiFile);
|
||||
}
|
||||
|
||||
virtual void Seek(int nOffset, eSeek seekMode)
|
||||
{
|
||||
int mode = 0;
|
||||
switch (seekMode)
|
||||
{
|
||||
case SeekCurrent:
|
||||
mode = SEEK_CUR; break;
|
||||
case SeekStart:
|
||||
mode = SEEK_SET; break;
|
||||
case SeekEnd:
|
||||
mode = SEEK_END; break;
|
||||
}
|
||||
|
||||
fseek(m_fiFile, nOffset, seekMode);
|
||||
}
|
||||
|
||||
virtual unsigned int Tell()
|
||||
{
|
||||
return (unsigned int)ftell(m_fiFile);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class CMemoryStream :
|
||||
public CAbstractStream
|
||||
{
|
||||
protected:
|
||||
unsigned char *m_pbBuffer;
|
||||
unsigned int m_nOffset;
|
||||
unsigned int m_nLength;
|
||||
bool m_bCopy;
|
||||
|
||||
public:
|
||||
CMemoryStream(unsigned char *pbBuffer, unsigned int nLength, bool bCopy = true)
|
||||
{
|
||||
m_bCopy = bCopy;
|
||||
m_nOffset = 0;
|
||||
m_nLength = nLength;
|
||||
|
||||
if (bCopy)
|
||||
{
|
||||
m_pbBuffer = (unsigned char *)malloc(nLength);
|
||||
memcpy(m_pbBuffer, pbBuffer, nLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pbBuffer = pbBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~CMemoryStream()
|
||||
{
|
||||
if (m_bCopy && m_pbBuffer)
|
||||
{
|
||||
free(m_pbBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned int Read(void *pbBuffer, int nNumberOfBytes)
|
||||
{
|
||||
if (m_nOffset + nNumberOfBytes > m_nLength)
|
||||
nNumberOfBytes = m_nLength - m_nOffset;
|
||||
|
||||
memcpy(pbBuffer, m_pbBuffer + m_nOffset, nNumberOfBytes);
|
||||
m_nOffset += nNumberOfBytes;
|
||||
|
||||
return nNumberOfBytes;
|
||||
}
|
||||
|
||||
virtual unsigned int Write(const void *pbBuffer, int nNumberOfBytes)
|
||||
{
|
||||
if (m_nOffset + nNumberOfBytes > m_nLength)
|
||||
nNumberOfBytes = m_nLength - m_nOffset;
|
||||
|
||||
memcpy(m_pbBuffer + m_nOffset, pbBuffer, nNumberOfBytes);
|
||||
m_nOffset += nNumberOfBytes;
|
||||
|
||||
return nNumberOfBytes;
|
||||
}
|
||||
|
||||
virtual void Seek(int nOffset, eSeek seekMode)
|
||||
{
|
||||
switch(seekMode)
|
||||
{
|
||||
case SeekStart:
|
||||
m_nOffset = nOffset; break;
|
||||
case SeekCurrent:
|
||||
m_nOffset += nOffset; break;
|
||||
case SeekEnd:
|
||||
m_nOffset = m_nLength + nOffset; break;
|
||||
}
|
||||
|
||||
if (m_nOffset > m_nLength)
|
||||
m_nOffset = m_nLength;
|
||||
}
|
||||
|
||||
virtual unsigned int Tell()
|
||||
{
|
||||
return m_nOffset;
|
||||
}
|
||||
|
||||
};
|
75
saco/archive/TinyEncrypt.cpp
Normal file
75
saco/archive/TinyEncrypt.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
|
||||
#include "TinyEncrypt.h"
|
||||
#include "Obfuscator.h"
|
||||
|
||||
//------------------------------------
|
||||
|
||||
DWORD CTinyEncrypt::ms_dwRounds = 32;
|
||||
DWORD CTinyEncrypt::ms_dwInitDelta = OBFUSCATE_DATA(0x9E3779B9);
|
||||
DWORD CTinyEncrypt::ms_dwInitSum = 0;
|
||||
BOOL CTinyEncrypt::ms_bInitDone = FALSE;
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CTinyEncrypt::CTinyEncrypt(void)
|
||||
{
|
||||
if (!ms_bInitDone) {
|
||||
ms_dwInitDelta = UNOBFUSCATE_DATA(ms_dwInitDelta);
|
||||
ms_dwInitSum = ms_dwInitDelta * ms_dwRounds;
|
||||
ms_bInitDone = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
CTinyEncrypt::~CTinyEncrypt(void)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
void CTinyEncrypt::SetKey(BYTE *pbKey, BYTE bytXORKey)
|
||||
{
|
||||
memcpy(m_pdwKey, pbKey, TEA_KEY_SIZE);
|
||||
|
||||
if (bytXORKey != 0)
|
||||
{
|
||||
BYTE *pbKeyRef = reinterpret_cast<BYTE*>(m_pdwKey);
|
||||
for(DWORD i=0; i<TEA_KEY_SIZE; i++)
|
||||
pbKeyRef[i] ^= bytXORKey;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
void CTinyEncrypt::DecryptBlock(DWORD &dwV0, DWORD &dwV1)
|
||||
{
|
||||
DWORD dwSum = ms_dwInitSum;
|
||||
|
||||
DWORD dwV0old = dwV0;
|
||||
DWORD dwV1old = dwV1;
|
||||
|
||||
for(DWORD i=0; i<ms_dwRounds; i++) {
|
||||
dwV1 -= ((dwV0 << 4 ^ dwV0 >> 5) + dwV0) ^ (dwSum + m_pdwKey[dwSum>>11 & 3]);
|
||||
dwSum -= ms_dwInitDelta;
|
||||
dwV0 -= ((dwV1 << 4 ^ dwV1 >> 5) + dwV1) ^ (dwSum + m_pdwKey[dwSum & 3]);
|
||||
}
|
||||
|
||||
m_pdwKey[0] ^= dwV0old;
|
||||
m_pdwKey[1] ^= dwV1old;
|
||||
m_pdwKey[2] ^= dwV0old;
|
||||
m_pdwKey[3] ^= dwV1old;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
void CTinyEncrypt::DecryptData(DWORD dwLength, BYTE *pbData)
|
||||
{
|
||||
DWORD dwBlocks = dwLength / 4;
|
||||
DWORD *pdwData = reinterpret_cast<DWORD*>(pbData);
|
||||
for(DWORD i=0; i<dwBlocks; i+=2) {
|
||||
DecryptBlock(pdwData[i+0], pdwData[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------
|
27
saco/archive/TinyEncrypt.h
Normal file
27
saco/archive/TinyEncrypt.h
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define TEA_KEY_SIZE 16
|
||||
|
||||
class CTinyEncrypt
|
||||
{
|
||||
private:
|
||||
static DWORD ms_dwRounds;
|
||||
static DWORD ms_dwInitDelta;
|
||||
static DWORD ms_dwInitSum;
|
||||
static BOOL ms_bInitDone;
|
||||
|
||||
DWORD m_pdwKey[TEA_KEY_SIZE/sizeof(DWORD)];
|
||||
|
||||
void DecryptBlock(DWORD &dwV0, DWORD &dwV1);
|
||||
|
||||
public:
|
||||
CTinyEncrypt(void);
|
||||
~CTinyEncrypt(void);
|
||||
|
||||
void SetKey(BYTE* pbKey, BYTE bytXORKey);
|
||||
|
||||
void DecryptData(DWORD dwLength, BYTE* pbData);
|
||||
};
|
@ -6,6 +6,8 @@ HANDLE hInstance=0;
|
||||
|
||||
CGame *pGame=0;
|
||||
|
||||
CFileSystem *pFileSystem=NULL;
|
||||
|
||||
// forwards
|
||||
|
||||
LONG WINAPI exc_handler(_EXCEPTION_POINTERS* exc_inf);
|
||||
@ -20,34 +22,17 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
if(tSettings.bDebug || tSettings.bPlayOnline)
|
||||
{
|
||||
SetUnhandledExceptionFilter(exc_handler);
|
||||
//dword_1026EB3C = (int)sub_100C4FF0;
|
||||
|
||||
// TODO: DllMain
|
||||
/*
|
||||
dword_1026EB3C = (int)sub_100C4FF0;
|
||||
GetModuleFileNameA((HMODULE)hInstance, &Filename, 0x104u);
|
||||
v3 = strlen(&Filename);
|
||||
if ( *(&Filename + v3) != 92 )
|
||||
{
|
||||
do
|
||||
v4 = *((_BYTE *)&v12 + v3-- + 3);
|
||||
while ( v4 != 92 );
|
||||
}
|
||||
v5 = &v15[v3];
|
||||
*(_DWORD *)v5 = 1886216563;
|
||||
*((_DWORD *)v5 + 1) = 1633776430;
|
||||
v5[8] = 0;
|
||||
v6 = operator new(0x935u);
|
||||
v12 = v6;
|
||||
v16 = 0;
|
||||
if ( v6 )
|
||||
v7 = (int *)sub_10065350(v6);
|
||||
else
|
||||
v7 = 0;
|
||||
dword_1026EB44 = (int)v7;
|
||||
v8 = *v7;
|
||||
v16 = -1;
|
||||
if ( !(unsigned __int8)(*(int (__thiscall **)(int *, int *))(v8 + 4))(v7, &dword_100EDB18) )
|
||||
__debugbreak();*/
|
||||
CHAR szArchiveFile[MAX_PATH];
|
||||
GetModuleFileNameA((HMODULE)hInstance, szArchiveFile, MAX_PATH);
|
||||
DWORD dwFileNameLen = strlen(szArchiveFile);
|
||||
while(szArchiveFile[dwFileNameLen] != '\\')
|
||||
dwFileNameLen--;
|
||||
strcpy(szArchiveFile+dwFileNameLen+1, ARCHIVE_FILE);
|
||||
|
||||
pFileSystem = new CArchiveFS();
|
||||
if(!pFileSystem->Load(ARCHIVE_FILE)) _asm int 3
|
||||
|
||||
AddFontResourceA("gtaweap3.ttf");
|
||||
AddFontResourceA("sampaux3.ttf");
|
||||
|
@ -20,6 +20,8 @@ typedef struct _GAME_SETTINGS {
|
||||
|
||||
#include "game/game.h"
|
||||
|
||||
#include "archive/ArchiveFS.h"
|
||||
|
||||
void SetStringFromCommandLine(char *szCmdLine, char *szString);
|
||||
void SetStringFromQuotedCommandLine(char *szCmdLine, char *szString);
|
||||
void InitSettings();
|
||||
|
@ -169,6 +169,61 @@
|
||||
RelativePath=".\game\util.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="archive"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\archive\ArchiveCommon.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\ArchiveFS.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\ArchiveFS.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\CryptoContext.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\CryptoContext.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\CryptoFns.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\CryptoFns.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\Hasher.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\Hasher.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\KeyPair.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\KeyPair.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\Obfuscator.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\Signer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\Signer.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\Stream.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\TinyEncrypt.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive\TinyEncrypt.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\audiostream.cpp">
|
||||
</File>
|
||||
|
Loading…
Reference in New Issue
Block a user