fortigate 7.6.3版本固件解密

此文档编写于:2025年5月
使用的 FortiGate 版本:7.6.3
主要参考文章:FortiGate Firmware Analysis (noways.io)
Recent modifications in FortiGate firmware crypto (randorisec.fr)

vm Images下载

官方下载地址:https://support.fortinet.com/support/#/downloads/vm
选项参考如下图:

image

提取rootfs.gz​与flatkc

具体操作可参考此文章的 "FortiGate-VM" 章节:https://www.noways.io/blogs/tech/fortigate-firmware-analysis

配置FortiGate-VM

将 "1.vm Images下载" 中下载下来的文件解压,并将 "FortiGate-VM64.ovf" 导入 vmware

image

将 “网络适配器” 全部修改为 "NAT"

image

登入虚拟机。其默认账户为"admin",密码为空(即按一下回车就行),登录后会提示输入密码,根据提示操作即可。
而后参考文章操作,对 FortiGate-VM 进行配置

config system interface
edit port1
set mode static
set ip 192.168.80.100 255.255.255.0 # 根据你的NAT网络配置进行修改
end
config router static
edit 1
set device port1
set gateway 192.168.80.2    # 根据你的NAT网络配置进行修改
end

若配置正确,即可在本机上访问到 web 界面

image

现在可以关闭 FortiGate-VM 了

挂载vmdk并提取rootfs.gz

在 FortiGate-VM 的文件夹中找到 "[your-vm-name]-disk1.vmdk",并移入虚拟机中

image

参考文章操作,挂载磁盘

└─$ sudo modprobe nbd max_part=16
└─$ sudo qemu-nbd -c /dev/nbd1 ./fgt-disk1.vmdk
└─$ sudo mount /dev/nbd1p1 ./fortigate
└─$ tree -a -L 1 ./fortigate 
./fortigate
├── boot
├── boot.msg
├── capwap
├── cmdb
├── config
├── datafs.tar.gz
├── datafs.tar.gz.bak
├── datafs.tar.gz.chk
├── datafs.tar.gz.chk.bak
├── .db
├── .db.x
├── dhcp6s
├── dhcpddb.bak
├── dhcp_ipmac.dat.bak
├── etc
├── extlinux.conf
├── filechecksum
├── flatkc
├── flatkc.chk
├── flatkc.sig
├── hash_bin.sha256
├── ldlinux.c32
├── ldlinux.sys
├── lib
├── log
├── lost+found
├── rootfs.gz
├── rootfs.gz.chk
└── web-ui

11 directories, 19 files

最后使用cp​指令,将rootfs.gz​与flatkc​复制出来即可(方便后续操作,非必要)

在挂载磁盘时,如遇操作权限不够,sudo​即可(本人操作时只遇到这一个问题)

将​flatkc​转为elf格式

有现成的工具:marin-m/vmlinux-to-elf: A tool to recover a fully analyzable .ELF from a raw kernel, through extracting the kernel symbol table (kallsyms) (github.com)

如何使用其readme​写得也比较清楚了,不再赘述。

解密rootfs.gz

加密过程大体没变。加密过程的具体分析及解密脚本,参考这篇文章:https://blog.randorisec.fr/fortigate-rootfs-decryption/。这里我就丢一个加密整体流程吧:

image

但是文章里的解密脚本不能直接拿来用,有两处需要修改

修改①

通过对flatkc.elf​中加密过程的分析,发现:用于生成chacha20的key和iv的偏移值需要修改
(位于参考文章中的"Signature decryption"章节)

image

##############################################
#   修改前
#def derivate_chacha20_params(seed):
#    sha = sha256()
#    sha.update(seed[5:])
#    sha.update(seed[:5])
#    key = sha.digest()
#    sha = sha256()
#    sha.update(seed[2:])
#    sha.update(seed[:2])
#    iv = sha.digest()[:16]
#    return key, iv
##############################################
#   报错信息
#Traceback (most recent call last):
#  File "...\decrypt_rootfs.py", line 193, in <module>
#    decoded_key, _ = decoder.decode(
#                     ^^^^^^^^^^^^^^^
#  ........................
#pyasn1.error.PyAsn1Error: <TagSet object, tags 0:0:13> not in asn1Spec: <RSAPublicKey schema object, tagSet=<TagSet object, tags 0:32:16>, subtypeSpec=<ConstraintsIntersection object>, componentType=<NamedTypes object, types <NamedType object, type modulus=<Integer schema object, tagSet <TagSet object, tags 0:0:2>>>, <NamedType object, type publicExponent=<Integer schema object, tagSet <TagSet object, tags 0:0:2>>>>, sizeSpec=<ConstraintsIntersection object>>
##############################################
#   修改后
def derivate_chacha20_params(seed):
    sha = sha256()
    sha.update(seed[6:])    #根据上文v46修改
    sha.update(seed[:6])
    key = sha.digest()
    sha = sha256()
    sha.update(seed[3:])
    sha.update(seed[:3])    #根据上文iv修改
    iv = sha.digest()[:16]
    return key, iv

