|
| 1 | +## 什么是 qemu |
| 2 | + |
| 3 | +[qemu](https://www.qemu.org/) 是一款由 [Fabrice Bellard](https://bellard.org/) 等人编写的可以执行硬件虚拟化的开源托管虚拟机,具有运行速度快(配合 kvm),跨平台等优点。 |
| 4 | + |
| 5 | +qemu 通过动态的二进制转化模拟 CPU,并且提供一组设备模型,使其能够运行多种未修改的客户机OS。 |
| 6 | + |
| 7 | +### 运行模式 |
| 8 | + |
| 9 | +qemu 有多种运行模式,常用的有 `User-mode emulation` 和 `System emulation` 两种。 |
| 10 | + |
| 11 | +#### User-mode emulation |
| 12 | +用户模式,在这个模式下,qemu 可以运行单个其他指令集的 linux 或者 macOS/darwin 程序,**允许了为一种架构编译的程序在另外一种架构上面运行**。 |
| 13 | + |
| 14 | +#### System emulation |
| 15 | +系统模式,在这个模式下,qemu 将模拟一个完整的计算机系统,包括外围设备。 |
| 16 | + |
| 17 | +> 之后将分别为两种情况举例 |
| 18 | +
|
| 19 | +## 安装 qemu |
| 20 | + |
| 21 | +### 使用包管理 |
| 22 | +一般情况下,如无特殊需要(如为了运行某个 CTF 比赛中的异架构程序或者 kernel)直接使用对应的包管理直接安装即可 |
| 23 | +```bash |
| 24 | + Arch: pacman -S qemu |
| 25 | + |
| 26 | + Debian/Ubuntu: apt-get install qemu |
| 27 | + |
| 28 | + Fedora: dnf install @virtualization |
| 29 | + |
| 30 | + Gentoo: emerge --ask app-emulation/qemu |
| 31 | + |
| 32 | + RHEL/CentOS: yum install qemu-kvm |
| 33 | + |
| 34 | + SUSE: zypper install qemu |
| 35 | +``` |
| 36 | + |
| 37 | +> 这里只说明在 linux 下的安装过程,其他系统的安装过程请参考 [官方网站](https://www.qemu.org/download/) |
| 38 | +
|
| 39 | +### 从源码编译 |
| 40 | +通过包管理安装的 qemu 版本一般较老,如果需要新版的 qemu,可以从源码编译,这里以编译最新版的 qemu 为例。 |
| 41 | + |
| 42 | +```bash |
| 43 | +wget https://download.qemu.org/qemu-3.1.0-rc3.tar.xz |
| 44 | +tar xvJf qemu-3.1.0-rc3.tar.xz |
| 45 | +cd qemu-3.1.0-rc3 |
| 46 | +``` |
| 47 | + |
| 48 | +通过 `./configure --help` 的查看编译时的选项, `--target-list` 选项为可选的模拟器,默认全选 |
| 49 | + |
| 50 | +> `--target-list` 中的 `xxx-soft` 和 `xxx-linux-user` 分别指系统模拟器和应用程序模拟器, 生成的二进制文件名字为 `qemu-system-xxx` 和 `qemu-xxx` |
| 51 | +
|
| 52 | +这里直接使用默认选项进行编译 |
| 53 | +``` |
| 54 | +./configure |
| 55 | +make -j8 |
| 56 | +``` |
| 57 | + |
| 58 | +继续安装 |
| 59 | +```bash |
| 60 | +sudo make install |
| 61 | +``` |
| 62 | + |
| 63 | +成功安装 |
| 64 | +```bash |
| 65 | +~ qemu-arm --version |
| 66 | +qemu-arm version 3.0.93 |
| 67 | +Copyright (c) 2003-2018 Fabrice Bellard and the QEMU Project developers |
| 68 | +``` |
| 69 | + |
| 70 | +## 使用 qemu |
| 71 | +以 CISCN 2017 的 [babydriver](https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/kernel/CISCN2017-babydriver) 举例,查看启动脚本 |
| 72 | + |
| 73 | +```bash |
| 74 | +CISCN2017_babydriver [master●] bat boot.sh |
| 75 | +───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── |
| 76 | + │ File: boot.sh |
| 77 | +───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── |
| 78 | + 1 │ #!/bin/bash |
| 79 | + 2 │ |
| 80 | + 3 │ qemu-system-x86_64 -initrd rootfs.cpio -kernel bzImage -append 'console=ttyS0 root=/dev/ram oops=panic panic=1' -enable-kvm -monitor /dev/null -m 64M - |
| 81 | + │ -nographic -smp cores=1,threads=1 -cpu kvm64,+smep |
| 82 | +``` |
| 83 | +可以看出这道题目是用 `qemu-system-x86_64` 启动了以 `rootfs.cpio` 为文件系统的 kernel `bzImage`,启动时的参数为 `console=ttyS0 ... panic=1`,为这个进程分配 64M 内存。 |
| 84 | + |
| 85 | +> 更多参数的含义请通过 `-h` 或者 [qemu-doc](https://qemu.weilnetz.de/doc/qemu-doc.html) 查看。 |
| 86 | +
|
| 87 | + |
| 88 | +> 如果使用包管理安装 qemu,直接安装 `qemu-system-x86_64` 即可 |
| 89 | + ```bash |
| 90 | + sudo apt install qemu-system_x86-64 |
| 91 | + ``` |
| 92 | + |
| 93 | +因为使用了 kvm,所以启动时要用 root 权限启动 |
| 94 | +```bash |
| 95 | +CISCN2017_babydriver [master●] sudo ./boot.sh |
| 96 | +...... |
| 97 | +...... |
| 98 | +/ $ id |
| 99 | +uid=1000(ctf) gid=1000(ctf) groups=1000(ctf) |
| 100 | +/ $ ls |
| 101 | +bin etc init linuxrc root sys usr |
| 102 | +dev home lib proc sbin tmp |
| 103 | +``` |
| 104 | + |
| 105 | +> 这道题目的更多分析可以看 [link](https://ctf-wiki.github.io/ctf-wiki/pwn/linux/kernel/kernel_uaf/#ciscn2017-babydriver) |
| 106 | +
|
| 107 | + |
| 108 | +同样,再看下 Codegate 2018 的[Melong](https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/arm/Codegate2018_Melong) |
| 109 | +```bash |
| 110 | +Codegate2018_Melong [master] check melong |
| 111 | ++ file melong |
| 112 | +melong: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=2c55e75a072020303e7c802d32a5b82432f329e9, not stripped |
| 113 | ++ checksec melong |
| 114 | +[*] '/home/m4x/Projects/pwn_repo/Codegate2018_Melong/melong' |
| 115 | + Arch: arm-32-little |
| 116 | + RELRO: Partial RELRO |
| 117 | + Stack: No canary found |
| 118 | + NX: NX enabled |
| 119 | + PIE: No PIE (0x10000) |
| 120 | +``` |
| 121 | +可以看出是 32 位 的 arm 程序,需要安装 `qemu-arm` |
| 122 | + |
| 123 | +> 如果使用包管理安装,则 |
| 124 | + ```bash |
| 125 | + $ sudo apt-get install qemu-user |
| 126 | + $ sudo apt-get install qemu-use-binfmt qemu-user-binfmt:i386 |
| 127 | + ``` |
| 128 | + 这样就安装了 `qemu-arm` |
| 129 | + |
| 130 | +但同时因为程序是动态链接的,还需要同时安装对应的 libc,可以使用 `apt search "libc6-" | grep "ARCH"` 搜索,如 |
| 131 | +```bash |
| 132 | +Codegate2018_Melong [master] apt search "libc6-"| grep arm |
| 133 | +p libc6-arm64-cross - GNU C Library: Shared libraries (for cross-compiling) |
| 134 | +v libc6-arm64-dcv1 - |
| 135 | +v libc6-armel-armel-cross - |
| 136 | +p libc6-armel-armhf-cross - Dummy package to get libc6:armel installed |
| 137 | +p libc6-armel-cross - GNU C Library: Shared libraries (for cross-compiling) |
| 138 | +v libc6-armel-dcv1 - |
| 139 | +p libc6-armhf-armel-cross - Dummy package to get libc6:armhf installed |
| 140 | +v libc6-armhf-armhf-cross - |
| 141 | +p libc6-armhf-cross - GNU C Library: Shared libraries (for cross-compiling) |
| 142 | +v libc6-armhf-dcv1 - |
| 143 | +p libc6-dbg-arm64-cross - GNU C Library: detached debugging symbols (for cross-compiling) |
| 144 | +v libc6-dbg-arm64-dcv1 - |
| 145 | +p libc6-dbg-armel-cross - GNU C Library: detached debugging symbols (for cross-compiling) |
| 146 | +v libc6-dbg-armel-dcv1 - |
| 147 | +p libc6-dbg-armhf-cross - GNU C Library: detached debugging symbols (for cross-compiling) |
| 148 | +v libc6-dbg-armhf-dcv1 - |
| 149 | +p libc6-dev-arm64-cross - GNU C Library: Development Libraries and Header Files (for cross-compiling) |
| 150 | +v libc6-dev-arm64-cross:i386 - |
| 151 | +v libc6-dev-arm64-dcv1 - |
| 152 | +v libc6-dev-armel-armel-cross - |
| 153 | +p libc6-dev-armel-armhf-cross - Dummy package to get libc6-dev:armel installed |
| 154 | +p libc6-dev-armel-cross - GNU C Library: Development Libraries and Header Files (for cross-compiling) |
| 155 | +v libc6-dev-armel-cross:i386 - |
| 156 | +v libc6-dev-armel-dcv1 - |
| 157 | +p libc6-dev-armhf-armel-cross - Dummy package to get libc6-dev:armhf installed |
| 158 | +v libc6-dev-armhf-armhf-cross - |
| 159 | +p libc6-dev-armhf-cross - GNU C Library: Development Libraries and Header Files (for cross-compiling) |
| 160 | +v libc6-dev-armhf-cross:i386 - |
| 161 | +v libc6-dev-armhf-dcv1 - |
| 162 | +``` |
| 163 | +只需要安装 `libc6-ARCH-cross` 的包即可。 |
| 164 | + |
| 165 | +装好后使用 `-L` 指定共享库路径即可运行文件。 |
| 166 | +```bash |
| 167 | +$ qemu-arm -L /usr/arm-linux-gnueabi ./melong |
| 168 | +``` |
| 169 | + |
| 170 | +> 这道题目的更多分析可以看 [link](http://m4x.fun/post/how-2-pwn-an-arm-binary/#codegate2018-melong) |
| 171 | +
|
| 172 | +如果是静态的程序,不需要 libc,则可以不用 `-L` 选项,如 Jarvis-OJ 的 [typo](https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/arm/jarvisOJ_typo) |
| 173 | + |
| 174 | +```bash |
| 175 | +jarvisOJ_typo [master] check ./typo |
| 176 | ++ file ./typo |
| 177 | +./typo: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=211877f58b5a0e8774b8a3a72c83890f8cd38e63, stripped |
| 178 | ++ checksec ./typo |
| 179 | +[*] '/home/m4x/Projects/pwn_repo/jarvisOJ_typo/typo' |
| 180 | + Arch: arm-32-little |
| 181 | + RELRO: Partial RELRO |
| 182 | + Stack: No canary found |
| 183 | + NX: NX enabled |
| 184 | + PIE: No PIE (0x8000) |
| 185 | +jarvisOJ_typo [master] qemu-arm ./typo |
| 186 | +Let's Do Some Typing Exercise~ |
| 187 | +Press Enter to get start; |
| 188 | +Input ~ if you want to quit |
| 189 | +^C |
| 190 | +``` |
| 191 | +
|
| 192 | +## 如何 debug |
| 193 | +
|
| 194 | +分两种情况 |
| 195 | +
|
| 196 | +1. 调试 qemu 这个进程 |
| 197 | +2. 调试 qemu 内运行的程序 |
| 198 | +
|
| 199 | +### 调试 qemu |
| 200 | +对于第一种情况,直接使用 gdb attach 到 qemu 的进程号即可,为了调试时方便可以在编译时加上 `--enable-debug` 选项以保留符号等信息。 |
| 201 | +``` |
| 202 | + --enable-debug enable common debug build options |
| 203 | +``` |
| 204 | +在之后的 qemu 逃逸中会着重介绍这个过程。 |
| 205 | +
|
| 206 | +### 调试 qemu 中的进程 |
| 207 | +qemu 提供了 gdb 的接口,通过 `-g` 指定端口来调用 |
| 208 | +``` |
| 209 | +-g port QEMU_GDB wait gdb connection to 'port' |
| 210 | +``` |
| 211 | +
|
| 212 | +同时为了调试异架构的程序,需要安装 `gdb-multiarch` |
| 213 | +```bash |
| 214 | +sudo apt install gdb-multiarch |
| 215 | +``` |
| 216 | +例如 Melong 中,使用 |
| 217 | +```bash |
| 218 | +$ qemu-arm -g 1234 -L /usr/arm-linux-gnueabi ./melong |
| 219 | +``` |
| 220 | +启动程序,在另一个 shell 中使用 `gdb-multiarch` 启动程序并连接到指定的端口即可调试 |
| 221 | +```bash |
| 222 | +Codegate2018_Melong [master] gdb-multiarch ./melong -q |
| 223 | +pwndbg: loaded 175 commands. Type pwndbg [filter] for a list. |
| 224 | +pwndbg: created $rebase, $ida gdb functions (can be used with print/break) |
| 225 | +Reading symbols from ./melong...(no debugging symbols found)...done. |
| 226 | +pwndbg> target remote localhost:1234 |
| 227 | +``` |
| 228 | +
|
| 229 | +> 使用 gdb-multriarch 可以调试大多数的程序。 |
| 230 | +> |
| 231 | +> 但也有部分程序不能使用 gdb-multiarch,这时可以编译对应架构的 Toolchain,如 `arm-none-eabi-gdb` |
| 232 | +> |
| 233 | +> 或者使用系统模式的 qemu 创建一个对应架构的虚拟机,文末放了一片链接,以后也会介绍这种方法。 |
| 234 | +
|
| 235 | +特别的是系统模式的 qemu 还提供了另外几个参数 |
| 236 | +``` |
| 237 | +-gdb dev wait for gdb connection on 'dev' |
| 238 | +-s shorthand for -gdb tcp::1234 |
| 239 | +-S freeze CPU at startup (use 'c' to start execution) |
| 240 | +``` |
| 241 | +
|
| 242 | +`-gdb` 作用类似 `-g`,使用 `-gdb tcp::1234` 即可在 gdb 中通过 1234 端口调试。 |
| 243 | +
|
| 244 | +`-s` 是 `-gdb tcp::1234` 的缩写 |
| 245 | +
|
| 246 | +`-S` 让虚拟机停在启动的地方方便调试,类似于 pwntools 的 [gdb.debug()](http://docs.pwntools.com/en/stable/gdb.html?highlight=gdb.debug#pwnlib.gdb.debug) |
| 247 | +
|
| 248 | +## 设备模拟 |
| 249 | +
|
| 250 | +## 内存分配 |
| 251 | +
|
| 252 | +## Reference |
| 253 | +
|
| 254 | +https://wiki.qemu.org/Main_Page |
| 255 | +
|
| 256 | +https://qemu.weilnetz.de/doc/qemu-doc.html |
| 257 | +
|
| 258 | +https://wiki.qemu.org/Documentation |
| 259 | +
|
| 260 | +https://en.wikipedia.org/wiki/QEMU |
| 261 | +
|
| 262 | +https://www.ringzerolabs.com/2018/03/the-wonderful-world-of-mips.html |
0 commit comments