64비트 BOF 문제인 듯 하다. ida로 코드를 확인해보자.

 

저 함수를 실행하면 쉘이 따질 것이다. 해보자!

 

1. s 부터 ret까지의 거리는 0x120이다. 

 

2. callMeMaybe 주소(8byte)로 36번 도배하자.

 

익스를 짜보자.

 

성공적으로 익스가 되었다.

 

플래그는 HackCTF{64b17_b0f_15_51mpl3_700} 이다.

'HackCTF > WriteUp' 카테고리의 다른 글

HackCTF - Simple_Overflow_ver_2 [150]  (0) 2021.01.19
HackCTF - x64 Simple_size_BOF [150]  (0) 2021.01.17
HackCTF - 내 버퍼가 흘러넘친다!!! [150]  (0) 2020.12.22
HackCTF - Basic_BOF #2 [100]  (0) 2020.12.06
HackCTF - Basic_FSB [100]  (2) 2020.12.05

ㅇㅂㅇ

BOF 문제다. 파일을 다운받고 한번 실행해보자.

 

두 개의 입력을 받는다. IDA로 코드를 확인해보자.

 

s 변수는 main함수 내에 있고 name 변수는 보이지 않는다. 전역변수다.

 

name의 주소는 0x0804A060 이다.

 

이번엔 gdb로 prob1을 확인해보자.

 

음.. gets에 입력되는 부분에 bp를 걸고 어디에 입력되는지 확인해보자.

 

이렇게 두 개의 변수에 각각 AAAA와 AAAABBBBCCCCDDDD를 입력했다.

 

스택값을 확인해보자.

 

s 변수에는 0xffffd164 부터 입력이 됐다.

 

그런데 빨간 박스 부분을 보니 메인함수 ret 때 호출이 되는 주소인 것을 확인할 수 있었다.

 

그렇다면 s 변수에서 입력받을 때 0xffffd17c 에  쉘코드를 넣어 실행시켜주면 될 것 같다.

 

 

 


SCENARIO

 

1. 전역변수 name에 쉘코드를 입력해준다.

 

2. s를 입력할 때 overflow시켜 ret 주소에 name의 주소를 넣어준다.

 

 


 

 

이제 익스를 짜보자!

 

쉘코드는 다른 블로그에서 참고 하였다.

m.blog.naver.com/mathboy7/220215329450

 

쉘코드 모음

포너블 문제 풀때 여러모로 유용하게 사용되는 쉘코드들을 작성해서 모아봤습니다. 찾기 편하시라고.... 블...

blog.naver.com

 

실행을 해보자.

 

익스를 성공했다.

 

플래그는 HackCTF{1_l0v3_70p_pwn3r_m4lhyuk} 이다.

'HackCTF > WriteUp' 카테고리의 다른 글

HackCTF - Simple_Overflow_ver_2 [150]  (0) 2021.01.19
HackCTF - x64 Simple_size_BOF [150]  (0) 2021.01.17
HackCTF - x64 Buffer Overflow [150]  (0) 2021.01.13
HackCTF - Basic_BOF #2 [100]  (0) 2020.12.06
HackCTF - Basic_FSB [100]  (2) 2020.12.05

1. NX-Bit ( NX bit, Never eXecute bit, 실행 방지 비트 )

 

 - 프로세스 명령어나 코드 또는 데이터 저장을 위한 메모리 영역을 따로 분리하는 CPU의 기술이다.

 

 - NX 특성으로 지정된 모든 메모리 구역은 데이터 저장을 위해서만 사용되며, 프로세스 명령어가 그 곳에 상주하지 않음 으로써 실행되지 않도록 만들어 준다.

 

> 인텔 : XD-bit (eXecute Disable) = NX-bit

 

 

2. DEP (Data Execution Prevention)

 

 - 마이크로소프트 윈도우 운영체제에 포한된 보안기능이고, 악의적인 코드가 실행되는 것을 방지하기 위해 메모리를 추가로 확인하는 하드웨어 및 소프트웨어 기술이다.

 

 - DEP의 두 가지 모드

 

   > 하드웨어 DEP : 메모리에 명시적으로 실행 코드가 포함되어 있는 경우를 제외하고, 프로세스의 모든 메모리 위치에서 실행할 수 없도록 표시한다.

 

   > 소프트웨어 DEP : CPU가 하드웨어 DEP를 지원하지 않는 경우 사용한다.

 

 

