[Source] Decrypting Shen's XOR File Count Encryption

10/21/2016 22:33 Cups#1
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*) &current_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*) &current_file.offset, 8);
input->read((char*) &current_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);
}
}
10/21/2016 22:47 jonny94els#2
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?
10/21/2016 23:08 Cups#3
Quote:
Originally Posted by jonny94els View Post
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.
10/22/2016 03:19 jonny94els#4
Quote:
Originally Posted by Cups. View Post
Send me a pm with your game.exe and Updater and I'll do it after work tomorrow.
ready, you send message with the game and updater

received my message?
10/23/2016 17:35 sanguto#5
I like your work and what you do and through it. Good job
10/24/2016 23:23 jonny94els#6
let me know if you get my message with the Game.exe and Updater.exe to send back thanks
10/30/2016 06:26 R00G3R#7
I guess encryption is useless now. Thank you!
03/22/2018 05:55 mERA44#8
why remove this it was helpful for many beginners and other people
06/07/2020 20:39 werblade#9
Quote:
Originally Posted by Cups View Post
Send me a pm with your game.exe and Updater and I'll do it after work tomorrow.
hi, can you help me @[Only registered and activated users can see links. Click Here To Register...] to add my game and updater

i have shaiyapacker.exe updater and shaiya but i use my custome game and updater so i cannot use shaiyapacker.exe and i cannot encrypt my data.sah

@[Only registered and activated users can see links. Click Here To Register...] or someone can help me ?
05/08/2021 19:49 juanzaraico#10
Tazas necesito negociar contigo, algo si puedes dejarme tus redes sociales te lo agradezco
06/28/2021 15:31 rn4444#11
Hello, sir. Can you be more specific? Or send a video tutorial
10/10/2022 09:52 vovan681#12
Hello, can you share a video lesson or a guide. thank you in advance.
Skype : trup68
03/26/2024 08:15 snowbanshee#13
I'm getting error
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc