m1stadev / PyIMG4

A Python library/CLI tool for parsing Apple's Image4 format.
MIT License
48 stars 8 forks source link

Properly handle encrypted LZFSE-compressed IM4P payloads #7

Closed m1stadev closed 2 years ago

m1stadev commented 2 years ago

@doronz88 I *finally* got around to finishing this PR, could you try it out?

doronz88 commented 2 years ago

I'm missing the length field from the IM4P when trying to send the iBEC. This is the code I used:

im4p = pyimg4.IM4P(data=data)
img4 = pyimg4.IMG4(im4p=data, im4m=blob).output()

When examining the im4p object, it seems the compression is: Compression.UNKNOWN.

print(im4p) # IM4P(fourcc=ibec, description="iBoot-8419.40.112")
print(im4p.payload.compression) # Compression.UNKNOWN
m1stadev commented 2 years ago

I'm missing the length field from the IM4P when trying to send the iBEC.

This is the code I used:


im4p = pyimg4.IM4P(data=data)

img4 = pyimg4.IMG4(im4p=data, im4m=blob).output()

When examining the im4p object, it seems the compression is: Compression.UNKNOWN.


print(im4p) # IM4P(fourcc=ibec, description="iBoot-8419.40.112")

print(im4p.payload.compression) # Compression.UNKNOWN

Right now it displays that compression type because it isn't able to detect the LZFSE compression using the payload alone, but I could change that to show LZFSE compression (or alternatively, a new compression type that shows the payload is both LZFSE-compressed and encrypted, which I initially planned to do with this PR but later removed). I can change that behavior, but do you think it'd be better to add a new compression type for LZFSE+encrypted, or just use the LZFSE compression type?

doronz88 commented 2 years ago

I think another enum member is the best for it - but still, what interface will allow adding the size field for those components? Can it be parsed directly when I pass the data?

m1stadev commented 2 years ago

I think another enum member is the best for it - but still, what interface will allow adding the size field for those components? Can it be parsed directly when I pass the data?

Right now, If you pass an encrypted+LZFSE-compressed IM4P, it will parse and store the uncompressed size automatically. If you passed only the encrypted+LZFSE-compressed data, you would need to manually specify the size (by setting IM4PData.lzfse_payload_size), and the keybags (by appending Keybag objects to the IM4PData.keybags list (Come to think of it, I need to add methods for adding/removing keybags and make IM4PData.keybags private sometime.)), then create an IM4P. I may change the IM4PData.lzfse_payload_size property to just be a method instead, because I feel like it's doing too much as a property.

m1stadev commented 2 years ago

@doronz88 Also, could you DM me the iBEC you're using to test via Discord (m1sta#9999) please?