3. NX-Bit 우회 방법

 

 - ROP ( Return-Oriented-Programming )

 

 - RTL ( Return-to-Libc ) 

'메모용' 카테고리의 다른 글

ASLR 정리  (0) 2021.08.24
Format String Bug - simplefsb (Y.CTF)  (0) 2020.12.12
PLT & GOT 간단하게 정리.  (0) 2020.08.21

FSB 공부를 하며 FSB에 관한 문제를 더 풀어보고 정리하고 싶어서 메모에다가 남긴다.

 

먼저, 파일을 다운받고 IDA로 열어서 코드를 확인해보자.

 

main()
init()

main함수에 printf(&buf) 부분에서 FSB 취약점이 터지는걸 확인할 수 있다.

 

함수를 살펴보면,

 

hide()

hide라고 아주 수상하게 생긴 함수가 존재한다.

 

/bin/sh

hide 함수를 이용해서 해결하면 될 것 같다.

 

우분투에서 한번 실행해보자.

 

처음 입력한 AAAA가 포맷 스트링을 입력한 후로 4번째에 hex 값으로 출력이 되었다.

 

그렇다면, 순서는 이렇다.

 

1. read 함수로 입력을 받을 때 앞 부분에 exit 함수의 GOT 주소를 넣어준다.

 

2. %hn (%n)을 활용해서 처음에 넣은 exit_GOT 주소위치에 hide 함수의 주소를 넣도록 조작한다.

 

※ %hn은 %n과 다르게 2byte씩 들어간다.

 

 

먼저, hide의 주소와 exit의 GOT주소를 구해보자.

hide() address
exit() GOT address 

두 개의 주소를 구했다.

 

3가지 방법으로 익스를 짜볼 것이다.. 

 

먼저, %n을 써서 짜보자!

 

 

hide 주소인 0x080485b3을 10진수로 바꿔주고 앞에 got 주소가 4byte였기 때문에 -4를 해준다.

 

그리고 %4$n에서 4$는 오프셋이다.

 

이렇게 익스를 하면 시간이 조금 걸린다.

 

flag

 

 

두 번째로 %hn을 써서 익스를 짜보자.

 

기본 문자열 개수는 GOT - 2와 GOT 주소인 "\x16\xa0\x04\x08" + "\x18\xa0\x04\x08" = 8byte 이다.

 

잘 이해가 되지 않는다면 이 글을 보면 도움이 될 것 같다..

 

http://kaspyx.tistory.com/82

 

포맷 스트링 버그(format string bug) 공격시에 플래그(flag)사용하기

/* written by kaspy (kaspyx@gmail.com) */ 이전에 잠시 공부한적이 있지만, 까먹고있다가 이참에 공부해서 정리하게되었다. 포맷 스트링 버그 취약점을 가진 프로그램이 있을때, $-flag를 이용한 공격이 기

kaspyx.tistory.com

flag

똑같이 익스가 터진걸 볼 수 있다.

 

 

 

세 번째로는 pwntools가 제공하는 FSB 저격 함수를 사용해서 익스를 짜보자!

 

이 함수를 알고난 뒤로는 웬만해서는 앞의 방법들로 FSB 문제를 풀지 않을 것 같다.

 

익스를 짜보자.

 

fmtstr_payload()

정말,, fmtstr_payload() 함수가 귀찮은 일들을 한번에 다 해결 해준다..

 

fmtstr_payload() 함수에 대해 더 자세히 알고싶다면 pwntools 기술문서에 가서 더 알아보자.

 

docs.pwntools.com/en/stable/fmtstr.html#pwnlib.fmtstr.fmtstr_payload

 

pwnlib.fmtstr — Format string bug exploitation tools — pwntools 4.3.1 documentation

A tuple (score, value, mask) where score equals the number of matching bytes between the returned value and target.