修改②

通过debug模式下的打印发现(自行添加了两处logging.debug​):crypto_ctx结构体内参数顺序需要修改

image

image

image

##############################################
#   修改前
#class crypto_ctx(ctypes.Structure):
#    _pack_ = 1
#    _fields_ = [
#        ("padding", ctypes.c_uint8 * 174),
#        ("null", ctypes.c_uint8),
#        ("u", crypto_ctx_ctr_u),
#        ("aes_key", ctypes.c_uint8 * 32),
#        ("rootfs_hash", ctypes.c_uint8 * 32),
#    ]
##############################################
#   报错信息
#Traceback (most recent call last):
#  File "...\decrypt_rootfs.py", line 209, in <module>
#    assert sha.digest() == bytes(sig_struct.rootfs_hash), "rootfs corrupted?"
#           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#AssertionError: rootfs corrupted?
##############################################
#   修改后
class crypto_ctx(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("padding", ctypes.c_uint8 * 174),
        ("null", ctypes.c_uint8),
        ("rootfs_hash", ctypes.c_uint8 * 32), # rootfs_hash是第一个参数
        ("u", crypto_ctx_ctr_u),
        ("aes_key", ctypes.c_uint8 * 32),
    ]

​​

解密

脚本环境直接看 git 仓库里的 "setup"

运行方法看 git 仓库里的 "Usage"

(.venv) $ python decrypt_rootfs.py ./flatkc.elf ./rootfs.gz ./output_rootfs_dec.gz
(.venv) $ python decrypt_rootfs.py ./flatkc.elf ./rootfs.gz ./output_rootfs_dec.gz --debug  # debug模式

而后先使用gzip解压解密的文件,然后在使用cpio解压

└─$ file output_rootfs_dec.gz   # 可要可不要,file一下安心

└─$ gzip -dc -S .dec < output_rootfs_dec.gz > rootfs.cpio
└─$ mkdir tmp; cd tmp; sudo cpio -idv < ../rootfs.cpio
└─$ ll
total 56676
-r--r--r-- 1 root root 41834768 May 13 21:41 bin.tar.xz
drwxr-xr-x 2 root root     4096 May 13 21:41 boot
drwxr-xr-x 3 root root     4096 May 13 21:41 data
drwxr-xr-x 2 root root     4096 May 13 21:41 data2
drwxr-xr-x 8 root root    20480 May 13 21:41 dev
lrwxrwxrwx 1 root root        8 May 13 21:41 etc -> data/etc
lrwxrwxrwx 1 root root        1 May 13 21:41 fortidev -> /
lrwxrwxrwx 1 root root       10 May 13 21:41 init -> /sbin/init
drwxr-xr-x 5 root root     4096 May 13 21:41 lib
lrwxrwxrwx 1 root root        4 May 13 21:41 lib64 -> /lib
-r--r--r-- 1 root root 15413732 May 13 21:41 migadmin.tar.xz
-r--r--r-- 1 root root   659488 May 13 21:41 node-scripts.tar.xz
drwxr-xr-x 2 root root     4096 May 13 21:41 proc
drwxr-xr-x 2 root root     4096 May 13 21:41 sbin
drwxr-xr-x 2 root root     4096 May 13 21:41 sys
drwxr-xr-x 2 root root     4096 May 13 21:41 tmp
drwxr-xr-x 3 root root     4096 May 13 21:41 usr
-r--r--r-- 1 root root    55172 May 13 21:41 usr.tar.xz
drwxr-xr-x 9 root root     4096 May 13 21:41 var

└─$ sudo xz --check=sha256 -d bin.tar.xz
└─$ tar -xf bin.tar
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