본문으로 바로가기
반응형
━[Document Infomation] ━━━━━━━━━━━━━━━━━━━━━
 :: Title  :: 제 3회 순천향대학교 정보보호 페스티벌 보고서
 :: Date   :: 2005. 11. 28
 :: Author :: singi
 :: Contact:: E-Mail : sjh21a@hotmail.com
              Homepage : http://work.hackerschool.org/~sjh21a
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


━[Index] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
0x00. 대회 시작.
0x01. Level1 (정보보안 기본 지식을 묻는 문제)
0x02. Level2 (특수문자로 이루어진 디렉토리 접근/Race Condition 기본 문제)
0x03. Level3 (4차 방정식을 풀어서, 나온 값들을 프로그램에 입력)
0x04. Level4 (simple reversing)
0x05. Level5 (guessing & simple cookie sniffing & spoofing)
0x06. Level6 (IP header checksum calculation)
0x07. Level7 (simple sql query injection)
0x08. Level8 (hard cracking (simple?))
0x09. 마치면서.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━




━[0x00. 대회시작]━━━━━━━━━━━━━━━━━━━━━━━━━━━

사실 전 대회 참가 목적이 새로 바꾼 닉네임 홍보용(?) 으로 출전 했는데

본의 아니게 입상까지 하게 되었네요..참..OTL

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

━[0x01. Level1]━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Level1은 정보보안에 관한 기초지식을 묻는 문제였습니다.

총 20문제였는데, 그 중 18문제를 맞쳐야만 통과 가능 했습니다.

자신 했던 문제들도 구글링과 텀즈를 이용해 검색하니 틀린 것이 많았습니다.

잘 알고 있던 문제들도 자신감 없게 만드는 그런 무서운 문제였습니다.

제일 기억에 남는 문제는

네트워크장비에 대한 문제들이였는데 몰랐던 부분을 알 수 있었습니다.

자세한 문제는 기억이 나지 않지만, 

서로 다른 프로토콜 간에 통신을 위해서 어떤 장비가 쓰이는지.

snmp 의 취약점이 아닌 것은 무엇인지.

sis 필기과목이 아닌 것.

메시지인증을 하는 이유로 알맞은 것은 대략 이정도 였습니다.

문제는 복사를 해놓질 않아서 생각이 나질 않는군요.

꽤 오랜 찍기 끝에 Level2 로 접근 할 수 있게 되었습니다.

pass : no surprise
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


━[0x02. Level2]━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Level2는 특수문자로 만들어진 방에 접근 하는 방법과 password 가 담긴

파일을 읽어내는 문제였습니다.

로그인을 해보니, Hint는 

“건망증이 심한 김모씨는 자신이 자주 쓰는 비밀번호를 잘 잊어버려서 자신만의
 ‘비밀의 방’에 꼭꼭 숨겨 두었다. 그런데 건망증이 심해 자기가 만들어놓은
 방에 들어가지 못하는 것이다. 김모씨의 비밀번호를 찾아주세요~!

이었습니다.

일단 vi 와 ls 명령으로 디렉토리들을 살펴 보니 기본 디렉토리 외에 ^B, ^V, ? 라는 디렉토리들이 존재 했습니다.

vi 로 특수문자로 이루어진 방을 조사해본 결과 ^B 라는 디렉토리에  비밀의 방이라는 디렉토리가 있고

그안에 passwd 라는 파일이 있고 이것을 읽어야 다음 레벨로 진입이 가능 했습니다.

이 passwd 파일의 기본 퍼미션은 

-r--r----- root     root   passwd ???? 

일반적인 상식으론 접근 할 수 없습니다. 일단 이 문제는 보류 하고 vi 를 이용해서가 아닌

직접 특수문자 디렉토리에 접근 했습니다.

cd 명령에 perl 을 조금 섞어주면 되는데.

cd `perl -e 'print "\x??"'` 이런식으로 ?? 에 맞는 16진수 문자를 입력하면 됩니다.

^B 와 ^V 였으므로, 16진수 표에서

^B = 02, ^V = 16 입니다.

chamber of secret 디렉토리의 이름 뒤엔 스페이스가 많았지만, 간단하게 tab을 눌러줌으로써 커버했습니다.

여전히 passwd 파일의 퍼미션은 변경되지 않았고(제가 보고 있었을때만ㅠ) tmp 나 .sys 같은 디렉토리가 보였습니다.

게시판에 질문을 통해서, "특정 상황이 될 때 읽을 수 있다" 라는 힌트를 얻은 뒤

race condition 을 생각 했습니다. 바로 간단한 소스를 만들어서 실행을 시켰습니다. 소스는

1번
#include <stdio.h>
int main()
{
while(1) {
system("cat ../../password");
}
}
와 

2번
#include <stdio.h>

int main()
{
while(1) {
symlink("../../password","pass");
unlink("./pass");
}
}
(혹시 몰라서 2개 다 돌렸습니다)