docs.pwntools.com

 

성공적으로 익스가 됐다.

 

플래그는 YCTF{S1mPl3_1s_tH3_b3sT} 이다.

 

 

'메모용' 카테고리의 다른 글

ASLR 정리  (0) 2021.08.24
메모리 보호 기법 [ NX-Bit(MS : DEP) ]  (0) 2020.12.18
PLT & GOT 간단하게 정리.  (0) 2020.08.21

먼저 파일을 윈도우와 우분투에 받자. 그리고 IDA로 디스어셈해보자.

 

IDA

문제의 이름이 BOF인 만큼 fgets() 함수에서 입력받는 과정에서 버퍼 사이즈를 잘 못 지정해서 취약점이 발생한 것 같다.

 

fgets() 함수에 대해 알아보자.

 

fgets(char * str, int num, FILE * stream) 
 - 첫 번째 인자는 읽어들인 문자열을 저장할 char 배열을 가리키는 포인터이다.
 - 두 번재 인자는 마지막 NULL문자를 포함하여 읽어들일 최대 문자 수이다.
 - 세 번재 인자는 문자열을 읽어들일 스트림의 FILE 객체를 가리키는 포인터이다.
 - 리턴값은 성공했을 경우 char 배열을 리턴하고 아무런 문자가 없거나 오류가 발생했을 때는 NULL이 리턴된다.

 

 

shell()

shell() 함수가 존재한다. gdb로 좀 더 살펴보자.

 

빨간 네모박스를 잘 보자.

 

ebp-0xc 위치에 0x80484b4 가 들어간다. 그 다음 eax에 ebp-0xc 위치의 값이 들어간 뒤 call 된다.

 

그렇다면 ebp-0xc 위치에 shell 함수의 주소를 입력하면 call 에서 shell 함수가 호출될 것이다. 

 

해보자.

 

 

먼저, fgets로 입력된 값이 어느 위치에 들어가는지 알아보자.

 

fgets가 호출된 다음 부분에 bp를 걸고 실행해보자.

 

0xffffd0cc에 입력을 받는 것을 알았다.

 

두 번째로 ebp-0xc의 주소를 알아내보자.

 

$ebp address

$ebp의 주소에서 0xc를 빼주면 ebp-0xc의 주소인 0xffffd14c이 나온다.

 

세 번째로 0xffffd14c 주소에 넣을 shell 함수의 주소를 알아내 보자.

 

shell address

마지막으로 입력되는 주소에서 ebp-0xc의 거리를 계산해보자.

 

위의 네모박스는 입력받는 곳이고, 밑은 ebp-0xc의 자리이다.

 

0xffffd14c - 0xffffd0cc = 0x80

 

거리가 나왔다.

 

이젠 필요한 재료(?)들이 다 모였다. 익스를 짜보자.

 

exploit.py

입력받는 곳으로부터 A로 128byte를 채우면 ebp-0xc의 자리에 위치한다. 이 곳에 shell 함수의 주소를 넣는다.

 

128byte + 4byte = 132byte 이다. 위의 fgets 함수의 버퍼 사이즈를 넘지 않는다.

 

133byte

실행해보자.

 

flag

터졌다.

 

플래그는 HackCTF{h3y_dud3_600d_f0r_y0u} 이다.

Format String Bug (FSB) : printf() 함수 계열을 사용할 때, 인자로 포맷 스트링과 포맷 스트링에 대응하는 인자를 사용하지 않고 바로 변수를 인자로 지정했을 때, 악의적인 공격자가 포맷 스트링을 입력하여 스택의 값을 leak 하거나, RET나 _DTOR_END__, GOT와 같은 프로그램의 흐름을 제어할 수 있는 메모리 주소값을 변조하여 악의적인 행동을 할 수 있게 된다.

 

윈도우와 우분투에 파일을 다운받고 IDA로 코드를 확인해보자.

 

main 함수
vuln 함수

메인함수에선 따로 확인할건 없어보인다.

 

vuln 함수를보자.

 

snprintf 함수와 printf 함수에서 서식문자를 따로 지정해주지 않고 바로 넘겨버린다.

 

