Created
September 7, 2014 03:49
-
-
Save sourenaraya/89f34d8be2cb598e4f4c to your computer and use it in GitHub Desktop.
script for extract and replace JPEG images in samsung SBL.img (bootloader.img). Tested on maguro (i9250).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE | |
# Version 2, December 2004 | |
# | |
# Copyright (C) 2014 Souren Araya | |
# | |
# Everyone is permitted to copy and distribute verbatim or modified | |
# copies of this license document, and changing it is allowed as long | |
# as the name is changed. | |
# | |
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE | |
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
# | |
# 0. You just DO WHAT THE FUCK YOU WANT TO. | |
# THIS PROGRAM CAN COMPLETELY BREAK YOUR PHONE! YOU HAVE BEEN WARNED. | |
from os.path import isfile | |
from io import BytesIO | |
soi = b'\xff\xd8\xff\xe0' | |
eoi = b'\xff\xd9' | |
def scan(source, verbose=False): | |
f = open(source, 'rb') | |
found = [] | |
last_offset = 0 | |
while True: | |
f.seek(last_offset) | |
start_offset = f.read().find(soi) | |
if start_offset != -1: | |
f.seek(start_offset+last_offset) | |
length = f.read().find(eoi)+2 # FFD9 bytes | |
if verbose: | |
print('JPEG found at offset %i, length %i' % (last_offset+start_offset, length)) | |
found.append({'offset': last_offset+start_offset, 'length': length}) | |
last_offset = last_offset+start_offset+length | |
else: | |
break | |
return found | |
def extract(source, offset, length, extension='jpg'): | |
f = open(source, 'rb') | |
output_name = '%i:%i.%s' % (offset, length, extension) | |
outfile = open(output_name, 'wb') | |
f.seek(offset) | |
content = f.read(length) | |
if content: | |
outfile.write(content) | |
outfile.flush() | |
outfile.close() | |
print('File %s written.' % output_name) | |
return True | |
else: | |
print('Invalid offset %s. Source file length is' % (offset, len(f.read))) | |
return False | |
def extract_everything(infile): | |
if not isfile(infile): | |
print('Source file does not exist\nExiting.') | |
return False | |
images = scan(infile) | |
print('Found %i images.' % len(images)) | |
if len(images) > 0: | |
print('Extracting...') | |
for i in images: | |
extract(infile, i['offset'], i['length']) | |
return True | |
else: | |
print('Exiting') | |
def replace(output, source, offset, length, verbose=True): | |
if not (isfile(output) and isfile(source)): | |
print('Source file or output file does not exist\nExiting.') | |
return False | |
outfile = open(output, 'r+b') | |
sourcefile = open(source, 'rb') | |
sourceobj = sourcefile.read() | |
if not len(sourceobj) <= length: | |
print('Source file does not fit. Correct size is %i bytes or less.\nExiting.' % length) | |
return False | |
outfile.seek(offset) | |
tmpfile = BytesIO(b'\x00' * length) | |
outfile.seek(offset) | |
outfile.write(tmpfile.read()) | |
outfile.seek(offset) | |
outfile.write(sourceobj) | |
outfile.flush() | |
outfile.close() | |
if verbose: | |
print('Replaced succesfully') | |
return True | |
if __name__ == "__main__": | |
import argparse | |
from os.path import basename | |
ap = argparse.ArgumentParser() | |
ap.add_argument('-e', nargs=4, | |
help='extract fragment of SOURCE by OFFSET with LENGTH and EXTENSION of output file\n %s -e sbl.img 1118428 3305 jpg' % basename(__file__), | |
metavar=('SOURCE', 'OFFSET', 'LENGTH', 'EXTENSION')) | |
ap.add_argument('-s', nargs=1, | |
help='find JPEGs in SOURCE, print offsets to console\n %s -s sbl.img' % basename(__file__), | |
metavar=('SOURCE')) | |
ap.add_argument('-a', nargs=1, help='extract all JPEGs from SOURCE\n %s -a sbl.img' % basename(__file__), | |
metavar=('SOURCE')) | |
ap.add_argument('-r', nargs=4, | |
help='replace fragment of OUTPUT with SOURCE by OFFSET with LENGTH\n %s -r sbl.img 1118428:3305.jpg 1118428 3305' % basename(__file__), | |
metavar=('OUTPUT', 'SOURCE', 'OFFSET', 'LENGTH')) | |
opts = ap.parse_args() | |
if not any([opts.e, opts.s, opts.a, opts.r]): | |
ap.print_usage() | |
quit() | |
if opts.e: | |
extract(opts.e[0], int(opts.e[1]), int(opts.e[2]), opts.e[3]) | |
if opts.s: | |
scan(opts.s[0], True) | |
if opts.a: | |
extract_everything(opts.a[0]) | |
if opts.r: | |
replace(opts.r[0], opts.r[1], int(opts.r[2]), int(opts.r[3]), True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
dump your SBL partition:
dd if=/dev/disk/by-partlabel/sbl of=/home/nemo/sbl.raw
modify, than writ it back:
dd if=/home/nemo/sbl.raw of=/dev/disk/by-partlabel/sbl
easy way to get suitable image:
convert -define jpeg:extent=LENGTH input.png output.jpg