조금 후에 터미널 창에 아래와 같은 메시지가 출력이 되었습니다.


good job :)

password is "info security"

패스워드 메세지를 쉽게 보려면

$ ./1 2>/dev/null <-- 명령어

깨끗하게 패스워드만 출력 됩니다.

pass : info security

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


━[0x03. Level3]━━━━━━━━━━━━━━━━━━━━━━━━━━━━

레벨3에 진입하면 level3이라는 프로그램과 약간의 Hint가 있었습니다.

Hint의 내용은

x*x*x*x - 34*x*x*x - 340*x*x + 1858*x + 12915

        a < b < c < d

이런 내용이었습니다. 

        "a < b < c < d" 의 조건을 만족해야 패스워드가 나온 다는 것을 알았습니다.

level3 이라는 프로그램은 프로그램 실행 중에 특정 시그널 ctrl+c, ctrl+z, ctrl+\ 을

입력하면 ctrl+c = a--, ctrl+z = c++, ctrl+\ = b-- 그리고 d의 값은 0~60 까지 증가 됩니다.

d가 60이 되면 프로그램은 종료가 되지요.

*특정 시그널은 c,z 는 손으로 알아내고, \ 를 프로그램을 사용 했습니다.*

*제가 2,3,4 레벨의 발표를 맡았기 때문에 그쪽에 소스를 첨부하도록 하겠습니다.*

게시판의 질문의 답을 보니 4차 방정식의 근을 구하라는 문제였습니다.

(자수해서 광명 찾자 -_-;)

하지만 전 솔직히 2차 방정식도 모릅니다. 그래서 많은 공학도분들이 사용하신다는 mathematica 라는 프로그램으로

위의 방정식의 근을 구했습니다. 나온 결과는 {{x -> -9}, {x -> -5}, {x -> 7}, {x -> 41}}

즉, a < b < c < d 조건을 통해서 a=-9, b=-5, c=7, d=41 가 됩니다.

a 값은 ctrl+c 를 9번 눌러서 -9로 맞춰주고, b 와 c도 마찬가지 방법으로 맞쳐 줍니다. 

21초 안에 입력을 해야 합니다.  그리고 이제 이 d 값이 41이 되면 다음 레벨의 패스워드가 출력 됩니다.

pass : rage against the cracker

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


━[0x04. Level4]━━━━━━━━━━━━━━━━━━━━━━━━━━━━

level4에 진입해 보니 특정 파일을 내려 받았습니다.

프로그램을 다운 받고, 실행 시켜 보니 ip 를 입력 하라는 문구가 보였습니다.

아무리 입력을 해도 아무 반응이 없어서, ollydbg 로 프로그램을 뜯어보게 되었습니다.

일단 search for -> all referenced text strings 를 사용해서

프로그램에서 사용하고 있는 문자열들을 보았습니다.

0592842722, 2027148262, 2320512323, 2221114222 와

HTTPTEST, .index.bak, GET, index.html, GET

등과 같은 정보를 보았습니다. 프로그램 을 실행 시켰을 때 위쪽에 뜨는

"Get Index!!" 라는 이름과 연관지어 생각해 본 결과 level4 프로그램은 특정 ip 에 접속 해서

.index.bak 과 index.html을 받아오는 프로그램으로 예상했습니다.

그런 후 ASCII "0592842722" 에 break point 를 걸어서 프로그램을 실행 시켰습니다. (f9)

00401D9E  |. E8 6CF2FFFF    CALL level4.0040100F

부분에서 프로그램이 실행 되었습니다. 창에다가 아무 문자나, 숫자를 입력해 보았습니다.

그러면 위에서 break point(bp) 를 설정한 곳에서 멈추게 되는데,

004012D0  |. 68 8C004200    PUSH level4.0042008C                     ;  ASCII "0592842722"
004012D5  |. 8D95 D403FEFF  LEA EDX,DWORD PTR SS:[EBP+FFFE03D4]
004012DB  |. 52             PUSH EDX
004012DC  |. E8 8F070000    CALL level4.00401A70
004012E1  |. 83C4 08        ADD ESP,8
004012E4  |. 68 7C004200    PUSH level4.0042007C                     ;  ASCII "2027148262"
004012E9  |. 8D85 DE03FEFF  LEA EAX,DWORD PTR SS:[EBP+FFFE03DE]
004012EF  |. 50             PUSH EAX
004012F0  |. E8 7B070000    CALL level4.00401A70
004012F5  |. 83C4 08        ADD ESP,8
004012F8  |. 68 6C004200    PUSH level4.0042006C                     ;  ASCII "2320512323"
004012FD  |. 8D8D E803FEFF  LEA ECX,DWORD PTR SS:[EBP+FFFE03E8]
00401303  |. 51             PUSH ECX
00401304  |. E8 67070000    CALL level4.00401A70
00401309  |. 83C4 08        ADD ESP,8
0040130C  |. 68 5C004200    PUSH level4.0042005C                     ;  ASCII "2221114222"

