cgy12306

Holyshield CTF jmper Write-up 본문

CTF Write-up

Holyshield CTF jmper Write-up

cgy12306 2019. 10. 31. 15:16
IDA로 바이너리를 분석해보자.


off_202010이 있는 값을 qword_202060[29]에 넣는다. 

off_202010에는 printf 함수에 대한 정보를 갖고 있다.




getchar로 입력받은 값이 문자 '1'이이 아니면 break로 반복문을 빠져 나오고, 문자 '2'이면 다시 반복문을 빠져나온다.

setjmp 함수는 호출 당하기 전의 스택 상황을 환경 변수에 저장 했다가 longjmp 함수가 호출되면 환경 변수에 저장해놨던 값을 다시 불러온다.

setjmp는 무조건 return 값을 0을 반환하기 때문에 !로 참을 만들어 줬다.

이후 sub_95A 함수를 호출한다. 인자로는 qword_202060을 넘긴다.

sub_95A 함수의 내부이다.


gets로 a1에 값을 받는다. a1의 문자열에 'n'이 있는지 검증한다.

이후 qword_202060[29], 즉 printf 함수를 호출 한다.

호출 후에 longjmp를 호출한다.

longjmp 내부에 들어가 보면


이 부분이 보일 것이다.

rip + 0x2016a4 지점의 주소를 rax에 넣는다.

rax 영역은 qword_202060가 있는 영역이다.

rax+ 0xe8 지점을 rdx에 넣고, rdx를 call 한다.

gets에서 문자열의 길이를 검증하지 않으니 이 부분을 조종해서 원하는 함수를 호출할 수 있을 것이다.

A를 0xe8개와 B를 6개 넣어봤다.






현재 알아낸 정보까지 코드를 작성해 봤다. (plt랑 got는 무시...)


B가 들어간 부분이 rip에 들어가게 된다.

이제 leak 할 부분을 찾아야 하는데 PIE 기법이 걸려있어서 일반적인 방법으로는 힘들다.




하지만 이 부분에서 printf 함수를 호출하게 되는데 a1을 호출하기 때문에 FSB 기법을 사용할 수 있게 된다.

%lx를 입력해서 주소를 알아내고 libc base의 offset을 계산해서 libc가 PIE 기법으로 인해 주소가 변경돼도 같은 함수를 찾을 수 있게 해준다.


printf로 찍어낸 주소와 현재 libc base의 주소를 빼서 offset을 구했다.




system 함수의 offset을 구했다.

여기서 주의할 점은 printf로 주소를 찍어내도 recv를 string으로 받기 때문에 이 string을 hex로 변경해줘야 한다.

이제 두번째 입력 때 rip를 조종하면 된다.

rip에 system을 호출하는 주소를 넣는다.

system의 인자안에 /bin/sh을 넣어줘야 하는데 n은 필터링이 걸려있어서 종료가 된다.

이럴땐 와일드 카드를 이용하면 된다.

?를 입력하면 한 글자에 아무런 값이 들어가도 된다는 뜻이다.
*를 입력하면 길이에 제한되지 않고 아무런 값이 들어갈 수 있게 된다.

/bin/sh ==> /bi?/sh

뒤에 NULL문자도 넣어줘야 strchr에서 /bin/sh만 읽어들인다. 

NULL문자를 넣지 않으면 뒤에 A도 읽어온다. 

최종 페이로드는 아래와 같다.



'CTF Write-up' 카테고리의 다른 글

WITHCON 2016 malloc  (0) 2020.04.18
Codegate 2016 floppy  (0) 2020.04.18
Codegate 2017 Angrybird  (0) 2020.03.02
Rooters CTF ch03 Write-up  (0) 2019.10.31
Rooters CTF vuln Write-up  (0) 2019.10.31
Comments