Skip to content

Instantly share code, notes, and snippets.

@trietptm
Forked from NeatMonster/frida-libjpeg.py
Created January 6, 2021 11:50
Show Gist options
  • Save trietptm/1ca67304217d9c546af706a52807eca8 to your computer and use it in GitHub Desktop.
Save trietptm/1ca67304217d9c546af706a52807eca8 to your computer and use it in GitHub Desktop.
Dumping JPEGs w/ Frida
import frida, sys
images = {}
def on_message(message, data):
global image
if message['type'] == 'send':
if message['payload'].startswith('['):
message = message['payload']
save = message[message.index(']')+1:]
data = message[1:message.index(']')-1]
data = bytearray([int(s) for s in data.split(',')])
if save not in images:
images[save] = bytearray()
if data not in images[save]:
images[save] += data
#print save, len(data)
elif message['payload'].startswith('*BOOM*'):
name = message['payload'][6:]
if name in images:
images[name] = bytearray()
print "BOOOM!", name
else:
print("[*] {0}".format(message['payload']))
else:
print message
code32 = """Interceptor.attach(Module.findExportByName("libjpeg.so" , "jpeg_read_header"), {
onEnter: function(args) {
var save = args[0];
send('jpeg_read_header ' + save);
//send(' jpeg_error_mgr: ' + Memory.readU32(args[0].add(0)).toString(16));
//send(' jpeg_memory_mgr: ' + Memory.readU32(args[0].add(4)).toString(16));
//send(' jpeg_progress_mgr: ' + Memory.readU32(args[0].add(8)).toString(16));
//send(' client_data: ' + Memory.readU32(args[0].add(12)).toString(16));
//send(' is_decompressor: ' + Memory.readU32(args[0].add(16)));
//send(' global_state: ' + Memory.readS32(args[0].add(20)));
var src = Memory.readU32(args[0].add(24));
//send(' jpeg_source_mgr: ' + src.toString(16));
src = ptr("0x" + src.toString(16));
//send(' image_width: ' + Memory.readU32(args[0].add(28)));
//send(' image_height: ' + Memory.readU32(args[0].add(32)));
//send('');
var address = Memory.readU32(src.add(0));
//send(' next_input_byte: ' + address.toString(16));
address = ptr("0x" + address.toString(16));
var length = Memory.readU32(src.add(4));
//send(' bytes_in_buffer: ' + length);
var init_source = Memory.readU32(src.add(8));
//send(' init_source: ' + init_source.toString(16));
init_source = ptr("0x" + init_source.toString(16));
var fill_input_buffer = Memory.readU32(src.add(12));
//send(' fill_input_buffer: ' + fill_input_buffer.toString(16));
fill_input_buffer = ptr("0x" + fill_input_buffer.toString(16));
var skip_input_data = Memory.readU32(src.add(16));
//send(' skip_input_data: ' + skip_input_data.toString(16));
skip_input_data = ptr("0x" + skip_input_data.toString(16));
// Shit fix
send('*BOOM*' + save)
if (Memory.readU32(args[0].add(12)) == 1)
return;
Memory.writeU32(args[0].add(12), 1);
var intercept_is = Interceptor.attach(init_source, {
onEnter: function(args) {
if (!save.equals(args[0]))
intercept_is.detach();
},
onLeave: function(retval) {
send('init_source ' + save + ' ' + Memory.readU32(src.add(4)));
var address = Memory.readU32(src.add(0));
//send(' next_input_byte: ' + address.toString(16));
address = ptr("0x" + address.toString(16));
var length = Memory.readU32(src.add(4));
//send(' bytes_in_buffer: ' + length);
if (length == 0) return;
var bytes = Memory.readByteArray(address, length);
bytes = new Int8Array(bytes);
var dump = '[';
for (var i = 0; i < bytes.length; ++i)
dump += (bytes[i] & 0xff) + ',';
send(dump + ']' + save);
}
});
var intercept_fib = Interceptor.attach(fill_input_buffer, {
onEnter: function(args) {
if (!save.equals(args[0]))
intercept_is.detach();
},
onLeave: function(retval) {
if (retval != 1)
send('retval ' + retval);
send('fill_input_buffer ' + save + ' ' + Memory.readU32(src.add(4)));
var address = Memory.readU32(src.add(0));
//send(' next_input_byte: ' + address.toString(16));
address = ptr("0x" + address.toString(16));
var length = Memory.readU32(src.add(4));
//send(' bytes_in_buffer: ' + length);
if (length == 0) return;
var bytes = Memory.readByteArray(address, length);
bytes = new Int8Array(bytes);
var dump = '[';
for (var i = 0; i < bytes.length; ++i)
dump += (bytes[i] & 0xff) + ',';
send(dump + ']' + save);
}
});
var intercept_sid = Interceptor.attach(skip_input_data, {
onEnter: function(args) {
if (!save.equals(args[0]))
intercept_sid.detach();
},
onLeave: function(retval) {
send('skip_input_data ' + save);
}
});
},
onLeave: function(retval) {}
});
"""
code64 = """Interceptor.attach(Module.findExportByName("libjpeg.so" , "jpeg_read_header"), {
onEnter: function(args) {
var save = args[0];
send('jpeg_read_header ' + save);
//send(' jpeg_error_mgr: ' + Memory.readU64(args[0].add(0)).toString(16));
//send(' jpeg_memory_mgr: ' + Memory.readU64(args[0].add(8)).toString(16));
//send(' jpeg_progress_mgr: ' + Memory.readU64(args[0].add(16)).toString(16));
//send(' client_data: ' + Memory.readU64(args[0].add(24)).toString(16));
//send(' is_decompressor: ' + Memory.readU32(args[0].add(32)));
//send(' global_state: ' + Memory.readS32(args[0].add(36)));
var src = Memory.readU64(args[0].add(40));
//send(' jpeg_source_mgr: ' + src.toString(16));
src = ptr("0x" + src.toString(16));
//send(' image_width: ' + Memory.readU32(args[0].add(48)));
//send(' image_height: ' + Memory.readU32(args[0].add(52)));
//send('');
var address = Memory.readU64(src.add(0));
//send(' next_input_byte: ' + address.toString(16));
address = ptr("0x" + address.toString(16));
var length = Memory.readU64(src.add(8));
//send(' bytes_in_buffer: ' + length);
var init_source = Memory.readU64(src.add(16));
//send(' init_source: ' + init_source.toString(16));
init_source = ptr("0x" + init_source.toString(16));
var fill_input_buffer = Memory.readU64(src.add(24));
//send(' fill_input_buffer: ' + fill_input_buffer.toString(16));
fill_input_buffer = ptr("0x" + fill_input_buffer.toString(16));
var skip_input_data = Memory.readU64(src.add(32));
//send(' skip_input_data: ' + skip_input_data.toString(16));
skip_input_data = ptr("0x" + skip_input_data.toString(16));
// Shit fix
send('*BOOM*' + save)
if (Memory.readU64(args[0].add(24)) == 1)
return;
Memory.writeU64(args[0].add(24), 1);
var intercept_is = Interceptor.attach(init_source, {
onEnter: function(args) {
if (!save.equals(args[0]))
intercept_is.detach();
},
onLeave: function(retval) {
send('init_source ' + save + ' ' + Memory.readU64(src.add(8)));
var address = Memory.readU64(src.add(0));
//send(' next_input_byte: ' + address.toString(16));
address = ptr("0x" + address.toString(16));
var length = Memory.readU64(src.add(8));
//send(' bytes_in_buffer: ' + length);
if (length == 0) return;
var bytes = Memory.readByteArray(address, length);
bytes = new Int8Array(bytes);
var dump = '[';
for (var i = 0; i < bytes.length; ++i)
dump += (bytes[i] & 0xff) + ',';
send(dump + ']' + save);
}
});
var intercept_fib = Interceptor.attach(fill_input_buffer, {
onEnter: function(args) {
if (!save.equals(args[0]))
intercept_is.detach();
},
onLeave: function(retval) {
if (retval != 1)
send('retval ' + retval);
send('fill_input_buffer ' + save + ' ' + Memory.readU64(src.add(8)));
var address = Memory.readU64(src.add(0));
//send(' next_input_byte: ' + address.toString(16));
address = ptr("0x" + address.toString(16));
var length = Memory.readU64(src.add(8));
//send(' bytes_in_buffer: ' + length);
if (length == 0) return;
var bytes = Memory.readByteArray(address, length);
bytes = new Int8Array(bytes);
var dump = '[';
for (var i = 0; i < bytes.length; ++i)
dump += (bytes[i] & 0xff) + ',';
send(dump + ']' + save);
}
});
var intercept_sid = Interceptor.attach(skip_input_data, {
onEnter: function(args) {
if (!save.equals(args[0]))
intercept_sid.detach();
},
onLeave: function(retval) {
send('skip_input_data ' + save);
}
});
},
onLeave: function(retval) {}
});
Interceptor.attach(Module.findExportByName("libjpeg.so" , "jpeg_start_output"), {
onEnter: function(args) {
send('jpeg_start_output ' + args[0]);
}
});
Interceptor.attach(Module.findExportByName("libjpeg.so" , "jpeg_finish_output"), {
onEnter: function(args) {
send('jpeg_finish_output ' + args[0]);
}
});
"""
device = frida.get_remote_device()
process = device.spawn(["org.thoughtcrime.securesms"]) # com.android.gallery3d
session = device.attach(process)
script = session.create_script(code32) # code64
script.on('message', on_message)
script.load()
device.resume(process)
#session.detach()
try:
sys.stdin.read()
except KeyboardInterrupt:
for name, image in images.items():
if image:
#name = str(hash(str(image)))
with open(name + '.jpg', 'wb') as f:
f.write(image)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment