hint
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
void shellout(void);
int main()
{
char string[100];
int check;
int x = 0;
int count = 0;
fd_set fds;
printf("Enter your command: ");
fflush(stdout);
while(1)
{
if(count >= 100)
printf("what are you trying to do?\n");
if(check == 0xdeadbeef)
shellout();
else
{
FD_ZERO(&fds);
FD_SET(STDIN_FILENO,&fds);
if(select(FD_SETSIZE, &fds, NULL, NULL, NULL) >= 1)
{
if(FD_ISSET(fileno(stdin),&fds))
{
read(fileno(stdin),&x,1);
switch(x)
{
case '\r':
case '\n':
printf("\a");
break;
case 0x08:
count--;
printf("\b \b");
break;
default:
string[count] = x;
count++;
break;
}
}
}
}
}
}
void shellout(void)
{
setreuid(3099,3099);
execl("/bin/sh","sh",NULL);
}
풀이
1. 간략하게 이해해 보면 count가 0부터 시작해서 100이 되면 프로그램을 끝낸다. 이 count는 밑에 switch문의 default에서 증가시켜 준다.
또, 아래쪽 분기문에는 파일 디스크립터와 표준 입력이 나오는데 뭔가 키보드 입력을 가지고 분기한다는 것을 알 수 있다.
switch문에는 세가지가 있는데, 0x08을 입력한 경우엔 카운트 값을 감소시키고 default에서는 string[count]의 위치에 표준 입력으로 입력한 값을 넣고 카운트를 증가시킨다.
마지막으로 check변수가 0xdeadbeef가 되면 shellout()이라는 함수로 이동시키며 level19의 쉘을 얻게 해준다.
gdb를 이용해서 스택 구조를 보면 다음과 같다.
low address ... fds | dummy | count | x | check | string[100] | dummy(20) | sfp | ret | ... high address
2. 처음에는 0x08을 12개 입력하고 다음으로 음수를 입력하여 count를 -200 정도로로 변경 하고 x값을 그대로 적어주고 check+string[100]+dummy(20)+sfp 만큼의 쓰레기값을 입력하고 마지막으로 shellout()의 주소를 ret에 적어주려고 삽을 준비했는데,
이럴바엔 0x08을 4개 입력하여 string[-4]에 0xdeadbeef를 차례대로 넣어주면 된다는걸 깨달았다.
'WARGAME > hackerschool ftz,lob' 카테고리의 다른 글
[해커스쿨 ftz] level 20 -> Clear (0) | 2014.08.29 |
---|---|
[해커스쿨 ftz] level 19 -> level 20 (0) | 2014.08.23 |
[해커스쿨 ftz] level 17 -> level 18 (0) | 2014.08.23 |
[해커스쿨 ftz] level 16 -> level 17 (0) | 2014.08.22 |
[해커스쿨 ftz] level 15 -> level 16 (0) | 2014.08.22 |