Τι χρώμα έχει το file system μου?


Διαβάζοντας το παραπάνω τίτλο, όλοι θα σκέφτεστε “Τι καμμενιά ερώτηση είναι αυτή?“, και δικαιολογήστε πλήρως. Πέρσι το χειμώνα chat-αρα με ένα φίλο και κάναμε χαλαρό brainstorming γενικής φύσης γύρω από coding & project-άκια. Σε κάποια φάση του λέω, “apth stigmh pou ta panta swzontai apo thn skype-fb ktl, giati na mh kanoume kati to opoio de tha to katalavainei kaneis?” (στο chat πάντα greeklish). Εκείνη την εποχή άκουγα πολύ ψυχεδέλειες και ασχολιόμουν κάπως και με image processing για τη δουλειά και για τη πάρτη μου. Οπότε του λέω “To vrhka! Ta panta (h plhroforia) einai xarakthres, giati na mhn pairnw triades xarakthrwn, na tis metatrepw stis dekadikes times tous, na ta kanw pixel kai na ta swzw se mia megalh photografia?” και μου απαντάει “Ti les?De to piasa!”. Σε αυτό το αρθράκι θα εξηγήσω τι ακριβώς εννοούσα, καθώς και κάποια πολύ cool αποτελέσματα & εφαρμογές.

Παρατηρήσεις

Όλα είναι χαρακτήρες, όλα τα αρχεία, όλα τα προγράμματα, όλες οι εικόνες, τα πάντα είναι χαρακτήρες. Τα πάντα αποτελούνται απο readable & μη-readable χαρακτήρες (π.χ photos/executables). Αν δε με πιστεύετε, ανοίξτε μια φωτογραφία με έναν text editor. Βλέπετε χαρακτήρες? Φυσικά και βλέπετε!


1 char = 1 byte # with integer value between range (0,255)
1 integer = 4 bytes
1 pixel = r,g,b # integers with range (0,255)
1 pixel size depends on img format implementation (jpg,png etc)

Π.χ: το string “abc”(3 bytes) -> (r=97,g=98,b=99) -> 2 bytes per pixel x 1 pixel -> 2 bytes photo
Χμμ, 3 bytes > 2 bytes, άρα μας συμφέρει να βλέπουμε κάθε τριάδα χαρακτήρων σαν ένα pixel.

Aλγόριθμος

Το διάγραμμα δείχνει το control flow της απλοποιημένης μεθόδου:

pixelize

Υποθέσεις – Aπλοποιήσεις

1.Θεωρώ ότι η εξής συνθήκη ισχύει για το μέγεθος των αρχείων που θα δεκτώ σαν input:
( sum(file_size) + file_n*headers_length ) % 3 == 0, ή κοινώς το περιεχόμενο του κάθε αρχείου τοποθετήθηκε ολόκληρο
σε μια output photo και δεν χρειάστηκε να μοιραστεί σε 2 photo (τη παρούσα & την επόμενη).
2. Τα πάντα χωράνε τέλεια σε μια photo με output_file_size == FIXED_SIZE


Επεξηγήσεις

1. Διάβασε όλα τα αρχεία που θες να κομπρεσσάρεις και βάλτα στην c. Επίσης, για κάθε αρχείο, σώσε το όνομα του και το μέγεθος του ( σε bytes) σε ένα dictionary (file_info).
2-6. Κάνε το τεράστιο στρίνγκ τριάδες-pixels και σώστα στην content.
7. Φτιάξε την αρχή & το τέλος του header του κάθε αρχείου. Τo mark για την αρχή θα είναι ” ενώ για το τέλος ”.
8-10. Για κάθε αρχείο σχημάτισε το content του (f_content) ως: start + file_name + ‘,’ + size in bytes + ‘CONTENT->’ + pixels + end
11. Χωράει και άλλο?
12. Εάν όχι γράψτο στο ‘test_’+αριθμός photo που έχεις γράψει ++ + ‘.jpg’

Αποτελέσματα