이 함수에서 FSB 취약점이 발생한다는 것을 알 수 있다.  두 함수에 대해 알아보자.

 

sprintf(char * buffer, const char * format, ...)

 - ... 은 가변 파라미터를 뜻 한다.
 - 첫 번째 인자에 두 번째 인자의 내용이 문자열로써 담기게 된다.


snprintf(char * buffer, int buf_size, const char * format, ...)
 - sprintf 함수에서 두 번째 인자로 size가 추가된 함수로, buffer overflow를 방지하기위해 출력할 문자열의 길이를 지정하였다.

 

flag 함수

gdb를 이용해 basic_fsb에 flag 함수가 있는걸 확인했다.

 

이 함수를 이용하면 될 것 같다.

 

우분투에서 파일을 실행해서 서식문자를 넣어보자.

 

%x = hex

두 번째 서식문자에는 입력된 AAAA의 hex값인 41414141이 출력된다.

 

%n : 서식문자 앞까지의 바이트 수를 계산 후 출력, 출력했던 값을 주소로 생각하고 계산한 값을 주소에 넣는다.

 

그렇다면 위의 서식문자를 바탕으로 이렇게 사용할 수 있을 것 같다.

 

-> printf_GOT 주소에 %n 이 오게한 다음, %n이 flag 함수의 주소를 계산하게 만들면 문제가 해결될 것이다!!

 

GOT는 PLT가 참조하는 테이블이다. 쉽게 말하면 함수의 실제 주소가 들어있다.

 

자! 이제 printf_GOT의 주소와 flag 함수의 주소를 찾아보자.

 

printf_GOT 주소

 

flag 함수 주소

모두 찾았다. python으로 익스를 짜보자.

 

flag 함수의 주소값 0x80485b4을 10진수로 바꾼만큼 %x 포맷을 이용해 출력 해준다.

 

그리고 위에서 포맷스트링 두 번째부터 입력값이 출력됐기 때문에 -4byte를 해줘야 한다.

 

0x80485b4 -> 134514100

 

134514100 - 4 = 134514096

 

실행해보자.

 

flag

익스가 되고 플래그가 나왔다.

 

플래그는 HackCTF{여보게_오늘_반찬은_포맷스트링이_어떠한가?} 이다.

 

 

문제를 이해하기 위해 많은 시간을 들였다. 좀 더 열심히 공부해야겠다.

ㅇㅂㅇ

문제를 보니 파일에서 플래그를 찾으라고 한다. 힌트는 파일의 헤더를 고쳐야한다고 한다.

 

일단 Hxd로 열어보자.

 

Hxd editor

Header Signature를 보니 뭔지 잘 모르겠다.

 

file signature 모음은 (forensic-proof.com/archives/300) 여기서 확인해보자.

 

Footer Signature를 확인 해보자.

 

png Footer Signature

footer를 보니 png 파일의 footer signature 였다.

 

헤더를 수정하고 확장자를 바꾼 뒤에 실행해보자.

 

헤더 수정
??

아직 실행되지 않는다.

 

자세히보니 png 파일 헤더 청크에 문제가 있어 보인다.

 

png 파일 구조에 대해 알아보자.

 

File Signature (8 byte)
{
  Length (4 byte),
  Chunk Type (4 byte),
  Chunk Data (length byte),
  CRC (4byte)
}

이런 구조로 이루어져 있다.

 

하지만 pngcheck라는 좋은 툴이 존재한다.

 

우분투에서 한번 사용해보자.

 

문제 파일을 다운하자.
pngcheck도 다운하자.
bless hexEditor

파일 헤더는 고쳐주자.

 

이제 pngcheck를 써서 차례대로 고쳐보자.

 

IHDR Chunk

정상적인 IHDR Chunk로 바꿔주자.

 

그리고 한번 더 pngcheck를 해보자.

 

CRC Chunk
ㅇㅂㅇ

빨간 박스 부분도 맞게 고쳐주자.

 

한번더 pngcheck를 써보자.

 

too large

Chunk의 길이가 본 길이보다 길다고 한다. 줄여주자!

 

ㅇㅂㅇ