같은 문자열들이 있었습니다. 일단 아래쪽에 루프로 생각 되는 구문이 있었기 때문에 계속 진행시켰습니다.

00401340  |> 8B8D D003FEFF  /MOV ECX,DWORD PTR SS:[EBP+FFFE03D0]
00401346  |. 83C1 01        |ADD ECX,1
00401349  |. 898D D003FEFF  |MOV DWORD PTR SS:[EBP+FFFE03D0],ECX
0040134F  |> 83BD D003FEFF > CMP DWORD PTR SS:[EBP+FFFE03D0],4
00401356  |. 7D 60          |JGE SHORT level4.004013B8
00401358  |. 6A 03          |PUSH 3
0040135A  |. 8B95 D003FEFF  |MOV EDX,DWORD PTR SS:[EBP+FFFE03D0]
00401360  |. 6BD2 0A        |IMUL EDX,EDX,0A
00401363  |. 8D8415 D403FEF>|LEA EAX,DWORD PTR SS:[EBP+EDX+FFFE03D4]
0040136A  |. 0385 D003FEFF  |ADD EAX,DWORD PTR SS:[EBP+FFFE03D0]
00401370  |. 50             |PUSH EAX
00401371  |. 8D8D FC03FEFF  |LEA ECX,DWORD PTR SS:[EBP+FFFE03FC]
00401377  |. 51             |PUSH ECX
00401378  |. E8 E3070000    |CALL level4.00401B60
0040137D  |. 83C4 0C        |ADD ESP,0C
00401380  |. C685 0004FEFF >|MOV BYTE PTR SS:[EBP+FFFE0400],0
00401387  |. 83BD D003FEFF >|CMP DWORD PTR SS:[EBP+FFFE03D0],3
0040138E  |. 74 09          |JE SHORT level4.00401399
00401390  |. C685 FF03FEFF >|MOV BYTE PTR SS:[EBP+FFFE03FF],2E
00401397  |. EB 07          |JMP SHORT level4.004013A0
00401399  |> C685 FF03FEFF >|MOV BYTE PTR SS:[EBP+FFFE03FF],0
004013A0  |> 8D95 FC03FEFF  |LEA EDX,DWORD PTR SS:[EBP+FFFE03FC]
004013A6  |. 52             |PUSH EDX
004013A7  |. 8D85 0404FEFF  |LEA EAX,DWORD PTR SS:[EBP+FFFE0404]
004013AD  |. 50             |PUSH EAX
004013AE  |. E8 CD060000    |CALL level4.00401A80
004013B3  |. 83C4 08        |ADD ESP,8
004013B6  |.^EB 88          \JMP SHORT level4.00401340

이것이 주의 깊게 본 것인데, f8로 실행 시키면서 본 결과 059.027.205.111 이라는 아이피를 만들어 줍니다.

즉, 아무 문자열이나 입력 해도 위의 문자열을 입력해 주지요.

그리고 ASCII "숫자~~" 들도 연관성을 가지고 있는데, 이것을 통해서 아래의 loop 의 대략적인 알고리즘을 추측 할 수 있습니다.

ASCII 숫자들은 0592842722   2027148262   2320512323   2221114222

주의 깊게 보시면 루프가 한번씩 돌 때 마다 +1 증가가 되서 아이피를 만들어 줍니다. 즉

0592842722 ---> 059

2027148262 ---> 027 (맨 앞에 1글자 jump +1)

2320512323 ---> 205 (맨 앞에 2글자 jump +2)

2221114222 ---> 111(맨 앞에 3글자 jump +3)

059.027.205.111 (level2 문제 서버 IP) 가 만들어 집니다. 만들어진 아이피로 index.bak 와 index.html을 출력해 주는 프로그램입니다.

이제 내려가면서 다른 구문들을 보지요. 

