From 0c3df85ea07971587f910c661b9ecc514ec27af9 Mon Sep 17 00:00:00 2001 From: Pin Date: Tue, 21 Sep 2021 01:15:03 -0400 Subject: Extended PNG Support Signed-off-by: Pin --- Makefile | 12 +- cmd/crc.c | 304 -------------------------- cmd/pspng.c | 620 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/crc.h | 8 - include/crc_util.h | 17 +- include/pspng.h | 7 + src/crc_util.c | 6 +- 7 files changed, 654 insertions(+), 320 deletions(-) delete mode 100644 cmd/crc.c create mode 100644 cmd/pspng.c delete mode 100644 include/crc.h create mode 100644 include/pspng.h diff --git a/Makefile b/Makefile index 9d3cb0d..c06d92d 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,17 @@ LIBRARIES = `pkg-config --libs zlib libsodium` -Iinclude -SOURCES = ./src/* ./cmd/crc.c +SOURCES = ./src/* ./cmd/pspng.c OUTPUT_DIR = ./bin OUTPUT = -o ${OUTPUT_DIR}/PROG +INSTALL_OUTPUT = ${OUTPUT_DIR}/PROG build: output_dir - gcc -Wall ${LIBRARIES} ${SOURCES} ${OUTPUT:PROG=crc} + gcc -Wall -pthread ${LIBRARIES} ${SOURCES} ${OUTPUT:PROG=pspng} debug: output_dir - gcc -Wall -g ${LIBRARIES} ${SOURCES} ${OUTPUT:PROG=crc} + gcc -Wall -g -pthread ${LIBRARIES} ${SOURCES} ${OUTPUT:PROG=pspng} + +install: + mv ${INSTALL_OUTPUT:PROG=pspng} /usr/bin/ output_dir: mkdir -p ${OUTPUT_DIR} @@ -16,4 +20,4 @@ clean: rm -rf $(OUTPUT_DIR) **.h.gch memcheck: debug - valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes -s ${OUTPUT_DIR}/crc + valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes -s ${OUTPUT_DIR}/pspng diff --git a/cmd/crc.c b/cmd/crc.c deleted file mode 100644 index b872e6c..0000000 --- a/cmd/crc.c +++ /dev/null @@ -1,304 +0,0 @@ -#pragma GCC optimize("Ofast") - -#include -#include -#include -#include -#include -#include -#include -#include "crc_util.h" -#include "CRCLib.h" -#include "crc.h" -#include "compress_util.h" - -const long idat_signature = 1229209940; -const long iend_signature = 1229278788; - -unsigned long first_idat(unsigned char *addr) { - int idat_found = 0; - unsigned long offset = 8; - int jump_offset = 0; - int header_type = 0; - while(idat_found == 0) { - jump_offset = check_header_length(addr, offset); - header_type = check_header_length(addr, offset+4); - if(header_type == idat_signature) { - idat_found = 1; - } else { - offset = offset + jump_offset + 12; - } - } - return offset; -} - -int total_idat(unsigned char *addr) { - int iend_found = 0; - int found_idat = 0; - unsigned long offset = 8; - int jump_offset = 0; - int header_type = 0; - while(iend_found == 0) { - jump_offset = check_header_length(addr, offset); - header_type = check_header_length(addr, offset+4); - if(header_type == iend_signature) { - iend_found = 1; - } else { - if(header_type == idat_signature) { - found_idat++; - } - offset = offset + jump_offset + 12; - } - } - return found_idat; -} - -int update_file_crc(unsigned char *addr, unsigned long offset , unsigned int crc_num) { - int startCRC = 8 + offset + check_header_length(addr, offset); - unsigned char new_crc; - for(int i = 0; i < 4; i++) { - new_crc = crc_num >> (8*(3-i)) & 0xFF; - addr[startCRC+i] = new_crc; - } - return 0; -} - -void random_data_change(unsigned char *color_data, int width, int length) { - int searching = 1; - size_t rounds = 0; - width = 16; - int color_range = 3; - unsigned char temp_color_data[length]; - - do { - rounds++; - // Creating temporary data set - memcpy(temp_color_data, color_data, length); - // Generating random byte to change - int random_num = randombytes_uniform(length); - // Checking for index break - if(random_num % ((width * color_range) + 1)) { - if(color_data[random_num] == 255) { - temp_color_data[random_num]--; - } else { - temp_color_data[random_num]++; - } - unsigned char *check_data_buff = NULL; - size_t check_data_length = 0; - zlib_compress_data(temp_color_data, length, &check_data_buff, &check_data_length); - - unsigned char full_data[check_data_length+4]; - full_data[0] = 0x49; - full_data[1] = 0x44; - full_data[2] = 0x41; - full_data[3] = 0x54; - for(int i = 0; i < check_data_length; i++) { - full_data[i+4] = check_data_buff[i]; - } - unsigned int temp_crc = crc(full_data, check_data_length); - if ((temp_crc >> (8*3)) == 10 ) { - printf("Found in %zu rounds!\n", rounds); - memcpy(color_data, temp_color_data, length); - searching = 0; - } - free(check_data_buff); - } - - } while(searching == 1); -} - -void build_png_file(struct PNG_FILE_STRUCT *png_file, char *out_file_name) { - FILE *fp; - - fp = fopen(out_file_name, "w"); - - union{ - unsigned char data[sizeof(struct PNG_START_FILE_STRUCT)]; - struct PNG_START_FILE_STRUCT png_data; - }start_data; - - start_data.png_data = png_file->png_start_data; - - // IHDR Data - for(int i = 0; i < sizeof(start_data.data); i++) { - fputc(start_data.data[i], fp); - } - // IDAT Data - for(int i = 0; i < 4; i++) { - fputc(png_file->png_idat_data.idat_length[i], fp); - } - for(int i = 0; i < 4; i++) { - fputc(png_file->png_idat_data.idat_header[i], fp); - } - for(int i = 0; i < be32toh(png_file->png_idat_data.idat_data_length); i++) { - fputc(png_file->png_idat_data.idat_data[i], fp); - } - // Generating CRC - unsigned char full_data[be32toh(png_file->png_idat_data.idat_data_length)+4]; - for(int i = 0; i < 4; i++) { - full_data[i] = png_file->png_idat_data.idat_header[i]; - } - for(int i = 0; i < be32toh(png_file->png_idat_data.idat_data_length); i++) { - full_data[i+4] = png_file->png_idat_data.idat_data[i]; - } - - unsigned int int_crc = crc(full_data, be32toh(png_file->png_idat_data.idat_data_length)); - unsigned char new_crc[4]; - - for(int i = 0; i < 4; i++) { - new_crc[i] = int_crc >> (8*(3-i)) & 0xFF; - fputc(new_crc[i], fp); - } - // IEND Data - unsigned char IEND_DATA[12] = { 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82}; - for(int i = 0; i < 12; i++) { - fputc(IEND_DATA[i], fp); - } - fclose(fp); -} - -int change_idat_content(unsigned char *addr, struct PNG_FILE_STRUCT *png_file, char *message, int accuracy, unsigned long offset, char *out_file_name) { - if(accuracy > 4) { - printf("Warning, accuracy cannot be larger than 4"); - return EXIT_FAILURE; - } - if(accuracy > 2) { - printf("Notice, this could take a long time..."); - } - if(total_idat(addr) < strlen((char*)message)) { - printf("Warning, message exceeds IDAT amount\n"); - exit(EXIT_FAILURE); - } - - int idat_length = check_header_length(addr, offset); - printf("IDAT Length: %d\n", idat_length); - - long size = 1; - size_t idat_byte_length = 0; - unsigned char* idat_data = calloc(size, sizeof(unsigned char)); - for(size_t i = 0; i <= idat_length; i++) { - if(i == size) { - size *= 2; - idat_data = reallocarray(idat_data, size, sizeof(unsigned char)); - } - idat_data[i] = addr[i+offset+8]; - idat_byte_length = i; - } - unsigned char temp_idat_data[idat_byte_length]; - for(int i = 0; i <= idat_length; i++) { - temp_idat_data[i] = idat_data[i]; - } - // Decompressing Data - unsigned char *uncom_data_buff = NULL; - size_t uncom_data_size = 0; - zlib_decompress_data(temp_idat_data, idat_byte_length, &uncom_data_buff, &uncom_data_size); - - random_data_change(uncom_data_buff, 16, uncom_data_size); - - // Compress Data - unsigned char *com_data_buff; - size_t com_data_size = 0; - zlib_compress_data(uncom_data_buff, uncom_data_size, &com_data_buff, &com_data_size); - - png_file->png_idat_data.idat_data = calloc(com_data_size, sizeof(unsigned char)); - - png_file->png_idat_data.idat_data_length = be32toh(com_data_size); - - for(size_t i = 0; i < com_data_size; i++) { - png_file->png_idat_data.idat_data[i] = com_data_buff[i]; - } - - // Build PNG File - build_png_file(png_file, out_file_name); - - free(uncom_data_buff); - free(com_data_buff); - free(idat_data); - free(png_file->png_idat_data.idat_data); - - return 0; -} - -// This is where it all starts -int main(int argc, char **argv) { - FILE *fp; - size_t i = 0; - unsigned long offset = 0; - struct PNG_FILE_STRUCT png_file_data; - char *in_file_name = NULL; - char *out_file_name = NULL; - char *message = NULL; - - static const struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"file", required_argument, NULL, 'f'}, - {"outfile", required_argument, NULL, 'o'}, - {"message", required_argument, NULL, 'm'}, - {0, 0, 0, 0} - }; - - const char* usage = - "Usage: crc [options]\n" - " -h, --help Shows help message\n" - " -f, --file Denotes input file\n" - " -o, --outfile Denotes output file\n" - " -m, --message Encoded message\n" - "\n"; - - int c; - while (1) { - int option_index = 0; - c = getopt_long(argc, argv, "hf:o:m:", long_options ,&option_index); - if(c == -1) { - break; - } - switch(c) { - case 'h': - printf("%s", usage); - exit(EXIT_SUCCESS); - case 'f': - in_file_name = optarg; - break; - case 'o': - out_file_name = optarg; - break; - case 'm': - message = optarg; - break; - } - } - - if(in_file_name == NULL) { - printf("Input file required!\n"); - exit(EXIT_FAILURE); - } else if(out_file_name == NULL) { - printf("Output file required!\n"); - exit(EXIT_FAILURE); - } else if(message == NULL) { - printf("Message required!\n"); - exit(EXIT_FAILURE); - } - - if(sodium_init() == -1) { - return EXIT_FAILURE; - } - - fp = fopen(in_file_name, "rt"); - if (fp == NULL) { - printf("File error\n"); - exit(EXIT_FAILURE); - } - - unsigned char *file_data = file_to_char_array(fp, &i); - fclose(fp); - - populate_start_png(file_data, &png_file_data.png_start_data); - - offset = first_idat(file_data); - - populate_idat_png(file_data, &png_file_data.png_idat_data, offset); - - change_idat_content(file_data, &png_file_data, message, 1, offset, out_file_name); - - free(file_data); -} diff --git a/cmd/pspng.c b/cmd/pspng.c new file mode 100644 index 0000000..59c8699 --- /dev/null +++ b/cmd/pspng.c @@ -0,0 +1,620 @@ +#pragma GCC optimize("O0") + +#include +#include +#include +#include +#include +#include +#include +#include +#include "crc_util.h" +#include "CRCLib.h" +#include "pspng.h" +#include "compress_util.h" + +//#define MAX_IDAT_SIZE 16384 +#define MAX_WINDOW_SIZE 32768 +#define MAX_IDAT_SIZE 8192 + +const long idat_signature = 1229209940; +const long iend_signature = 1229278788; + +unsigned long first_idat(unsigned char *addr) { + int idat_found = 0; + unsigned long offset = 8; + long jump_offset = 0; + unsigned long header_type = 0; + while(idat_found == 0) { + jump_offset = check_header_length(addr, offset); + header_type = check_header_length(addr, offset+4); + if(header_type == idat_signature) { + idat_found = 1; + } else { + offset = offset + jump_offset + 12; + } + } + return offset; +} + +int total_idat(unsigned char *addr) { + int searching = 0; + int found_idat = 0; + unsigned long offset = 0; + unsigned long idat_length = 0; + unsigned long header_type = 0; + + unsigned long first_idat_offset = first_idat(addr); + offset = first_idat_offset; + + while(searching == 0) { + found_idat++; + idat_length = check_header_length(addr, offset); + // Jumping Offset + IDAT LENGTH + 3 bytes for 2 CRCs and 1 LEN fields + offset = offset+12+idat_length; + header_type = check_header_length(addr, offset+4); + if(header_type != idat_signature) { + searching = 1; + } + } + return found_idat; +} + +int update_file_crc(unsigned char *addr, unsigned long offset , unsigned int crc_num) { + int startCRC = 8 + offset + check_header_length(addr, offset); + unsigned char new_crc; + for(int i = 0; i < 4; i++) { + new_crc = crc_num >> (8*(3-i)) & 0xFF; + addr[startCRC+i] = new_crc; + } + return 0; +} + +static void random_window_bit_change(unsigned char *data, int width, int rounds, int color_range, size_t length, size_t offset) { + size_t random_num = 0; + size_t filter_chunk_byte = 0; + size_t change_num = 0; + long prior_chuck_check = 0; + for (int i = 0; i < rounds; i++) { + random_num = 0; + do { + random_num = randombytes_uniform(length) + offset; + filter_chunk_byte = (random_num - (random_num % ((width * color_range) + 1))); + } while((random_num % ((width * color_range) + 1)) == 0); + + if(data[filter_chunk_byte] == 0) { + // None Filter Type Change + if(data[random_num] == 255) { + data[random_num]--; + } else { + data[random_num]++; + } + } else if(data[filter_chunk_byte] == 1) { + // Sub Filter Type Change + if(data[random_num] == 255) { + data[random_num]--; + change_num = 1; + } else { + data[random_num]++; + change_num = -1; + } + // Starting after random change + for(int j = 1; j < 2; j++) { + data[random_num+(color_range * j)] = (data[random_num+(color_range * j)] + change_num) % 256; + } + } else if(data[filter_chunk_byte] == 2) { + printf("2\n"); + if(data[random_num] == 255) { + data[random_num]--; + } else { + data[random_num]++; + } + } else if(data[filter_chunk_byte] == 3) { + // Average Filter Type Change + //printf("HEE: %d\n", data[(filter_chunk_byte - (width * color_range))-1]); + prior_chuck_check = filter_chunk_byte; + do { + //printf("C: %d\n", data[prior_chuck_check]); + prior_chuck_check = (prior_chuck_check - (width * color_range)-1); + //printf("CH: %ld\n", prior_chuck_check); + } while(prior_chuck_check >= 0); + + if(data[random_num] == 255) { + data[random_num]--; + } else { + data[random_num]++; + } + } else if(data[filter_chunk_byte] == 4) { + printf("4\n"); + if(data[random_num] == 255) { + data[random_num]--; + } else { + data[random_num]++; + } + } else { + printf("ERROR ;( %ld\n", filter_chunk_byte); + } + + } + return; +} + +static int verify_crc_chunks(unsigned char *data, size_t data_length, int crc_depth, unsigned int max_data_length, char message, size_t iteration) { + unsigned char* testing_chunk; + unsigned int crc_check = 0; + unsigned int test_data_length = 0; + unsigned int crc_check_length; + int rounds = 0; + + for(int i = 0; i < crc_depth; i++) { + if((max_data_length * (i+1)) > data_length) { + test_data_length = (data_length - (max_data_length * i)); + testing_chunk = calloc(test_data_length+4, sizeof(unsigned char)); + // If this is met we need to stop verification + i = crc_depth; + } else { + test_data_length = max_data_length; + testing_chunk = calloc(test_data_length+4, sizeof(unsigned char)); + } + // Setting first chunk to IDAT + testing_chunk[0] = 0x49; + testing_chunk[1] = 0x44; + testing_chunk[2] = 0x41; + testing_chunk[3] = 0x54; + for(int j = 0; j < test_data_length; j++) { + testing_chunk[j+4] = data[(test_data_length*rounds)+j+(MAX_WINDOW_SIZE*iteration)]; + } + crc_check_length = test_data_length+4; + crc_check = crc(testing_chunk, crc_check_length); + + if ((crc_check >> (8*3)) != message ) { + free(testing_chunk); + return 1; + } + printf("FOUND: %c\n", message); + // Used as an alternative to i + // Since i needs to be changed it max data length is met + rounds++; + } + free(testing_chunk); + return 0; +} + +static int crc_embed_data(unsigned char *data, unsigned int data_length, int bit_width, int color_range, unsigned int sliding_window, char message, size_t offset , size_t iteration) { + unsigned char *check_data; + size_t check_data_length = 0; + + random_window_bit_change(data, bit_width, 2, color_range, sliding_window, offset); + + // Compressing data for test + zlib_compress_data(data, data_length, &check_data, &check_data_length); + + int match_crc = verify_crc_chunks(check_data, check_data_length, 1, MAX_IDAT_SIZE, message, iteration); + + if(match_crc == 0) { + printf("COM SIZE: %zu\n", check_data_length); + free(check_data); + return 0; + } + free(check_data); + return 1; +} + +void *random_data_change_thread_call(void *w) { + struct EMBED_THREAD_STRUCT *data = w; + unsigned char* temp_color_data = calloc(data->uncom_data_len, sizeof(unsigned char)); + char cur_message; + int searching = 1; + do { + // Creating temporary data set + memcpy(temp_color_data, data->data, data->uncom_data_len); + + // Look into testing these values more + if(data->uncom_data_len > 800000) { + data->data_len = 90000 + (90000 * data->cur_iteration); + } else { + data->data_len = data->uncom_data_len; + } + if(data->uncom_data_len > 16000) { + data->win_size = 9000 + (9000 * data->cur_iteration); + } else { + data->win_size = data->uncom_data_len; + } + + cur_message = data->message[data->cur_iteration]; + + searching = crc_embed_data(temp_color_data, data->data_len, data->width, data->color_range, data->win_size, cur_message, data->cur_offset, data->cur_iteration); + + pthread_mutex_lock(&data->mutex_lock); + if (searching == 0 && *data->searching == 1) { + *data->searching = searching; + printf("CUR MESSAGE: %c\n", cur_message); + memcpy(data->data, temp_color_data, data->uncom_data_len); + pthread_mutex_unlock(&data->mutex_lock); + break; + } + pthread_mutex_unlock(&data->mutex_lock); + + } while(*data->searching == 1); + free(temp_color_data); + pthread_exit(0); +} + +size_t generate_offset(unsigned char *data, size_t data_len, size_t iteration) { + unsigned char *com_data_buff = NULL; + unsigned char *uncom_data_buff = NULL; + size_t com_data_size = 0; + size_t uncom_data_size = 0; + + printf("Gen Offset\n"); + zlib_compress_data(data, data_len, &com_data_buff, &com_data_size); + + zlib_decompress_data(com_data_buff, (MAX_WINDOW_SIZE * (iteration+1)), &uncom_data_buff, &uncom_data_size); + + printf("NEW SIZE: %zu\n", uncom_data_size); + + free(com_data_buff); + free(uncom_data_buff); + return uncom_data_size; +} + +void random_data_change(unsigned char *color_data, unsigned char *width, size_t length, char *message) { + int searching = 1; + int core_count = 24; + unsigned int sliding_window = 0; + unsigned int compress_data_length = 0; + // Needs to be turned into a variable + int color_range = 3; + int waiting = 0; + // Union for width type cast + union { + uint32_t width_int; + unsigned char width_array[4]; + }w; + memcpy(w.width_array, width, 4); + + struct EMBED_THREAD_STRUCT *t_data = malloc(sizeof(struct EMBED_THREAD_STRUCT)); + + if(pthread_mutex_init(&t_data->mutex_lock, NULL) != 0) { + printf("Mutex Lock Error\n"); + return; + } + t_data->searching = &searching; + t_data->message = message; + t_data->data = color_data; + t_data->data_len = compress_data_length; + t_data->uncom_data_len = length; + t_data->cur_offset = 0; + t_data->width = be32toh(w.width_int); + t_data->color_range = color_range; + t_data->win_size = sliding_window; + pthread_t tid; + t_data->thread_id = tid; + for(int j = 0; j < strlen(message); j++) { + // Setting Iteration bit and searching + t_data->cur_iteration = j; + *t_data->searching = 1; + for(int i = 0; i < core_count; i++) { + pthread_create(&tid, NULL, random_data_change_thread_call, t_data); + } + // Waiting for all threads to complete + waiting = 0; + do { + pthread_join(tid, NULL); + waiting++; + } while(waiting!=core_count); + pthread_mutex_destroy(&t_data->mutex_lock); + + // Only generate new offset if not last char in message + if(j != (strlen(message) - 1)) { + t_data->cur_offset = generate_offset(color_data, t_data->uncom_data_len, j); + } + } + return; +} + +void build_png_file(struct PNG_FILE_STRUCT *png_file, char *out_file_name) { + FILE *fp; + unsigned char *full_data; + unsigned int int_crc; + unsigned char new_crc[4]; + unsigned char IEND_DATA[12] = { 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82}; + + fp = fopen(out_file_name, "w"); + + union{ + unsigned char data[sizeof(struct PNG_START_FILE_STRUCT)]; + struct PNG_START_FILE_STRUCT png_data; + }start_data; + + start_data.png_data = png_file->png_start_data; + + printf("IHDR SIZE: %zu\n", sizeof(struct PNG_START_FILE_STRUCT)); + + // IHDR Data + for(int i = 0; i < sizeof(start_data.data); i++) { + fputc(start_data.data[i], fp); + } + + // Generating IDAT CHUNKS + int idat_loop = 0; + uint32_t current_len = 0; + do { + // Setting IDAT length chunk variable + if ((be32toh(png_file->png_idat_data.idat_data_length)-(MAX_IDAT_SIZE*idat_loop)) > MAX_IDAT_SIZE) { + current_len = MAX_IDAT_SIZE; + } else { + current_len = (be32toh(png_file->png_idat_data.idat_data_length)-(MAX_IDAT_SIZE*idat_loop)); + } + + // IDAT LENGTH WRITE + for(int i = 0; i < 4; i++) { + //fputc(png_file->png_idat_data.idat_length[i], fp); + fputc(current_len >> (8*(3-i)), fp); + } + // IDAT HEADER WRITE + for(int i = 0; i < 4; i++) { + fputc(png_file->png_idat_data.idat_header[i], fp); + } + // IDAT DATA WRITE + //for(int i = 0; i < be32toh(png_file->png_idat_data.idat_data_length); i++) { + for(int i = 0; i < current_len; i++) { + fputc(png_file->png_idat_data.idat_data[i+(MAX_IDAT_SIZE*idat_loop)], fp); + } + + // Generating CRC + //unsigned char *full_data = malloc(be32toh(png_file->png_idat_data.idat_data_length)+4); + full_data = malloc(current_len+4); + for(int i = 0; i < 4; i++) { + full_data[i] = png_file->png_idat_data.idat_header[i]; + } + for(int i = 0; i < current_len; i++) { + full_data[i+4] = png_file->png_idat_data.idat_data[i+(MAX_IDAT_SIZE*idat_loop)]; + } + + int_crc = crc(full_data, current_len+4); + + // IDAT CRC WRITE + for(int i = 0; i < 4; i++) { + new_crc[i] = int_crc >> (8*(3-i)) & 0xFF; + fputc(new_crc[i], fp); + } + + // Adding to loop count + idat_loop++; + } while((idat_loop-1) < (be32toh(png_file->png_idat_data.idat_data_length) / MAX_IDAT_SIZE)); + + // IEND Data + for(int i = 0; i < 12; i++) { + fputc(IEND_DATA[i], fp); + } + free(full_data); + fclose(fp); +} + +unsigned char* populate_idat_array(unsigned char *addr, unsigned long offset, size_t *idat_byte_length) { + size_t size = 8; + //size_t idat_byte_length = 0; + size_t idat_length = 0; + //unsigned char* idat_data = calloc(size, sizeof(unsigned char)); + unsigned char* idat_data = calloc(size, sizeof(unsigned char)); + + for(size_t i = 0; i < total_idat(addr); i++) { + idat_length = check_header_length(addr, offset); + for(size_t j = 0; j < idat_length; j++) { + if(*idat_byte_length == size) { + size *= 2; + idat_data = reallocarray(idat_data, size, sizeof(unsigned char)); + } + idat_data[*idat_byte_length] = addr[offset+8+j]; + *idat_byte_length += 1; + } + // Offset 3 bytes for 2 length fields and 1 crc + offset = offset + idat_length + 12; + } + return idat_data; +} + +int change_idat_content(unsigned char *addr, struct PNG_FILE_STRUCT *png_file, char *message, int accuracy, unsigned long offset, char *out_file_name) { + if(accuracy > 4) { + printf("Warning, accuracy cannot be larger than 4"); + return EXIT_FAILURE; + } + if(accuracy > 2) { + printf("Notice, this could take a long time..."); + } + if(total_idat(addr) < strlen(message)) { + printf("Warning, message exceeds IDAT amount\n"); + exit(EXIT_FAILURE); + } + + size_t idat_byte_length = 0; + unsigned char *idat_data = populate_idat_array(addr, offset, &idat_byte_length); + + unsigned char* temp_idat_data = calloc(idat_byte_length, sizeof(unsigned char)); + memcpy(temp_idat_data, idat_data, idat_byte_length); + + // Decompressing Data + unsigned char *uncom_data_buff = NULL; + size_t uncom_data_size = 0; + zlib_decompress_data(temp_idat_data, idat_byte_length, &uncom_data_buff, &uncom_data_size); + + printf("ORIG UNCOM LEN: %zu\n", uncom_data_size); + + // Start data testing + random_data_change(uncom_data_buff, png_file->png_start_data.file_width, uncom_data_size, message); + + //return 0; + // Compress Data + unsigned char *com_data_buff; + size_t com_data_size = 0; + zlib_compress_data(uncom_data_buff, uncom_data_size, &com_data_buff, &com_data_size); + + printf("COM LEN: %zu\n", com_data_size); + + png_file->png_idat_data.idat_data = calloc(com_data_size, sizeof(unsigned char)); + + png_file->png_idat_data.idat_data_length = be32toh(com_data_size); + + for(size_t i = 0; i < com_data_size; i++) { + png_file->png_idat_data.idat_data[i] = com_data_buff[i]; + } + + // Build PNG File + build_png_file(png_file, out_file_name); + + // Freeing used memory + free(uncom_data_buff); + free(com_data_buff); + free(idat_data); + free(temp_idat_data); + free(png_file->png_idat_data.idat_data); + + return 0; +} + +// This is where it all starts +int main(int argc, char **argv) { + FILE *fp; + size_t i = 0; + unsigned long offset = 0; + int uncompress_call = 0; + int compress_call = 0; + struct PNG_FILE_STRUCT png_file_data; + char *in_file_name = NULL; + char *out_file_name = NULL; + char *message = NULL; + + static const struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + {"file", required_argument, NULL, 'f'}, + {"outfile", required_argument, NULL, 'o'}, + {"message", required_argument, NULL, 'm'}, + {"compress", no_argument, NULL, 'c'}, + {"uncompress", no_argument, NULL, 'u'}, + {0, 0, 0, 0} + }; + + const char* usage = + "Usage: pspng [options]\n\n" + " -c --compress Compress Message\n" + " -u --uncompress Currently used for debugging\n" + " -h, --help Shows help message\n" + " -f, --file Denotes input file\n" + " -o, --outfile Denotes output file\n" + " -m, --message Encoded message\n" + "\n"; + + int c; + while (1) { + int option_index = 0; + c = getopt_long(argc, argv, "hf:o:m:uc", long_options ,&option_index); + if(c == -1) { + break; + } + switch(c) { + case 'h': + printf("%s", usage); + exit(EXIT_SUCCESS); + case 'f': + in_file_name = optarg; + break; + case 'o': + out_file_name = optarg; + break; + case 'm': + message = optarg; + break; + case 'c': + compress_call = 1; + break; + case 'u': + uncompress_call = 1; + break; + } + } + + if(in_file_name == NULL) { + printf("Input file required!\n"); + exit(EXIT_FAILURE); + } + + if(compress_call == 1) { + if(out_file_name == NULL) { + printf("Output file required!\n"); + exit(EXIT_FAILURE); + } else if(message == NULL) { + printf("Message required!\n"); + exit(EXIT_FAILURE); + } + } + + if(sodium_init() == -1) { + return EXIT_FAILURE; + } + + fp = fopen(in_file_name, "rt"); + if (fp == NULL) { + printf("File error\n"); + exit(EXIT_FAILURE); + } + + + unsigned char *file_data = file_to_char_array(fp, &i); + fclose(fp); + + populate_start_png(file_data, &png_file_data.png_start_data); + + offset = first_idat(file_data); + + if(uncompress_call == 1) { + size_t idat_byte_length = 0; + unsigned long cur_idat_len = 0; + //unsigned char message_data[8192]; + unsigned char* idat_data = populate_idat_array(file_data, offset, &idat_byte_length); + + //for(int i = 0; i < idat_byte_length; i++) { + //printf("%02X ", idat_data[i]); + //} + printf("\nDecompressed Data:\n\n"); + // Decompressing data + //unsigned char *uncom_data_buff = NULL; + //size_t uncom_data_size = 0; + //zlib_decompress_data(idat_data, idat_byte_length, &uncom_data_buff, &uncom_data_size); + //for(int i = 0; i < uncom_data_size; i++) { + // printf("%02X ", uncom_data_buff[i]); + //} + //printf("\n"); + + do { + for(int j = 0; j < 64; j++) { + cur_idat_len = 0; + for(int i = 0; i < 4; i++) { + cur_idat_len += (file_data[offset+i] << (24-(8*i))); + } + //printf("%c", file_data[offset+cur_idat_len+8]); + if((j % 4) == 0) { + printf("%c", file_data[offset+cur_idat_len+8]); + } + // Offset Plus idat length + 3 bytes + offset += cur_idat_len + 12; + } + } while(offset < idat_byte_length); + + free(idat_data); + free(file_data); + return EXIT_SUCCESS; + } + + if(compress_call == 1) { + populate_idat_png(file_data, &png_file_data.png_idat_data, offset); + + change_idat_content(file_data, &png_file_data, message, 1, offset, out_file_name); + + free(file_data); + return EXIT_SUCCESS; + } + + free(file_data); + return EXIT_FAILURE; +} diff --git a/include/crc.h b/include/crc.h deleted file mode 100644 index bf3b74a..0000000 --- a/include/crc.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -int check_file_header(char *addr); -int check_header_length(unsigned char *addr, long offset); -unsigned long first_idat(unsigned char *addr); -int total_idat(unsigned char *addr); -void build_png_file(struct PNG_FILE_STRUCT *png_file, char *out_file_name); -int change_idat_content(unsigned char *addr, struct PNG_FILE_STRUCT *png_file, char *message, int accuracy, unsigned long offset, char *out_file_name); diff --git a/include/crc_util.h b/include/crc_util.h index 5670cdb..41ffc40 100644 --- a/include/crc_util.h +++ b/include/crc_util.h @@ -33,9 +33,24 @@ struct PNG_FILE_STRUCT { struct PNG_IDAT_FILE_STRUCT png_idat_data; }; +struct EMBED_THREAD_STRUCT { + pthread_mutex_t mutex_lock; + pthread_t thread_id; + int *searching; + unsigned char *data; + unsigned int data_len; + size_t uncom_data_len; + size_t cur_offset; + size_t cur_iteration; + int width; + int color_range; + unsigned int win_size; + char *message; +}; + extern const long png_signature[8]; -int check_header_length(unsigned char *addr, long offset); +unsigned long check_header_length(unsigned char *addr, long offset); int check_file_header(char *addr); int create_cc_file(unsigned char *addr, unsigned long file_length); unsigned char* file_to_char_array(FILE *in_file, size_t* size); diff --git a/include/pspng.h b/include/pspng.h new file mode 100644 index 0000000..645c63b --- /dev/null +++ b/include/pspng.h @@ -0,0 +1,7 @@ +#pragma once + +int check_file_header(char *addr); +unsigned long first_idat(unsigned char *addr); +int total_idat(unsigned char *addr); +void build_png_file(struct PNG_FILE_STRUCT *png_file, char *out_file_name); +int change_idat_content(unsigned char *addr, struct PNG_FILE_STRUCT *png_file, char *message, int accuracy, unsigned long offset, char *out_file_name); diff --git a/src/crc_util.c b/src/crc_util.c index 2b99d11..bd59941 100644 --- a/src/crc_util.c +++ b/src/crc_util.c @@ -4,8 +4,8 @@ const long png_signature[8] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a }; -int check_header_length(unsigned char *addr, long offset) { - unsigned int res = 0; +unsigned long check_header_length(unsigned char *addr, long offset) { + unsigned long res = 0; for( int i = 0; i < 4; i++ ) { res |= addr[offset+i]; if (i < 3) { @@ -71,7 +71,7 @@ int create_cc_file(unsigned char *addr, unsigned long file_length) { } unsigned char* file_to_char_array(FILE *in_file, size_t* size) { - unsigned int c; + unsigned long c; unsigned long file_data_cap = 8; unsigned char* file_data = calloc(file_data_cap, sizeof(unsigned char)); -- cgit v1.2.3