A file with this size 16515603 in hexadecimal is 0x1302FC. To store large values, up to 4 gigabytes, we will need 4 bytes:
0xFC, 0x02, 0x13, 0x00
We will use:
bytFile.insert(bytFile.end(), { static_cast<char>((bytText.size() >> 24) & 0xFF), static_cast<char>((bytText.size() >> 16) & 0xFF), static_cast<char>((bytText.size() >> 8) & 0xFF), static_cast<char>((bytText.size() >> 0) & 0xFF) });
1) Let's update the patch:
#include <fstream> #include <iostream> #include <string> #include <vector> #include <sstream> std::vector<char> file_read_bin(const std::string& fileName) { std::string filePath = fileName; std::ifstream file(filePath, std::ios::binary); if (file.fail()) { std::cerr << "Erro ao abrir o arquivo " << filePath << std::endl; } // Read bytes std::vector<char> bytFile((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); file.close(); return bytFile; } void file_write_bin(const std::string& filePath, std::vector<char> bytFile) { // Write bytes std::ofstream outFile(filePath, std::ios::binary); if (outFile.fail()) { std::cerr << "Erro ao abrir o arquivo " << filePath << " para escrita" << std::endl; } outFile.write(bytFile.data(), bytFile.size()); outFile.close(); std::cout << "Arquivo alterado com sucesso" << std::endl; } int main(int argc, char *argv[]){ if (argc != 4) { std::cout << "Require 3 args: program.exe data.txt 163857\n"; return 1; } const char* program_file = argv[1]; const char* data_file = argv[2]; std::vector<char> bytFile = file_read_bin( program_file ); std::vector<char> bytText = file_read_bin( data_file ); int correctSize = std::stoi(argv[3]); int size = bytFile.size(); int diff = size - correctSize; // Logs std::cout << "size: " << size << "\n"; std::cout << "correctSize: " << correctSize << "\n"; // Remove old code if(size > correctSize ){ bytFile.erase(bytFile.end() - diff, bytFile.end() ); } // Add content bytFile.insert(bytFile.end(), bytText.begin(), bytText.end()); // Add content size bytFile.insert(bytFile.end(), { static_cast<char>((bytText.size() >> 24) & 0xFF), static_cast<char>((bytText.size() >> 16) & 0xFF), static_cast<char>((bytText.size() >> 8) & 0xFF), static_cast<char>((bytText.size() >> 0) & 0xFF) }); // Add file name std::string data_filename_str(data_file); data_filename_str+="\0"; bytFile.insert(bytFile.end(), data_filename_str.c_str(), data_filename_str.c_str() + data_filename_str.size() ); // Add name size bytFile.insert( bytFile.end(), data_filename_str.size() ); // Add symbol exist new file std::string symbol = "^"; bytFile.insert(bytFile.end(), symbol.c_str(), symbol.c_str() + symbol.size() ); // Rewrite file_write_bin(program_file, bytFile); return 0; }
2) Compile
g++ patch.cpp -o patch
3) Update the program.cpp
As the function is getting too big with too many responsibilities, now let's refactor the code and separate these functions:
int getFileNamesize(std::vector<char> bytFile, int size) std::string getFileName(std::vector<char> bytFile, int size, int fileNameSize) int getContentSize(std::vector<char> bytFile, int size, int fileNameSize) std::string getContent(std::vector<char> bytFile, int size, int fileNameSize, int contentSize, int contentStart) int getContent(std::vector<char> bytFile, int size)
program.cpp
#include <fstream> #include <iostream> #include <windows.h> #include <sstream> #include <string> #include <locale> int assetsCount = 0; std::vector<char> file_read_bin(const std::string& fileName) { std::string filePath = fileName; std::ifstream file(filePath, std::ios::binary); if (file.fail()) { std::cerr << "Erro ao abrir o arquivo " << filePath << std::endl; } // Read bytes std::vector<char> bytFile((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); file.close(); return bytFile; } std::string getHexValue(const std::vector<char>& bytFile, int size, int byteCount) { std::stringstream ss; ss << std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned int>(static_cast<unsigned char>(bytFile[size - byteCount])); return ss.str(); } int hexToInt(std::string hexStr) { return std::stoi(hexStr, nullptr, 16); } int getFileNamesize(std::vector<char> bytFile, int size){ std::string sizeHex = getHexValue(bytFile, size, 2); return hexToInt( sizeHex ); } std::string getFileName(std::vector<char> bytFile, int size, int fileNameSize){ std::string fileName = ""; int startfileName = fileNameSize + 2; for (int i = startfileName; i > 2; i--) { std::string byteInStringFormat; byteInStringFormat.push_back(static_cast<char>(bytFile[size - i])); // convert byte to char fileName += byteInStringFormat; } return fileName; } int getContentSize(std::vector<char> bytFile, int size, int fileNameSize){ std::string byte_24 = getHexValue(bytFile, size, fileNameSize + 3); std::string byte_16 = getHexValue(bytFile, size, fileNameSize + 4); std::string byte_08 = getHexValue(bytFile, size, fileNameSize + 5); std::string byte_00 = getHexValue(bytFile, size, fileNameSize + 6); std::stringstream ss; ss << std::hex << byte_00 << byte_08 << byte_16 << byte_24; int contentSize; ss >> contentSize; return contentSize; } std::string getContent(std::vector<char> bytFile, int size, int fileNameSize, int contentSize, int contentStart){ std::string content = ""; for (int i = contentStart; i > fileNameSize+3+3; i--) { std::string byteInStringFormat; byteInStringFormat.push_back(static_cast<char>(bytFile[size - i])); // convert byte to char content += byteInStringFormat; } return content; } int getContent(std::vector<char> bytFile, int size) { if( bytFile[size - 1] != '^') { // Exist new file? std::cout << "end" << "\n"; return 0; } assetsCount+=1; std::cout << assetsCount << "-----------------" << "\n"; // Get file name size in last byte int fileNameSize = getFileNamesize(bytFile, size); std::cout << "content name size: " << fileNameSize << "\n"; // Get file name in last byte std::string fileName = getFileName(bytFile, size, fileNameSize); std::cout << "content name: " << fileName << "\n"; // Get content size in 4 bytes int contentSize = getContentSize(bytFile, size, fileNameSize); std::cout << "content size: " << contentSize << "\n"; // Get content int contentStart = contentSize+fileNameSize+3+3; std::string content = getContent(bytFile, size, fileNameSize, contentSize, contentStart); // Print big string int stringSize = content.size(); int maxLineSize = 80; for (int i = 0; i < stringSize; i += maxLineSize) { int lineSize = std::min(stringSize - i, maxLineSize); std::cout << content.substr(i, lineSize) << std::endl; } // End int final = size - (contentStart + 1); std::cout << "-----------------" << "\n"; getContent(bytFile, final+1); // get new file return 0; } int main(int argc, char *argv[]){ // Read file std::string filename = std::string(argv[0]) + ".exe"; std::vector<char> bytFile = file_read_bin( filename ); int size = bytFile.size(); // Logs std::cout << "file size: " << size << std::endl; std::cout << "last byte: " << getHexValue(bytFile, size, 1) << std::endl; //std::cout << "int size : " << contentSize << std::endl; // console "pt-BR" accentuation errors system("chcp 1252 > nul"); setlocale(LC_ALL, "pt_BR.UTF-8"); getContent(bytFile, size); return 0; }
4) Compile
g++ program.cpp -o program
5) Exec and get "file size"
program
file size: 172032 last byte: 00 end
6) Create um big content data3.txt
Create the file "data3.txt" and add this content:
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js
To make it easier to verify that everything went right, you can add a "ã" at the beginning and end of this file:
ã/*! jQuery v3.6.4 |
(C.jQuery=C.$=S),S});ã
7) Apply pacth
patch program.exe data3.txt 172032
8) Run program.exe
program
file size: 261846 last byte: 5e 1----------------- content name size: 9 content name: data3.txt content size: 89799 ã/*! jQuery v3.6.4 (...) ned"==typeof e&&(C.jQuery=C.$=S),S});ã ----------------- end
8) Apply a new patch with new size
patch program.exe data3.txt 261846
9) Run program.exe
First clear console
cls
program
Result
file size: 351660 last byte: 5e 1----------------- content name size: 9 content name: data3.txt content size: 89799 ã/*! jQuery v3.6.4 | (...) ned"==typeof e&&(C.jQuery=C.$=S),S});ã ----------------- 2----------------- content name size: 9 content name: data3.txt content size: 89799 ã/*! jQuery v3.6.4 | (...) ned"==typeof e&&(C.jQuery=C.$=S),S});ã ----------------- end
Embedding Files in an Executable - SDL/Windows - Part 5
https://dev.to/gurigraphics/embedding-files-in-an-executable-sdlwindows-part-5-2he4
Top comments (0)