320x100

Pwntools

Pwntools는 파이썬으로 작성된 CTF(해킹 대회)와 익스플로잇 개발을 위한 도구 모음입니다. 이 라이브러리는 다양한 익스플로잇 작업을 쉽게 수행할 수 있도록 돕는 여러 기능을 제공합니다.

 

Stack 

스택은 거꾸로 자란다.

힙(Heap)은 컴퓨터 과학에서 동적 메모리 할당을 위한 데이터 구조 및 메모리 영역을 의미합니다.

buffer

 

기본 세팅 

 

 

Lucky draw 정적 분석 실습

Stack over flow

"Stack Overflow"는 일반적으로 프로그램이 스택 메모리를 초과하여 발생하는 오류입니다

 

  • $ wget {binary address}
  • # 바이너리에 실행 권한 부여
  • $ chmod +x lucky_draw
  • $ ./lucky_draw

IDA를 사용하여 lucky_draw 실행 후 바이너리 정적 분석

 

바이너리 파일을 실행시켜 문제가 어떻게 돌아가는지 점검을 해보니 문자를 넣을 수 있는 구간은 1번 add 기능과 3번 winner기능인 것으로 확인되었다.

IDA에서 add 함수부터 확인 시작

버퍼의 크기는 40 

read 크기는 0x860 (2144 size) 를 받는다

-> stack over flow 상황

 

1번 기능에 아무문자나 40개보다 많이  stack over flow 가 발생하는지 확인 -> 에러 발생

 

두번째 문자를 넣을 수 있는 곳 winner 기능 확인

버퍼의 크기는 24

read 크기는 0x98 를 받는다

-> stack over flow 상황

 

3번 기능에 아무문자나 24개보다 많이 넣어서 stack over flow 가 발생하는지 확인 -> 1번 기능과 동일하게 에러 발생

 

stack over flow 는 이런 상황에서 발생

 

 


 

Canary ( = 같은 기능을 수행 NX,malloc)

 

 

  • 스택 오버플로우 보호 완화 기법(mitigation)
  • 함수 호출 시 카나리 값을 스택 프레임의 최상단에 저장, 함수 종료 시 스택 오버플로우를 검사

 

Master Canary

  • 로컬 카나리는 함수 종료 시 검사를 위해 마스터 카나리와 비교 -> 값이 다르면 스택오버플로우가 발생했다고 판단하고 프로그램을 비정상 종료시킴 (stack smashing detected error 발생)
  • 일반적으로 마스터 카나리는 전역 공간에 저장되나 쓰레드에서는 마스터 카나리가 스택 영역에 저장

 

그렇다면 카나리를 우회하는 법이 있을까?

만약 카나리의 값과 마스터카나리값을 동일한 문자로 덮어버린다면 우회할 수 있다.

 

 

 

buffer size 0x28 보다 큰 임의의 값을 넣어준다 -> 0x100

 

 

앞에 p. 는 Pwntools로 분석을 쉽게 하기 위한 매크로를 만들고 있다고 생각하면 됌

sendlineafter설명

 

코드를 작성한 이후 테스트를 하고 싶으면 vscode와 연결되어 있는 터미널에

python3 {file name}  이런식으로 스크립트를 실행해주면 자동으로 넘어가서 테스트를 쉽게 할 수 있다.

버퍼오버플로우가 발생하고 카나리가 프로그램을 자동으로 종료시켜주는 것을 확인 할 수 있다.

 

로컬 카나리까지만 덮으면 전역카나리와 비교 후 값이 달라서 에러가 나는 것 확인

 

GDB를 통한 디버깅

  • tmux
  • python3 {file name} GDB

*GDB: 리눅스(C, C++. 바이너리) 디버거

 

break point 를 걸고 버퍼를 확인하는 작업을 GDB 에서 할 수 있다.

 

GDB에서 확인해야할 사항: 로컬 카나리 (stack frame 에 있는 것) ,마스터 카나리 (실제 원본 카나리)

 

x/gx $rbp-8 명령어를 통해서 로컬 카나리 확인이 가능하다.

 

