5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
*.png
|
||||||
|
*.out
|
||||||
|
*.woo
|
||||||
|
*.wow
|
||||||
|
bin/
|
||||||
16
Makefile
Normal file
16
Makefile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
LIBRARIES = `pkg-config --libs zlib libsodium` -Iinclude
|
||||||
|
SOURCES = ./src/* ./cmd/crc.c
|
||||||
|
OUTPUT_DIR = ./bin
|
||||||
|
OUTPUT = -o ${OUTPUT_DIR}/PROG
|
||||||
|
|
||||||
|
build: output_dir
|
||||||
|
gcc -Wall ${LIBRARIES} ${SOURCES} ${OUTPUT:PROG=crc}
|
||||||
|
|
||||||
|
debug: output_dir
|
||||||
|
gcc -Wall -g ${LIBRARIES} ${SOURCES} ${OUTPUT:PROG=crc}
|
||||||
|
|
||||||
|
output_dir:
|
||||||
|
mkdir -p ${OUTPUT_DIR}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OUTPUT_DIR) **.h.gch
|
||||||
190
cmd/crc.c
Normal file
190
cmd/crc.c
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sodium.h>
|
||||||
|
#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];
|
||||||
|
|
||||||
|
memcpy(temp_color_data, 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);
|
||||||
|
searching = 0;
|
||||||
|
}
|
||||||
|
free(check_data_buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
} while(searching == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int change_idat_content(unsigned char *addr, unsigned char *message, int accuracy, unsigned long offset) {
|
||||||
|
//printf("Starting IDAT Tranform\n");
|
||||||
|
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");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idat_length = check_header_length(addr, offset);
|
||||||
|
printf("IDAT Length: %d\n", idat_length);
|
||||||
|
|
||||||
|
int prop_found = 0;
|
||||||
|
long size = 1;
|
||||||
|
long rounds = 0;
|
||||||
|
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];
|
||||||
|
while(prop_found == 0) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
free(uncom_data_buff);
|
||||||
|
|
||||||
|
//printf("Found %d in %d rounds\n", checked_crc ,rounds);
|
||||||
|
//printf("Full CRC: %08X\n", crcnum);
|
||||||
|
//printf("Original: %02X\n", idat_data[j]);
|
||||||
|
//printf("Change offset: %d to hex: %02X\n", j, temp_idat_data[j]);
|
||||||
|
//addr[offset+8+j] = temp_idat_data[j];
|
||||||
|
//update_file_crc(addr, offset, crcnum);
|
||||||
|
prop_found = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(idat_data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is where it all starts
|
||||||
|
int main() {
|
||||||
|
FILE *fp;
|
||||||
|
size_t i = 0;
|
||||||
|
unsigned long offset = 0;
|
||||||
|
unsigned char *message = malloc(sizeof(char));
|
||||||
|
message[0] = '\0';
|
||||||
|
|
||||||
|
if(sodium_init() == -1) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen("./1.png", "rt");
|
||||||
|
if (fp == NULL) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *file_data = file_to_char_array(fp, &i);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
offset = first_idat(file_data);
|
||||||
|
change_idat_content(file_data, message, 1, offset);
|
||||||
|
free(file_data);
|
||||||
|
free(message);
|
||||||
|
//create_cc_file(file_data, i);
|
||||||
|
}
|
||||||
51
include/CRCLib.h
Normal file
51
include/CRCLib.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/* Table of CRCs of all 8-bit messages. */
|
||||||
|
unsigned long crc_table[256];
|
||||||
|
|
||||||
|
/* Flag: has the table been computed? Initially false. */
|
||||||
|
int crc_table_computed = 0;
|
||||||
|
|
||||||
|
/* Make the table for a fast CRC. */
|
||||||
|
void make_crc_table(void)
|
||||||
|
{
|
||||||
|
unsigned long c;
|
||||||
|
int n, k;
|
||||||
|
|
||||||
|
for (n = 0; n < 256; n++) {
|
||||||
|
c = (unsigned long) n;
|
||||||
|
for (k = 0; k < 8; k++) {
|
||||||
|
if (c & 1)
|
||||||
|
c = 0xedb88320L ^ (c >> 1);
|
||||||
|
else
|
||||||
|
c = c >> 1;
|
||||||
|
}
|
||||||
|
crc_table[n] = c;
|
||||||
|
}
|
||||||
|
crc_table_computed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Update a running CRC with the bytes buf[0..len-1]--the CRC
|
||||||
|
should be initialized to all 1's, and the transmitted value
|
||||||
|
is the 1's complement of the final running CRC (see the
|
||||||
|
crc() routine below). */
|
||||||
|
|
||||||
|
unsigned long update_crc(unsigned long crc, unsigned char *buf,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
unsigned long c = crc;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (!crc_table_computed)
|
||||||
|
make_crc_table();
|
||||||
|
for (n = 0; n < len; n++) {
|
||||||
|
c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the CRC of the bytes buf[0..len-1]. */
|
||||||
|
unsigned long crc(unsigned char *buf, int len)
|
||||||
|
{
|
||||||
|
return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL;
|
||||||
|
}
|
||||||
|
|
||||||
8
include/compress_util.h
Normal file
8
include/compress_util.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
void zlib_decompress_data(unsigned char *data_chunk, size_t file_length, unsigned char **buff, size_t *sz);
|
||||||
|
void zlib_compress_data(unsigned char *data_chunk, size_t file_length, unsigned char **buff, size_t *sz);
|
||||||
6
include/crc.h
Normal file
6
include/crc.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
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);
|
||||||
|
int change_idat_content(unsigned char *addr, unsigned char *message, int accuracy, unsigned long offset);
|
||||||
11
include/crc_util.h
Normal file
11
include/crc_util.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// PNG File Struct
|
||||||
|
struct PNG
|
||||||
|
|
||||||
|
extern const long png_signature[8];
|
||||||
|
|
||||||
|
int 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);
|
||||||
126
src/compress_util.c
Normal file
126
src/compress_util.c
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "compress_util.h"
|
||||||
|
|
||||||
|
#define CHUNK 1024
|
||||||
|
|
||||||
|
void zlib_decompress_data(unsigned char *data_chunk, size_t file_length, unsigned char **buff, size_t *sz) {
|
||||||
|
int ret;
|
||||||
|
unsigned int have;
|
||||||
|
z_stream strm;
|
||||||
|
// Adding one to zero here
|
||||||
|
unsigned char out[CHUNK];
|
||||||
|
unsigned char in[CHUNK];
|
||||||
|
|
||||||
|
errno=0;
|
||||||
|
FILE *data_stream = fmemopen(data_chunk, file_length, "r");
|
||||||
|
FILE *of = open_memstream((char**)buff, sz);
|
||||||
|
if(data_stream == NULL) {
|
||||||
|
perror("F MEM OPEN");
|
||||||
|
}
|
||||||
|
|
||||||
|
strm.zalloc = Z_NULL;
|
||||||
|
strm.zfree = Z_NULL;
|
||||||
|
strm.opaque = Z_NULL;
|
||||||
|
strm.avail_in = 0;
|
||||||
|
strm.next_in = Z_NULL;
|
||||||
|
ret = inflateInit(&strm);
|
||||||
|
if(ret != Z_OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
strm.avail_in = fread(in, 1, CHUNK, data_stream);
|
||||||
|
if(ferror(data_stream)) {
|
||||||
|
(void)inflateEnd(&strm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(strm.avail_in == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strm.next_in = in;
|
||||||
|
|
||||||
|
do {
|
||||||
|
strm.avail_out = CHUNK;
|
||||||
|
strm.next_out = out;
|
||||||
|
ret = inflate(&strm, Z_NO_FLUSH);
|
||||||
|
assert(ret != Z_STREAM_ERROR);
|
||||||
|
switch(ret) {
|
||||||
|
case Z_NEED_DICT:
|
||||||
|
ret = Z_DATA_ERROR;
|
||||||
|
case Z_DATA_ERROR:
|
||||||
|
case Z_MEM_ERROR:
|
||||||
|
(void)inflateEnd(&strm);
|
||||||
|
printf("Error: %d\n", ret);
|
||||||
|
printf("MSG: %s\n", (char*)strm.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
have = CHUNK - strm.avail_out;
|
||||||
|
fwrite(out, 1, have, of);
|
||||||
|
} while(strm.avail_out == 0);
|
||||||
|
} while(ret != Z_STREAM_END);
|
||||||
|
|
||||||
|
(void)inflateEnd(&strm);
|
||||||
|
|
||||||
|
fclose(data_stream);
|
||||||
|
fclose(of);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zlib_compress_data(unsigned char *data_chunk, size_t file_length, unsigned char **buff, size_t *sz) {
|
||||||
|
int ret, flush;
|
||||||
|
unsigned int have;
|
||||||
|
z_stream strm;
|
||||||
|
unsigned char in[CHUNK];
|
||||||
|
unsigned char out[CHUNK];
|
||||||
|
int level = 9;
|
||||||
|
int method = Z_DEFLATED;
|
||||||
|
int windowBits = 10;
|
||||||
|
int memLevel = 9;
|
||||||
|
//int strategy = Z_DEFAULT_STRATEGY;
|
||||||
|
int strategy = Z_FILTERED;
|
||||||
|
|
||||||
|
FILE *data_stream = fmemopen(data_chunk, file_length, "r");
|
||||||
|
FILE *out_data_stream = NULL;
|
||||||
|
out_data_stream = open_memstream((char**)buff, sz);
|
||||||
|
|
||||||
|
strm.zalloc = Z_NULL;
|
||||||
|
strm.zfree = Z_NULL;
|
||||||
|
strm.opaque = Z_NULL;
|
||||||
|
ret = deflateInit2(&strm, level, method, windowBits, memLevel, strategy);
|
||||||
|
if (ret != Z_OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
strm.avail_in = fread(in, 1, CHUNK, data_stream);
|
||||||
|
if (ferror(data_stream)) {
|
||||||
|
(void)deflateEnd(&strm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flush = feof(data_stream) ? Z_FINISH : Z_NO_FLUSH;
|
||||||
|
strm.next_in = in;
|
||||||
|
|
||||||
|
do {
|
||||||
|
strm.avail_out = CHUNK;
|
||||||
|
strm.next_out = out;
|
||||||
|
|
||||||
|
ret = deflate(&strm, flush);
|
||||||
|
assert(ret != Z_STREAM_ERROR);
|
||||||
|
have = CHUNK - strm.avail_out;
|
||||||
|
if(fwrite(out, 1, have, out_data_stream) != have || ferror(out_data_stream)) {
|
||||||
|
(void)deflateEnd(&strm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while(strm.avail_out == 0);
|
||||||
|
assert(strm.avail_in == 0);
|
||||||
|
|
||||||
|
} while(flush != Z_FINISH);
|
||||||
|
assert(ret == Z_STREAM_END);
|
||||||
|
|
||||||
|
fclose(data_stream);
|
||||||
|
fclose(out_data_stream);
|
||||||
|
|
||||||
|
(void)deflateEnd(&strm);
|
||||||
|
}
|
||||||
64
src/crc_util.c
Normal file
64
src/crc_util.c
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "crc_util.h"
|
||||||
|
|
||||||
|
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;
|
||||||
|
for( int i = 0; i < 4; i++ ) {
|
||||||
|
res |= addr[offset+i];
|
||||||
|
if (i < 3) {
|
||||||
|
res <<= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_file_header(char *addr) {
|
||||||
|
int signature_match = 0;
|
||||||
|
for( int i = 0; i < 8; i++ ) {
|
||||||
|
if (addr[i] != png_signature[i]) {
|
||||||
|
signature_match = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Sig Match: %d\n", signature_match);
|
||||||
|
return signature_match;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int create_cc_file(unsigned char *addr, unsigned long file_length) {
|
||||||
|
FILE *fp;
|
||||||
|
fp = fopen("png2.png", "w");
|
||||||
|
|
||||||
|
if(fp == NULL) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < file_length; i++){
|
||||||
|
fputc(addr[i], fp);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* file_to_char_array(FILE *in_file, size_t* size) {
|
||||||
|
unsigned int c;
|
||||||
|
unsigned long file_data_cap = 8;
|
||||||
|
unsigned char* file_data = calloc(file_data_cap, sizeof(unsigned char));
|
||||||
|
|
||||||
|
for(size_t i = 0;(c = fgetc(in_file)) != EOF; i++) {
|
||||||
|
if(i == file_data_cap) {
|
||||||
|
file_data_cap *= 2;
|
||||||
|
file_data = reallocarray(file_data, file_data_cap, sizeof(unsigned char));
|
||||||
|
if(file_data == NULL) {
|
||||||
|
perror("FAILED ARRAY RESIZE");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_data[i] = c;
|
||||||
|
*size += 1;
|
||||||
|
}
|
||||||
|
return file_data;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user