python - 从原始 ext4 图像读取文件信息、权限
python - read file info, permissions from raw ext4 image
我正在尝试解压缩 android 11 个图像/从原始 .img 获取信息以获取 selinux 信息、符号链接等
我正在使用这个很棒的工具:https://github.com/cubinator/ext4/blob/master/ext4.py35.py
我的代码如下所示:
#!/usr/bin/env python3
import argparse
import sys
import os
import ext4
parser = argparse.ArgumentParser(description='Read <modes, symlinks, contexts and capabilities> from an ext4 image')
parser.add_argument('ext4_image', help='Path to ext4 image to process')
args = parser.parse_args()
exists = os.path.isfile(args.ext4_image)
if not exists:
print("Error: input file " f"[{args.ext4_image}]" " was not found")
sys.exit(1)
file = open(args.ext4_image, "rb")
volume = ext4.Volume(file)
def scan_dir (root_inode, root_path = ""):
for entry_name, entry_inode_idx, entry_type in root_inode.open_dir():
if entry_name == "." or entry_name == "..":
continue
entry_inode = root_inode.volume.get_inode(entry_inode_idx)
entry_inode_path = root_path + "/" + entry_name
if entry_inode.is_dir:
scan_dir(entry_inode, entry_inode_path)
if entry_inode_path[-1] == '/':
continue
xattrs_perms = list(entry_inode.xattrs())
found_cap = False
found_con = False
if "security.capability" in f"{xattrs_perms}": found_cap = True
if "security.selinux" in f"{xattrs_perms}": found_con = True
contexts = ""
capability = ", \"capabilities\", 0x0"
if found_cap:
if found_con:
capability = f"{xattrs_perms[1:2]}"
else:
capability = f"{xattrs_perms[0:1]}"
capability = capability.split(" ")[1][:-3][+2:].encode('utf-8').decode('unicode-escape').encode('ISO-8859-1')
capability = hex(int.from_bytes(capability[4:8] + capability[14:18], "little"))
capability = ", \"capabilities\", " f"{capability}"
capability = f"{capability}"
if found_con:
contexts = f"{xattrs_perms[0:1]}"
contexts = f"{contexts.split( )[1].split('x00')[0][:-1][+2:]}"
contexts = f"{contexts}"
filefolder = ''.join(entry_inode_path.split('/', 1))
print("set_metadata(\""f"{filefolder}" "\", \"uid\", " f"{str(entry_inode.inode.i_uid)}" ", \"gid\", " f"{str(entry_inode.inode.i_gid)}" ", \"mode\", " f"{entry_inode.inode.i_mode & 0x1FF:0>4o}" f"{capability}" ", \"selabel\", \"" f"{contexts}" "\");")
scan_dir(volume.root)
file.close()
然后我只需要做 ./read.py vendor.img
就可以了。
直到最近我从 android 11 开始尝试这个奇怪的 vendor.img 并遇到了这个奇怪的问题。
Traceback (most recent call last):
File "./tools/metadata.py", line 53, in <module>
scan_dir(volume.root)
File "./tools/metadata.py", line 26, in scan_dir
scan_dir(entry_inode, entry_inode_path)
File "./tools/metadata.py", line 26, in scan_dir
scan_dir(entry_inode, entry_inode_path)
File "./tools/metadata.py", line 29, in scan_dir
xattrs_perms = list(entry_inode.xattrs())
File "/home/semaphore/unpacker/tools/ext4.py", line 976, in xattrs
for xattr_name, xattr_value in self._parse_xattrs(inline_data[offset:], 0, prefix_override = prefix_override):
File "/home/semaphore/unpacker/tools/ext4.py", line 724, in _parse_xattrs
xattr_inode = self.volume.get_inode(xattr.e_value_inum, InodeType.FILE)
NameError: name 'xattr' is not defined
我试过只在此处删除 if 并在 else 之后保留代码:https://github.com/cubinator/ext4/blob/master/ext4.py35.py#L722
遗憾的是没有运气。貌似工具还没做完?但没有其他选择。
欢迎任何帮助:)
谢谢。
编辑:有人建议用 xattr_entry
替换 xattr
所以我做了,我得到了这个错误:takes 2 positional arguments but 3 were given
我尝试修复它并得到:
File "/home/semaphore/unpacker/tools/ext4.py", line 724, in _parse_xattrs
xattr_inode = self.volume.get_inode(xattr_entry.e_value_inum)
File "/home/semaphore/unpacker/tools/ext4.py", line 595, in get_inode
inode_table_offset = self.group_descriptors[group_idx].bg_inode_table * self.block_size
IndexError: list index out of range
而且我无法修复此错误:(
也许除了从原始 ext4 映像获取 selinux 信息、功能、uid、gid 和权限之外,还有其他选择吗?
我了解到您曾尝试自己解决问题,但您从未发布过您当前使用的代码片段。
我不确定,但在我看来你修改了 get_inode 的签名而不是修改传递给它的参数。
例如你试过了吗:
xattr_inode = self.volume.get_inode(xattr_entry.e_value_inum)
我想出了另一种方法。
首先挂载镜像(需要 root 权限):
os.system("sudo mount -t ext4 -o loop vendor.img vendor")
然后对每个文件使用:os.lstat
和 os.getxattr
。它提供了所有信息:
stat_info = os.lstat(file)
try:
cap = hex(int.from_bytes(os.getxattr(file, "security.capability")[4:8] + os.getxattr(file, "security.capability")[14:18], "little"))
except:
cap = "0x0"
try:
selabel = os.getxattr(file, b"security.selinux", follow_symlinks=False).decode().strip('\n[=10=]')
except:
selabel = "u:object_r:unlabeled:s0"
metadata.append("set_metadata(\"/" + file + "\", \"uid\", " + str(stat_info.st_uid) + ", \"gid\", " + str(stat_info.st_gid) + ", \"mode\", " + oct(stat_info.st_mode)[-4:] + ", \"capabilities\", " + cap + ", \"selabel\", \"" + selabel + "\");")
像这样。这是我能找到的唯一解决方案
我正在尝试解压缩 android 11 个图像/从原始 .img 获取信息以获取 selinux 信息、符号链接等
我正在使用这个很棒的工具:https://github.com/cubinator/ext4/blob/master/ext4.py35.py
我的代码如下所示:
#!/usr/bin/env python3
import argparse
import sys
import os
import ext4
parser = argparse.ArgumentParser(description='Read <modes, symlinks, contexts and capabilities> from an ext4 image')
parser.add_argument('ext4_image', help='Path to ext4 image to process')
args = parser.parse_args()
exists = os.path.isfile(args.ext4_image)
if not exists:
print("Error: input file " f"[{args.ext4_image}]" " was not found")
sys.exit(1)
file = open(args.ext4_image, "rb")
volume = ext4.Volume(file)
def scan_dir (root_inode, root_path = ""):
for entry_name, entry_inode_idx, entry_type in root_inode.open_dir():
if entry_name == "." or entry_name == "..":
continue
entry_inode = root_inode.volume.get_inode(entry_inode_idx)
entry_inode_path = root_path + "/" + entry_name
if entry_inode.is_dir:
scan_dir(entry_inode, entry_inode_path)
if entry_inode_path[-1] == '/':
continue
xattrs_perms = list(entry_inode.xattrs())
found_cap = False
found_con = False
if "security.capability" in f"{xattrs_perms}": found_cap = True
if "security.selinux" in f"{xattrs_perms}": found_con = True
contexts = ""
capability = ", \"capabilities\", 0x0"
if found_cap:
if found_con:
capability = f"{xattrs_perms[1:2]}"
else:
capability = f"{xattrs_perms[0:1]}"
capability = capability.split(" ")[1][:-3][+2:].encode('utf-8').decode('unicode-escape').encode('ISO-8859-1')
capability = hex(int.from_bytes(capability[4:8] + capability[14:18], "little"))
capability = ", \"capabilities\", " f"{capability}"
capability = f"{capability}"
if found_con:
contexts = f"{xattrs_perms[0:1]}"
contexts = f"{contexts.split( )[1].split('x00')[0][:-1][+2:]}"
contexts = f"{contexts}"
filefolder = ''.join(entry_inode_path.split('/', 1))
print("set_metadata(\""f"{filefolder}" "\", \"uid\", " f"{str(entry_inode.inode.i_uid)}" ", \"gid\", " f"{str(entry_inode.inode.i_gid)}" ", \"mode\", " f"{entry_inode.inode.i_mode & 0x1FF:0>4o}" f"{capability}" ", \"selabel\", \"" f"{contexts}" "\");")
scan_dir(volume.root)
file.close()
然后我只需要做 ./read.py vendor.img
就可以了。
直到最近我从 android 11 开始尝试这个奇怪的 vendor.img 并遇到了这个奇怪的问题。
Traceback (most recent call last):
File "./tools/metadata.py", line 53, in <module>
scan_dir(volume.root)
File "./tools/metadata.py", line 26, in scan_dir
scan_dir(entry_inode, entry_inode_path)
File "./tools/metadata.py", line 26, in scan_dir
scan_dir(entry_inode, entry_inode_path)
File "./tools/metadata.py", line 29, in scan_dir
xattrs_perms = list(entry_inode.xattrs())
File "/home/semaphore/unpacker/tools/ext4.py", line 976, in xattrs
for xattr_name, xattr_value in self._parse_xattrs(inline_data[offset:], 0, prefix_override = prefix_override):
File "/home/semaphore/unpacker/tools/ext4.py", line 724, in _parse_xattrs
xattr_inode = self.volume.get_inode(xattr.e_value_inum, InodeType.FILE)
NameError: name 'xattr' is not defined
我试过只在此处删除 if 并在 else 之后保留代码:https://github.com/cubinator/ext4/blob/master/ext4.py35.py#L722
遗憾的是没有运气。貌似工具还没做完?但没有其他选择。
欢迎任何帮助:)
谢谢。
编辑:有人建议用 xattr_entry
替换 xattr
所以我做了,我得到了这个错误:takes 2 positional arguments but 3 were given
我尝试修复它并得到:
File "/home/semaphore/unpacker/tools/ext4.py", line 724, in _parse_xattrs
xattr_inode = self.volume.get_inode(xattr_entry.e_value_inum)
File "/home/semaphore/unpacker/tools/ext4.py", line 595, in get_inode
inode_table_offset = self.group_descriptors[group_idx].bg_inode_table * self.block_size
IndexError: list index out of range
而且我无法修复此错误:(
也许除了从原始 ext4 映像获取 selinux 信息、功能、uid、gid 和权限之外,还有其他选择吗?
我了解到您曾尝试自己解决问题,但您从未发布过您当前使用的代码片段。
我不确定,但在我看来你修改了 get_inode 的签名而不是修改传递给它的参数。
例如你试过了吗:
xattr_inode = self.volume.get_inode(xattr_entry.e_value_inum)
我想出了另一种方法。
首先挂载镜像(需要 root 权限):
os.system("sudo mount -t ext4 -o loop vendor.img vendor")
然后对每个文件使用:os.lstat
和 os.getxattr
。它提供了所有信息:
stat_info = os.lstat(file)
try:
cap = hex(int.from_bytes(os.getxattr(file, "security.capability")[4:8] + os.getxattr(file, "security.capability")[14:18], "little"))
except:
cap = "0x0"
try:
selabel = os.getxattr(file, b"security.selinux", follow_symlinks=False).decode().strip('\n[=10=]')
except:
selabel = "u:object_r:unlabeled:s0"
metadata.append("set_metadata(\"/" + file + "\", \"uid\", " + str(stat_info.st_uid) + ", \"gid\", " + str(stat_info.st_gid) + ", \"mode\", " + oct(stat_info.st_mode)[-4:] + ", \"capabilities\", " + cap + ", \"selabel\", \"" + selabel + "\");")
像这样。这是我能找到的唯一解决方案