티스토리 뷰
checksec으로 보호기법을 확인해보면 NX + Canary를 찾을 수 있다.
물론 socket + fork로 돌아가는 환경이 아니기 때문에 ASLR도 유효하다.
간단하게 분석을 해보면 우리가 문자열을 입력하면 flag같이 생긴(?) 문자열로 만들어 준다.
1. Input Flag:
말 그대로 문자열을 입력해준다. userFlag를 malloc으로 256만큼 할당해서
uRead함수로 값을 받는다.
2, 3번은 생략
4. Leetify:
뜻이 따로 있는줄 알고 보니 없음..
우리가 입력한 문자열을 진짜 flag같이 만들어 준다.
예를 들어 A -> 4, O -> 0 과 같이 우리가 흔히 볼 수 있는
알파벳을 숫자로 바꿔서 표기하는 표기법을 직접 제공한다.
5. Add Prefix:
단순하게 "0ctf{" + userFlag + "}" 와 같이 만들어 준다고 보면 된다.
Vuln
4. Leetify는 위에서 설명했듯 어떤 문자를 숫자(char형)으로 바꿔주는 역할을 한다.
그런데 여기서 h 혹은 H를 정말 H같이 생긴 "1-1"로 바꿔주는데 중요한건 H를 모두
"1-1"로 바꿔주기 때문에 1바이트가 3바이트가 되는 현상을 볼 수 있다.
여기서 Overflow가 일어난다.
userFlag[x] = "1"
userFlag[x+1] = "-"
userFlag[x+2] = "1"
와 같은 알고리즘을 사용했다고 보면 된다.
물론 덮어씌어지지 않게 pSrc가 v5 + 2를 가르키게 한다.
하지만 여기서 세그멘테이션 오류가 난다.
원래 정상적이라면 stack_chk_fail()함수가 실행 돼야 하지만 단순히 세그폴트가 떳다.
트레이싱을 해보자
gdb로 디버깅을 해보면 저 부분은 strcpy부분인 것을 알 수 있다.
물론 Leetify함수 마지막 부분에 있는 strcpy에서 나는 것이다.
그런데 이 부분에서 세그폴트가 뜨는 것은 &src가 아니라 aFlag부분이 변조 돼서 일어나는 오류다.
Leetify는 인자로 aFlag를 받아서 문자열을 바꿔준 후 strcpy로 aFlag에 다시 넣어준다.
여기서 세그폴트가 뜨는 것이고 이 부분에서 알 수 있는 것은 우리가 argv[1]을 변조할 수 있으며
변조한 주소에 &src를 복사 할 수 있다는 것이다.
PWNING
다른 문제를 풀 때 풀이에서 본 stack_chk_fail() 함수를 덮어쓰는 방법을 선택했다.
쉬울줄 알았지만 트레이싱과 디버깅이 굉장히 많이 필요했던 문제였다.
일단 stack_chk_fail을 printf나 다른 함수로 바꿔준다.
그러면 카나리를 우회할 수 있다. 그 후에는 ROP를 해 주면 된다.
주의해야 할 점은 stack_chk_fail을 printf@plt로 바꿔주면
그 후 printf를 사용하지 못한다는 것이다. 이건 상황마다 다른것 같기도 한데
나는 디버깅을 할 때 printf@plt가 완전히 다른 값으로 바뀌어 진 것을 확인해서
LIBC주소를 LEAK할 때 puts함수를 사용하였다. 이 부분에서 많이 해메었다.. 디버깅을 열심히 합시다.
-> stack_chk_fail@got를 printf@plt만 들어가는 것이 아니라 뒤에 있는 문자열까지 들어가서
뒤에 있는 got함수들을 사용하지 못하는 거였습니다!
또한 read함수를 사용하여 system@libc의 인자가 될 문자열을 받으려 했으나
0x00이 들어가면 그 부분이 완전히 들어가지 않는 현상이 일어나서 uRead함수를 사용하였다.
read함수는 FD가 무조건 0x00이 돼야 하지만 uREAD는 BUf와 SIZE만 정해주면 되기 때문에 사용할 수 있다.
트레이싱을 해보면 printf@plt로 덮어쓴 stack_chk_fail()함수가 처음 실행 된 후
그 다음 실행되는 함수는 stack_chk_fail()함수가 위치하는 바로 전 4바이트 이다.
[*] 왜 그런지는 모르겠다.. 디버깅을 더 해봐야겠다.
주의해야 할 점이 너무 많지만 그 점만 감안하면 ROP자체는 매우 쉬운 편이다.
LIBC를 LEAK하고 SYSTEM함수의 주소를 구한 후 read로 받은 인자와 함께 실행시켜 주기만 하면
Exploit에 성공 할 수 있다.
좀 어렵게 푼 감이 있다. 확실히 트레이싱과 디버깅이 중요하다는 것을 깨달았다.
공부가 많이 부족한 거 같다.. 조금 더 열심히 하도록 하자
조금 어려운 문제들은 대부분 ret를 직접 바꾸는 것이 없는 것 같다. 또한 기본적인 ROP를 방해하는
요소들도 곳곳에 숨어 있다. 조금 더 꼼꼼한 분석과 디버깅을 하자
'Pwnable > CTF' 카테고리의 다른 글
CampCTF 2015 hacker_level exponly (1) | 2015.08.25 |
---|---|
Inc0gnito 2015 anti-hexray exponly (0) | 2015.08.25 |
Plaid CTF 2014 [Kappa] (2) | 2015.04.06 |
CODEGATE 2015 JUNIOR [ SYSTEMSHOCK ] (0) | 2015.03.28 |
CODEGATE 2015 JUNIOR 예선 WRITE UP (0) | 2015.03.16 |