stack frame point 에 rbp 가 위치하는데 그곳에서 8만큼 떨어진 위치에 로컬 카나리가 위치한다. 

그렇기 떄문에 rbp-8 을 하는 것

 

로컬카나리 - rsi 를 해서 rsi의 랭스가 0x28인것을 확인

다시말해 rsi 는 buffer에 위치해서 0x28만큼 떨어져있다.

 

 

마스터카나리는 fs_base에 저장이 되어있다.아래와같이 얼만큼 떨어져있는지 확인가능

Buffer ~ Master Canary 오프셋 확인

 

 

 

 

 

 

 

 

로컬카나리와 전역카나리 모두를 같은 문자로 덮어서 우회 시도

마스터카나리까지 덮으려면 얼마나 문자를 적어야할지 계산을 해야함

Buffer ~ Master Canary 오프셋 848이니까 그것보다 큰 850을 넣어서 테스트 

테스트 continue 하면

첫번째 break point에서 죽음 

 

왜냐면, 그 사이에 덮어서는 안되는 어떠한 주소를 임의의 문자로 같이 덮어버림 -> 그래서 비교하는 로직까지도 도착하지 못하고 그냥 죽어버림

그래서 위치까지 파악하면서 계산을 하고 발생한 크러쉬를 우회해서 접근해야함

memo()

Another bof function

리턴 주소를 조작하여 반복해서 buffer overflow를 유발할 수 있음

 

Shellcode는 일반적으로 버퍼 오버플로우와 같은 취약점을 이용하여 원격 코드 실행을 목표로 하는 작은 코드 조각을 의미합니다. 이 코드는 주로 쉘을 실행하기 위해 설계되며, 공격자가 시스템에서 명령을 실행할 수 있도록 해줍니다.

 

최근에는 카나리와 비슷한 동작을 하는 NX가 Shellcode 공격을 다 막는다.

그렇기 때문에 나온 기법이 ROP 이다.

 

 

ROP (Return Oriented Programming)

  • ROP는 주로 실행 방지 메커니즘(NX 비트 등)을 우회하기 위해 사용됩니다. 이 기술은 악의적인 코드를 직접 삽입하는 대신, 기존의 실행 가능한 코드 조각(“gadget”)을 사용하여 원하는 동작을 수행합니다.
  • 스택 주소는 실행 할 수가 없는데 코드영역은 CPU가 실행시켜야 할 코드가 들어가있으니 리턴할떄 쉘코드를 스택에 쓰고 스택으로가는게 아니라 코드영역으로 가면 어떨까 하는것
  • Idea: 바이너리에 존재하는 코드를 재활용
  • “Gadget”: pop rdi ; pop rsi ; ret
  • 스택을 공격자가 조작한 입력으로 overwrite
  • “gadget”을 연결해 프로그램 실행 흐름 조작

 

 

STAGE2

 

기존에 데이터 영역에 있던 got 이라는 섹션에서 특정 라이브러리 함수에 있는 주소를 하나 유추하고 싶음

ASLR 이 작동되고있기 때문에 정확한 위치 파악을 위해 임의의 주소를 하나 빼오는 것 스크립트에서는 read 오프셋을 빼오려고 시도 이러한 방식을 leak 이라고 한다.

 

***ASLR (Address Space Layout Randomization)**는 시스템의 메모리 주소 공간의 배치를 무작위로 변경하여 보안을 강화하는 기법입니다. 주로 버퍼 오버플로우와 같은 공격을 방어하기 위해 사용됩니다

 

다시말해, 정상적 메모리 값 하나 빼와서 거기서 실제 주소를 계산해서 라이브러리 베이스의 주소를 찾는다.

-> 어느 위치에 메모리가 어디에 올라가 있는지를 파악할 수 있다.

 

STAGE3

ROP call 을 진행

bin/shell 과 특정프로세스를 만들어주는 execve 을 call 해서 빈쉘을 열어준다

스텍 포인터를 맞춰주고 rop를 돌려보면 결론적으로 실행되는 내용은 쉘이 떨어진다.

 

