✔️ 디버거
컴퓨터 과학에서는 실수로 발생한 프로그램의 결함을 버그(bug)라고 한다.
특히 완성된 코드에서는 이러한 버그를 찾는 것은 매우 어려운데,
이러한 어려움을 해소하고자 버그를 없애고 줄이기 위해
디버거(Debugger)라는 도구가 개발되었고 리눅스의 대표적인
디버거 중 하나인 gdb에 대해 설명한다.
✔️ gdb
GNU debugger, gdb는 리눅스의 대표적인 디버거이며
해당 강의에서 진행하는 Ubuntu 18.04에는 기본적으로 설치되어 있다.
해당 커리큘럼에서는 pwndbg를 기준으로 설명한다.
현재 해당 파일에서 진입점인 Entry Point, EP는 0x540을 나타내고 있다.
pwndbg에 start를 한 모습이다. 초록색으로 화살표가 가리키고 있는 부분부터
진입점을 나타내어 프로그램을 분석할 수 있게 해준다.
이러한 분석에 있어서 pwndbg는 주요 메모리들의 상태를 프로그램이 실행되고 있는
맥락(Context)이라고 부르며, 해당 인터페이스를 갖추고 있다.
이러한 맥락은 크게 4개의 영역으로 구분된다.
① registers: 레지스터의 상태를 보여준다.
② disasm: rip부터 여러 줄에 걸쳐 디스어셈블된 결과를 보여준다.
③ stack: rsp부터 여러 줄에 걸쳐 스택 값들을 보여준다.
④ backtrace: 현재 rip에 도달할 때까지 어떤 함수들이 중첩되어 호출됐는지 보여준다.
이러한 디버거에는 특정 주소에 중단점(breakpoint)를 설정할 수 있는 b와
중단된 프로그램을 실행시키는 continue, c가 존재한다.
또한, 단순히 실행만 하는 run, r이 존재한다.
그 외에도 step into, si / next instruction, ni / info, i / kill, k / pdisas, pd 가 존재한다.
그리고 gdb는 기계어를 디스어셈블하는 기능을 기본적으로 가지므로
disassemble main과 같이 작성하였을 때 해당 main 함수가 반환될 때까지
전부 디스어셈블하여 보여준다.
이러한 디스어셈블 내용을 u, nearpc, pdisassemble을 통해 가독성 좋게 출력해준다.
위에서 설명한 ni와 si는 중단점부터 실행하는 명령어로 ni는 서브루틴의 내부로 들어가지
않지만, si는 서브루틴의 내부로 들어간다는 차이점이 존재한다.
main+57 주소에 중단점을 걸고 들어간다음, ni 명령어를 사용하면
그 다음 62번째 주소를 가리키게 된다.
si도 다음으로 넘어가는 것은 동일하지만, 내부가 궁금할 때 si를 사용하고
그렇지 않은 경우에는 ni를 사용하면 된다.
finish는 si를 통해 모두 분석한 후 함수의 끝까지 한 번에 실행하기 위해 사용된다.
gdb에서는 임의 주소의 값을 관찰하기 위해서 특정 주소에 원하는 길이만큼
데이터를 원하는 형식으로 인코딩하여 볼 수 있는 x 명령어도 존재한다.
x 명령어를 x/10gc $rsp 와 같이 작성하게 되면
1) rsp부터 80바이트를 8바이트씩 hex 형식으로 출력한다.
2) rip부터 5줄의 어셈블리 명령어를 출력한다.
3) 특정 주소의 문자열을 출력한다.
telscope는 pwndbg가 제공하는 강력한 메모리 덤프 기능이다.
tele 명령어로 사용이 가능하고, vmmap은 가상 메모리의 레이아웃을 보여주어
어떤 파일이 매핑된 영역일 경우 해당 파일의 경로까지 보여준다.
gdb를 통해 디버깅할 수 없을 때 파이썬으로 입력값을 생성하고 사용하는 방법이 있다.
run 명령어 인자로 $()와 함께 파이썬 코드를 입력할 수 있다.
또한, $()와 함께 값을 입력하면서 입력값으로 전달하기 위해서는 '<<<'문자를 사용한다.
✔️ pwntools
파이썬으로 여러 개의 익스플로잇 스크립트를 작성하다 보면,
자주 사용하는 함수들이 있는데 이러한 함수들을 반복적으로 구현하는 것은
비효율적이므로 시스템 해커들이 집대성하여 pwntools라는 파이썬 모듈을
제작하였다고 한다. 익스플로잇의 대부분이 pwntools를 이용하여 제작 및 공유되므로
해당 모듈의 사용법을 익혀야한다!!
$ sudo apt-get update
$ sudo apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
$ python3 -m pip install --upgrade pip
$ python3 -m pip install --upgrade pwntools
위의 명령어들을 통해서 파이썬과 관련 라이브러리, pwntools 설치를 위해
작업해주고 pip와 pwntools를 각각 업그레이드 하는 명령어도 작성해준다.
pwntools가 정상적으로 임포트되는 것을 확인할 수 있다.
http://docs.pwntools.com/en/latest/
pwntools에 관한 공식 문서는 위에서 확인할 수 있는데,
다음과 같은 pwntools API 사용법들이 존재한다.
1. process & remote
- process 함수는 익스플로잇을 로컬 바이너리를 대상으로 할 때 사용하는 함수이다.
- remote 함수는 원격 서버를 대상으로 할 때 사용하는 함수이다.
- 전자는 익스플로잇 테스트 및 디버깅을, 후자는 대상 서버를 실제 공격하기 위해 사용한다.
2. send
- send는 데이터를 프로세스에 전송하기 위해 사용한다.
- send, sendline, sendafter, sendlineafter 등 다양한 함수가 정의되어 있다.
- line은 라인피드가, after는 1인자를 출력하면 2인자를 입력, lineafter는 합친 느낌이다.
3. recv
- recv는 프로세스에서 데이터를 받기 위해 사용한다.
- recv()와 recvn()은 차이점이 존재하는데, recv(n)은 최대 n 바이트를 받는 것이므로
모두 받지 못해도 에러를 발생시키지는 않지만, recvn(n)은 정확히 n 바이트의
데이터를 받지 못하면 계속해서 기다린다.
- 그외에도 recvline(), recvuntil(), recvall() 등의 함수가 존재한다.
4. packing & unpacking
- 익스플로잇 작성 시 어떠한 값을 리틀 엔디언의 바이트 배열로 변경한다.
- 또는 역의 과정을 거쳐야 하는 경우에 사용한다.
- p32, p64, u32, u64 등이 존재한다.
5. interactive
- 셸 획득, 익스플로잇 특정 상황에 직접 입력을 주면서 출력을 확인할 때 사용한다.
- 호출하고 나면 터미널로 프로세스에 데이터를 입력하고 출력을 확인할 수 있다.
6. ELF
- ELF 헤더에는 익스플로잇에 사용될 정보가 기록되어 있다.
- pwntools를 사용하여 해당 정보들을 쉽게 참조할 수 있다.
7. context.log
- 익스플로잇에 버그가 발생하면 익스플로잇도 디버깅해야 한다.
- pwntools에는 디버깅 편의를 돕는 로깅 기능이 있고,
로그 레벨은 context.log_level 변수로 조절할 수 있다.
8. context.arch
- pwntools의 기능 들은 공격 대상의 아키텍처에 영향을 받는다.
- 그러므로 아키텍쳐 정보를 프로그래머가 지정할 수 있게 하며,
해당 값에 따라서 몇몇 함수들의 동작이 달라진다.
- ex) amd64는 x86-64 아키텍처 등을 의미한다.
9. shellcraft
- 정적으로 생성된 코드의 단점과 구성 가능한 문자의 종류 등에 따라서
해당 제약 조건이 존재하는 상황에서 새로 직접 셸 코드를 작성한다.]
10. asm
- 어셈블 기능을 제공하는데, 아키텍처를 미리 지정해야 한다.
화이팅 💪
'CTF > 시스템해킹' 카테고리의 다른 글
[Dreamhack] Stack Canary (0) | 2022.10.23 |
---|---|
[Dreamhack] Stack Buffer Overflow (0) | 2022.10.22 |
[Dreamhack] Shellcode + shell_basic (0) | 2022.10.22 |
[Dreamhack] Background - CS (0) | 2022.10.20 |
[Dreamhack] System hacking Introduction (0) | 2022.10.18 |