FTZ level15 분기 루틴 2

2017. 5. 23. 14:39SystemHacking/FTZ

 

 

 

level15는 level14문제에서 int형 변수에서 포인터형 변수로 바뀌고 나머지는 모두 똑같은 문제입니다


바로 문제 풀이 시작하겠습니다

힌트파일에 attackme 실행파일의 소스가 들어있습니다

해당 파일을 tmp 디렉토리에 복사하고 컴파일 시킨후 gdb분석을 시작합니다

( gdb분석을 통해 각 변수들의 메모리 위치를 파악한다 )


< 그림 15.1 >


먼저 소스코드 실행 흐름을 파악해보겠습니다


< 그림 15.2 >


[1] Procedure Prelude

$0x38 = 56byte만큼의 공간을 지역변수에게 할당한다


[2] fgets()

fgets( buf , 45 , stdin )    45만큼의 문자열을 입력받고, buf에 저장한다

* buf의 시작주소를 알 수 있습니다 ( <main+27>에서 "0xbffffffc8" )


[3] cmpl

if ( *check == 0xdeadbeef ) 조건문

* check변수의 시작주소를 알 수 있습니다 ( <main+39>에서 "0xbfffffff0" )


[4] setreuid

setreuid( 3096 , 3096 )    level16의 권한을 가진다


[5] system()

system("/bin/sh")    [4]와 같이 작동하여 level16의 쉘이 떨어진다



## [2]번 [3]번 에서 buf와 check의 시작주소를 알아냈습니다

## 둘 사이의 간격은 0xbfffffff0 - 0xffffffc8 = 40byte 가 나옵니다

## buf의 크기 20byte와 dummy가 20byte만큼 존재함을 알수 있습니다

## 해당 스택 구조를 그림으로 그려보면 다음과 같습니다


< 그림 15.3 >


메모리 구조를 더 자세히 살펴보도록 하겠습니다


< 그림 15.4 >


fgets( buf , 45 , stdin ) 함수가 실행된 바로 직후에 Break를 걸어주었고, 현재 최상위 레지스터 esp레지스터에는 buf가 존재하고 있습니다

(gdb) x/30xw $esp 명령어를 통해 esp레지스터를 조사해보겠습니다


< 그림 15.5 >


[1] buf의 시작주소    "0xbffff820"

"0x41414141" 이 위치해있음을 보고 알 수 있습니다

해당 주소에 buf의 길이 20byte와 20byte의 dummy를 더해주면 check의 주소입니다


[2] check의 시작주소    "0xbffff848"

해당 주소에 존재하는 값을 출력해보면 "0xbffff858"이 출력됩니다

즉, *check는 "0xbffff858" 주소에 있는 값을 가르키게 됩니다


[3] RET의 시작주소    "0xbffff85c"

check의 시작주소에 check의 크기 + crap + dummy = 16byte를 더하면 RET의 주소가 나옵니다

해당 주소에 존재하는 값을 출력해보면 "0x42015574"가 출력됩니다


[4] SFP의 시작주소    "0xbffff858"

RET주소에서 4byte앞에 존재하는 SFP주소입니다. 해당 위치에 존재하는 값은 "0xbffff878"입니다




우리가 그린 스택그림과 일치하는 메모리 구조를 가지고 있음을 파악했습니다

이제 해당파일을 공격할 차례입니다. 공격방법은 다음과 같습니다


[1] 특정 위치에 "0xdeadbeef" 값을 위치시킵니다 ( 해당 값이 위치한 주소를 정확히 알아야합니다 )

[2] check변수의 앞까지 버퍼오버플로우시킵니다

[3] check변수에는 "0xdeadbeef" 값이 위치한 주소를 입력시킵니다

=> *check = "0xdeadbeef" 가 만족된다

[4] 조건이 만족되어 level16의 쉘이 떨어집니다


처음에 위의 방식으로 문제를 풀기 위해 다음과 같은 명령어를 입력했습니다


[level15 @ftz level15]$ (python -c 'print "\xef\xbe\xad\xde"+"A"*36+"buf의시작주소" ' ; cat ) | ./attackme 


위에서 구했던 buf의 시작주소는 임시로 만든 파일의 시작주소고 실제로 공격대상인 buf의 시작주소를 구해야 했습니다

하지만, BreakPoint지점을 정해주고 프로세스를 실행시키려고 했으나 권한이 막혀있어서 buf의 시작주소를 구할 수 가 없었습니다.



따라서 다른 방식을 사용하여 해당 문제를 풀도록 하겠습니다.

"0xdeadbeef" 문자를 직접 입력하는 것이아니라 이미 시스템내부에 존재하는 "0xdeadbeef" 문자열을 사용하는 것입니다

"0xdeadbeef" 문자열이 어디에 위치해 있는지 알아내봅시다


< 그림 15.6 >


해당 조건문에서 check가 가르키고 있는 메모리공간의 값과 "0xdeadbeef"값을 비교하고 있습니다

"0xdeadbeef" 문자열이 하드 코딩 되어있는 상태여서 프로그램 내부에 존재한다고 합니다 

해당 문자열이 존재하는 메모리 주소는 " 0x080484b2 " 입니다 !

그럼 공격코드를 작성해서 공격해보겠습니다


< 그림 15.7 >


buf와 dummy의 공간 40byte를 "A"문자 40개로 가득 채운다음 check의 메모리 공간에 "\xdeadbeef"가 존재하는 메모리주소를 덮어 씌웠습니다

공격이 성공한 모습을 확인 할 수 있습니다


문제풀이는 완료되었습니다. level16으로 넘어갑니다.


문제풀이에 다른 방식이 또 하나 있습니다 ! 바로 환경변수를 이용하는 방식입니다

환경변수를 이용한 버퍼오버플로우가 궁금하시면 해당 페이지로 이동하시면 잘 정리해놓았으니 참고하세요 여기 <<


< 그림 15.8 >

먼저 환경변수 " superEH " 를 선언하고 해당 환경변수에 " 0xdeadbeef " 를 저장합니다

그리고 " /tmp/getaddr " 실행파일은 위에 있는 링크에 설명해놨습니다 ( 환경변수의 주소를 얻어오는 실행파일 )

superEH 환경변수의 주소를 얻어왔습니다. 그럼 40바이트만큼 버퍼오버플로우 시킨 뒤 " check "변수의 주소공간에 덮어씌우면 공격성공입니다


환경변수를 이용한 버퍼오버플로우 공격은 매우 유용하다고 생각합니다. 


# 참고 #

 참고한 교재에서는 buf의 시작주소에 "\xdeadbeef"값을 입력하고 해당주소값을 check의 메모리 공간에 덮어씌워서 공격을 시도한다

 실제로 따라하려고 해봣지만 권한이 막혀있어서 해당 방법으로 문제를 풀 수가 없었다

 

 실행하는 파일명에 따라 주소값이 변한다는 개념 기억하자

 +의문점    : 코드에 printf 함수를 추가해서 해당 변수의 주소를 확인한 값과 gdb로 분석한 주소값이 다름 -> why??




'SystemHacking > FTZ' 카테고리의 다른 글

FTZ level17 포인터 변조 2  (0) 2017.05.28
FTZ level16 포인터 변조 1  (0) 2017.05.23
FTZ level14 분기루틴 1  (0) 2017.05.23
FTZ level13 스택 가드 ( Stack Guard )  (0) 2017.05.23
FTZ level12 Buffer OverFlow  (0) 2017.05.23