728x90

파일을 실행시키면 위처럼 진행된다. 해당 파일을 ida로 열어보면

main함수이다.



1번 add_note 함수이다.


show note에서 format string bug 취약점이 의심된다.

Show_note &ptr에서 fsb를 발생시킬 수 있는데 이 &ptr은 buf add_note에서 볼 수 있다.


add_note함수에서 입력값이 candidate2함수에 들어가면

v2 즉 content에 입력한 값이 &ptr로 들어간다.


add_note에 %x를 30개 저장하고 show_note를 실행하면 스택의 내용들이 나온다.


위내용을 보기위해 gdb로 열어봤다.

스택 영역을 잘 분석하면 %x로 14번째에 0xffffd048이 박혀있고, 0xffffd048은 22번째를 가리키고 있다. 이를 통해서 쉘을 얻을 수 있다.

14번째에 printf의 got를 입력하고 22번째에 shell 주소를 넣어주면 된다.

14번째의 printf got -> 0x0804b010

22번째 system("/bin/sh") -> 0x8048a37


쉘획득


system("/bin/sh")이 바이너리 안에 존재해서 쉽게 풀 수 있었다.

728x90

'CTF_writeup > 2018' 카테고리의 다른 글

PCTF_2013_ropasaurusrex  (0) 2018.12.22
MMA-CTF-2-greeting  (0) 2018.12.22
Trustealth CTF easy  (0) 2018.12.22
ISITDTU_CTF_dead_note_lv1  (0) 2018.12.22
ISITDTU CTF_xoxopwn  (0) 2018.12.22
728x90

32bit ELF 파일이고 stripped 되어있어 심볼들이 제거되어있다.

checksec으로 확인해본 결과 NX가 걸려있어 rop로 문제를 풀어야할 것이다.

위 실행파일을 ida로 열어보면

main함수이다.

sub_80483F4함수는

입력을 받는 함수인데 여기서 overflow가 발생한다.

이를 통해서 rop페이로드를 만들어주면 될것이다.


rop 계획

read 함수 주소 릭 -> libc base 주소를 알아냄 -> bss영역에 /bin/sh\x00입력 -> write got에 libc system함수 입력 -> write함수 호출 + 인자에 /bin/sh입력


read와 write함수를 사용하기 때문에 ropgadgetdms pop3ret 가젯을 써준다.


sfp까지 덮기 위한 더미 140개 -> 출력을 위한 write plt 호출 및 read got 출력

-> 입력하기 위해 read함수 호출과 bss 영역 할당, 길이는 "/bin/sh\x00"까지 -> write_got를 system으로 덮어준다. -> write 호출


페이로드



728x90

'CTF_writeup > 2018' 카테고리의 다른 글

Noote_ver0  (0) 2018.12.22
MMA-CTF-2-greeting  (0) 2018.12.22
Trustealth CTF easy  (0) 2018.12.22
ISITDTU_CTF_dead_note_lv1  (0) 2018.12.22
ISITDTU CTF_xoxopwn  (0) 2018.12.22
728x90

Format string Bug

return 위의 sprinf 함수는 %s에 v5값을 넣어서 s에서 출력해준다. 이후 return에서 해당 문자열을 출력시켜준다.


위 소스중 prinf에서 format string bug가 발생합니다. format string bug는 출력하는 문자열에 문자 format을 입력하면 해당 형식에 맞게 stack에 있는 값을 출력해줍니다.


프로그램에 일정 문자열을 삽입해주고 서식문자를 통해 해당 문자가 몇번째에 출력되는지 파악합니다.

문자 2개를 입력한뒤 문자 4개를 입력하면 12번째에 4개의 문자가 입력되는것을 확인 할 수있습니다.


계획

문자와 서식문자들을 입력할 때 사용하는 getnline함수이다.

위 함수의 strchr함수를 system함수로 바꿔주고, main을 한번더 실행시켜 main에서 인자에 /bin/sh을 입력해주면 쉘을 얻을 수 있을것이다.


getnline함수에 값을 입력한후 한번더 메인으로 돌아가기 위해


위 주소를 써준다. .fini_array는 프로세스 종료전에 실행되는 함수의 포인터 배열 이라고 나온다. 즉 프로세스가 종료될 때 실행시키는 함수이다.

이주소를 main 시작 주소로 바꿔주고 strchr주소에 system 주소를 넣어준다.


알아야 할것 : main 주소, system 주소, strchr 주소, .fini_array주소




주의할 점 : 

노란색 박스로 출력되는 부분도 %d에 포함되기때문에 aa까지 총 20바이트가 포함되어있는 값으로 계산해야한다.




format string bug에서 got overwrite를 할때 2byte씩 잘라서 보내준다. 값이 너무 크기때문


payload += "%{}d%12$hn".format((main&0xffff)-32) // “%{}d%12$hn”.format((main&0xffff)-32)에서 {}format의 내용이 들어간다. (Main&0xffff) - 32

