import os
import struct
import lzma
import hashlib
DEBUG = False # 调试标志
BASE_ADDRESS = 0x00120200 # 基地址偏移量
# Base类,用于存储基地址的数据
class Base:
def __init__(self):
self.startFilePos = 0 # 基地址在文件中的起始位置
self.data = bytearray(0x15C8) # 存储基地址的数据
# SingleFileData类,用于存储单个文件的数据
class SingleFileData:
def __init__(self):
self.fileInt = [0, 0] # 存储文件的大小和其他属性
self._dataSize = 0 # 文件数据的大小
self.fileData = bytearray() # 文件数据
self.nextSingleFileData = None # 下一个文件数据节点的引用
# SingleFile类,用于存储单个文件的信息
class SingleFile:
def __init__(self):
self.startFilePos = 0 # 文件在文件中的起始位置
self.data = bytearray(0x194) # 存储文件信息的数据
self._times = 0 # 文件包含的子文件数量
self._isFolder = False # 文件是否是文件夹
self._fileSize = 0 # 文件的总大小
self.firstFileData = None # 第一个文件数据节点的引用
# 读取基地址的函数
def read_base(file):
# 定位到基地址的位置并读取数据
file.seek(BASE_ADDRESS)
base = Base()
base.startFilePos = file.tell() # 记录基地址在文件中的位置
base.data = bytearray(file.read(0x15C8)) # 读取基地址的数据
return base
# 读取下一个文件的函数
def read_next_file(file, need_data):
# 创建SingleFile对象来存储文件信息
single_file = SingleFile()
single_file.startFilePos = file.tell() # 记录文件在文件中的起始位置
single_file.data = bytearray(file.read(0x194)) # 读取文件信息的数据
single_file._isFolder = (single_file.data[200] == -1) # 判断文件是否是文件夹
single_file._times = single_file.data[0x190] # 获取文件包含的子文件数量
first_file_data = None # 记录第一个文件数据节点的引用
for i in range(single_file._times):
file_data = SingleFileData() # 创建SingleFileData对象来存储文件数据
file_data.fileInt = struct.unpack('<2I', file.read(8)) # 读取文件的大小和其他属性
single_file._fileSize += file_data.fileInt[0] # 计算文件的总大小
# 如果不是文件夹,且需要数据,则读取文件数据
if not single_file._isFolder:
if not DEBUG:
file_data.fileData = bytearray(file.read(file_data.fileInt[0])) # 读取文件数据
else:
file.seek(file_data.fileInt[0], os.SEEK_CUR) # 跳过文件数据
# 将文件数据节点连接到单个文件对象上
if first_file_data is None:
single_file.firstFileData = file_data
first_file_data = file_data
else:
first_file_data.nextSingleFileData = file_data
first_file_data = file_data
return single_file
# 提取文件的函数
def extract_file(f, output_folder):
# 获取文件名并构建文件路径
filename = re.sub(r'[^\w\-_. ]', '', f.data.decode("utf-16le").replace("\x00", ""))
path = os.path.join(output_folder, filename)
os.makedirs(os.path.dirname(path), exist_ok=True) # 创建文件夹
with open(path, "wb") as file_handle:
file_data = f.firstFileData
while file_data is not None:
if file_data.fileData is not None:
file_handle.write(file_data.fileData) # 写入文件数据
file_data = file_data.nextSingleFileData
return path
# 计算文件MD5值的函数
def calculate_md5(file_path):
hasher = hashlib.md5()
with open(file_path, "rb") as file:
for chunk in iter(lambda: file.read(4096), b""):
hasher.update(chunk)
return hasher.hexdigest()
# 主函数
def main():
output_folder = r"F:\The couers of He predecessor\The fourth lesson\data" # 输出文件夹路径
with open("F:/The couers of He predecessor/The fourth lesson/MeiqiaWinLatest.exe", "rb") as f:
base = read_base(f) # 读取基地址
print(f"baseStartPos: {base.startFilePos:0x}") # 打印基地址的起始位置
while True:
file = read_next_file(f, not DEBUG) # 读取下一个文件
if file._fileSize <= 0:
break
extracted_file_path = ""
if not DEBUG:
extracted_file_path = extract_file(file, output_folder) # 提取文件
md5 = ""
if extracted_file_path:
md5 = calculate_md5(extracted_file_path) # 计算文件的MD5值
# 打印文件信息和MD5值
print(f"fileStartPos: {file.startFilePos:0x}\t\tisFolder: {file._isFolder}")
print(f"fileName: {file.data.decode('utf-16le')}\t\tfileZipSize: 0x{file._fileSize:0x}\n")
print(f"MD5: {md5}\n")
if __name__ == "__main__":
main()
安装包逆向2
最新推荐文章于 2024-08-24 23:35:04 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)