1919
2020import os
2121import time
22+ import struct
23+ from ubireader .ubifs .decrypt import lookup_inode_nonce , derive_key_from_nonce , datablock_decrypt , decrypt_symlink_target
2224from ubireader .ubifs .defines import *
2325from ubireader .ubifs import walk
2426from ubireader .ubifs .misc import decompress
@@ -39,9 +41,8 @@ def list_files(ubifs, list_path):
3941
4042 if len (inodes ) < 2 :
4143 raise Exception ('No inodes found' )
42-
44+
4345 inum = find_dir (inodes , 1 , pnames , 0 )
44-
4546 if inum == None :
4647 return
4748
@@ -86,7 +87,7 @@ def copy_file(ubifs, filepath, destpath):
8687
8788 for dent in inodes [inum ]['dent' ]:
8889 if dent .name == filename :
89- filedata = _process_reg_file (ubifs , inodes [dent .inum ], filepath )
90+ filedata = _process_reg_file (ubifs , inodes [dent .inum ], filepath , inodes )
9091 if os .path .isdir (destpath ):
9192 destpath = os .path .join (destpath , filename )
9293 with open (destpath , 'wb' ) as f :
@@ -114,8 +115,7 @@ def print_dent(ubifs, inodes, dent_node, long=True, longts=False):
114115
115116 lnk = ""
116117 if dent_node .type == UBIFS_ITYPE_LNK :
117- lnk = " -> " + inode ['ino' ].data .decode ('utf-8' )
118-
118+ lnk = " -> " + decrypt_symlink_target (ubifs , inodes , dent_node )
119119 if longts :
120120 mtime = inode ['ino' ].mtime_sec
121121 else :
@@ -142,33 +142,47 @@ def file_leng(ubifs, inode):
142142 return fl
143143 return 0
144144
145-
146- def _process_reg_file (ubifs , inode , path ):
145+ def _process_reg_file (ubifs , inode , path , inodes ):
147146 try :
148147 buf = bytearray ()
148+ start_key = (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS )
149149 if 'data' in inode :
150150 compr_type = 0
151151 sorted_data = sorted (inode ['data' ], key = lambda x : x .key ['khash' ])
152- last_khash = sorted_data [ 0 ]. key [ 'khash' ] - 1
152+ last_khash = start_key - 1
153153
154154 for data in sorted_data :
155-
156155 # If data nodes are missing in sequence, fill in blanks
157156 # with \x00 * UBIFS_BLOCK_SIZE
158157 if data .key ['khash' ] - last_khash != 1 :
159158 while 1 != (data .key ['khash' ] - last_khash ):
160- buf += b'\x00 ' * UBIFS_BLOCK_SIZE
159+ buf += b'\x00 ' * UBIFS_BLOCK_SIZE
161160 last_khash += 1
162161
163162 compr_type = data .compr_type
164163 ubifs .file .seek (data .offset )
165164 d = ubifs .file .read (data .compr_len )
165+
166+ if ubifs .master_key is not None :
167+ nonce = lookup_inode_nonce (inodes , inode )
168+ block_key = derive_key_from_nonce (ubifs .master_key , nonce )
169+ # block_id is based on the current hash
170+ # there could be empty blocks
171+ block_id = data .key ['khash' ]- start_key
172+ block_iv = struct .pack ("<QQ" , block_id , 0 )
173+ d = datablock_decrypt (block_key , block_iv , d )
174+ # if unpading is needed the plaintext_size is valid and set to the
175+ # original size of current block, so we can use this to get the amout
176+ # of bytes to unpad
177+ d = d [:data .plaintext_size ]
178+
166179 buf += decompress (compr_type , data .size , d )
180+
167181 last_khash = data .key ['khash' ]
168182 verbose_log (_process_reg_file , 'ino num: %s, compression: %s, path: %s' % (inode ['ino' ].key ['ino_num' ], compr_type , path ))
169183
170184 except Exception as e :
171- error (_process_reg_file , 'Warn' , 'inode num:%s :%s' % (inode ['ino' ].key ['ino_num' ], e ))
185+ error (_process_reg_file , 'Warn' , 'inode num:%s path :%s :%s ' % (inode ['ino' ].key ['ino_num' ], path , e ))
172186
173187 # Pad end of file with \x00 if needed.
174188 if inode ['ino' ].size > len (buf ):
0 commit comments