004013DB  |. 8BF4           MOV ESI,ESP
004013DD  |. 6A 00          PUSH 0
004013DF  |. 6A 00          PUSH 0
004013E1  |. 6A 00          PUSH 0
004013E3  |. 6A 00          PUSH 0
004013E5  |. 68 50004200    PUSH level4.00420050                     ;  ASCII "HTTPTEST"
004013EA  |. FF15 A0634200  CALL DWORD PTR DS:[<&WININET.InternetOpe>;  WININET.InternetOpenA


아까 보았던 HTTPTEST 가 InterOpenA 라는 함수에서 사용되었군요. 이것은 API 함수 입니다.

들어가는 인자들을 보았더니 잘 입력 되었더군요.

그리고 그 아래

00401407  |. 6A 00          PUSH 0
00401409  |. 6A 00          PUSH 0
0040140B  |. 6A 03          PUSH 3
0040140D  |. 68 9C004200    PUSH level4.0042009C
00401412  |. 68 9C004200    PUSH level4.0042009C
00401417  |. 6A 00          PUSH 0
00401419  |. 68 EC364200    PUSH level4.004236EC
0040141E  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00401421  |. 50             PUSH EAX
00401422  |. FF15 9C634200  CALL DWORD PTR DS:[<&WININET.InternetCon>;  WININET.InternetConnectA


InterConnectA 라는 함수가 있었습니다. 이것의 인자도 살펴 보기로 했습니다.

InternetConnect(hInternet,"server",0,"","",INTERNET_SERVICE_HTTP,0,0);

인자들을 하나하나씩 대입해 보았습니다.

00401407  |. 6A 00          PUSH 0 --> 0
00401409  |. 6A 00          PUSH 0 --> 0

0040140B  |. 6A 03          PUSH 3 --> INTERNET_SERVICE_HTTP

0040140D  |. 68 9C004200    PUSH level4.0042009C --> ""
00401412  |. 68 9C004200    PUSH level4.0042009C --> ""

00401417  |. 6A 00          PUSH 0 --> 0

00401419  |. 68 EC364200    PUSH level4.004236EC ??? (예상대로라면 059.027.205.111 이 있어야 할 것 입니다.)

0040141E  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00401421  |. 50             PUSH EAX  <--- hInternet 

004236ec 다음 구문 까지 진행 시킨 후, server 주소가 들어있어야할 저곳에 무엇이 있을지 살펴 보았습니다.

004236E8  00 00 40 00 00 00 00 00  ..@.....
004236F0  00 00 00 00 00 00 00 00  ........
004236F8  00 00 00 00 00 00 00 00  ........

..아무것도 없었습니다. *(아직까지 프로그램 변화 아무것도 안시켰습니다)

그래서 임의로 저 주소에 ip 주소를 넣어 보았으나, 

00401516  |. C68415 0802FFF>|MOV BYTE PTR SS:[EBP+EDX+FFFF0208],0

이 부분 쯤에서 멈추었습니다. 아마 ip 를 잘못 넣은 것 같았습니다.

직접 프로그래밍 할 생각도 했지만 대회 끝난 후의 재미로 남겨두었습니다.

다른 실력 좋은 분들은 프로그램을 고쳐서 답을 알아내셨겠지만, 저는 직접 http://59.27.205.111/index.html 과

http://59.27.205.111/.index.bak 을 요청해 보았습니다. 하지만 그 때는 작동이 안되더군요. (문제에 이상 있는 줄 알았습니다 OTL)

59.27.205.111 서버에 들어가서 확인하니 apache 서버도 없었습니다. (나중에 확인 하니 웹으로 접근이 되더군요.)

그래서 level2 권한으로 /var/www/html 에 접근 해서 .index.bak 파일을 열어 보았습니다. (접근이 가능하더군요;;정말 그땐 안됐어요오~)

답이 base64로 한번 encoding 된 상태였기 때문에 php 함수로 답을 알아내었습니다.

<?
$str="ISEhTGV2ZWw0ICEhIQ0KUGFzc3dvcmQgOiBrbm93IHlvdXIgZW5lbXk=";
echo base64_decode($str);
?>

$ php base64.php
!!!Level4 !!!
Password : know your enemy $


pass : know your enemy

level4 ps : 다른 분들은 직접 프로그램에서 받아오게 만드셨는지 궁금 합니다 ㅠㅠ 아니면 저게 문제인건가요?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


━[0x05. Level5]━━━━━━━━━━━━━━━━━━━━━━━━━━━

*이번 문제는 참 삽질을 많이 했던 문제입니다.
*id 알아내려고 삽질 하고, password 알아내려고 삽질 하고..참 이번 대회 중에 제일 많이 노가다 했습니다.

level5에 페이지에 접근 하면 화면에 id 와 pw 를 적는 폼과, guest page | level5 page가 있습니다.

일단 form 만 보고 밤새 도록 sql injection 만 시도했지만 되질 않았습니다 ㅠ (진짜 별에 별 쿼리 다 생각 했습니다;;)

다음 날 아침 힌트가 나왔는데, guessing..추측을 하라는 거였습니다. 사람들이 방관하기 쉬운...id list 를 만든 다음에

wwwhack 으로 crack을 해보았습니다.

id-list

guest
admin
member
auth
level05
user
nobody
test
tester
master
level5
hacker
account
login
administrator
anonymous

그래도 크랙이 성공하질 못해서 사전파일 생성기 까지 만들고 있던 도중, 정말 좋은 힌트가 하나 나왔습니다.

id는 guest 이고 pw 는 a*** 이었습니다. (비밀번호가 id 에 맞게 무척 간단했습니다...)

그리고 그 후에 추가적인 작업이 필요하다고 적혀있었습니다.

알아낸 id 와 pw 는 guest / asdf 입니다. 로그인을 한 후, guest page 에 접근하니 패스워드가 asdf 라고 출력 해주고,

level5 에 접근 해 보니 user-agent 와 reffer 값을 Security First, 192.168.?.??/level5.html 로 바꿔야 level5 페이지에 인증이 되는 거였습니다.

* SecurityFirst 가 브라우저 라고 하셔서, 정말 존재하는 브라우저인줄 알고 검색도 했었습니다. mook 인가 monk 라는 분 블로그에 약간이 정보가 *

cookie sniffing 과 spoofing 에 좋은 툴인 achilles 라는 툴로 공격을 시도 했습니다.

일단 guest 로 login을 한 후에, guest page 를 보고, 그 다음 level5 page 에 접근을 했습니다.

사용한 cookie 는

POST /level5/guqehdrhks/level5.php HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/msword, */*
Referer: 192.168.111.222/level5.html
Accept-Language: ko
Proxy-Connection: Keep-Alive
User-Agent: SecurityFirst Explorer
Host: 59.27.205.110
Cookie: r_num=%5C%27+union+select+%2A+from%23; user=level5


입니다.

level5 page에 접근 하자 마자 다음 레벨의 패스워드를 알려주었습니다.

pass : plastic tree
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


━[0x06. Level6]━━━━━━━━━━━━━━━━━━━━━━━━━━━

level6은 ip header 의 checksum 값을 계산 하는 문제입니다.
처음 생각 한 것은 raw socket 으로 쏘면서 sniffing 을 하는 것이었는데

조금 생각해 보니 뒤에 source ip 와 destination ip 가 바뀌면 checksum 값도 바뀌기 때문에

안됩니다. 그래서 생각한 방법이 손으로 직접 푸는 방법인데 구글링에서 검색하면 구하는 공식이 나옵니다.



45  00  00  40  F5  DA  40  00  80  06  
??  ??  C0  A8  00  02  42  A1  27  C3  


그전에 각 값들이 무엇을 뜻하는지 알아야 합니다. (패킷 스니핑 툴로 패킷을 하나 잡아서 ip header 부분을 보시면 됩니다.)

45 00 은 ip version 과 ihl (data offset)을 나타냅니다.

00 40 은 total length. 0x40 -> 64

f5 da 는 identification(id) 0xf5da -> 62938

80 은 time to live(ttl) 값을 나타냅니다 -> 0x80 -> 128

06 은 ip protocol 을 나타냅니다. 06 -> IPPROTO_TCP

C0  A8  00  02 이것은 source ip : 192.168.0.2

42  A1  27  C3 이것은 destination ip : 66.161.39.195

를 나타냅니다.

이제 첫번째 header 값을 구해 보겠습니다.
0. checksum을 0으로 초기화 한다. (빈칸이니 pass)

1. IP의 모든 헤더를 더해서, 16비트(2바이트)가 되도록 맞쳐준다.

45 00 + 00 40 + F5 DA + 40 00 + 80 06 + C0 A8 + 00 02 + 42 A1 + 27 C3 = 3262E

이제 16비트가 되도록 나눕시다. 3262E(20비트)

262E , 0003 = 3262E

이제  262E + 0003 = 2631

이로써 ip 모든 헤더를 더해서 16비트가 되도록 맞추어 주었습니다.

이제 마지막으로 1의 보수 연산을 시행 합니다.

0010 0110 0011 0001 <-- 2631

1101  1001 1100 1110 <-- 연산 결과
13(D)   9    12(C)  14(E)

* 첫번째 같은 경우는 계산기로 할 경우엔 맨 앞자리가 0이어서 4자리로 출력이 안됩니다. 뒤에서 부터 읽은 다음에 0을 추가 시켜주면 됩니다.*

첫번째 빈칸의 답은 D9 CE 입니다.

두번째 header 의 값도 같은 방법으로 계산 하면 됩니다.


45  00  00  3E  24  BD  00  00  80  11  
??  ??  3B  1B  CD  78  A8  7E  3F  01  

위와 똑같이 분석을 해보자면

45 00 은 ip version 과 ihl (data offset)을 나타냅니다.

00 3e 은 total length. 0x3E -> 62

24 bd 는 identification(id) 0x24bd ->9405

80 은 time to live(ttl) 값을 나타냅니다 -> 0x80 -> 128

11 은 ip protocol 을 나타냅니다. 11 -> 무엇이었는지 생각이 안납니다 ㅠ 아마 UDP 이었던 듯...OTL..

3B 1B CD 78 이것은 source ip : 59.27.205.120

A8 7E 3F 01 이것은 destination ip : 168.126.63.1


마찬가지로 checksum 구하는 공식으로 계산을 해보면


45  00  + 00  3E  + 24  BD  + 00  00  + 80  11 + 3B  1B + CD  78 + A8  7E + 3F  01   = 2DA1E

마찬가지로 20비트가 넘어가서

DA1E + 0002 = DA20 

이것을 이제 1의 보수 연산을 하면

1101 1010 0010 0000 <-- DA20

0010 0101 1101 1111 <--- 연산 결과

 2     5       13(D) 15(F)

따라서 두번째 빈칸의 답은 25 DF 가 됩니다.

위의 답들을 보내면 다음 레벨의 패스워드가 주어집니다.

pass : packet storm
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


━[0x07. level7]━━━━━━━━━━━━━━━━━━━━━━━━━━━━

level7은 너무 급하게(?) 풀어버려서 자세한 내용 분석은 하질 못했습니다.

이름 = name
별명 = nick
등록번호 = reg_num

이번 문제는 name 이나 nick 또는 reg_num 에 sql query 를 
전송은 b.php 가 하고 데이터를 뿌려주는 php 파일은 c.php 입니다.

이 c.php는 앞에 form 에서 입력한 데이터들을 불러옵니다.

이때 쓰이는 쿼리를 예상하면

select id,nick,reg_num from quiz_table where reg_num='$reg_num'

name 과 nick 창에도 삽질을 해보았지만, 굳이 별바른 에러 메시지가 보이질 않았기 때문에

다만 name 과 nick 에 문자열이나 숫자 말고 다른 문자가 들어가면

"태그를 사용할수 없습니다." 라는 문자열이 뜨지만, 무시했습니다.

그리곤 삽질 방향을 등록번호(reg_num)으로 돌렸습니다.

간단하게 등록번호를 적는 form 에 ' or 1=1# 를 이용해서 풀었습니나.

이름  : singi
별명  : asdf
등록번호 : ' or 1=1#

위와 같이 입력 한 뒤 전송 후 저장된 내용을 확인 하니

이미 입력 되어 있었던 내용들이 모두 출력 되면서 level8의 패스워드도 출력 되었습니다.

your information :

이 름 : password is :
별 명 : comeasyouare
등록번호 : 2002338720034713

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


━[0x08. Level8]━━━━━━━━━━━━━━━━━━━━━━━━━━━━

level8의 문제 페이지에 접근을 하니 level4 처럼 특정 파일을 내려 받아서

crack을 하는 문제 같았습니다. 

하지만 나중에 공지를 보니 SecurityFirst 의 key 를 알아내야 답이고, 

또 문제 푸는 과정에서 루틴변경, 코드 수정은 하면 안되었습니다.

조금 난감한 상황이지만, 그래도 일단 함수 루틴을 볼 겸 ollydbg 를 실행 시켰습니다.

삽질하면서 알아낸 내용이지만, 이 파일은 1개의 프로텍트와 2개의 fake를 가지고 있습니다.

작동하는 프로텍트는 파일이름이 특정 문자열이 아니면 시리얼이 맞아도 실패 메시지를 띄웁니다.

level4 와 마찬가지로 일단 search for -> all referenced text strings 를 사용해서

프로그램에서 사용된 문자열들을 보았습니다.

문자열들을 살펴보니, Sorry, you are wrong 란 문자열들이 3개가 있었습니다.

즉 분기가 있다는 뜻이겠지요.

시리얼이 맞았을때의 출력 결과도 있었습니다. 일단 삽질을 위해

맨 처음의 "Sorry you are wrong" 에 bp 를 걸었습니다. 그리고 실행 시킨 결과

level8.exe이 실행 되고, 아무문자열 입력 하고 확인을 누르니, bp 를 걸었던 지점에서 멈추었습니다.

계속 진행 하면

00401749  |. 68 44404000    PUSH level8.00404044                     ;  ASCII " Sorry You are wrong "
0040174E  |. E8 C1060000    CALL <JMP.&MFC42.#1200>
00401753  |> 6A 00          PUSH 0                                   ; /status = 0
00401755  |. FF15 CC314000  CALL DWORD PTR DS:[<&MSVCRT.exit>]       ; \exit


프로그램이 종료 되기 때문에, 이 함수를 불렀던 곳이 어딘지 살펴보기로 했습니다.

0040170C  /$ 55             PUSH EBP 이곳을 보면 아래 쪽 창에

Local call from 004016e6 이 출력 되는데 저 곳에서 이 함수가 불려졌다는 걸 알 수 있습니다.

Go to call from 004016e6 을 클릭 해서 역으로 올라가 보았습니다.

위 주소 근처의 명령문들을 본 결과 분기 란걸 알아 냈습니다.

004016E5  |. 51             PUSH ECX                                 ; /Arg1
004016E6  |. E8 21000000    CALL level8.0040170C                     ; \level8.0040170C
004016EB  |. 83C4 04        ADD ESP,4
004016EE  |> E8 C9010000    CALL level8.004018BC
004016F3  |. E8 71010000    CALL level8.00401869
004016F8  |. 8B95 6CFFFFFF  MOV EDX,DWORD PTR SS:[EBP-94]
004016FE  |. 52             PUSH EDX                                 ; /Arg1
004016FF  |. E8 A5000000    CALL level8.004017A9                     ; \level8.004017A9

0040170c 가 실패 메시지고, 004017a9 로 분기 되면 성공 메시지가 뜹니다.

바로 이 부분이 인증 실패의 함수인데

004016D5  |> C785 6CFFFFFF >MOV DWORD PTR SS:[EBP-94],2
004016DF  |. 8B8D 6CFFFFFF  MOV ECX,DWORD PTR SS:[EBP-94]
004016E5  |. 51             PUSH ECX                                 ; /Arg1
004016E6  |. E8 21000000    CALL level8.0040170C                     ; \level8.0040170C


위쪽 구문들 중에서 004016d5 로 jump 하는 구문들 찾아서 살펴보았습니다.

004016BE  |. 75 15          JNZ SHORT level8.004016D5

004016C7  |. 74 0C          JE SHORT level8.004016D5

찾아낸 곳들에 모두 bp 를 건 후 다시 실행 시켰습니다.

맨 처음 004016be 에서 실행이 멈추었습니다. 그 한 줄 위인 004016bb 에 bp 를 걸어서

eax 와 어떤 값을 비교 하는지 알아보았습니다.

004016BB  |. 3B42 60        CMP EAX,DWORD PTR DS:[EDX+60] 

흠..정말 ollydbg가 좋다고 느낀 순간이었습니다.

Stack DS:[0012FEE4]=000004d2 <-- 입력한 시리얼(1234)
EAX=10412f6a   <-- test 의 올바른 serial 272707434

하지만 이때 까진 아직 프로텍트가 있는 줄 몰라서 인증은 실패 했습니다.

*여기 까지 한 후, eax 값에 들어 있는 것을 시리얼로 확신하고 그냥 입력할까도 생각 했지만,

풀이방법 때문에 계속 삽질을 택했습니다.*

사용되었던 함수들을 보기 위해서 Search for -> all intermodular calls 명령으로

프로그램에 사용된 함수들을 보았습니다.

다행히도 쉽게 알아 볼 수 있을만한 함수들이 사용되어서 쉽게 찾을 수 있었습니다.

004019ba 부분에 strcmp 함수가 사용 되었는데 무엇인지 몰라서 strcmp 가 사용된 곳으로 가서

프로그램을 읽었습니다.

004019AE  |> 68 E8404000    /PUSH level8.004040E8                    ; /s2 = "sch_sf.exe"
004019B3  |. 8D8D F8FEFFFF  |LEA ECX,DWORD PTR SS:[EBP-108]          ; |
004019B9  |. 51             |PUSH ECX                                ; |s1
004019BA  |. E8 CD040000    |CALL <JMP.&MSVCRT.strcmp>               ; \strcmp

아까 보았던 sch_sf.exe 라는 것이 strcmp 의 인자로 사용되었습니다. 그럼 이제 이곳에 bp 를 건 뒤

004019B3  |. 8D8D F8FEFFFF  |LEA ECX,DWORD PTR SS:[EBP-108]          ; |

에 무엇이 들어가는지 본 뒤에 sch_sf.exe 로 바꿔 주면 될 것 입니다. (예상은 했지만 삽질을 좋아하는 성격이라서)

실행 해 보았으나, strcmp 에서 멈추질 않았습니다. 다른방법으로 접근을 생각 해보았습니다.

그러던 중 아까 위에서 살펴 봤듯이 인증 실패 메시지가 여러개 있어서 그 이유가 무엇인지

찾아보았습니다. 결론은 fake 였습니다. 

00401869 <-- fake 1 시작 부분

004018bc <-- fake 2 시작 부분

위의 2개의 함수가 fake 인 이유는, 언뜻 보기엔 인증 실패 메시지를 출력한다고 생각 하지만

본래의 구문과 살펴보면 다른 부분이 있습니다.

<정상 루틴>
00401739  |. 8945 08        MOV DWORD PTR SS:[EBP+8],EAX
0040173C  |. 817D 08 238167>CMP DWORD PTR SS:[EBP+8],5678123
00401743  |. 75 0E          JNZ SHORT level8.00401753
00401745  |. 6A 00          PUSH 0
00401747  |. 6A 00          PUSH 0
00401749  |. 68 44404000    PUSH level8.00404044                     ;  ASCII " Sorry You are wrong "
0040174E  |. E8 C1060000    CALL <JMP.&MFC42.#1200>



<비정상 루틴1>
0040189E  |. 8945 FC        MOV DWORD PTR SS:[EBP-4],EAX
004018A1  |. 817D FC 238167>CMP DWORD PTR SS:[EBP-4],5678123
004018A8  |. 74 0E          JE SHORT level8.004018B8
004018AA  |. 6A 00          PUSH 0
004018AC  |. 6A 00          PUSH 0
004018AE  |. 68 78404000    PUSH level8.00404078                     ;  ASCII " Sorry You are wrong "
004018B3  |. E8 5C050000    CALL <JMP.&MFC42.#1200>


<비정상 루틴2>
004018F1  |. 8945 FC        MOV DWORD PTR SS:[EBP-4],EAX
004018F4  |. 817D FC 238167>CMP DWORD PTR SS:[EBP-4],5678123
004018FB  |. 74 0E          JE SHORT level8.0040190B
004018FD  |. 6A 00          PUSH 0
004018FF  |. 6A 00          PUSH 0
00401901  |. 68 90404000    PUSH level8.00404090                     ;  ASCII " Sorry You are wrong "
00401906  |. E8 09050000    CALL <JMP.&MFC42.#1200>


정상 루틴은 JNE 지만, 비정상 루틴들은 모두 JE 로 처리해 줬습니다. 즉 "Sorry You are wrong"

문구가 출력되지 않고 넘어가는 것이죠. 

하지만 아직 strcmp 에 대한 의문이 풀린 것은 아니죠.

맨 처음으로 돌아와서 보니

00401F6E  |> 46             /INC ESI
00401F6F  |. 8975 8C        |MOV DWORD PTR SS:[EBP-74],ESI
00401F72  |. 8A06           |MOV AL,BYTE PTR DS:[ESI]
00401F74  |. 3AC3           |CMP AL,BL
00401F76  |. 74 04          |JE SHORT sch_sf.00401F7C
00401F78  |. 3C 22          |CMP AL,22
00401F7A  |.^75 F2          \JNZ SHORT sch_sf.00401F6E


이 부분에서 파일 이름을 체크 하는것과 비슷한 처리를 해주고 있었습니다.

그 이상은 알아내지 못하고, 004016BB 에 다시 bp 를 걸고

그 아래는 어떻게 되어 있는지 알아 보았습니다.

004016C0  |. E8 6A020000    CALL level8.0040192F

strcmp 가 속해 있는 함수들의 집합(?) 이 시작되는 주소 였습니다.

많은 함수가 사용되었지만, 관심사는 strcmp 이기 때문에 strcmp만 보았습니다.

004019AE  |> 68 E8404000    /PUSH level8.004040E8                    ; /s2 = "sch_sf.exe"
004019B3  |. 8D8D F8FEFFFF  |LEA ECX,DWORD PTR SS:[EBP-108]          ; |
004019B9  |. 51             |PUSH ECX                                ; |s1
004019BA  |. E8 CD040000    |CALL <JMP.&MSVCRT.strcmp>               ; \strcmp
004019BF  |. 83C4 08        |ADD ESP,8
004019C2  |. 85C0           |TEST EAX,EAX
004019C4  |. 75 07          |JNZ SHORT level8.004019CD
004019C6  |. C745 FC 010000>|MOV DWORD PTR SS:[EBP-4],1
004019CD  |> 8D95 D4FEFFFF  |LEA EDX,DWORD PTR SS:[EBP-12C]
004019D3  |. 52             |PUSH EDX                                ; /pProcessentry
004019D4  |. 8B85 D0FEFFFF  |MOV EAX,DWORD PTR SS:[EBP-130]          ; |
004019DA  |. 50             |PUSH EAX                                ; |hSnapshot = 000000B0 (window)
004019DB  |. E8 44060000    |CALL <JMP.&KERNEL32.Process32Next>      ; \Process32Next
004019E0  |. 85C0           |TEST EAX,EAX
004019E2  |.^75 CA          \JNZ SHORT level8.004019AE


Process32Next 가 사용되었군요.

파일이름을 "sch_sf.exe" 로 바꿔줘야 하는건 맞는데

엄밀히 따지자면, 프로세스 리스트에 이름이 sch_sf.exe 가 있어야 인증이 성공 합니다.

즉, level8.exe 의 파일이름이 sch_sf.exe 가 아니어도, 다른 파일의 이름을 sch_sf.exe로 바꾸고

실행 시켜 놓고, level8.exe 를 실행 시켜서, 인증을 해도 성공 메시지가 출력 됩니다.

이제서야 궁금증이 풀렸기에 레벨8 인증을 했습니다.

pass : 451238960
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━




━[0x09. 마치면서]━━━━━━━━━━━━━━━━━━━━━━━━━━━

휴, 올해에도 역시 재미있는 문제들이 많이 많이 출제 되었군요!!

기쁨 기쁨 ^-^  삽질도 많이 했지만, 경험을 통해 다시 또 얻은 게 많아졌습니다.

솔직히 포기 하려고도 했지만, 몸이 따라주질 않았습니다.

흠..올리디버거 복사한게 좀 어정쩡 하네요. 그림파일로 하면 더 멋있을텐데, 그 놈의 귀차니즘이 뭔지 ;(

무언가 부족한것이 있으면 메일 보내주세요

다시 한번 문제 출제 해주신 순천향대학교 분들게 감사드립니다.

고교 마지막 추억이 되겠네요! bye bye~~

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
반응형

'Security > 보고서' 카테고리의 다른 글

KISA 2007 보고서  (0) 2007.06.14
대덕대 해킹대회 보고서  (0) 2007.03.31
제3회 HUST 해킹대회 보고서  (0) 2007.03.31
AHF 2005 보고서  (0) 2007.03.31
Netcat 을 이용한 웹해킹  (0) 2007.03.28