Apple Silicon配置二进制环境(二)

  • Author:ZERO-A-ONE
  • Date:2022-07-31

本系列旨在记录我本人在使用基于M1 Pro的Apple Silicon芯片MacBook Pro笔记本搭建适用于二进制研究的环境,包括逆向、PWN之类的场景

0x1 前序补充

之前有朋友反映Wine配IDA Pro还是有些麻烦,之后发现可以使用最新的PD虚拟机跑Windows11 ARM,就可以直接跑IDA Pro 7.5或者IDA Pro 7.6

提供一个我自己明确能跑起来的IDA Pro 7.5 版本

https://pan.quark.cn/s/775be0173189

如果遇到Python插件无法启动的情况,可以考虑使用官方提供的ARM架构同版本的Python去替换原来的Python包

0x2 PWN全家桶

对于一个PWN手或者二进制研究员而言,以下的工具是必不可少的:

  • pwntools —— CTF framework and exploit development library
  • pwndbg —— a GDB plug-in that makes debugging with GDB suck less, with a focus on features needed by low-level software developers, hardware hackers, reverse-engineers and exploit developers
  • pwngdb —— gdb for pwn
  • ROPgadget —— facilitate ROP exploitation tool
  • roputils —— A Return-oriented Programming toolkit
  • one_gadget —— A searching one-gadget of execve(‘/bin/sh’, NULL, NULL) tool for amd64 and i386
  • angr —— A platform-agnostic binary analysis framework
  • radare2 —— A rewrite from scratch of radare in order to provide a set of libraries and tools to work with binary files
  • seccomp-tools —— Provide powerful tools for seccomp analysis
  • linux_server[64] —— IDA 7.0 debug server for linux
  • tmux —— a terminal multiplexer
  • ltrace —— trace library function call
  • strace —— trace system call

然而以上这些工具往往运行在X86架构上才能比较稳妥,如果Apple Silicon需要曲线救国的话,我目前的解决方案是一台VPS + Docker + Termius。这一套下来其实和在本地虚拟机上对二进制文件进行调试没有什么太大的区别

2.1 PWN Docker

VPS的购买应该就不用再啰嗦了,直接到如何部署PWN Docker就好了。这里使用到的Docker是一个基于修改后的ubuntu 20.04镜像。它里面已经包含了大量的常用工具

https://github.com/skysider/pwndocker

2.1.1 安装Docker

下载安装脚本:

curl -fsSL https://get.docker.com -o get-docker.sh

使用阿里云镜像下载安装:

sh get-docker.sh --mirror Aliyun

执行脚本后会自动识别arm架构,下载安装对应版本docker,稍等片刻即可

将当前用户加入docker组:

sudo usermod -aG docker $USER

退出当前终端并重新登录,此时操作docker不再需要加sudo权限

安装python和pip:

sudo apt-get install -y python python-pip

安装libffi-dev,否则在安装docker-compose的时候会报错:

sudo apt-get install -y libffi-dev

安装docker-compose

sudo apt install docker-compose

下载安装Docker图形化界面portainer

#下载 Docker 图形化界面 portainer
sudo docker pull portainer/portainer
#创建 portainer 容器
sudo docker volume create portainer_data
#运行 portainer
sudo docker run -d -p 9000:9000 --name portainer --restart always -v /

2.1.2 安装PWN-Docker

首先使用git命令拖下来

git clone https://github.com/skysider/pwndocker.git

然后进入pwn-docker文件

docker-compose up -d

之后都是执行以下命令进入pwn docker

docker exec -it pwn_test /bin/bash

2.1.3 TMUX启动鼠标控制

这里强烈推荐看起TMUX的鼠标控制功能,这样在PWNTOOLS使用TMUX分屏调试的时候十分方便

临时启动

老版本的Tmux开启鼠标模式的方法:

先按Ctrl + B, 松开以后,输入冒号,输入set mouse-mode on 回车。

新版本取消了这条命令。

在新版本中,开启鼠标模式的方法为:

先按Ctrl + B, 松开以后,输入冒号,输入set -g mouse on 回车。

永久启动

查看tmux当前版本:

tmux -V

编辑tmux配置文件 :

vim ~/.tmux.conf

tmux2.1之后版本:

set -g mouse on

tmux2.1之前版本:

setw -g mouse-resize-pane on
setw -g mouse-select-pane on
setw -g mouse-select-window on
setw -g mode-mouse on

2.2 Tips for pwn docker

2.2.1 使用不同的libc运行

这里因为我们需要调试,而pwn docker里面虽然内置了一些libc,但是没有保存.debug文件,我们需要自行手动下载完整版的glibc-all-in-one

git clone https://github.com/matrix1001/glibc-all-in-one

然后我们需要更新libc的目录,然后查看可下载的glibc

./update_list             #更新最新版本的glibc
cat list                 #查看可下载的glibc

