ARM

跟 Azeria 小姐姐学 ARM

Posted by API Caller on April 30, 2019

最新的 F5 又买不起, 不学汇编怎么行呐, 学吧就. 买了😏

资料文档

  • 《Lab: ARM Assembly Shellcode - From Zero to ARM Assembly Bind Shellcode》

Emulate RASPBERRY PI With QEMU

小姐姐给了我从难到简单三个选项, 这我能怂么, 果断选 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mkdir ~/qemu_vms
cd ~/qemu_vms

# 下载内核
wget https://raw.githubusercontent.com/dhruvvyas90/qemu-rpi-kernel/master/kernel-qemu-4.4.34-jessie

# 下载镜像
wget http://downloads.raspberrypi.org/raspbian/images/raspbian-2017-04-10/2017-04-10-raspbian-jessie.zip

# 校验一下  6d7b11bb3d64524203edf6c80c499456fb5fef53
sha1sum 2017-04-10-raspbian-jessie.zip

# 解压
unzip 2017-04-10-raspbian-jessie.zip
1
fdisk -l 2017-04-10-raspbian-jessie.img

教程里说 You see that the filesystem (.img2) starts at sector 137216. Now take that value and multiply it by 512, in this case it’s 512 * 137216 = 70254592 bytes. Use this value as an offset in the following command:

然而实际上这里是 92160.

1
2
3
4
5
# 建立目录, 不懂为啥小姐姐要建到 /mnt
mkdir raspbian

# 挂载
sudo mount -v -o offset=$((512*92160)) -t ext4 2017-04-10-raspbian-jessie.img raspbian
1
sudo gedit raspbian/etc/fstab

第一列分别改成 /dev/sda1/dev/sda2, 改完长这样:

1
2
3
proc            /proc           proc    defaults          0       0
/dev/sda1  /boot           vfat    defaults          0       2
/dev/sda2  /               ext4    defaults,noatime  0       1
1
sudo gedit raspbian/etc/ld.so.preload

注释掉, 改完长这样:

1
# /usr/lib/arm-linux-gnueabihf/libarmmem.so
1
2
# 卸载镜像
sudo umount raspbian
1
2
# 启动
qemu-system-arm -kernel kernel-qemu-4.4.34-jessie -cpu arm1176 -m 256 -M versatilepb -serial stdio -append "root=/dev/sda2 rootfstype=ext4 rw" -hda 2017-04-10-raspbian-jessie.img -redir tcp:5022::22

这个启动要一段时间, 内存最大只能 256, 让我的 128G 内存无所适从.

进桌面后打开终端, passwd 改一下密码, 原本的密码是 raspberry, 我改成了 morenmima.

1
2
3
# 开启 ssh
sudo service ssh restart
sudo update-rc.d ssh enable

然后 Ctrl + Alt 切到宿主机, 打开终端连接 ssh

1
ssh [email protected] -p 5022
1
2
# 打开语言支持
sudo nano /etc/locale.gen 

取消 en_GB.UTF-8 en_US.UTF-8 zh_CN.UTF-8 的注释

1
sudo locale-gen

去掉 GUI

1
sudo raspi-config # Boot Options - Desktop / CLI - Console Autologin

接下来扩容

1
2
3
4
5
6
7
8
9
10
11
cp 2017-04-10-raspbian-jessie.img raspbian.img
qemu-img resize raspbian.img +6G

# 启动, 跟之前参数不一样
qemu-system-arm -kernel kernel-qemu-4.4.34-jessie -cpu arm1176 -m 256 -M versatilepb -serial stdio -append "root=/dev/sda2 rootfstype=ext4 rw" -hda 2017-04-10-raspbian-jessie.img -hdb raspbian.img -redir tcp:5022::22

sudo cfdisk /dev/sdb # 删掉 sdb2  建立新分区  pri - write

sudo resize2fs /dev/sdb2
sudo fsck -f /dev/sdb2 # 一路 y?
sudo halt # 关机
1
2
# 用新的 img 启动
qemu-system-arm -kernel kernel-qemu-4.4.34-jessie -cpu arm1176 -m 256 -M versatilepb -serial stdio -append "root=/dev/sda2 rootfstype=ext4 rw" -hda raspbian.img -redir tcp:5022::22

然后换源, 安装 vim 等等.

折腾虚拟网卡

1
2
3
4
5
6
7
sudo apt install uml-utilities
sudo tunctl -t tap0 -u azeria # -u 后面跟自己的用户名
sudo ifconfig tap0 172.16.0.1/24
ifconfig tap0

