Computer Security

#1 Tool : gdb 본문

시스템 해킹

#1 Tool : gdb

쿠리 Kuri 2022. 6. 3. 18:30

VMware 을 이용해 우분투 18.04 버전을 깔아놨다.

gdb 사용법은 간단하다.

 

 

git clone https://github.com/pwndbg/pwndbg
cd pwndbg
./setup.sh

이와 같은 코드를 우분투에 쳐주면

다운이 완료 된다.

 

그 뒤에

gdb를 입력하면
$ gdb
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
Find the GDB manual and other documentation resources online at:
For help, type "help".
Type "apropos word" to search for commands related to "word".
pwndbg: loaded 193 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
pwndbg>

이런식으로 뜨는데, 이러면 gdb가 정상적으로 깔린 것이다.

 

간단하게 실습해보자.

그러기 위해선 다시 커맨드로 돌아가

gcc를 다운 받아야한다.

gcc다운 받는 방법은 

sudo apt update
sudo apt install build-essential

를 입력한다.

 

그 뒤에 우분투 내에서 debugee.c 파일을 만들 것인데

하는 방법은 

vi debugee.c 라는 쉘 스크립트를 만들어준다.

그 쉘스크립트에 들어가서 i 버튼을 누르면 직접 작성 할 수 있게 되는데

// Name: debugee.c
// Compile: gcc -o debugee debugee.c -no-pie
#include <stdio.h>
int main(void) {
  int sum = 0;
  int val1 = 1;
  int val2 = 2;
  sum = val1 + val2;
  printf("1 + 2 = %d\\n", sum);
  return 0;
}

직접 작성 후에 

esc 버튼을 누르고  : 입력후 wq 를 입력하면 탈출된다.

 

그 뒤에, gcc -o debugee debugee.c 를 입력한뒤,  gdb debugee 를 입력해주면,

$ gcc -o debugee debugee.c
$ gdb debugee
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
pwndbg: loaded 193 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
Reading symbols from debugee...(no debugging symbols found)...done.
pwndbg>

라는 문구가 뜨면 성공이다.

 

그다음 start 를 입력하면

이런식으로 쭉 도출된다.

 

프로그램은 실행되면서 레지스터를 비롯한 여러 메모리에 접근한다.

따라서 디버거를 이용해 프로그램의 실행 과정을 자세히 관찰하려면 컴퓨터의 각종 메모리를 한눈에 파악할 수 있는것이 좋다.

pwndbg는 주요 메모리들의 상태를 프로그램이 실행되고 있는 맥락(Context)라고 부르며, 이를 가독성 있게 표현할 수 있는 인터페이스를 갖추고 있다.


context는 크게 4개의 영역으로 구분된다.

 

1.register : 레지스터의 상태를 보여준다.

2.disasm: rip 부터 여러 줄에 걸쳐 디스어셈블된 결과를 보여준다.

3.stack: rsp 부터 여러 줄에 걸쳐 스택의 값들을 보여준다.

4.backtrace: 현재 rip에 도달할 때까지 어떤 함수들이 중첩되어 호출됐는지 보여준다.

 

gdb를 이용하여 프로그램을 분석할 때, 일반적으로 전체 프로그램 중 아주 일부분의 동작에만 관심이 있다.

이 예제에선 main함수가 분석의 대상이라 가정하겠다.

이런 상황에서, 진입점부터 main함수까지, 코드를 한 줄씩 실행시켜가며 main 함수에 도달해야 한다면, 디버깅은 그렇게 효율적인 분석 방법이 아닐 것이다.

 

그래서 많은 디버거에는 break와 continue라는 기능이 있다.

break는 특정 주소에 중단점(breakpint)을 설정하는 기능이고, continue는 중단된 프로그램을 계속 실행시키는 기등이다.

break로 원하는 함수에 중단점을 설정하고, 프로그램을 계속 실행하면 해당 함수까지 멈추지 않고 실행한 다음 중단된다.

그러면 중단된 지점부터 다시 세밀하게 분석이 가능하다.

 

이들을 활용해 현재 중단된 start 함수부터 main 함수까지 실행시키면

b *main
c 입력

 


앞으로 start가 진입점부터 프로그램을 분석할 수 있도록 자동으로 중단점을 설정해줬다면, run은 단순히 실행만 시킨다.

따라서 중단점을 설정해놓지 않았다면 프로그램이 끝까지 멈추지 않고 실행된다.

지금은 main함수에 중단점을 설정해 놨기 때문에  run 명령어를 실행해도, main함수에서 실행이 멈춘다.

