Discussion on [Source] Decrypting Shen's XOR File Count Encryption within the Shaiya PServer Guides & Releases forum part of the Shaiya Private Server category.
The encryption keys obviously differ for each client, and can be found by simply opening the client in OllyDBG and searching for "xor r32,const" and scrolling down to the last entries, or checking the memory location in Cheat Engine. Shen1l's encryption works by simply XOR'ing the value that contains the number of files in a folder.
Wrote this as a request, and I figured it'll also help teach some people about the structure of the SAH. Might even help you implement something similiar over your own without needing to pay for it, but who knows, one can always dream.
Code:
/**
* Author: Triston Plummer ("Cups")
* Date: 22/10/2016
*
* Used for decrypting Shen1l's XOR file count encryption for the SAH format.
*/
#include <fstream>
#include <iostream>
#include <vector>
// The encryption keys
int keys[4] = { 0x22, 0x68, 0x61, 0x74 };
// A file structure
#pragma pack(push, 1)
struct File {
// The amount of bytes in the files name
uint32_t name_length;
// The name of the file
char* file_name;
// The offset of the files data
uint64_t offset;
// The length of the files data
uint64_t length;
};
#pragma pack(pop)
// A folder structure
#pragma pack(push, 1)
struct Folder {
// The amount of bytes in the folder name
uint32_t name_length;
// The name of the folder
char* folder_name;
// The number of files in the folder
uint32_t file_count;
// The number of sub-directories contained within this folder
uint32_t sub_folder_count;
// The files contained within this folder
std::vector<File> files;
// The folders contained within this folder
std::vector<Folder> folders;
// The parent folder
Folder* parent_folder;
};
#pragma pack(pop)
// Writes the folder and it's data to the output file
void write_folder(Folder* folder, std::ofstream* output);
// Reads a folder
void read_folder(Folder* folder, std::ifstream* input);
int main(int argc, char** argv) {
// A series of null bytes, used for writing
char null_array[50] = { 0 };
// The file instance
std::ifstream* input = new std::ifstream((argc >= 2 ? argv[1] : "data.sah"), std::ifstream::in | std::ifstream::binary);
// If the file couldn't be opened
if (!input->is_open()) {
std::cout << "Unable to open the file specified!" << std::endl;
return 1;
}
// The file header
char header[3];
input->read((char*) &header, 3);
// Skip the next 4 bytes
input->ignore(4);
// The total number of files in the header
int total_number_files;
// Read the total number of files
input->read((char*) &total_number_files, 4);
// Skip the next 45 bytes (we should now be at an offset of 56)
input->ignore(45);
// The root directory
struct Folder root_directory;
// Define the values for the root directory
root_directory.folder_name = "Data\0";
// Read the folder
read_folder(&root_directory, input);
// Close the header file
input->close();
// Write the decrypted header file
std::ofstream* output = new std::ofstream((argc >= 3 ? argv[2] : "data_decrypted.sah"), std::ios::out | std::ios::binary);
// If the file was opened
if (!output->is_open()) {
std::cout << "Error writing" << std::endl;
return 1;
}
// Write the 3-byte header
output->write("SAH", 3);
// Write the 4 null bytes
output->write((char*) null_array, 4);
// Write the total number of files
output->write((char*) &total_number_files, 4);
// Write the 45 null bytes
output->write((char*) null_array, 40);
// Write a "1" followed by 4 null bytes
output->write((char*) "\x01\0\0\0\0", 5);
// Writes the root folder
write_folder(&root_directory, output);
// Append 8 null bytes
output->write((char*) null_array, 8);
// Close the output file
output->close();
return 0;
}
/**
* Recursively reads a specified folder
*
* [MENTION=1985011]param[/MENTION] folder
* The folder to read
*
* [MENTION=1985011]param[/MENTION] input
* The input file
*/
void read_folder(Folder* folder, std::ifstream* input) {
// The number of files in the current directory
int number_files_current_dir;
input->read((char*) &number_files_current_dir, 4);
// Decrypt the value
for (int i = 0; i < 4; i++) {
number_files_current_dir ^= keys[i];
}
// The number of files in the directory
folder->file_count = number_files_current_dir;
// Loop through the files in the current directory
for (int i = 0; i < folder->file_count; i++) {
// The current file being read
struct File current_file;
// The length of the file name
input->read((char*) ¤t_file.name_length, 4);
// The file name
char* name = new char[current_file.name_length];
input->read((char*) name, current_file.name_length);
current_file.file_name = name;
// The offset and length
input->read((char*) ¤t_file.offset, 8);
input->read((char*) ¤t_file.length, 8);
// Add the file to the root directory instance
folder->files.push_back(current_file);
}
// The number of sub-folders in the current directory
int sub_folder_count;
input->read((char*) &sub_folder_count, 4);
folder->sub_folder_count = sub_folder_count;
// Loop through the sub-directories
for (int i = 0; i < folder->sub_folder_count; i++) {
// The sub-directory
struct Folder directory;
// Define the directories parent folder
directory.parent_folder = folder;
// The length of the folder name
input->read((char*) &directory.name_length, 4);
// The folder name
char* name = new char[directory.name_length];
input->read((char*) name, directory.name_length);
directory.folder_name = name;
// Read the sub-directory
read_folder(&directory, input);
// Add the directory to the list of sub-folders
folder->folders.push_back(directory);
}
}
/**
* Recursively writes a specified folder to an output file
*
* [MENTION=1985011]param[/MENTION] folder
* The folder to write
*
* [MENTION=1985011]param[/MENTION] output
* The output file
*/
void write_folder(Folder* folder, std::ofstream* output) {
// Write the number of files in the current folder
output->write((char*) &folder->file_count, 4);
// Loop through the files in the current directory, and write them
for (auto &file : folder->files) {
// The number of bytes in the file name
output->write((char*) &file.name_length, 4);
// The name of the file
output->write((char*) file.file_name, file.name_length);
// The offset and length of the file
output->write((char*) &file.offset, 8);
output->write((char*) &file.length, 8);
}
// Write the number of sub-directories in the current directory
output->write((char*) &folder->sub_folder_count, 4);
// Loop through the sub-directories
for (auto &sub_folder : folder->folders) {
// The number of bytes in the folder name
output->write((char*) &sub_folder.name_length, 4);
// The name of the folder
output->write((char*) sub_folder.folder_name, sub_folder.name_length);
// Write the current folder
write_folder(&sub_folder, output);
}
}
shen one I encrypt my data me but when I asked to change the updater told me that will not do, now I can not change updater that shen1 not pass me the encryption key, you could help?
shen one I encrypt my data me but when I asked to change the updater told me that will not do, now I can not change updater that shen1 not pass me the encryption key, you could help?
Send me a pm with your game.exe and Updater and I'll do it after work tomorrow.
decrypting the file property 01/21/2014 - Metin2 Private Server - 3 Replies Hi, I have a problem when decrypting the file property disappears files in folders a, b, c, have any idea what could be?When i take files from other sources (folders a,b,c etc ), it gives me these errors after encryption
0121 09:42:18783 :: Failed to decompress : property/b/01.Ľş/b1-038-wall-corner.prb
0121 09:42:18797 :: LZObject: Decompress failed : ret -4, CompressedSize 0
0121 09:42:18797 :: Failed to decompress : property/a/łŞą«/sassafras_fall1.prt
0121 09:42:18798 :: LZObject:...
File Encryption 09/09/2013 - General Coding - 23 Replies Hallöle ihr 1337 H4xX0r,
ich suche jemanden, der mir sagen kann, was in der Datei ist, die ich da unten angefertig habe. Ich bastel zur Zeit eine neue Res Encrpytion, welche sicher sein muss und nicht gecrackt werden kann.
Der erste, der mir den genauen Inhalt der Datei liefern kann, bekommt von mir 100€ PSC oder Amazon Gutschein.
Das ganze mir dann per PM melden, sonst werte ich es nicht.
PS: Deadline bis zum 16.09.2013 00:00.
What about encryption html file ? 07/23/2010 - Aion - 0 Replies Hello,
Atm we can encrypt/decrypt .PAK file, and decrypt XML & HTML files.
But do we can re-encrypt HTML & XML files ?
I've searched everywhere, and I don't find =(
AIONasm never finished =(
Thanks.