# 启动, 参数又不一样了
sudo qemu-system-arm -kernel ~/qemu_vms/kernel-qemu-4.4.34-jessie -cpu arm1176 -m 256 -M versatilepb -serial stdio -append "root=/dev/sda2 rootfstype=ext4 rw" -hda ~/qemu_vms/raspbian.img -net nic -net tap,ifname=tap0,script=no,downscript=no -no-reboot

进去之后在树莓派里面分配 ip

1
sudo ifconfig eth0 172.16.0.2/24

现在直接连接分配的 172.16.0.2 即可

1
2
# 好像无效, 管它呢先改了再说
sudo nano /etc/network/interfaces
1
2
3
4
5
# iface eth0 inet manual
iface eth0 inet static
address 172.16.0.2    
netmask 255.255.255.0
gateway 172.16.0.255
1
sudo nano /etc/dhcpcd.conf
1
2
3
4
interface eth0
static ip_address=172.16.0.2
static routers=172.16.0.255
static domain_name_servers=1.1.1.1

写个脚本方便启动

1
2
#!/bin/bash
sudo qemu-system-arm -kernel ~/qemu_vms/kernel-qemu-4.4.34-jessie -cpu arm1176 -m 256 -M versatilepb -serial stdio -append "root=/dev/sda2 rootfstype=ext4 rw" -hda ~/qemu_vms/raspbian.img -net nic -net tap,ifname=tap0,script=no,downscript=no -no-reboot

跑个 hello world 试一哈

1
vim hw.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.section .text
.global _start
.arm

// The program starts here in (32-bit) ARM mode.
_start:
    mov r0, #1               @ STDOUT
    adr r1, label            @ R1 = address of string
    mov r2, #12               @ R2 = size of string
    mov r7, #4               @ R7 = syscall number for 'write'
    svc #0                   @ invoke syscall
_exit:
    mov r7, #1               @ R7 = syscall number for 'exit'
    svc #0                   @ invoke syscall
label:
.string "azeria prpr\n"
1
2
3
as hw.s -o hw.o
ld hw.o -o hw
./hw

速查

看着真乱…

架构 处理器家族
ARMv1 ARM1
ARMv2 ARM2、ARM3
ARMv3 ARM6、ARM7
ARMv4 StrongARM、ARM7TDMI、ARM9TDMI
ARMv5 ARM7EJ、ARM9E、ARM10E、XScale
ARMv6 ARM11、ARM Cortex-M
ARMv7 ARM Cortex-A、ARM Cortex-M、ARM Cortex-R
ARMv8 Cortex-A35、Cortex-A50系列、Cortex-A72、Cortex-A73

List of ARM microarchitectures

字节序

fixed little-endian and data accesses

  • ARM3 之后默认大端
  • 可以切换
  • 由 CPSR 寄存器的第 9 bit 决定

寄存器

用户层可访问和控制前 16 个寄存器.

# 别名 用途
R0-R6 - 通用寄存器
R7 - Holds Syscall Number
R8-R10 - 通用寄存器
R11 FP 栈帧指针
R12 IP 内部程序调用
R13 SP 栈指针
R14 LR 链接寄存器(一般存放函数返回地址)
R15 PC 程序计数寄存器
R0 - 通用寄存器

指令

  • 1 Word = 4 Bytes
  • h = half
  • b = Byte
  • s = signed
1
2
3
4
5
6
7
8
9
10
11
ldr     @ Load Word
ldrh    @ Load unsigned Half Word
ldrsh   @ Load signed Half Word
ldrb    @ Load unsigned Byte
ldrsb   @ Load signed Bytes

str     @ Store Word
strh    @ Store unsigned Half Word
strsh   @ Store signed Half Word
strb    @ Store unsigned Byte
strsb   @ Store signed Byte

CPSR

标记 含义
N(Negative) 指令结果为负值时置1
Z(Zero) 指令结果为零值时置1
C(Carry) 对于加法有进位则置1, 对于减法有借位则置0
V(Overflow) 指令结果不能用32位的二进制补码存储, 即发生了溢出时置1
E(Endian) 小端序置0, 大端序置1
T(Thumb) 当为Thumb模式时置1, ARM模式置0
M(Mode) 当前的权限模式(用户态, 内核态)
J(Jazelle) 允许ARM处理器去以硬件执行java字节码的状态标示