#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; //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) // check안에 0xdeadbeef가 입력되어 있을 시 shelldout()함수 실행 shellout(); else { FD_ZERO(&fds); // fds의 소켓셋을 비움 FD_SET(STDIN_FILENO,&fds); //소켓셋에 표준입력 fd number 추가 if(select(FD_SETSIZE, &fds, NULL, NULL, NULL) >= 1) // 이 부분에서 입력이 되는것으로 추정... { if(FD_ISSET(fileno(stdin),&fds)) { read(fileno(stdin),&x,1); switch(x) { case '\r': //carrage return이나 이걸뭐라하더라 에....암튼 띄어쓰기 문자가 나오면 \a를 출력함 case '\n': printf("\a"); break; case 0x08: //0x8이 입력되면 count는 -1이 되고 아래 \b을 두번 출력 count--; printf("\b \b"); break; default: //그게아닌 남은 모든것은 string의 count인덱스가 가리키는곳에 x의 값을 집어넣고 count증가 string[count] = x; count++; break; } } } } } } void shellout(void) { setreuid(3099,3099); execl("/bin/sh","sh",NULL); }
소스가 참 길고 어렵네요 저에겐 조금 많이 어려운 소스였습니다.
분명 입력은 이루어지고 check에 0xdeadbeef가 들어있으면 shellout함수를 실행해 권한이상승되고 쉘을 얻을 수 있습니다.
이 문제는 음…코드 이해력을 가장 많이 필요로 하네요 삽질을 쫌 했습니다
Check에 0xdeadbeef만 있음 되니 이제 디버깅을 하며 메모리에 변수 위치들을 파악만 하면 될거같습니다..
Ebp-0x6c와 ebp-0x70부분에 0이 들어가고 0xfc에 eax만큼 공간을 할당합니다 아마 string과 dummy일것입니다
중요한 건 가장 아래에 ebp-0x68부분에 0xdeadbeef와 비교를 하는건데요 그렇다면 추측을 해보면 스택의 위치는 대강 이렇게 나옵니다.
그렇다면 우리는 string에 count의 위치만큼 입력을 받으니 이것과 0x08을 이용해 string의 인덱스를 “ –4”만큼 이동하여 string[-4]부터 0xdeadbeef를 입력받으면 check에 0xdeadbeef가 들어가게 되는 셈입니다. 어차피 -4부터 switch문으로 count는 1씩 증가할 테니 -4 -3 -2 -1에 입력이 될것입니다.
이제 입력을 받게 되면 그만이겠네요, 그리고 select는 gets함수와 비슷한 방식으로 입력을 받더군요
./attackme $(perl –e ‘print )…이런 식이 아니라
(perl –e ‘print….”’;cat)|./attackme 이런식으로 입력을 받아야 합니다
그럼 이렇게 입력을 하게 된다면 쉘이 떠오를 것입니다
이렇게 level18을 클리어 했지만 좀 가장 많이 아쉬움이 남는 문제였습니다.
소스 분석력이 많이 떨어진다고 느끼는 단계였습니다.
Phantom@TeamH4C