위의 hn은 앞의 출력된 문자의 수를 2바이트 만큼 입력하겠다는 문자열이다.


payload += "%{}d%13$hn".format(0x10000+(system>>16)-(main&0xffff))

위에서 +0x10000(sytem>>16)-(main&0xffff)가 음수이기 때문이다. 위에서는 크기를 나타내야하기 때문에 +0x10000으로 양수 값을 맞춰준다.


fsb에서는 “%{}d%hn”.format(구해야하는값)을 통해서 {}에 편하게 값을 넣어주는게 좋을것같다.

728x90

'CTF_writeup > 2018' 카테고리의 다른 글

Noote_ver0  (0) 2018.12.22
PCTF_2013_ropasaurusrex  (0) 2018.12.22
Trustealth CTF easy  (0) 2018.12.22
ISITDTU_CTF_dead_note_lv1  (0) 2018.12.22
ISITDTU CTF_xoxopwn  (0) 2018.12.22
728x90

문제바이너리중 취약점이 존재하는 함수이다.

buf의 위치는 ebp-6c에 있다. 그러나 read함수를 통해 받아올수 있는 값은 0x82만큼이다 여기서 overflow가 발생한다.

ret값을 system함수로 덮어주고 안에 인자값으로 /bin/sh을 넣어주면 될 거 같다.


system주소는 0x080848310이고, /bin/sh의 주소는 0x0804a020이다.


페이로드는 Dummy값 112byte + system 주소 + dummy 4byte + /bin/sh 로 넣어주면 될것이다.

위 소스를 실행시키면

쉘을 획득할 수 있다.

728x90

'CTF_writeup > 2018' 카테고리의 다른 글

Noote_ver0  (0) 2018.12.22
PCTF_2013_ropasaurusrex  (0) 2018.12.22
MMA-CTF-2-greeting  (0) 2018.12.22
ISITDTU_CTF_dead_note_lv1  (0) 2018.12.22
ISITDTU CTF_xoxopwn  (0) 2018.12.22
728x90

프로그램을 실행하면 위처럼 1번 옵션인 add_note를 했을 때 index, number of note, content를 입력할 수 있다.

2번 옵션인 del note를 실행하면 index값을 입력해주고, 해당 index에 노트가 존재하면 지우고 없으면 없다고 출력해준다.


위 바이너리를 ida로 열어본다.

메인 소스코드이다. 각 옵션들에 따라 해당 함수를 실행시키는 것을 알 수 있다.


2번옵션인 delete_note 함수 소스이다.

get num으로 값을 받아서 해당 인덱스에 해당하는 부분을 free해주는것으로 보인다.


1번 옵션인 add_note 함수이다.

for문안을 보면 qword_2020e0[v2+i] 를 보면 note의 index로 입력해주는 v2 값을 배열의 인덱스로 사용한다.


qword_2020e0에 들어가면 bss영역임을 확인 할 수 있다. 해당 주소에서 조금더 올라가면


Got영역이 나온다. V2 입력값을 음수로 입력 및 조절해서 got영역으로 이동시킬 수 있고 content를 입력해주는 함수를 통해 got overwrite가 가능하다.


exploit을 하기 위해서 

stlen 함수에 의해서 content의 길이가 3byte 보다 작아야하기 때문에 strlen got overwrite를 통해 strlen 길이 제한을 없애준다.

if문을 정상적으로 통과해야 got overwrite가 가능하기 때문에 3byte 크기로 overwrite해줘야 한다.


어떤식으로 overwrite를 해주냐면 strlen의 반환값인 eax를 0으로 고정시켜주는 asm을 짜야한다.

xor eax,eax

ret

을 기계어로 디스어셈블 해준다.

\x31\xc0\xc3 -> 3byte가 나온다.

위 기계어를 strlen함수의 got에 overwrite해주고

이후에 exploit을 계획하면된다.

content를 입력하는 부분을 보면 길이제한이 8바이트로 제한되어있다. 그렇기 때문에 바로 쉘코드를 삽입하지 못하고

system_exec를 디스어셈블해서 atoi 함수에 넣어준다.


atoi 함수는 note옵션을 입력할 떄 사용된다.

해당 코드는 system_exec함수를 호출하기 위한 코드이다. 64bit syscall에서는 인자순서에따라 들어가는 레지스터들이 정해져있다.

2번째, 3번째인자로 들어가는 esi 와 edx를 0으로 초기화해주고 system_exec에 해당하는 syscall number를 al에 넣고 syscall을 실행해준다.


위 코드를 통해 argv, envp를 0으로 초기화해줬다. 이후 atoi함수가 실행될때 filename을 /bin/sh로 입력해주면 실행이 될것이다.

위 코드는 \x31\xf6\x31\xd2\xb0\x3b\x0f\x05로 8byte이다.


atoi함수가 실행되는 옵션 번호를 받아오는 함수이다.

해당 입력값은 &nptr로 들어가는데 이값이 sys_execve가 되면 rdi값으로 들어가게 된다.

