Ogre Version: :1.7.2 SDK:
Operating System: :Windows XP SP3:
Render System: :Either:
Compiler: :MinGW with Codeblocks:
Hello,
I have an application that uses encrypted zip files to avoid kids to steal/claim other people's skins and maps.
The problem is that the application first has to decrypt the files in to a zip (with .sys extension in a hidden folder) so then Ogre can read the zip files, but someone found out and spread the word.
I want to make Ogre read the encrypted zip files directly, so kids can't mess around.
Seems like Ogre 1.7 code is getting rare and I have been 2 days trying to figure out where to start.
I tried reading Resources and ResourceManagers but it didn't give me a clue.
And I tried Obfuscated+Zip but I get compilation errors and missing zzip/plugin.h even after downloading zzip.
I'm not sure if I should Upgrade Ogre to 1.11 first and because I have no clue how to compile Ogre from source and if still compatible with Windows XP, and I don't want to mess too much with the code since my C++ knowledge is poor and I'm new with Ogre.
Can anyone push me in the right direction please?
Btw, the encryption is just a XOR to a pseudorandom number generator.
[Solved] Help to read Obfuscated zip in Ogre 1.7
-
- Gnoblar
- Posts: 7
- Joined: Fri Dec 28, 2018 7:52 pm
- x 1
[Solved] Help to read Obfuscated zip in Ogre 1.7
Last edited by Tikoucas on Tue Jan 08, 2019 2:23 am, edited 1 time in total.
-
- Gnoblar
- Posts: 7
- Joined: Fri Dec 28, 2018 7:52 pm
- x 1
Re: [solved] Help to read Obfuscated zip in Ogre 1.7
I figured out that I needed Zlib together with zziplib to be able to compile them (they are 2 different things)
I kept on getting a missing header "plugin.h" because one of them were missing.
Then I ran in to compilation errors but I managed to get the code working by making some changes, but I know very little of C++ and I don't know what I'm doing.
In ObfuscatedZip.cpp I Changed the next line:
by adding 1 extra argument: bool readOnly
Commented the next line:
At this point the source code compiled fine.
I followed the tutorial about how to initialize stuff in main.cpp and I managed to sucessfully load a file "hello.OBFUSZIP" (a zip file with a XOR operation on it)
My next step was to do a better Xor Key of something larger than 1 byte, as most the users already guessed the key <.<
Maybe at some point I will get a pseudorandom number generator from the Wikipedia and use it for my XOR key, but I know they might still get stuff from RAM anyway.
Hoping a simple XOR string will stop kids from stealing and claiming the art from other users for now.
The resulting code was this:
I kept on getting a missing header "plugin.h" because one of them were missing.
Then I ran in to compilation errors but I managed to get the code working by making some changes, but I know very little of C++ and I don't know what I'm doing.
In ObfuscatedZip.cpp I Changed the next line:
Code: Select all
Ogre::DataStreamPtr ObfuscatedZip::open(const Ogre::String& filename) const
Code: Select all
Ogre::DataStreamPtr ObfuscatedZip::open(const Ogre::String& filename, bool readOnly) const
Code: Select all
Ogre::LogManager::getSingleton().logMessage( mName + " - Unable to open file " + filename + ", error was '" + zzDesc + "'");
I followed the tutorial about how to initialize stuff in main.cpp and I managed to sucessfully load a file "hello.OBFUSZIP" (a zip file with a XOR operation on it)
My next step was to do a better Xor Key of something larger than 1 byte, as most the users already guessed the key <.<
Maybe at some point I will get a pseudorandom number generator from the Wikipedia and use it for my XOR key, but I know they might still get stuff from RAM anyway.
Hoping a simple XOR string will stop kids from stealing and claiming the art from other users for now.
The resulting code was this:
Code: Select all
/*
* ObfuscatedZip.cpp
*/
#include "ObfuscatedZip.h"
#include <zzip/zzip.h>
#include <zzip/plugin.h>
//namespace MyNameSpace
//{
// Change this magic number to a value of your choosing.
#define LONGITUDLLAVE 68
static const char xor_value[LONGITUDLLAVE] = {104,21,, ... ,7}; //68 bytes key. ofc I deleted it :)
static zzip_plugin_io_handlers xor_handlers = { };
// Change "SYM" to match the file extension of your choosing.
static zzip_strings_t xor_fileext[] = { ".SYM", ".SYO", 0 };
// Static method that un-obfuscates an obfuscated file.
static zzip_ssize_t xor_read (int fd, void* buf, zzip_size_t len)
{
int xor_i = lseek(fd,0,SEEK_CUR); //obtener la posicion actual del archivo
const zzip_ssize_t bytes = read(fd, buf, len);
zzip_ssize_t i;
char* pch = (char*)buf;
xor_i = xor_i % LONGITUDLLAVE; //mover contador a una posicion válida
for (i=0; i<bytes; ++i)
{
pch[i] ^= (char) xor_value[xor_i];
xor_i++;
if (xor_i >= LONGITUDLLAVE)
{
xor_i = 0;
}
}
return bytes;
}
/// Utility method to format out zzip errors
Ogre::String getZzipErrorDescription(zzip_error_t zzipError)
{
Ogre::String errorMsg;
switch (zzipError)
{
case ZZIP_NO_ERROR:
break;
case ZZIP_OUTOFMEM:
errorMsg = "Out of memory.";
break;
case ZZIP_DIR_OPEN:
case ZZIP_DIR_STAT:
case ZZIP_DIR_SEEK:
case ZZIP_DIR_READ:
errorMsg = "Unable to read zip file.";
break;
case ZZIP_UNSUPP_COMPR:
errorMsg = "Unsupported compression format.";
break;
case ZZIP_CORRUPTED:
errorMsg = "Corrupted archive.";
break;
default:
errorMsg = "Unknown error.";
break;
};
return errorMsg;
}
//-----------------------------------------------------------------------
ObfuscatedZip::ObfuscatedZip(const Ogre::String& name, const Ogre::String& archType )
: Archive(name, archType), mZzipDir(0)
{
zzip_init_io(&xor_handlers, 0);
xor_handlers.fd.read = &xor_read;
}
//-----------------------------------------------------------------------
ObfuscatedZip::~ObfuscatedZip()
{
unload();
}
//-----------------------------------------------------------------------
void ObfuscatedZip::load()
{
if (!mZzipDir)
{
zzip_error_t zzipError;
mZzipDir = zzip_dir_open_ext_io(mName.c_str(), &zzipError, xor_fileext, &xor_handlers);
checkZzipError(zzipError, "opening SYX file");
// Cache names
ZZIP_DIRENT zzipEntry;
while (zzip_dir_read(mZzipDir, &zzipEntry))
{
Ogre::FileInfo info;
info.archive = this;
// Get basename / path
Ogre::StringUtil::splitFilename(zzipEntry.d_name, info.basename, info.path);
info.filename = zzipEntry.d_name;
// Get sizes
info.compressedSize = static_cast<size_t>(zzipEntry.d_csize);
info.uncompressedSize = static_cast<size_t>(zzipEntry.st_size);
// folder entries
if (info.basename.empty())
{
info.filename = info.filename.substr (0, info.filename.length () - 1);
Ogre::StringUtil::splitFilename(info.filename, info.basename, info.path);
// Set compressed size to -1 for folders; anyway nobody will check
// the compressed size of a folder, and if he does, its useless anyway
info.compressedSize = size_t (-1);
}
mFileList.push_back(info);
}
}
}
//-----------------------------------------------------------------------
void ObfuscatedZip::unload()
{
if (mZzipDir)
{
zzip_dir_close(mZzipDir);
mZzipDir = 0;
mFileList.clear();
}
}
//-----------------------------------------------------------------------
Ogre::DataStreamPtr ObfuscatedZip::open(const Ogre::String& filename, bool readOnly) const
{
// Format not used here (always binary)
ZZIP_FILE* zzipFile =
zzip_file_open(mZzipDir, filename.c_str(), ZZIP_ONLYZIP | ZZIP_CASELESS);
if (!zzipFile)
{
int zerr = zzip_error(mZzipDir);
Ogre::String zzDesc = getZzipErrorDescription((zzip_error_t)zerr);
//Ogre::LogManager::getSingleton().logMessage( mName + " - Unable to open file " + filename + ", error was '" + zzDesc + "'");
printf("ObfuscatedZip: Error in line %d\r\n",__LINE__); //Warning: c++ newbie commented the line above
// return null pointer
return Ogre::DataStreamPtr();
}
// Get uncompressed size too
ZZIP_STAT zstat;
zzip_dir_stat(mZzipDir, filename.c_str(), &zstat, ZZIP_CASEINSENSITIVE);
// Construct & return stream
return Ogre::DataStreamPtr(OGRE_NEW ObfuscatedZipDataStream(filename, zzipFile, static_cast<size_t>(zstat.st_size)));
}
//-----------------------------------------------------------------------
Ogre::StringVectorPtr ObfuscatedZip::list(bool recursive, bool dirs)
{
Ogre::StringVectorPtr ret = Ogre::StringVectorPtr(OGRE_NEW_T(Ogre::StringVector, Ogre::MEMCATEGORY_GENERAL)(), Ogre::SPFM_DELETE_T);
Ogre::FileInfoList::iterator i, iend;
iend = mFileList.end();
for (i = mFileList.begin(); i != iend; ++i)
if ((dirs == (i->compressedSize == size_t (-1))) &&
(recursive || i->path.empty()))
ret->push_back(i->filename);
return ret;
}
//-----------------------------------------------------------------------
Ogre::FileInfoListPtr ObfuscatedZip::listFileInfo(bool recursive, bool dirs)
{
Ogre::FileInfoList* fil = OGRE_NEW_T(Ogre::FileInfoList, Ogre::MEMCATEGORY_GENERAL)();
Ogre::FileInfoList::const_iterator i, iend;
iend = mFileList.end();
for (i = mFileList.begin(); i != iend; ++i)
if ((dirs == (i->compressedSize == size_t (-1))) &&
(recursive || i->path.empty()))
fil->push_back(*i);
return Ogre::FileInfoListPtr(fil, Ogre::SPFM_DELETE_T);
}
//-----------------------------------------------------------------------
Ogre::StringVectorPtr ObfuscatedZip::find(const Ogre::String& pattern, bool recursive, bool dirs)
{
Ogre::StringVectorPtr ret = Ogre::StringVectorPtr(OGRE_NEW_T(Ogre::StringVector, Ogre::MEMCATEGORY_GENERAL)(), Ogre::SPFM_DELETE_T);
// If pattern contains a directory name, do a full match
bool full_match = (pattern.find ('/') != Ogre::String::npos) ||
(pattern.find ('\\') != Ogre::String::npos);
Ogre::FileInfoList::iterator i, iend;
iend = mFileList.end();
for (i = mFileList.begin(); i != iend; ++i)
if ((dirs == (i->compressedSize == size_t (-1))) &&
(recursive || full_match || i->path.empty()))
// Check basename matches pattern (zip is case insensitive)
if (Ogre::StringUtil::match(full_match ? i->filename : i->basename, pattern, false))
ret->push_back(i->filename);
return ret;
}
//-----------------------------------------------------------------------
Ogre::FileInfoListPtr ObfuscatedZip::findFileInfo(const Ogre::String& pattern,
bool recursive, bool dirs)
{
Ogre::FileInfoListPtr ret = Ogre::FileInfoListPtr(OGRE_NEW_T(Ogre::FileInfoList, Ogre::MEMCATEGORY_GENERAL)(), Ogre::SPFM_DELETE_T);
// If pattern contains a directory name, do a full match
bool full_match = (pattern.find ('/') != Ogre::String::npos) ||
(pattern.find ('\\') != Ogre::String::npos);
Ogre::FileInfoList::iterator i, iend;
iend = mFileList.end();
for (i = mFileList.begin(); i != iend; ++i)
if ((dirs == (i->compressedSize == size_t (-1))) &&
(recursive || full_match || i->path.empty()))
// Check name matches pattern (zip is case insensitive)
if (Ogre::StringUtil::match(full_match ? i->filename : i->basename, pattern, false))
ret->push_back(*i);
return ret;
}
//-----------------------------------------------------------------------
bool ObfuscatedZip::exists(const Ogre::String& filename)
{
ZZIP_STAT zstat;
int res = zzip_dir_stat(mZzipDir, filename.c_str(), &zstat, ZZIP_CASEINSENSITIVE);
return (res == ZZIP_NO_ERROR);
}
//---------------------------------------------------------------------
time_t ObfuscatedZip::getModifiedTime(const Ogre::String& filename)
{
// Zziplib doesn't yet support getting the modification time of individual files
// so just check the mod time of the zip itself
struct stat tagStat;
bool ret = (stat(mName.c_str(), &tagStat) == 0);
if (ret)
{
return tagStat.st_mtime;
}
else
{
return 0;
}
}
//-----------------------------------------------------------------------
void ObfuscatedZip::checkZzipError(int zzipError, const Ogre::String& operation) const
{
if (zzipError != ZZIP_NO_ERROR)
{
Ogre::String errorMsg = getZzipErrorDescription(static_cast<zzip_error_t>(zzipError));
OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR,
mName + " - error whilst " + operation + ": " + errorMsg,
"ObfuscatedZip::checkZzipError");
}
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
ObfuscatedZipDataStream::ObfuscatedZipDataStream(ZZIP_FILE* zzipFile, size_t uncompressedSize)
: mZzipFile(zzipFile)
{
mSize = uncompressedSize;
}
//-----------------------------------------------------------------------
ObfuscatedZipDataStream::ObfuscatedZipDataStream(const Ogre::String& name, ZZIP_FILE* zzipFile, size_t uncompressedSize)
:DataStream(name), mZzipFile(zzipFile)
{
mSize = uncompressedSize;
}
//-----------------------------------------------------------------------
ObfuscatedZipDataStream::~ObfuscatedZipDataStream()
{
close();
}
//-----------------------------------------------------------------------
size_t ObfuscatedZipDataStream::read(void* buf, size_t count)
{
zzip_ssize_t r = zzip_file_read(mZzipFile, (char*)buf, count);
if (r<0) {
ZZIP_DIR *dir = zzip_dirhandle(mZzipFile);
Ogre::String msg = zzip_strerror_of(dir);
OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR,
mName+" - error from zziplib: "+msg,
"ObfuscatedZipDataStream::read");
}
return (size_t) r;
}
//-----------------------------------------------------------------------
void ObfuscatedZipDataStream::skip(long count)
{
zzip_seek(mZzipFile, static_cast<zzip_off_t>(count), SEEK_CUR);
}
//-----------------------------------------------------------------------
void ObfuscatedZipDataStream::seek( size_t pos )
{
zzip_seek(mZzipFile, static_cast<zzip_off_t>(pos), SEEK_SET);
}
//-----------------------------------------------------------------------
size_t ObfuscatedZipDataStream::tell(void) const
{
return zzip_tell(mZzipFile);
}
//-----------------------------------------------------------------------
bool ObfuscatedZipDataStream::eof(void) const
{
return (zzip_tell(mZzipFile) >= static_cast<zzip_off_t>(mSize));
}
//-----------------------------------------------------------------------
void ObfuscatedZipDataStream::close(void)
{
if (mZzipFile != 0)
{
zzip_file_close(mZzipFile);
mZzipFile = 0;
}
}
//-----------------------------------------------------------------------
const Ogre::String& ObfuscatedZipFactory::getType(void) const
{
static Ogre::String name = "SYM";
return name;
}
//}