├── Algorithm.cpp ├── Algorithm.h ├── BuildRelease └── HideMeIn ├── CMakeLists.txt ├── CustomHeader.cpp ├── CustomHeader.h ├── Examples ├── print.bmp └── song.wav ├── LICENSE ├── README.md ├── main.cpp └── main.h /Algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Algorithm.h" 3 | 4 | using namespace std; 5 | 6 | int PlayWithWaveBuffer(vector& buffer, string& msg, string& inputExt) 7 | { 8 | char* modulusBytes = new char[4] {0}; // Max number of modulus in bytes 9 | char* customHeader = new char[MY_HEADER] {0}; // Custom header 10 | string fileExtension = ""; 11 | 12 | string end = "@<;;"; 13 | msg += end; 14 | 15 | // How many times the buffer is bigger than the message 16 | long modulus = ((buffer.size() - WAV_HEADER - START_SPACE) / (msg.size() + MY_HEADER)); 17 | 18 | cout << "Spreading level: " << modulus << endl; 19 | 20 | // Verify if it is safe to hide the message. Must me at must half the size of the space avaible 21 | if(modulus <= 3) 22 | { 23 | cout << "The message might be to big for the audio file" << endl; 24 | return ERROR; 25 | } 26 | 27 | CreateHeader(modulus, modulusBytes, customHeader, fileExtension, false); 28 | 29 | int n = 0; 30 | int pos = 0; 31 | 32 | // Write my custom header first (Spread) 33 | for (vector::iterator it = buffer.begin() + WAV_HEADER + START_SPACE; 34 | it != buffer.end(); ++it) 35 | { 36 | if (n % MY_HEADER_MODULE == 0) 37 | { 38 | *it = customHeader[pos]; 39 | pos++; 40 | //cout << "Header -> " << *it << endl; // Uncomment this to see the message being written 41 | 42 | if (pos == MY_HEADER) 43 | { 44 | cout << "Header wrote" << endl; 45 | break; 46 | } 47 | } 48 | n++; 49 | } 50 | 51 | // Delete arrays we are not using it anymore 52 | modulusBytes = new char[1]; // Relocate memory 53 | delete[] modulusBytes; 54 | delete[] customHeader; 55 | 56 | int j = 0; 57 | pos = 0; 58 | // Since the actual data of the wav starts at byte 44. Everything above is just header things that we don't care atm 59 | for (vector::iterator it = buffer.begin() + WAV_HEADER + n + MY_HEADER_MODULE + START_SPACE; 60 | it != buffer.end(); ++it) 61 | { 62 | if (j % modulus == 0) 63 | { 64 | *it = msg.at(pos); 65 | pos++; 66 | //cout << *it << endl; // Uncomment this to see the message being written 67 | 68 | if (pos >= msg.size()) 69 | break; 70 | } 71 | j++; 72 | } 73 | 74 | if (pos < msg.size()) 75 | { 76 | cout << "Maybe the whole file was not written in" << endl; 77 | } 78 | 79 | return OutputBindedData(buffer, inputExt); 80 | } 81 | 82 | int PlayWithWaveBuffer(vector& buffer, vector& msgBuffer, string& fileExtension, string& inputExt) 83 | { 84 | char* modulusBytes = new char[4] {0}; // Max number of modulus in bytes 85 | char* customHeader = new char[MY_HEADER] {0}; // Custom header 86 | 87 | if (buffer.size()/4 <= msgBuffer.size()) 88 | { 89 | cout << "The message might be to big for the audio file" << endl; 90 | return ERROR; 91 | } 92 | 93 | msgBuffer.push_back('@'); 94 | msgBuffer.push_back('<'); 95 | msgBuffer.push_back(';'); 96 | msgBuffer.push_back(';'); 97 | 98 | // How many times the buffer is bigger than the message 99 | // buffer.size() - (HEADER SIZE = 44 bytes) - (My own tags to de hidden file = 3 bytes) 100 | long modulus = ((buffer.size() - WAV_HEADER - START_SPACE) / (msgBuffer.size() + MY_HEADER)); 101 | 102 | cout << "Spreading level: " << modulus << endl; 103 | 104 | // Verify if it is safe to hide the message. Must me at must half the size of the space avaible 105 | if(modulus <= 3) 106 | { 107 | cout << "The message might be to big for the audio file" << endl; 108 | return ERROR; 109 | } 110 | 111 | CreateHeader(modulus, modulusBytes, customHeader, fileExtension, true); 112 | 113 | int n = 0; 114 | int pos = 0; 115 | 116 | // Write my custom header first (Spread) 117 | for (vector::iterator it = buffer.begin() + WAV_HEADER + START_SPACE; 118 | it != buffer.end(); ++it) 119 | { 120 | if (n % MY_HEADER_MODULE == 0) 121 | { 122 | *it = customHeader[pos]; 123 | pos++; 124 | //cout << "Header -> " << *it << endl; // Uncomment this to see the message being written 125 | 126 | if (pos == MY_HEADER) 127 | { 128 | cout << "Header wrote" << endl; 129 | break; 130 | } 131 | } 132 | n++; 133 | } 134 | 135 | // Delete arrays we are not using it anymore 136 | modulusBytes = new char[1]; // Relocate memory 137 | delete[] modulusBytes; 138 | delete[] customHeader; 139 | 140 | int j = 0; 141 | pos = 0; 142 | for (vector::iterator it = buffer.begin() + WAV_HEADER + n + MY_HEADER_MODULE + START_SPACE; 143 | it != buffer.end(); ++it) 144 | { 145 | if (j % modulus == 0) 146 | { 147 | *it = msgBuffer.at(pos); 148 | pos++; 149 | //cout << *it << endl; // Uncomment this to see the message being written 150 | 151 | if (pos >= msgBuffer.size()) 152 | break; 153 | } 154 | j++; 155 | } 156 | 157 | if (pos < msgBuffer.size()) 158 | { 159 | cout << "Maybe the whole file was not written in" << endl; 160 | } 161 | 162 | return OutputBindedData(buffer, inputExt); 163 | } 164 | 165 | /** 166 | * Look for the custom header and define what type of message is in it 167 | * 168 | * @param buffer: File loaded into a buffer 169 | * */ 170 | int FindHiddenMessage(vector& buffer) 171 | { 172 | char* customHeader = new char[MY_HEADER] {0}; // Custom header 173 | 174 | int n = 0; 175 | int pos = 0; 176 | cout << "Looking for the hidden message..." << endl; 177 | // Since the actual data of the wav starts at byte 44 we start from it. Everything above is just header things that we don't care atm 178 | for (vector::iterator it = buffer.begin() + WAV_HEADER + START_SPACE; 179 | it != buffer.end(); ++it) 180 | { 181 | if (n % MY_HEADER_MODULE == 0) 182 | { 183 | customHeader[pos] = *it; 184 | //cout << "Custom Header: " << customHeader[pos] << endl; // Uncomment this if you want to see the header being read 185 | pos++; 186 | if (pos == MY_HEADER) 187 | { 188 | //cout << "Header has been read " << endl; 189 | break; 190 | } 191 | } 192 | n++; 193 | } 194 | 195 | CustomHeader cHeader (customHeader); 196 | 197 | // Clean memory 198 | delete[] customHeader; 199 | 200 | if (cHeader.GetType() == 'b') 201 | { 202 | cout << "File detected. Retrieving it..." << endl; 203 | cHeader.SetLastPosition(n); 204 | return FindHiddenBinaryInWave(buffer, cHeader); 205 | } 206 | else if (cHeader.GetType() == 't'){ 207 | cout << "String detected. Retrieving it..." << endl; 208 | cHeader.SetLastPosition(n); 209 | return FindHiddenTextInWave(buffer, cHeader); 210 | } 211 | else{ 212 | // If it hits here it's because there was no message found in the file 213 | cout << "Failed to detect a hidden file." << endl; 214 | cout << "No custom header was found." << endl; 215 | return ERROR; 216 | } 217 | } 218 | 219 | int FindHiddenTextInWave(vector& buffer, CustomHeader& customHeader) 220 | { 221 | string msgText; 222 | 223 | int modulus = customHeader.GetModulus(); 224 | int lastPos = customHeader.GetLastPosition(); 225 | 226 | int n = 0; 227 | int pos = 0; 228 | vector::iterator tempIterator; 229 | // Since the actual data of the wav starts at byte 44. Everything above is just header things that we don't care atm 230 | for (vector::iterator it = buffer.begin() + WAV_HEADER + lastPos + MY_HEADER_MODULE + START_SPACE; 231 | it != buffer.end(); ++it) 232 | { 233 | if (n % modulus == 0) 234 | { 235 | if (*it == 64) 236 | { 237 | // @ 238 | //Setting the iterator to the next possible position 239 | tempIterator = buffer.begin() + n + 44 + MY_HEADER_MODULE + START_SPACE + lastPos + modulus; 240 | 241 | if (*tempIterator == 60) { 242 | //< 243 | //Setting the iterator to the next possible position 244 | tempIterator = buffer.begin() + n + 44 + MY_HEADER_MODULE + START_SPACE + lastPos + (2* modulus); 245 | 246 | if (*tempIterator == 59) { 247 | // ; 248 | // Setting the iterator to next possible flag 249 | tempIterator = buffer.begin() + n + 44 + MY_HEADER_MODULE + START_SPACE + lastPos + (3 * modulus); 250 | 251 | if (*tempIterator == 59){ 252 | // End of message reached 253 | cout << "Message recovered size: " << pos << " bytes" << endl; 254 | 255 | // Output text 256 | cout << "Message: " << msgText.c_str() << endl; 257 | return SUCCESS; 258 | } 259 | } 260 | } 261 | } 262 | 263 | msgText[pos] = *it; 264 | //cout << msgText[pos] << endl; // Uncomment this if yuo want to see the characters being read 265 | pos++; 266 | 267 | } 268 | n++; 269 | } 270 | 271 | // If it hits here it's because there was no message found in the file 272 | cout << "No message found :(" << endl; 273 | return ERROR; 274 | 275 | } 276 | 277 | int FindHiddenBinaryInWave(vector& buffer, CustomHeader& customHeader) 278 | { 279 | vector msgBuffer; 280 | 281 | int modulus = customHeader.GetModulus(); 282 | int lastPos = customHeader.GetLastPosition(); 283 | 284 | int n = 0; 285 | int pos = 0; 286 | vector::iterator tempIterator; 287 | // Since the actual data of the wav starts at byte 44. Everything above is just header things that we don't care atm 288 | for (vector::iterator it = buffer.begin() + + WAV_HEADER + lastPos + MY_HEADER_MODULE + START_SPACE; 289 | it != buffer.end(); ++it) 290 | { 291 | if (n % modulus == 0) 292 | { 293 | if (*it == 64) 294 | { 295 | // @ 296 | //Setting the iterator to the next possible position 297 | tempIterator = buffer.begin() + n + 44 + MY_HEADER_MODULE + START_SPACE + lastPos + modulus; 298 | 299 | if (*tempIterator == 60) { 300 | //< 301 | //Setting the iterator to the next possible position 302 | tempIterator = buffer.begin() + n + 44 + MY_HEADER_MODULE + START_SPACE + lastPos + (2* modulus); 303 | 304 | if (*tempIterator == 59) { 305 | // ; 306 | // Setting the iterator to next possible flag 307 | tempIterator = buffer.begin() + n + 44 + MY_HEADER_MODULE + START_SPACE + lastPos + (3 * modulus); 308 | 309 | if (*tempIterator == 59){ 310 | // End of message reached 311 | cout << "Message recovered size: " << pos << " bytes" << endl; 312 | return OutputBinFile(msgBuffer, customHeader); 313 | } 314 | } 315 | } 316 | } 317 | 318 | msgBuffer.push_back(*it); 319 | //cout << "Data recovered: " << msgBuffer[pos] << endl; // Uncomment this if you want to see the characters being read 320 | pos++; 321 | 322 | } 323 | n++; 324 | } 325 | 326 | // If it hits here it's because there was no message found in the file 327 | cout << "Could not find the end tags of the hidden file :(" << endl; 328 | return ERROR; 329 | } 330 | 331 | int WriteMessageFromEnd(vector& buffer, string msg) 332 | { 333 | // Verify if it is safe to hide the message in the buffer 334 | if ((buffer.size() / 4) < msg.size()) 335 | { 336 | cout << "The message might be to big for the audio file" << endl; 337 | return ERROR; 338 | } 339 | 340 | // Inverse iterator runs backwards 341 | int n = 0; 342 | int pos = 0; 343 | for (vector::reverse_iterator i = buffer.rbegin(); 344 | i != buffer.rend(); ++i) 345 | { 346 | if (n%1000 == 0) 347 | { 348 | *i = msg.at(pos); 349 | pos++; 350 | cout << *i << endl; 351 | 352 | if (pos >= msg.size()) 353 | break; 354 | } 355 | n++; 356 | } 357 | 358 | return SUCCESS; 359 | } 360 | 361 | int OutputBindedData(vector& buffer, string& fileExtension) 362 | { 363 | string fileName; 364 | if (fileExtension == "") 365 | fileName = "output"; 366 | else 367 | fileName = "output." + fileExtension; 368 | 369 | ofstream output(fileName, std::ios::binary); 370 | output.write((const char*)&buffer[0], buffer.size()); 371 | output.close(); 372 | cout << "File has been saved as: " << fileName << endl; 373 | 374 | return SUCCESS; 375 | } 376 | 377 | int OutputBinFile(vector& buffer, CustomHeader& cHeader) 378 | { 379 | string fileName; 380 | if (cHeader.GetExtension() == "") 381 | fileName = "output"; 382 | else 383 | fileName = "output." + cHeader.GetExtension(); 384 | 385 | ofstream output(fileName, std::ios::binary); 386 | output.write((const char*)&buffer[0], buffer.size()); 387 | output.close(); 388 | cout << "File has been saved as: " << fileName << endl; 389 | 390 | return SUCCESS; 391 | } 392 | 393 | void CreateHeader(long& modulus, char* modulusBytes, char* customHeader, string& fileExtension, bool isBinaryType) 394 | { 395 | /** 396 | * Create custom header (9 bytes): 397 | * Modulus value: 4 bytes 398 | * File extension: 4 bytes 399 | * Message type (text or file): 1 byte 400 | * */ 401 | 402 | // If modulus is lesser than the max int value of 4 bytes assign it. 403 | // Otherwise, set a flag to use DEF_MODULE constant 404 | if (modulus <= 42946729) 405 | modulusBytes = reinterpret_cast(&modulus); 406 | else 407 | modulusBytes[0] = DEF_MODULE; 408 | 409 | int y, i; 410 | // Assign modulus to header 411 | for (i = 0; i < 4; i++) 412 | customHeader[i] = modulusBytes[i]; 413 | 414 | // Assign the file extension to recover later 415 | for(y = 0, i = 4; i < 8; i++) 416 | { 417 | // Dinamically fill the 4 bytes of the file extension even if its less than 4 characters 418 | if(fileExtension.size() > y ) 419 | customHeader[i] = fileExtension.at(y); 420 | else 421 | customHeader[i] = ' '; 422 | y++; 423 | } 424 | 425 | // Assign the type of the message 426 | if (isBinaryType) 427 | customHeader[8] = 'b'; 428 | else 429 | customHeader[8] = 't'; 430 | } -------------------------------------------------------------------------------- /Algorithm.h: -------------------------------------------------------------------------------- 1 | // guard header 2 | #ifndef __ALGORITHM_H_INCLUDED__ 3 | #define __ALGORITHM_H_INCLUDED__ 4 | 5 | #define SUCCESS 1 6 | #define ERROR 2 7 | #define DEF_MODULE 64 // The bigger the module, the more spread(?) the message 8 | #define WAV_HEADER 44 9 | #define MY_HEADER_MODULE 64 10 | #define START_SPACE 0 // Space skipped in order to dont put a message at the starts of the songs 11 | /** 12 | * My custom header with the attributes of the file to retireve: 13 | * 4 bytes for modulus value 14 | * 4 for file extension 15 | * 1 byte for the type of message to find (text or binary) 16 | * */ 17 | #define MY_HEADER 9 18 | 19 | #include 20 | #include 21 | #include 22 | #include "CustomHeader.h" 23 | 24 | void CreateHeader(long& modulus, char* modulusBytes, char* customHeader, std::string& fileExtension, bool isBinaryType); 25 | int OutputBinFile(std::vector& buffer, CustomHeader& cHeader); 26 | int OutputBindedData(std::vector& buffer, std::string& extension); 27 | int WriteMessageFromEnd(std::vector& buffer, std::string msg); 28 | int PlayWithWaveBuffer(std::vector& buffer, std::string& msg, std::string& inputExt); // Hide a string 29 | int PlayWithWaveBuffer(std::vector& buffer, std::vector& fileMsg, std::string& fileExtension, std::string& inputExt); // Hide a binary file 30 | int FindHiddenTextInWave(std::vector& buffer, CustomHeader& customHeader); 31 | int FindHiddenBinaryInWave(std::vector& buffer, CustomHeader& customHeader); 32 | int FindHiddenMessage(std::vector& buffer); 33 | 34 | #endif // __ALGORITHM_H_INCLUDED__ 35 | -------------------------------------------------------------------------------- /BuildRelease/HideMeIn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielcardeenas/AudioStego/03d04e065cdbec35db2a24b56a5696b6cafa19ca/BuildRelease/HideMeIn -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.4) 2 | project(hideme) 3 | 4 | FIND_PACKAGE( Boost 1.40 COMPONENTS program_options REQUIRED ) 5 | INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} ) 6 | 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 8 | 9 | set(SOURCE_FILES main.cpp main.h Algorithm.cpp Algorithm.h CustomHeader.cpp CustomHeader.h) 10 | add_executable(hideme ${SOURCE_FILES}) 11 | TARGET_LINK_LIBRARIES( hideme ${Boost_LIBRARIES} ) 12 | -------------------------------------------------------------------------------- /CustomHeader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CustomHeader.h" 4 | 5 | CustomHeader::CustomHeader(char* header) { 6 | // Set modulus first 7 | char* bytes = new char[4]; 8 | for (int i = 0; i < 4; i++) 9 | bytes[i] = header[i]; 10 | 11 | mModulus = *reinterpret_cast(bytes); 12 | 13 | // Set extension 14 | char* ext = new char[4]; 15 | for (int y = 0, i = 4; i < 8; i++, y++) 16 | ext[y] = header[i]; 17 | 18 | mExtension = std::string(ext); 19 | boost::algorithm::trim(mExtension); 20 | 21 | // Set type 22 | mType = header[8]; 23 | 24 | delete[] bytes; 25 | delete[] ext; 26 | } 27 | 28 | CustomHeader::CustomHeader() { 29 | // Initialize the variables 30 | return; 31 | } 32 | 33 | int CustomHeader::GetModulus() { 34 | return this->mModulus; 35 | } 36 | 37 | std::string CustomHeader::GetExtension() { 38 | return this->mExtension; 39 | } 40 | 41 | char CustomHeader::GetType() { 42 | return this->mType; 43 | } 44 | 45 | int CustomHeader::GetLastPosition() { 46 | return this->mLastPos; 47 | } 48 | 49 | void CustomHeader::SetLastPosition(int n) { 50 | this->mLastPos = n; 51 | } -------------------------------------------------------------------------------- /CustomHeader.h: -------------------------------------------------------------------------------- 1 | // guard header 2 | #ifndef __CUSTOMHEADER_H_INCLUDED__ 3 | #define __CUSTOMHEADER_H_INCLUDED__ 4 | 5 | class CustomHeader { 6 | int mModulus; 7 | std::string mExtension; 8 | char mType; 9 | int mLastPos = 0; 10 | public: 11 | CustomHeader(char* header); 12 | CustomHeader(); 13 | int GetModulus(); 14 | std::string GetExtension(); 15 | char GetType(); 16 | int GetLastPosition(); 17 | 18 | void SetLastPosition(int n); 19 | }; 20 | 21 | #endif // __cUSTOMHEADER_H_INCLUDED__ 22 | -------------------------------------------------------------------------------- /Examples/print.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielcardeenas/AudioStego/03d04e065cdbec35db2a24b56a5696b6cafa19ca/Examples/print.bmp -------------------------------------------------------------------------------- /Examples/song.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielcardeenas/AudioStego/03d04e065cdbec35db2a24b56a5696b6cafa19ca/Examples/song.wav -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Daniel Cardenas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AudioStego 2 | ========== 3 | 4 | Audio file steganography. Hides text or files inside audio files and retrieve them automatically. 5 | It actually supports only .mp3 and .wav files as inputs, but you can hide whatever kind of file or text on them. 6 | 7 | [Here](https://danielcardeenas.github.io/audiostego.html) is a post about this software. 8 | 9 | Build 10 | ========== 11 | This project uses [CMake](http://www.cmake.org/install/) to build. So download it before compiling. 12 | 13 | ```sh 14 | > sudo apt-get install libboost-all-dev 15 | > git clone https://github.com/danielcardeenas/AudioStego.git 16 | > cd AudioStego 17 | > mkdir build 18 | > cd build 19 | > cmake .. 20 | > make 21 | ``` 22 | And it should create be a file named `hideme` 23 | 24 | **Note: Boost libraries need to be installed to compile** 25 | 26 | How to use 27 | ========== 28 | 29 | ### Hiding data 30 | In order to hide a file inside another file 31 | 32 | ```sh 33 | > ./hideme file_used_to_hide_data file_to_hide 34 | ``` 35 | 36 | Or if you want to hide a string on it 37 | 38 | ```sh 39 | > ./hideme file_used_to_hide_data "'Message to hide'" 40 | ``` 41 | **(Notice the simple quotation inside double quotes)** 42 | 43 | Both will output a clone of the file with the hidden data as `output.(file extension)` 44 | 45 | ### Retrieving hidden data 46 | In order to retrieve a hidden message just set the "-f" or "--find" flag: 47 | 48 | ```sh 49 | > ./hideme [file_with_hidden_data] -f 50 | ``` 51 | 52 | It will automatically detect wether it's a string or a file and the type of the file itself. 53 | + If it's a file, it will create it as `output.(file extension)` 54 | + If it's a string message, it will print it on the console/terminal 55 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "main.h" 3 | #include "Algorithm.h" 4 | 5 | using namespace std; 6 | 7 | int main(int argc, char* argv[]) 8 | { 9 | string msg; 10 | string inputPath; 11 | string fileExt, inputExt; 12 | 13 | ifstream binStremFile; 14 | streampos binFileSize; 15 | vector msgBuffer; 16 | 17 | int mode = 1; // hide 18 | 19 | if (argc < 2) 20 | { 21 | cout << "Where are my the parameters mate?" << endl; 22 | cout << "To hide a string: ./HideMeIn [input_file] \"'string message'\" (Single quotation inside double quotation)" << endl; 23 | cout << "To hide a file: ./HideMeIn [input_file] [file_to_hide]" << endl; 24 | cout << endl; 25 | cout << "To retrieve something already hidden: ./HideMeIn [file_with_hidden_data] -f" << endl; 26 | return 0; 27 | } 28 | else if (argc == 2) { 29 | /** 30 | * When only the song path is passed. 31 | * Using the default message 32 | * @param: song 33 | * */ 34 | 35 | cout << "No message to hide was specified. Using a default string message..." << endl; 36 | inputPath = argv[1]; 37 | msg = "Default Message KEKLIFE"; 38 | //return 0; 39 | } 40 | else if (argc == 3){ 41 | /** 42 | * When only the song path and the (message or flag) are passed. 43 | * In case mode is passsed, find hidden message 44 | * @param: song, message/flag 45 | * */ 46 | 47 | inputPath = argv[1]; 48 | if(string(argv[2]) == "-f" || string(argv[2]) == "--find") 49 | { 50 | // Find the hidden message mode 51 | mode = 2; 52 | } 53 | else{ 54 | // User wants to hide data then 55 | // Decide whether is a string or a file 56 | if (string(argv[2])[0] == 39 && string(argv[2]).back() == 39) 57 | { 58 | // Quotation marks detected. Hide string message 59 | mode = 1; 60 | msg = string(argv[2]); 61 | 62 | // Get input file extension 63 | inputExt = GetFileExtension(string(argv[1])); 64 | } 65 | else { 66 | // Take it as a file path 67 | mode = 3; 68 | 69 | // Get files extension 70 | fileExt = GetFileExtension(string(argv[2])); 71 | inputExt = GetFileExtension(string(argv[1])); 72 | 73 | binStremFile.open(string(argv[2]), std::ios::binary ); 74 | binFileSize = binStremFile.tellg(); 75 | msgBuffer.reserve(binFileSize); // Reserve the amount of the file size of memory to the vector 76 | } 77 | } 78 | } 79 | else{ 80 | cout << "Too much argumments maybe? " << endl; 81 | 82 | cout << "To hide a string: ./HideMeIn [input_file] \"'string message'\" (Single quotation inside double quotation)" << endl; 83 | cout << "To hide a file: ./HideMeIn [input_file] [file_to_hide]" << endl; 84 | cout << endl; 85 | cout << "To retrieve something already hidden: ./HideMeIn [file_with_hidden_data] -f" << endl; 86 | return 0; 87 | } 88 | 89 | cout << "Doing it boss! " << endl; 90 | 91 | // Get input file 92 | ifstream input(inputPath, std::ios::binary ); 93 | if(!input.is_open()) 94 | { 95 | cout << "Unable to open the file given" << endl; 96 | return 0; 97 | } 98 | 99 | // Copy the song into a buffer and closing it because we don't want to touch that 100 | vector buffer( 101 | (istreambuf_iterator(input)), 102 | (istreambuf_iterator())); 103 | 104 | if (mode == 3) 105 | { 106 | /** 107 | * If we are going to hide a binary file: 108 | * Assign the binary file into a vector to play with him later and close the file. 109 | */ 110 | 111 | msgBuffer.assign( 112 | (istreambuf_iterator(binStremFile)), 113 | (istreambuf_iterator())); 114 | 115 | binStremFile.close(); 116 | } 117 | 118 | input.close(); 119 | 120 | /** 121 | * mode: 122 | * 1 -> hide a string 123 | * 2 -> retrieve message (string or binary) 124 | * 3 -> hide a binary file 125 | **/ 126 | 127 | if (mode == 1) 128 | { 129 | int status = PlayWithWaveBuffer(buffer, msg, inputExt); 130 | if (status == SUCCESS) 131 | cout << "Hiding process has finished successfully.\nCleaning memory..." << endl; 132 | else if (status == ERROR) 133 | cout << "Something failed.\nCleaning memory..." << endl; 134 | } 135 | else if (mode == 2){ 136 | int status = FindHiddenMessage(buffer); 137 | if (status == SUCCESS) 138 | cout << "Recovering process has finished successfully.\nCleaning memory..." << endl; 139 | else if (status == ERROR) 140 | cout << "Something failed.\nCleaning memory..." << endl; 141 | } 142 | else if (mode == 3){ 143 | int status = PlayWithWaveBuffer(buffer, msgBuffer, fileExt, inputExt); 144 | if (status == SUCCESS) 145 | cout << "Hiding process has finished successfully.\nCleaning memory..." << endl; 146 | else if (status == ERROR) 147 | cout << "Something failed.\nCleaning memory..." << endl; 148 | } 149 | 150 | // Force remove the buffer from memory 151 | vector().swap(buffer); 152 | vector().swap(msgBuffer); 153 | return 0; 154 | } 155 | 156 | /** 157 | * This will return the extension even on strings like "a.b.c.d.e.s.mp3" 158 | * If it cannot find the extension it will return "". 159 | * 160 | * @param fileName: The entire file name 161 | * */ 162 | string GetFileExtension(const string& fileName) 163 | { 164 | if(fileName.find_last_of(".") != std::string::npos) 165 | return fileName.substr(fileName.find_last_of(".")+1); 166 | return ""; 167 | } -------------------------------------------------------------------------------- /main.h: -------------------------------------------------------------------------------- 1 | // guard header 2 | #ifndef __MAIN_H_INCLUDED__ 3 | #define __MAIN_H_INCLUDED__ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | std::string GetFileExtension(const std::string& fileName); 10 | 11 | #endif // __MAIN_H_INCLUDED__ --------------------------------------------------------------------------------