빨간 부분을 0으로 만들어 4byte를 줄여주자.

 

한번더 pngcheck를 써보자.

 

ㅇㅂㅇ

?DET는 IDAT Chunk인 듯 하다. 바꿔주자.

 

IDAT Chunk

한번더 pngcheck를 써보자.

 

OK

거의 다 된것 같다.

 

파일의 확장자를 png로 바꾸고 실행해보자.

 

FLAG

플래그가 나왔다.

 

플래그는 picoCTF{c0rrupt10n_1847995} 이다.

 

'PicoCTF > WriteUp' 카테고리의 다른 글

[vault-door-3] - 200p  (0) 2020.12.01
[picobrowser] - 200p  (0) 2020.12.01
[plumbing] - 200p  (0) 2020.12.01
[Based] - 200p  (0) 2020.12.01
[So Meta] - 150p  (0) 2020.12.01

ㅇㅂㅇ

금고문 문제가 또 나왔다. 소스를 분석해보자.

 

import java.util.*;

class VaultDoor3 {
    public static void main(String args[]) {
        VaultDoor3 vaultDoor = new VaultDoor3();
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter vault password: ");
        String userInput = scanner.next();
	String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
	if (vaultDoor.checkPassword(input)) {
	    System.out.println("Access granted.");
	} else {
	    System.out.println("Access denied!");
        }
    }

    // Our security monitoring team has noticed some intrusions on some of the
    // less secure doors. Dr. Evil has asked me specifically to build a stronger
    // vault door to protect his Doomsday plans. I just *know* this door will
    // keep all of those nosy agents out of our business. Mwa ha!
    //
    // -Minion #2671
    public boolean checkPassword(String password) {
        if (password.length() != 32) {
            return false;
        }
        char[] buffer = new char[32];
        int i;
        for (i=0; i<8; i++) {
            buffer[i] = password.charAt(i);
        }
        for (; i<16; i++) {
            buffer[i] = password.charAt(23-i);
        }
        for (; i<32; i+=2) {
            buffer[i] = password.charAt(46-i);
        }
        for (i=31; i>=17; i-=2) {
            buffer[i] = password.charAt(i);
        }
        String s = new String(buffer);
        return s.equals("jU5t_a_sna_3lpm18gb41_u_4_mfr340");
    }
}

아래쪽에 입력받은 패스워드를 검사하는 함수의 for문들을 차례대로 따라가보자.

 

"jU5t_a_sna_3lpm18gb41_u_4_mfr340" 길이가 32byte이기 때문에 비교에 사용될 것 같다.

 

 

첫 번째 for 문이다.

for (i=0; i<8; i++) {
	buffer[i] = password.charAt(i);
}

"jU5t_a_s" 이 저장된다.

 

 

두 번째 for 문이다.

for (; i<16; i++) {
	buffer[i] = password.charAt(23-i);
}

i = 8 이다.

"1mpl3_an" 이 저장된다.

 

 

세 번째 for 문이다.

for (; i<32; i+=2) {
	buffer[i] = password.charAt(46-i);
}

i = 16 이다.

"4?r?m?4?u?1?b?8?" 이 저장된다.

 

 

네 번째 for 문이다.

for (i=31; i>=17; i-=2) {
	buffer[i] = password.charAt(i);
}

i = 31 이다.

"?g?4?_?_?_?f?3?0" 이 저장된다.

3번째와 4번째 for문에서 저장되는 값은 i가 교차하기 때문에 엇갈리게 해줘야 한다. (주의)

 

 

for문을 전부 차례대로 따라가 보았다.

 

이어 붙이면 플래그가 완성될 것 같다.

 

플래그는 picoCTF{jU5t_a_s1mpl3_an4gr4m_4_u_1fb380} 이다.

'PicoCTF > WriteUp' 카테고리의 다른 글

[c0rrupt] - 250p  (0) 2020.12.01
[picobrowser] - 200p  (0) 2020.12.01
[plumbing] - 200p  (0) 2020.12.01
[Based] - 200p  (0) 2020.12.01
[So Meta] - 150p  (0) 2020.12.01

+ Recent posts