FTZ level14 분기루틴 1

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

 

 

 

level14 에서는 특별한 함수나 개념은 없고, level13 스택가드 문제와 비슷한 개념의 문제입니다


바로 문제 풀이에 들어가겠습니다. 우선 힌트를 열어봅시다


< 그림 14.1 >


공격대상인 attackme의 코드를 옮겨 놓은 모습입니다. 특별히 어려운 코드는 없어보입니다

스택가드와 비슷한형태로 check변수의 값을 비교해서 프로세스를 실행할지 말지의 여부가 결정됩니다

힌트파일의 소스를 복사해서 새로운 실행파일을 만들어 줍시다

( attackme파일에 break를걸어주고 파일을 실행할 권한이 제한되어 있습니다.. )


< 그림 14.2 >


해당 소스파일을 컴파일 시키고 gdb를 실행시켜줍시다


< 그림 14.3 >


메인 함수를 디스어셈블하고 프로세스의 흐름을 읽어보도록 하겠습니다


< 그림 14.4 >


[1] Procedure Prelude

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

buf( 20byte ) + check(4byte) + crap(4byte) = 28byte    / 따라서 28byte만큼의 dummy가 존재함을 알 수 있습니다


[2] fgets()

fgets( buf , 45 , stdin )        45byte만큼의 입력을 받을 수 있고 입력한 내용은 buf변수에 저장된다


[3] setreuid()

setreuid( 3095 , 3095 )        프로세스 실행하는 동안에 level15의 권한을 가진다


[4] system()

system( "/bin/sh" )            쉘을 실행합니다 ( [3]함수에 의해서 level15의 쉘이 떨어짐 ) 



여기서 ! 가장 중요한 부분이 있습니다 바로 " <main+27>:lea " 부분과 " <main+39>:cmpl " 부분입니다


 어셈블러 lea : 0xffffffc8(%ebp), %eax

0xffffffc8 의 메모리 주소를 eax레지스터로 주소를 변경하라는 어셈블러입니다

0xffffffc8 해당 주소는 무엇일까요?  fgets함수의 인자로 들어가는 buf의 주소입니다


 어셈블러 cmpl : $0xdeadbeef, 0xfffffff0(%ebp)

0xfffffff0 주소에 있는 값과 16진수 0xdeadbeef 를 서로 비교하는 어셈블러입니다

0xfffffff0 주소는 무엇일까요? check변수의 주소입니다!



프로세스가 진행될 때 해당 변수들이 각 주소에 위치해 있습니다. 

이 두 주소사이의 간격을 통해서 두 변수사이의 dummy가 얼마만큼의 공간을 차지하고 있는지 알 수 있습니다

0xfffffff0 (check) - 0xffffffc8 (buf) = 40byte = buf 20byte + dummy 20byte

결과적으로, 두 변수 사이에 dummy가 20byte가 존재함을 알 수 있습니다


메모리의 스택의 구조를 그려보면 다음과 같다. attack.c 소스코드파일에 printf("%x", &crap ) 추가해서 crap과 dummy 의 위치 관계를 알아 낼 수있지만,  실제 해킹에서는 소스코드를 알 수 없으므로 비현실적입니다

그러므로 gdb를 통해서 어떻게 둘 사이의 위치관계를 알아 낼 수 있을지 고민해보고 알아내서 다시 블로깅 하겠습니다.


< 그림 14.5 >


해당 프로세스에 브레이크를 적절한 지점에 걸어주고 메모리 구조를 더 자세히 분석해보겠습니다


< 그림 14.6 >


fgets함수로 buf에 입력값을 저장한 바로 직후에 브레이크를 걸어주었습니다

따라서 스택의 최상위 레지스터인 esp 에는 buf가 위치해 있을겁니다

(gdb) x/20xw $esp 명령어로 확인 하고 메모리 구조를 파악해 보겠습니다 ㅡ 그림 14.7


< 그림 14.7 >


[1] buf의 시작주소 : " 0xbfffe9a0 "

0x41414141 입력한 문자열이 위치해있는 것이 보입니다


[2] check의 시작주소 : " 0xbfffe9c8 "

buf의 시작주소에서 buf의 길이와 dummy의 크기의 합 40byte를 더해주면 check변수의 주소가 된다

(gdb) x/x 0xbfffe9c8 명령어로 check변수의 값을 출력하면 [2]번상자의 값이 출력된다

[2]번 상자의 위치는 check변수의 위치이다


[3]  RET의 주소 : " 0xbfffe9dc "

check의 시작주소에서 check(4byte) + crap(4byte) + dummy(8byte) + SFP(4byte) = 20byte를 더해주면 RET주소가 된다

(gdb) x/x 0xbfffe9dc 명령어로 RET주소값을 출력하면 [3]번 상자의 값이 출력된다 

[3]번 상자의 위치는 RET의 위치이다


해당 프로세스의 디버깅 작업은 모두 끝났고 이제 attackme 파일을 공격해보자


[ 공격방법 ]

 1. buf(20byte) + dummy(20byte) 를 버퍼오버플로우 시킨다

 2. check변수에 "0xdeadbeef" 값을 넣는다

 3. 조건이 만족되어 level14의 쉘이 떨어진다     // end

 RET주소를 변질시키려면..? 

 4. 남아있는 crap(4byte) + dummy(8byte) 를 버퍼오버플로우 시킨다

 5. RET주소에 원하는 메모리 주소값을 덮어 씌운다 



이제 실제로 공격을 시도해보겠습니다.

직접 40byte를 입력하고 0xdeadbeef를 입력해도 되지만 python문법을 이용해서 공격을 시도하겠습니다 


< 그림 14.8 >


level15의 쉘이 떨어진 것을 확인 할 수 있습니다 !


이상 level14 번 문제풀이를 마치겠습니다