Post

ARM Assembly

http://recipes.egloos.com/5027277

http://armconverter.com/- 주소 부분이 0xffffff???로 나올 때는 직접 수정해주면 된다.

  • ARM assembly instruction은 기본적인 명령어에 추가적인 옵션을 덧붙여 사용하는 식으로 구성되어 있다.
  • RISK라서 모든 instruction의 크기가 같다. 단, ARM mode와 Thumb mode로 나뉜다.
  • 연산 방향은
  • arg/return value pass에 레지스터 r0-r3와 stack을 사용한다.
  • i386/amd64와 달리 ARM에서는 pc에 접근해 인자로 사용할 수 있을 뿐만 아니라 수정할 수도 있다. 그러나 여기서도 push {pc}는 안된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int f(int i){
putchar('a');
putchar('\n');
return i;
}

  

int main(){
printf("%p\n", f);
\_\_asm\_\_ \_\_volatile\_\_(
"mov r0, #1         \n\t"    // pass arg
"bl  0x83f5         \n\t"    // call 0x83f5

  

//  "bl  f              \n\t"    // 0x83f5 == f

  

/\*  "ldr r2, =0x83f5    \n\t"
"blx r2             \n\t" \*/
);
printf("return back\n");
return 0;
}

shellcode를 만드는 경우, 쉘코드 실행을 마치고 원래 진행하던 부분으로 돌아갈 수 있게 push {lr} ... pop {pc}를 반드시 적어주어야 한다.

b / bl
1
2
3
4
5
6
b addr     // jmp addr
=>  mov pc, =dest
bl addr    // call addr
=>  mov lr, =next instruction (pc)    // lr == r14
=>  mov pc, =dest

bx / blx

x : exchange

1
2
3
bx  Rm
blx Rm || label

  • Rm의 비트[0]이 0일 경우 프로세서가 ARM 상태로 변경되거나 ARM 상태를 유지한다.
  • Rm의 비트[0]이 1일 경우 프로세서가 Thumb 상태로 변경되거나 Thumb 상태를 유지한다.
ldr(load) / str(store)

* str만 연산 방향이 반대. * Rn == pc일 때는 update를 방지하기 위해 write back 연산자 !를 사용할 수 없다.

1
2
3
4
5
6
7
8
9
10
11
str Rd, [Rn, #offset]    // \*(Rn+offset) = Rd's value
ldr Rd, [Rn, #offset]    // Rd's value = \*(Rn+offset)
ldr Rd, [Rn, #offset]!   // Rn=Rn+offset으로 update 후, Rd's value = \*(Rn)    {pre-indexed 방식}
ldr Rd, [Rn], #offset    // Rd = \*(Rn) 후, Rn = Rn+offset으로 update    {post-indexed 방식}

ldr Rd, 0x800a12ab       // Rd's value = \*0x800a12ab
// 아래는 pseudo-instruction. compile 시 위 형식 또는 mov...로 변환된다.
ldr Rd, =0x800a12ab      // Rd's value = 0x800a12ab
=>  mov Rd, #0x800a12ab  // 단, 직접 이렇게 넣으면 mov의 operand 크기 제한 때문에
// 제대로 동작하지 않을 수 있음. 그래서 pseudo-instruction이 있는 것.

NOP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[ARM A32] ( arm )
NOP          ==> 0x00000000
mov r0, r0   ==> 0xe1a00000
mov r1, r1   ==> 0xe1a01001
mov r2, r2   ==> 0xe1a02002
... r3-r9, sl, fp, ip, sp(r13), lr(r14)
mov pc, pc   ==> 0xe1a0f00f

  

[ARM T32 - 16 bit] ( Thumb )
NOP          ==> 0xb000
mov r8, r8   ==> 0x46c0

  

[ARM T32 - 32 bit] ( Thumb )
NOP          ==> 0xf3af 8000

  

[ARM A64 - 64 bit] ( ARMv8-A == AArch 64 )
NOP          ==> 0xd503201f

This post is licensed under CC BY 4.0 by the author.