그렇기 때문에 overwrite이후 입력값이 rdi 즉 실행시키는 파일주소로 들어가 sys_call을 실행시킨다.

우리는 rdi -> &nptr에 /bin/sh을 넣어주면 될것이다.


========================흐름 정리=======================

1. qword_2020e0[v2+i] = strdup(&s)를 보면 content에 입력한 값이 bss영역을 참조하는 배열의 인덱스로 들어가는데, index값에 음수를 넣어 줌으로써 got영역에 접근이 가능하고 content_input 함수를 통해 그 주소에 입력이 가능하다. -> got overwrite가 가능하다.

그리고 qword 단위로 들어가기때문에 주소는 8byte단위로 잘라준다.


2. 위부분의 if문을 우회하기 위해 strlen 함수의 got를 overwrite 해야한다. strlen의 반환값은 eax에 저장되므로 우회하기 위해서 eax를 0으로 고정시켜주는 어셈블리어를 기계어로 변환하여 넣어준다.  => \x31\xc0\xc3

ret은 프로그램을 계속 실행시켜주기위해 저장해둔 eip를 pop하는 것이다.


3.이후 쉘 코드를 넣어야 하지만 contant_input의 크기가 8byte로 되어있기 때문에 8byte에 맞춰서 exploit을 계획해야한다. 여기서 get_num함수에 있는 atoi함수를 이용한다. 이유는 atoi에 입력한 값이 & 즉 주소로 들어가기 때문이다. sys_execv의 함수의 첫번쨰 인자도 파일의 주소를 넣어줘야하기 때문에 atoi의 &인자가 들어가면 편하다.


4. atoi 함수를 got overwrite하기 위해 sys_execve을 함수 호출 규약에 맞게 어셈코드를 짜준다.

xor esi, esi

xor edx,edx

mov al,0x3b

syscall

위 코드를 기계어 코드로 변환하면 \x31\xf6\x31\xd2\xb0\x3b\x0f\x05 총 8바이트이다.

위 기계어로 got overwrite를 해주고 실행시키고 싶은 /bin/sh을 입력하면 쉘을 실행시킬 수 있다.


페이로드이다.




32-bit와 64-bit system 함수 호출 규약의 차이를 잘알아야한다.

기계어를 입력해주기 위해선 python프로그램을 통해 입력해줘야한다.



contant_input 은 변수명을 왜저렇게 설정했는지 모르겠다 bob중이라 뇌가 이상해졌었나보다

728x90

'CTF_writeup > 2018' 카테고리의 다른 글

Noote_ver0  (0) 2018.12.22
PCTF_2013_ropasaurusrex  (0) 2018.12.22
MMA-CTF-2-greeting  (0) 2018.12.22
Trustealth CTF easy  (0) 2018.12.22
ISITDTU CTF_xoxopwn  (0) 2018.12.22
728x90

서버에 접속했을 때 이다. This is function x()>>>가 출력되며 자유롭게 입력이 가능하다.

여러가지 testcase들을 통해 접근한다.

test들을 통해 계산을 해주고 입력이 길면 Big size~를 출력해주는 것을 알 수 있다.

__file__는 파이썬 심볼로 현재 실행중인 파일의 위치와 이름을 반환해준다.

__file__을 통해 py 즉 파이썬 파일이라는 것을 알 수 있다.

open(__file__)은 현재 실행중인 파일의 주소와 정보를 출력해준다.

Mode 'r' 을 통해 읽기 모드를 지원한다는것을 알 수 있다.


open(__file__).read()를 입력하면 소스코드가 출력된다.

소스를 분석해보면

ThreadTCPServer(host,port), TreadTCPRequestHandler)     //목적지 호스트와 포트에 들어오는 request에 대해 해당 클래스에 있는 handler을 실행시킨다.


프로그램을 실행시키면

위 함수가 실행된다.

recv함수를 통해 입력을 받으면 self.data로 입력한 값이 들어가고 self.data를 x함수에 인자로 넣어준다.

입력한 데이터가 들어가는 곳이다.

지금까지는 플래그와 관련없는 프로그램이 동작하는 소스를 분석한것이다.


플래그와 관련이있는 부분은 o함수이다.

위 함수의 조건문을 충족하면 flag를 보여준다.

a는 우리가 입력할 문자열이다. 

플래그를 얻으려면 우리가 입력한 문자열과 key데이터들을 xor연산한값이 secret값과 일치해야한다.

그러므로 secret값을 hex디코딩 한 값과 key의 값을 xor연산하면 플래그가 나온다.


문제해결 소스

플래그


728x90

'CTF_writeup > 2018' 카테고리의 다른 글

Noote_ver0  (0) 2018.12.22
PCTF_2013_ropasaurusrex  (0) 2018.12.22
MMA-CTF-2-greeting  (0) 2018.12.22
Trustealth CTF easy  (0) 2018.12.22
ISITDTU_CTF_dead_note_lv1  (0) 2018.12.22

+ Recent posts