---
# System prepended metadata

title: ARM
tags: [ARM]

---

# ARM 
## I. Build binary và run binary 
### Build 
- 32bit : `arm-linux-gnueabi-gcc -o arm32 source.c`
- 64bit : `aarch64-linux-gnu-gcc -o arm64 source.c`
-> các option `PIE`, `RELRO` giống như trong AMD
### Run
- 32bit : `qemu-arm -L /usr/arm-linux-gnueabi ./arm32`
- 64bit : `qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./arm64`
## II. Debug binary
### Build docker ARM64 
```
sudo docker build --platform linux/arm64 -t demo .
sudo docker run --rm -p 1234:1234 -it --platform linux/arm64 {ID_images}
```
### Debug static 
- Terminal 1 : 
    ```
    qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu/ ./chall
    ```
    hoặc (với 32-bit)
    ```
    qemu-arm -g 1234 -L /usr/arm-linux-gnueabi ./arm32
    ```
- Terminal 2 : 
    ```
    gdb-multiarch ./chall
    target remote 0:1234
    ```
### Debug động
- script : 
    ```py
    def main():
        context.binary = exe = ELF('./chall',checksec=False)
        # p = process(exe.path)
        p = process(["qemu-aarch64", "-g", "1234", "-L", "/home/dynhlucw/pwnable/Wargame/pwnCollege/ropARM/level1.0", './chall'])
        GDB(p)
        sl(p,b'AAAA')
        p.interactive()
    ```
    -> Không muốn DEBUG thì comment dòng `qemu-aarch64` -> chạy `process(exe.path)`
- Terminal 1 : 
    ```
    python3 solve.py
    ```
    -> GDB attach mở -> `target remote 0:1234`