r 입력


gdb는 프로그램을 어셈블리 코드 단위로 실행하고, 결과를 보여준다.

프로그램의 코드는 기계어로 이루어져 있으므로, gdb는 기계어를 디스어셈블(Disassemble)하는 기능을 기본적으로 탑재하고 있다.

추가로 pwndbg에는 디스어셈블된 결과를 가독성 좋게 출력해주는 기능이있다.

 

disassemble은 gdb가 기본적으로 제공하는 디스어셈블 명령어다.

함수이름을 인자로 전달하면 해당 함수가 변환될 때 까지 전부 디스어셈블해 보여준다.

 

u,nearpc,pdisassemble는 pwndbg에서 제공하는 디스어셈블 명령어다.

디스어셈블된 코드를 가독성 좋게 출력해준다.


관찰하고자 하는 함수의 중단점에 도달했으면, 그 지점부터는 명령어를 한 줄씩 자세히 분석해야 한다.

이때 사용하는 명령어로 ni와 si가 있다.

 

ni와 si는 모두 어셈블리 명령어를 한 줄 실행한다는 공통점이 있다.

만약 call 등을 통해 서브루틴을 호출하는 경우 ni는 서브루틴의 내부로 들어가지 않지만, si는 서브루틴의 내부로 들어간다는 차이점이 있다.

 

ni를 입력하면

ni 입력전
ni 입력후

이렇게 한줄씩 실행된다.

 

함수의 내부까지 궁금할때는 si 를, 그렇지 않을때는 ni를 사용한다.

 

 

si(step into)로 함수 내부에 들어가서 필요한 부분을 모두 분석했는데, 함수의 규모가 커서 ni로는 원래 실행 흐름으로 돌아가기 어려울 수 있다.

이때는 finish라는 명령어를 사용해 함수의 끝까지 한 번에 실행할 수 있다.

finish


프로그램을 분석하다 보면 가상 메모리에 존재하는 임의 주소의 값을 관찰해야할 때가 있다.

이를 위해 gdb에서는 기본적으로 x라는 명령어를 제공한다. x를 이용하면 특정 주소에서 원하는 길이만큼의 데이터를 원하는 형식으로 인코딩해 볼 수 있다.

Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), c(char), s(string) and z(hex, zero padded on the left). Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).

 

ex)

1. rsp부터 80바이트를 8바이트씩 hex형식으로 출력

2.rip 부터 10줄의 어셈블리 명령어 출력

 

3.특정 주소의 문자열 출력


telescope 은 pwndbg가 제공하는 강력한 메모리 덤프 기능이다.

특정 주소의 메모리 값들을 보여주는 것에서 그치지 않고, 메모리가 참조하고 있는 주소를 재귀적으로 탐색해 값을 보여준다.

 


vmmap은 가상메모리의 레이아웃을 보여준다. 어떤 파일이 매핑된 영역일 경우, 해당 파일의 경로까지 보여준다.


gdb를 통해 디버깅할 때 직접 입력할 수 없을 때가 있다.

예를 들어, 숫자와 알파벳이 아닌 값을 입력하는 상황이다.

이러한 값은 이용자가 직접 입력할 수 없는 값이기 때문에

파이썬으로 입력값을 생성하고, 이를 사용해야 한다.

 

파이썬을 이용하는 방법을 살펴보기에 앞서 아래 코드를 작성하고 컴파일하자.

 

코드내용은 프로그램의 인자로 전달된 값과 이용자로부터 입력받은 값을 촐력하는 예제다.

 

똑같이 쉘스크립트로 debugee2.c 라는 파일을 만들어준다.

debugee2

그 뒤에 gdb debugee2로 디버깅을 시작한다.

$ gcc -o debugee2 debugee2.c
$ gdb debugee2
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
pwndbg: loaded 193 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
Reading symbols from debugee...(no debugging symbols found)...done.
pwndbg>

gdb/python argv

run 명령어의 인자로 $()와 함께 파이썬 코드를 입력하면 값을 전달할 수 잇다.


gdb/python input

이전과 같이 $()와 함께 파이썬 코드를 입력하면 값을 입력할 수 있다.

입력값으로 전달하기 위해서는 '<<<'문자를 사용한다.

 

'시스템 해킹' 카테고리의 다른 글

#4 pwntools  (0) 2022.06.08
#3 기본 시스템 용어2  (0) 2022.06.07
#2 기본 시스템 용어1  (0) 2022.06.06
Comments