*** execve는 Unix 및 Unix 계열 운영 체제에서 사용되는 시스템 호출로, 새로운 프로세스를 실행하는 데 사용됩니다. 이 시스템 호출은 주어진 프로그램을 현재 프로세스의 메모리 공간에서 실행하기 위해 사용되며, 기존 프로세스의 내용을 대체합니다.


NOTE

Use After Free

댕글링 포인터 (Dangling pointer) 

  • 해제된 영역의 포인터를 가리키고 있는 포인터

 

note.c 파일분석

 

 

excercise 4.1

 

아래와 같이 4가지 기능을 구현할 수 있다.

 

설명예시

    def write(self, idx: int, script: bytes, emoj: int):
        self._menu(1)
        self.conn.sendlineafter(b"index(1 ~ 16): ", str(idx).encode())  // index(1~16) 입력받는 출력이 나오면 입력값 idx 를 받는다
        self.conn.sendlineafter(b"script: ", script)  // script 입력받는 출력이 나오면 시크립트를 작성한다.
        self.conn.sendlineafter(b">>> ", str(emoj).encode())  // >>> 입력받는 출력이 나오면 앞에 이모지를 선택한다.

 

DEBUG 옵션을 추가하여 분석을 하면 무엇을 주고 받는지 확인할 수 있다.

 

 

취약점이 어디서 발생하는지 파악단계

  • 1번에 happy를 write 1번을 read했는데 happy가 잘 나옴
  • erase 로 1번 happy를 지웠다. (1번은 free가 되서 다시 할당할 수 있도록 운영체제에 돌아가야함)
  • 2번에 sad를 write read 하서 1번을 read했는데 sad가 나옴 (1번은 다 지워져있어야 정상아닌가?) 

댕글링포인터와 관련이 있다.

 

이미 해제된 포인터인데 그 값을 계속해서 가지고 있기 때문에 1번으로 다시 읽어도 읽을 수 있는데 심지어 1번에 새드가 저장되어있고 2번해도 새드가 잘 나온다.

 

이것이 USE AFTER FREE 취약점 

 

 

 

 

  • tmux
  • python3 example_04_b.py GDB
  • script 의 break point 를 만들어놈
  • c 할때마다 write, read, 순으로 걸림
  • write A 를 8개, Happy 
  • vis (vis는 Vi 모드에서 작동하는 텍스트 편집기로 힙의 구조를 확인, 분석한다)

"vis" command in gdb at each breakpoint to visualize the heap layout.

 

 

코드 분석

위의 USE AFTER FREE 취약점  스택구조 참고


Shellcoding Test

 

  • $ wget {binary address}
  • # 바이너리에 실행 권한 부여
  • $ chmod +x shellcoding_test
  • $ ./shellcoding_test

Seccomp

  • 리눅스 커널 샌드박스 보안 기능
  • 프로그램을 보호된 영역에서 동작해 시스템이 조작되는 것을 방지
  • 프로세스가 사용할 수 있는 시스템 콜을 제한

seccomp tools로 seccomp 정책 확인 가능

  • $ sudo apt install gcc ruby-dev gem
  • $ sudo gem install seccomp-tools
  • $ seccomp-tools dump ./shellcoding_test

 

0x40000000 이하는 모두 kill 한다.

 

x86_64 Assembly

 

Timing based side channel

 

 

 

정답

아래와 같은 shellcode를 통해서 한 문자열씩 비교해가면서 flag 를 추출할 수 있다.

 

 


시험

PPT 강조표시되어있는 내용

stack over flow

  • Canary

스택 오버플로우 보호 완화기법

  • ROP 는 어떨때 사용가능?

nx가 걸려잇어서 쉘코드를 실행하지 못하게 . 그래서 사용하는 기법

Note

heap → danglin pointer 를 통해서 발생하는 취약점

  • Use After Free
  • Seccomp

프로세스가 사용할 수 있는 시스템 콜을 제한하는 샌드박스 보안 기능

(메모리보호기능은 아니고 샌드박스 보안기능임)

  • Timing-based Side channel

실행시간을 비교한다

정상적일떄는

같은값이면 계속 본다.

정상작동하는지 시간을 비교한다.

 

 

300x250

+ Recent posts