Anyone care to share any cool steganography?
I frequent another forum and came across a post where someone wanted to write a program that uses the idea of steganography. I decided to see if I could write one myself. A few hours later I came up with something pretty close to what my goal was and while it's very simple, I was jumping up and down happy to see my message read from the image file. On smaller images, the program distorts the image (Because I'm hosing up the bits of the image), not so much on larger ones. Haven't found a case where it doesn't work so far. Didn't make use of "DELIMS" like I intended either. Going back over it, seems like it works with other files too, like MP3 files. If you want to try it, here's my source. Keep in mind I'm not the best programmer by far!!! Do you guys know of any really impressive steganographs?
stego.c : Usage: ./stego [image name] [message]
unstego.c : Usage: ./unstego out
stego.c : Usage: ./stego [image name] [message]
/* * This program takes as input a filename (intended to be an image) * as well as a character string. The program produces a file "out" * which contains the new image with the embedded message * Usage ./stego [filename] [message] */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define DELIMS "-" #define BLOCK 1024 #define debug(msg) printf("%s\n", msg) typedef struct{ FILE * file_ptr, * new_file_ptr; char * file_name, * file_buffer, * message; long long file_size, new_file_size; int message_written; }file_ctx; typedef struct{ int pos; int message_len; }message_info; void prep_file(file_ctx * ctx, char * file_name, char * message){ debug("preparing file"); if((ctx->file_ptr = fopen(file_name, "rb"))){ fseek(ctx->file_ptr, 0, SEEK_END); ctx->file_size = ftell(ctx->file_ptr); fseek(ctx->file_ptr, 0, SEEK_SET); ctx->file_name = file_name; if(!(ctx->new_file_ptr = fopen("out", "w+b"))){ perror("Error opening new file\n"); } } else{ perror("Error opening file\n"); ctx = NULL; exit(-1); } ctx->message = message; } void hide_message(file_ctx * ctx){ debug("hiding message"); ctx->file_buffer = malloc(BLOCK); ctx->new_file_size = ctx->file_size + strlen(DELIMS) + strlen(ctx->message); int n_read = 0, n_written = 0, half = (ctx->file_size / 2), total_read = 0, pos = 0, msg_len = strlen(ctx->message) + (strlen(DELIMS) * 2); message_info info; char * message = malloc(strlen(ctx->message) + (strlen(DELIMS) * 2)); strcat(message, DELIMS); strcat(message, ctx->message); strcat(message, DELIMS); debug(message); ctx->message_written = 0; while((n_read = fread(ctx->file_buffer, sizeof(char), BLOCK, ctx->file_ptr))){ if(!ctx->message_written){ /** Wait until we're about halfway through the file **/ if((total_read += n_read) >= half){ debug("writing the message"); /* Get the posistion before writing the file * start writing message to new file * Append the offset and message length to the end of the file */ pos = ftell(ctx->new_file_ptr); fwrite(message, sizeof(char), msg_len, ctx->new_file_ptr); ctx->message_written = 1; } } n_written = fwrite(ctx->file_buffer, sizeof(char), n_read, ctx->new_file_ptr); } fseek(ctx->new_file_ptr, -32, SEEK_END); info.pos = pos; info.message_len = strlen(ctx->message); fwrite(&info, 1, sizeof(info), ctx->new_file_ptr); printf("Pos: %d, Len: %d\n", info.pos, info.message_len); free(message); debug("message hidden"); } void clean_ctx(file_ctx * ctx){ debug("cleaning"); fclose(ctx->file_ptr); fclose(ctx->new_file_ptr); free(ctx->file_buffer); debug("cleaning done"); } int main(int argc, char ** argv){ if(argc == 3){ file_ctx ctx; prep_file(&ctx, argv[1], argv[2]); hide_message(&ctx); clean_ctx(&ctx); } else fputs("Invalid number of arguments\n", stdout); return 0; }
unstego.c : Usage: ./unstego out
#include <stdio.h> #include <stdlib.h> #include <string.h> #define BLOCK 1024 #define debug(in) printf("%s\n", in); typedef struct{ int pos; int message_len; }message_info; void poll_file(FILE * file, char * message){ unsigned int pos = 0, i = 0; message_info info; fseek(file, -32, SEEK_END); fread(&info, 1, sizeof(info), file); printf("Pos: %d, Len: %d\n", info.pos, info.message_len); fseek(file, info.pos+1 , SEEK_SET); for(i = 0; i < info.message_len; i++) message[i] = fgetc(file); } int main(int argc, char ** argv){ char message[BLOCK]; FILE * file; if((file = fopen(argv[1], "rb"))){ poll_file(file, message); printf("Message found in image: %s\n", message); } else printf("Error opening file\n"); fclose(file); return 0; }
Currently reading: Network Warrior, Unix Network Programming by Richard Stevens
Comments
-
AlexNguyen Member Posts: 358 ■■■■□□□□□□Do you guys know of any really impressive steganographs?
"How Al Qaeda hid secrets in a p.o.r.n. video"Knowledge has no value if it is not shared.
Knowledge can cure ignorance, but intelligence cannot cure stupidity. -
the_Grinch Member Posts: 4,165 ■■■■■■■■■■I took a course on practical crypto and it was pretty cool. A ton of programs out there, some very good and some very bad. The big thing is knowing how much you can put into the image/file with distortion. A lot of times it might just be a word or a key that leads you down another rabbit hole that only the person opening the file would understand.WIP:
PHP
Kotlin
Intro to Discrete Math
Programming Languages
Work stuff -
paul78 Member Posts: 3,016 ■■■■■■■■■■the_Grinch wrote: »I took a course on practical crypto and it was pretty cool.
There's an interesting course on Cryptography that's free online from Stanford University for those that can't afford tuition at some of these schools - https://www.coursera.org/#course/crypto