2012. 12. 18. 23:32

ARM 쉘코드 만들기(To make shellcode in ARM architecture)



ARM 프로세서는 일반적인 32비트 인스트럭션 셋을 제공하는 ARM 모드와, 16비트 인스트럭션 셋을 제공하는 Thumb 모드가 있다모든ARM 프로세서가 Thumb 모드를 지원하진 않고 ARM7 TDMI처럼 프로세서 이름에 T가 들어있는 제품군이 Thumb 모드를 지원하게 된다.

(Ex. ARM8 ARM7T ARM9T StringARM...)


ARM 프로세서는 총 16개의 레지스터가 존재한다 (R0~ R15 +PC)


R13 이 바로 스택포인터(Stack Pointer)로 사용되어 지진다.


R14 가 링크레지스터(LR) 가 된다. 이 R14는 링크레지스터(LR)로 사용된다. 이 R14가 실제로 함수가 호출될 시 리턴 어드레스를 담고 있다. 


R15(Program Counter)는 다른 PCU에서 PC 와 같은 역할을 한다. 





ARM 중요 명령어 


BEQ 나 MOV종류의 명령어들은 모두 조건을 걸 수 있따.


SWI : Software Interrupt 의 약어로 X86프로세서에서의 INT 명령어에 해당한다.



STMFD : sp!, {r4-r6,lr}; 스택에 r4-r6 와 lr 레지스터를 저장하고 sp를 그만큼 감소 시킨다.

LDMFD : sp!, {r4-r6,pc}; 스택에서 r4-r6와 pc를 복원하고 sp를 그만큼 증가 시킨다.




이렇게 두가지 모드를 제공하는 이유는 열약한 환경에서의 최적화를 하기 위함이다.


ARM 쉘코드를 만들때의 특성

1.범용레지스터 : r0-r7


2.push / pop 에 대한 것을 잘 사용하지 않음


3. 최대 가능수치 : 255


4.레지스터 변위에 대한 제한

{R13, R14, R15, R16} = {sp,lr,pc,cpsr}


5.ARM <---> Thumb

Thumb 모드의 T비트는 CPSR 에서 1만큼 떨어져 있다.


6.Branch Exchange (bx addr) 

분기점은 BX로 처리한다.


7.파라미터값들은 r0,r1,r2.. 같이 범용 레시즈터를 사용 한다.


 .global main

main:

.CODE 32

add r2,pc,#1

bx r2

.CODE 16

thumb:



헤더의 참조는 /usr/src/linux/arch/arm/include/arm/unistd.h 와 같음

(X86 코드와 똑같다)




R7 레지스터가 함수 호출번호를 담당한다.

svc 를 통해 커널을 직접 호출가능하다.

return 형은 함수호출 이후 r0 레지스터에 저장된다.



PUSH POP 을사용하지 말고 직접 쓰라는 것은 아래예시를 비교해 보면 알 수 있다.





위에서보기에 왼쪽은 같은 코드도 push pop 으로 파라미터값을 조절했고 오른쪽은 레지스터에 직접 담어 호출하도록 되어 있다.

오른쪽처럼 코딩하는것을 권장 한다. 




널값 제거하기


쉘코드를 공격코드로 사용하려면 NULL 을 회피하는 방법을 알아야한다.

R0를 사용하면 NULL이 포함되어 저장이 된다. 이를 피하기위해 Phrack 58호에서 소개된 방법들이다.




 Orignal

 Brand New

 e3a0041    mov   r0,    #65

 e0411001  sub r1,r1,r1

 e2812041   add r2, r1, #65

 e1a00112   mov  r0, r2, lsl r1(r0 = r2<<0)

 

 systemcall


e28f1004  add r1,pc,#4 <- get address of swi

e0422002 sub r2,r2,r2

e5c12001 strb r2, [r1,#1]

ef90ff0b  swi 0x90ff0b

   
   
   





Posted by k1rha