Το περιεχόμενο του output file (test_0.jpg) θα μοιάζει κάπως έτσι :

actual_file

Όπου τα πάντα είναι pixel (headers + content).


Πειραματάκια

Η πρώτη (από τις 3) εικόνα που παράχθηκε αφού συμπίεσα τις 71 εικόνες του /home/gclkaze/Pictures folder μου.

Όποιος υλοποιήσει τον decryptor τις παίρνει δώρο!

test_0

root@Tzertzelos:/home/gclkaze/Desktop/color/color# ls -loah test*.png pix*
-rw-r–r– 1 gclkaze 7,0M Φεβ 7 23:09 pix.tar.gz
-rw-r–r– 1 gclkaze 6,7M Φεβ 7 23:10 pix.zip
-rw-r–r– 1 root 3,0M Φεβ 8 17:40 test_0.png
-rw-r–r– 1 gclkaze 3,0M Φεβ 8 17:40 test_1.png
-rw-r–r– 1 gclkaze 998K Φεβ 8 17:40 test_2.png


6.7 M (zip) < 6.998 M (size for test_*.png) < 7.0 M (tar.gz)
Για αρχή, δε με χαλάει καθόλου!


Binaries

Τσεκάρετε τη photo του ELF Format και πείτε μου τη βλέπετε στις επόμενες photos…χμμμμ, ενδιαφέρον!

Elf_layout_en

Elf layout


ld

/usr/bin/ld (initial size: 823K, new size:197K, image size: 720×486,compression: ~1/4)

llvm-ld

/usr/lib/llvm-3.0/bin/llvm-ld (initial size: 74K, new size:40K, image size: 160×160,compression: ~1/2)

test_0

gcc-4.7(initial size: 566K, new size:288K, image size: 576×486,compression: ~1/2)

test_0

a.out (initial size: 6.5K, new size:2902 Bytes, image size:75×75,compression: ~1/2) a.out: μια main(int argc,char** argv) που επιστρέφει άσσο και #include <stdio.h>


test_0_with_function
a.out_function_call (initial size: 6.6K, new size:2906 Bytes, image size: 75×75,compression: ~1/2 ) a.out_function_call: μια main(int argc,char** argv) που καλεί τη foo() που επιστρέφει άσσο και #include <stdio.h>


Χμμμ, τα 2 τελευταία κάπως μοιάζουν ε?


Εφαρμογές & tunings

  • Συμπίεση: Υλοποιήστε file size picker κοινώς αλλάξτε το 2. output_file_size = FIXED_SIZE! Γιατί εάν θέλω να συμπιέσω το string “ti leei?” να πρέπει να το βάλω σε μια photo [1024×768] ( == FIXED_SIZE)? Βάλτο σε μια photo [75×75].
  • Κρυπτογράφηση: Ανακατώστε τα αρχεία μεταξύ τους και χώστε τη δομή του γράφου μέσα στη photo (ή photos), το offset να είναι δυναμικό. Πάρτε into account pixel size ανά photo format/implementation. Περάστε το και από κανά cipher ή παίξτε με timestamps/unique key.
  • Ασφάλεια – Pixel sequence detection for binaries: Οι photos διάφορων binaries μπορούν να αποτελούνται από κοινά modules άρα, module/binary signatures. Εάν κάποιος υλοποιούσε έναν high-precision pixel sequence matcher δεδομένου ότι έχει κάνει generate sample photos από πολλά binaries, ίσως να μπορούσε να αναγνωρίσει ήδη γνωστά modules μέσα σε ένα binary. Όχι 100% σίγουρος ότι στέκει αυτό στάνταρντ, αλλά θα το ψάξω.
  • Ψυχεδέλειες: Κάψιμο γέα!


Remarks

Μια εικόνα χίλιες λέξεις! Α, επίσης, κάποιος πρέπει να φτιάξει και τον decryptor για να μπορεί κάπως να αξιοποιήσει την ιδέα σαν compression utility.
Λογικό, απλώς το υπενθυμίζω! 


References

ASCII map
ELF format
Steganography

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s