- Author:ZERO-A-ONE
- Date:2022-07-31
This series aims to record my own use of the M1 Pro-based Apple Silicon chip MacBook Pro notebook to build an environment suitable for binary research, including scenarios such as reverse engineering and PWN
0x1 preamble supplement
Before, a friend reported that it was still troublesome to match Wine with IDA Pro, but later found that you can use the latest PD virtual machine to run Windows 11 ARM, and you can directly run IDA Pro 7.5 or IDA Pro 7.6
Provide a version of IDA Pro 7.5 that I can definitely run
https://pan.quark.cn/s/775be0173189
If you encounter the situation that the Python plugin cannot be started, you can consider using the officially provided Python of the same version as the ARM architecture to replace the original Python package
0x2 PWN family bucket
For a pwner or binary researcher, the following tools are essential:
- 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
However, the above tools are often run on the X86 architecture to be more secure. If Apple Silicon needs to save the country with curves, my current solution is a VPS + Docker + Termius. This set is actually not much different from debugging binary files on a local virtual machine
2.1 PWN Docker
The purchase of VPS should not be too long-winded, just go directly to how to deploy PWN Docker. The Docker used here is based on a modified ubuntu 20.04 image. It already contains a large number of commonly used tools
https://github.com/skysider/pwndocker
2.1.1 Install Docker
Download the installation script:
curl -fsSL https://get.docker.com -o get-docker.sh
Use the Alibaba Cloud mirror to download and install:
sh get-docker.sh --mirror Aliyun
After executing the script, it will automatically recognize the arm architecture, download and install the corresponding version of docker, and wait for a while.
Add the current user to the docker group:
sudo usermod -aG docker $USER
Exit the current terminal and log in again. At this time, you no longer need to add sudo permission to operate docker
Install python and pip:
sudo apt-get install -y python python-pip
Install libffi-dev, otherwise an error will be reported when installing docker-compose:
sudo apt-get install -y libffi-dev
Install docker-compose
sudo apt install docker-compose
Download and install the Docker graphical interface 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 Install PWN-Docker
First use the git command to drag down
git clone https://github.com/skysider/pwndocker.git
Then enter the pwn-docker file
docker-compose up -d
After that, execute the following command to enter pwn docker
docker exec -it pwn_test /bin/bash
2.1.3 TMUX starts mouse control
It is strongly recommended to look at the mouse control function of TMUX, which is very convenient when PWNTOOLS uses TMUX split-screen debugging
Temporary activation
How to enable the mouse mode in the old version of Tmux:
First press Ctrl + B, after releasing it, enter a colon and press set mouse-mode on
Enter.
The new version cancels this order.
In the new version, the method to enable mouse mode is:
First press Ctrl + B, after releasing it, enter a colon and press set -g mouse on
Enter.
permanent start
Check the current version of tmux:
tmux -V
Edit the tmux configuration file:
vim ~/.tmux.conf
Versions after tmux2.1:
set -g mouse on
Versions before 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 Run with different libc
Here because we need to debug, and although some libc is built in pwn docker, but the .debug file is not saved, we need to manually download the full version of glibc-all-in-one
git clone https://github.com/matrix1001/glibc-all-in-one
Then we need to update the directory of libc, and then check the downloadable glibc
./update_list #更新最新版本的glibc
cat list #查看可下载的glibc
We now create a tmp directory in the root directory
mkdir ~/tmp
Then we copy the libc we want to the tmp directory, here we take 64-bit 2.23 as an example
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
Then put our running program into the tmp directory, and use patchelf, first replace libc
patchelf --replace-needed libc.so.6 ./libc-2.23.so ./test
Then set the ld file
patchelf --set-interpreter ./ld-2.23.so ./test
View the program after 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)
Try to execute the following and found that it can be executed normally
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.
But if we directly use GDB for debugging, there will be problems, because we have not provided a symbol table, I recommend directly moving .debug to the same level directory of the topic
mkdir .debug
cd .debug
cp /ctf/work/2.23-0ubuntu11.3_amd64/.debug/* ./
Then we can start using gdb to execute instructions such as bins and heap normally
2.2.2 View memory with GDB
Here you can introduce the use of gdb to view memory
格式: x /nfu <addr>
- x: is the abbreviation of examine
- n: Indicates the number of memory units to be displayed
- f: Indicates the display mode, which can take the following values
- x: display variables in hexadecimal format
- d: display variables in decimal format
- u: display unsigned integers in decimal format
- o: display variables in octal format
- t: display variables in binary format
- a: display variables in hexadecimal format
- i: instruction address format
- c: display variables in character format
- f: display variables in floating-point format
- u: Indicates the length of an address unit, which can be taken as follows
- b: indicates a single byte
- h: indicates double byte
- w: Indicates four bytes, commonly used in 32-bit applications
- g: indicates eight bytes, commonly used in 64-bit applications
2.3 Some useful scripts
2.3.1 Docker
I recommend that you use some scripts to facilitate the use of Docker, without always having to memorize and view Docker instructions. I wrote the following script:
rundocker.py: start PWN Docker
import os
cmd = "docker exec -it pwn_test /bin/bash"
os.system(cmd)
todocker.py: Send the HOST file into 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: Send Docker files into 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
GDB debugging after custom LIBC
It is recommended to use pwntools to indirectly start GDB debugging, you can use the following script:
from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
p = process(["./test"], env={
"LD_PRELOAD":"./libc.so.6"})
gdb.attach(p, "b main")
p.interactive()
Before executing this script, you need to start tmux