Adam Shelly
1/30/2008 7:39:00 PM
On 1/30/08, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:
> Jim wrote:
> > Hello,
> >
> > I am reverse engineering a binary file that has an embedded PNG image
> > in it. I opened the file in a hex editor and found the png header
> > information, but how to use Ruby to extract the PNG to it's own file?
>
> Do you know the absolute starting position of the embedded PNG?
You can find it:
fp = File.new("has_embedded_png.dat","rb")
m= /\211PNG/.match(fp.read)
raise "no PNG" if !m
fp.seek(m.begin(0))
>
> If the end_pos has to be determined by reading a field, then this will
> take a little tinkering. I assume PNG has a length field somewhere? So
> you'll have to extract that (using String#unpack, perhaps) and chop off
> that many bytes from the start of the png_data string.
>
There's no total length field, just a series of 'chunks' each with
its own length.
Luckily, the 'IEND' chunk is always last, so you can just extract
chunks until you get to that one:
def extract_chunk(input, output)
lenword = input.read(4)
length = lenword.unpack('N')[0]
type = input.read(4)
data = length>0 ? input.read(length) : ""
crc = input.read(4)
return nil if length<0 || !(('A'..'z')===type[0,1])
#return nil if validate_crc(type+data, crc)
output.write lenword
output.write type
output.write data
output.write crc
return type
end
def extract_png(input, output)
hdr = input.read(8)
raise "Not a PNG File" if hdr[0,4]!= "\211PNG"
raise "file not in binary mode" if hdr[4,4]!="\r\n\032\n"
output.write(hdr)
loop do
chunk_type = extract_chunk(input,output)
p chunk_type
break if chunk_type.nil? || chunk_type == 'IEND'
end
end
ofp = File.new("out.png","wb")
extract_png(fp,ofp)
-Adam