## III. ARM 32-bit exploitation 
### 1. Thanh ghi 
- `r1-r6` : Các thanh ghi chung 
- `r0` : Giống eax, lưu giá trị trả về 
- `r7` : lưu syscall number 
- `r11` : frame pointer (giống ebp) = `fp`
- `r12` : intra procedural call = `ip`
- `r13` : stack pointer (giống esp) = `sp`
- `r14` : link register -> Chứa return address của hàm con. = `lr`
- `r15` : program counter -> trỏ đên lệnh tiếp theo = `pc`
- `cpsr` 
### 2. Load and store instructions
- `LDR R1, [R2]` 
- `STR R1, [R0]`
### 3. Stack
- push, pop -> push {r1,r2} = push {r2} -> push {r1}
### 4. function and calling convention 
```clikes!
# source.c

#include<stdio.h>
#include<stdlib.h>
void setup() {
	setvbuf(stdin, NULL, _IONBF, 0);
	setvbuf(stdout, NULL, _IONBF, 0);
	setvbuf(stderr, NULL, _IONBF, 0);
}
void callee(){
    char buf1[0x10] ;
    printf("Enter input for callee: ") ;
    fgets(buf1,0x10,stdin) ;
}
void caller(){
    char buf2[0x30] ;
    printf("Enter input for caller: ") ;
    fgets(buf2,0x10,stdin) ;
    callee() ;

}
int main(){
    setup();
    char buf3[0x50] ;
    caller() ;
    return 0 ;
}
```
#### Debug
- Hàm lấy đối số : 
    ![image](https://hackmd.io/_uploads/ByX0JS9Kkl.png)
- stack frame của main trước khi gọi `caller`
    ![image](https://hackmd.io/_uploads/HJQ7lHctJx.png)
- các thanh ghi quan trọng
    ![image](https://hackmd.io/_uploads/BJnJGH5Fke.png)
    - sp = esp 
    - r11 = fp = ebp 
    - pc = eip 
    - lr : lưu return address
- Các lệnh tạo và kết thúc 1 frame
    ```asm
    0x00010664 <+0>:     push    {r11, lr}
    0x00010668 <+4>:     add     r11, sp, #4
    ------------------------------------------
    -> push return addr -> push frame pointer
    ```
    
    ```asm
    0x106c4 <caller+96>     sub    sp, fp, #4          SP => 0x407fff58 (0x407fff5c - 0x4)
   0x106c8 <caller+100>    pop    {fp, pc}                    <main+36>
   -------------------------------------------
   sp = fp - 4
   pop fp -> pop pc 
    ```
### 5. ROP chain trong arm32

## IV. ARM 64-bit exploitation  
### Thanh ghi 
- `x0` : lưu địa chỉ trả về
- `x0 - x7` : đối số cho hàm
- `x8 - x18` : thanh ghi chung
- `x19 - x28` : callee-saved registers 
- `x29` = `fp` : giống `rbp` 
- `x30` = `lr` : lưu `return address`
- `x31` = `sp` : giống `rsp` 
- `pc` : giống `RIP`
### Lệnh ASM
### Function và calling convention
- lệnh `ret` : nhảy tới địa chỉ được lưu trong thanh ghi `x30` (`Link Register` - `LR`)
- Các lệnh gọi hàm: `BL`, `BLR`, `BR`
    - `BL` (Branch with Link) : nhảy đến hàm, lưu return address ở `x30` (gọi hàm có địa chỉ cố định)
    - `BLR` (Branch with Link to Register) : nhảy đến địa chỉ lưu ở thanh ghi (ví dụ: blr x9, ...)
    - `BR` (Branch to Register) : nhảy đến địa chỉ trong thanh ghi nhưng không lưu `return address` vào `x30` hay `LR`
#### calling convention
- `stp x29, x30, [sp, #-80]!` 
    ![image](https://hackmd.io/_uploads/SyhcY8cKkg.png)
    - `stp` = store pair : `sub sp, -0x50` -> lưu `x29` vào `[sp]` -> lưu `x30`(`LR`) vào `[sp+8]`  
- `mov    x29, sp` : mục đích để tạo frame cho 1 hàm, tuy nhiên frame trong arm64 ngược lại so với amd64
    ![image](https://hackmd.io/_uploads/HyXm6IcY1g.png)
    ![image](https://hackmd.io/_uploads/rkHOpLcYyg.png)
- `ldp    x29, x30, [sp], #0x30` : khôi phục lại x30, x29
    - `ldp` = load pair : load giá trị [sp+0x30] vào `x29` và [sp+0x38] vào `x30`
- `ret` = `BR x30` : nhảy đến địa chỉ lưu ở `x30`

### ARM64 Rop chain
#### 1. Lấy libc_base address
- Sau khi leak được 1 địa chỉ từ libc, ta cần tìm offset để tìm được libc_base
1. Tắt `ASLR` ở tất cả Terminal -> để làm cho địa chỉ cố định
2. Tìm `libc_base` cố định
    - chạy `binary` -> chờ nhập `input`
    `qemu-aarch64 -L /home/dynhlucw/pwnable/CTFs/wpictf2021/strong-arm ./arm_patched`
    - Đọc `infor proc maps` của tiến trình này : 
        - Lấy pid : `ps aux`
        - Sau đó lấy `pid` của tiến trình -> `cat /proc/{pid}/maps`
        ![image](https://hackmd.io/_uploads/SyHFEN191l.png)
    -> Từ đấy sẽ có được `libc_base`
#### 2. Đặt break point khi bật PIE
- Từ lấy `libc_base`, ta cũng có thể tắt `ASLR` để coi như tắt `PIE`
#### 3. Tìm gadget để ROP
- Vì ARM64 sẽ call `x30-lr` để nhảy vào 1 hàm khác -> được xem như return address.
- Ngoài ra, để nhảy còn có các lệnh call hàm như : `bl`, `blr`, `br`
- Cần tìm các gadget : `MOV`, `LDR` và `LDP` -> để load các giá trị vào các thanh ghi

:::success
- **Workflow để call system("/bin/sh\x00")** 
    - load địa chỉ `/bin/sh` vào `x0` hoặc gián tiếp rồi đưa vào `x0`
    - load địa chỉ system vào thanh ghi nào đó để mục tiêu call thanh ghi đó 
    - dùng `bl`, `br`, `blr` để call thanh ghi 

- **Tư duy ngược**
    - Nghĩ làm sao để call system bằng thanh ghi nào trước
    - Lần theo đó để load vào thanh ghi chọn để call system
:::