# 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ố :

- stack frame của main trước khi gọi `caller`

- các thanh ghi quan trọng

- 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]!`

- `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


- `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`

-> 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
:::