我们现在根目录创建一个tmp目录

mkdir ~/tmp

然后我们将我们想要的libc复制到tmp目录,这里以64位的2.23为例子

cp /glibc/2.27/64/lib/ld-2.23.so ~/tmp/ld-2.23.so
cp /glibc/2.23/64/lib/libc-2.23.so ~/tmp

然后把我们的运行程序也放入tmp目录,并使用patchelf,首先替换libc

patchelf --replace-needed libc.so.6 ./libc-2.23.so ./test

然后设置ld文件

patchelf --set-interpreter ./ld-2.23.so ./test

查看patch之后的程序

root@3e018bcbbf46:~/tmp# ldd ./test
        linux-vdso.so.1 (0x00007ffc031e0000)
        ./libc-2.23.so (0x00007f401411e000)
        ./ld-2.23.so => /lib64/ld-linux-x86-64.so.2 (0x00007f40144f1000)

尝试执行以下发现可以正常执行

root@3e018bcbbf46:~/tmp# ./test
This file doesn't demonstrate an attack, but shows the nature of glibc's allocator.
glibc uses a first-fit algorithm to select a free chunk.
If a chunk is free and large enough, malloc will select this chunk.
This can be exploited in a use-after-free situation.
Allocating 2 buffers. They can be large, don't have to be fastbin.
1st malloc(0x512): 0x556d1ef1f010
2nd malloc(0x256): 0x556d1ef1f530
we could continue mallocing here...
now let's put a string at a that we can read later "this is A!"
first allocation 0x556d1ef1f010 points to this is A!
Freeing the first one...
We don't need to free anything again. As long as we allocate smaller than 0x512, it will end up at 0x556d1ef1f010
So, let's allocate 0x500 bytes
3rd malloc(0x500): 0x556d1ef1f010
And put a different string here, "this is C!"
3rd allocation 0x556d1ef1f010 points to this is C!
first allocation 0x556d1ef1f010 points to this is C!
If we reuse the first allocation, it now holds the data from the third allocation.

但是如果我们直接使用GDB进行调试会出现问题,因为我们没有提供符号表,我推荐直接将.debug移动到题目的同级目录下

mkdir .debug
cd .debug
cp /ctf/work/2.23-0ubuntu11.3_amd64/.debug/* ./

然后我们就可以开始使用gdb正常执行bins和heap等指令

2.2.2 用GDB查看内存

这里可以介绍一下用gdb查看内存

格式: x /nfu <addr>
  • x:是 examine 的缩写
  • n:表示要显示的内存单元的个数
  • f:表示显示方式, 可取如下值
    • x:按十六进制格式显示变量
    • d:按十进制格式显示变量
    • u:按十进制格式显示无符号整型
    • o:按八进制格式显示变量
    • t:按二进制格式显示变量
    • a:按十六进制格式显示变量
    • i:指令地址格式
    • c:按字符格式显示变量
    • f:按浮点数格式显示变量
  • u:表示一个地址单元的长度,可按如下取值
    • b:表示单字节
    • h:表示双字节
    • w:表示四字节,32位应用常用
    • g:表示八字节,64位应用常用

2.3 一些好用的脚本

2.3.1 Docker

我推荐大家可以使用一些脚本,来方便使用Docker,不用总是去记忆和查看Docker的指令。我编写了以下脚本:

rundocker.py:启动PWN Docker

import os
cmd = "docker exec -it pwn_test /bin/bash"
os.system(cmd)

todocker.py:将HOST文件送入Docker内

import sys
import os

container_id = "3e018bcbbf46e1b770d245bf55a61e6474085abfd56d0afe2951805f7753ccc4"
pwndocker_dir = "/ctf/work"
path_dir = ""

if __name__ == '__main__':
    print(sys.argv[1])
    path_dir = sys.argv[1]
    cmd = "docker cp "  + path_dir + " "  + container_id + ":" + pwndocker_dir
    print(cmd)
    os.system(cmd)

fromdocker.py:将Docker文件送入HOST内

import sys
import os

container_id = "3e018bcbbf46e1b770d245bf55a61e6474085abfd56d0afe2951805f7753ccc4"
pwndocker_dir = "/ctf/work"
path_dir = "./"

if __name__ == '__main__':
    print(sys.argv[1])
    pwndocker_dir = sys.argv[1]
    cmd = "docker cp " + container_id + ":" + pwndocker_dir + " " + path_dir  
    print(cmd)
    os.system(cmd)

2.3.2 pwntools

自定义LIBC后的GDB调试

建议使用pwntools来间接启动GDB调试,可以使用以下脚本:

from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
p = process(["./test"], env={
    
    "LD_PRELOAD":"./libc.so.6"})
gdb.attach(p, "b main")
p.interactive()

在执行这个脚本前,需要启动tmux

猜你喜欢

转载自blog.csdn.net/kelxLZ/article/details/126098699