如何将vmlinux.elf重新打包回bzimage文件?

问题描述 投票:0回答:1

背景

我试图直接对从一些物联网设备获得的内核静态二进制文件(bzimage)进行一些修改。 Linux内核没有原始的编译环境。这是我的步骤:

  • 第1步:使用extract-vmlinuxvmlinux-to-elf从bzimage文件中提取
    vmlinux.elf
    (我们稍后将IOT设备中的bzimage文件称为
    bzimage_origin
  • 第2步:使用
    IDA PRO
    Ghidra
    等反汇编工具来分析目标
    vmlinux.elf
    文件。使用像
    keypatch
    这样的插件来静态修改程序控制流程。然后我们就得到了新的vmlinux文件
    vmlinux.elf_patched
  • 第3步:尝试重新打包
    vmlinux.elf_patched
    回bzimage文件
    bzimage_output

尝试步骤 3 时出现问题。

描述

对于总结问题标题的混乱表示歉意。也许有两个问题,但解决每个问题就足够了。

  • 如何将vmlinux.elf重新打包回bzimage文件?
  • 如何使用repo recreate-zImage生成
    VGA Normal
    输出模式bzimage内核文件?

试用

github 上的存储库可能会有所帮助。回购链接:recreate-zImage

该存储库有助于从源代码中的原始编译 bzimage 文件重新打包 bzimage 文件。如果我可以在工具从

vmlinux.elf
中提取它后替换
bzimage_origin
。问题解决了。

但是使用该工具之后(一个shell脚本

recreate-zimage.sh
)。输出的 bzimage 与原始图像不同。让我们看看
file
命令输出。

# file ./*
../bzimage_origin:          Linux kernel x86 boot executable bzImage, version 3.2.16 (root@ubuntu) #0 SMP Tue Jan 31 04:39:01 UTC 2023, RO-rootFS, swap_dev 0x3, Normal VGA
../bzimage_output:       Linux kernel x86 boot executable bzImage, version 3.2.16 (root@ubuntu) #0 SMP Tue Jun 27 19:39:52 PDT 2023, RO-rootFS, swap_dev 0x3, Prompt for Videomode

第一个是从源代码编译的原始版本。第二个是重新编译的版本,即

recreate-zimage.sh
的输出(Linux源代码为3.2.16)。请注意,第二个与第一个的输出模式不同。

我尝试了以下方法来更改其输出模式。但失败了。

详细图形支持设置

  • make menuconfig
    中编辑选项。转到“设备驱动程序”->“图形支持”。禁用大多数可能与视频模式相关的选项。选项设置如上。然而...不行。
  • 尝试直接在
    .config
    文件中禁用驱动程序模式。我在 .config 中评论了选项
    CONFIG_VIDEO_OUTPUT_CONTROL
    。然而,神秘力量在执行完shell脚本后,悄悄地将
    .config
    中的选项修改回之前的状态。
  • 调试shell脚本并尝试寻找一些线索。我使用
    bash -x
    选项来调试脚本,并注意到使用了与视频模式相关的共享库。可以通过下面的部分调试输出来证明。但我不知道下一步是什么。
+ SETUP_ELF_OBJS='arch/x86/boot/a20.o arch/x86/boot/bioscall.o arch/x86/boot/cmdline.o arch/x86/boot/copy.o arch/x86/boot/cpu.o arch/x86/boot/cpucheck.o arch/x86/boot/early_serial_console.o arch/x86/boot/edd.o arch/x86/boot/header.o arch/x86/boot/main.o arch/x86/boot/mca.o arch/x86/boot/memory.o arch/x86/boot/pm.o arch/x86/boot/pmjump.o arch/x86/boot/printf.o arch/x86/boot/regs.o arch/x86/boot/string.o arch/x86/boot/tty.o arch/x86/boot/video.o arch/x86/boot/video-mode.o arch/x86/boot/version.o arch/x86/boot/video-vga.o arch/x86/boot/video-vesa.o arch/x86/boot/video-bios.o  ' 

重现

系统信息

# uname -a
Linux ubuntu 5.4.0-148-generic #165~18.04.1-Ubuntu SMP Thu Apr 20 01:14:06 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.6 LTS
Release:    18.04
Codename:   bionic

重现步骤

无论来源编译的 bzimage 文件(您可以从 Linux 源代码编译 VGA-normal-output bzimage 文件,并假设您没有原始环境)。重现问题。您需要采取以下步骤:

  • 第1步:下载相同版本的linux内核源代码。(这里我的bzimage内核文件是Linux 3.2.16)。确保您已经安装了构建 Linux 内核的依赖项,如
    build-essential
  • 第2步:在KBUILD_FLAGS中添加
    -fno-pie
    ,解决内核构建不支持PIE错误
  • 第三步:将linux内核源码中的
    include/linux/compiler-gcc4.h
    复制到
    include/linux/compiler-gcc7.h
    。我在 Ubuntu 18.04 上构建内核,默认 gcc 版本是 7.5。所以
    include/linux/compiler-gcc7.h
    是构建所必需的。
  • 第四步:运行命令
    ./rebuild_kernel.sh KERNEL_SRC_ROOT BZIMGAE_ORIGIN_PATH BZIMAGE_OUTPUT_PATH

小贴士

  • 解决此存储库的问题或提供其他方式重新打包
    vmlinux.elf
    都可以。
  • 感谢您的帮助。
linux linux-kernel kernel embedded-linux
1个回答
0
投票

你可以做到这一点,我已经成功做到了。但这需要一些努力。以下是我建议牢记的一些事项。

  1. 找出您要从中提取的图像格式。如果您在
    bzImage
    上进行 binwalk,您将在不同位置看到压缩图像。
  2. vmlinux
    中手动提取内核
    bzImage
    。您需要弄清楚到底使用了什么压缩,以便稍后可以重新压缩它
  3. 虽然您可以使用
    vmlinux-to-elf
    创建包含符号的 ELF 文件,但您应该仅将其用作 Binary Ninja、Ghidra、IDA 等调试/分析的参考...不要尝试修改生成的 elf 文件并将其打包回去。
  4. 在您选择的工具中修改提取的vmlinux,修补asm等...
  5. 完成后,保存二进制文件,使用与原始文件完全相同的选项再次压缩它,并替换原始
    bzImage
    文件中的数据。

对于步骤

2
,我建议查看内核源代码以确定压缩的特定标志,并确保您可以解压缩和重新压缩而不对文件进行任何更改。重新压缩的文件应该与原始压缩版本相同。

可能不是您正在寻找的答案,但希望对将来的人有帮助。我可能会在某个时候写一篇带有示例的文章,因为它非常有趣。

© www.soinside.com 2019 - 2024. All rights reserved.