GEF – GDB Enhanced Features 소개

 

리눅스 환경에서 순수(?) 버전의 gdb 사용은 상당한 인내를 필요로 한다.
가장 기본적인 디버거답게 여러가지 기능들을 갖추고 있지만,
“보기 좋은 것까지 나한테 바라지 마라…”고 말하는 듯한 느낌이 들 때가 있다.

개인적으로 가장 gdb의 가장 불편한 점을 하나 꼽으라면
스택 정보를 볼 때, 매번 명령어를 입력해야 한다는 것이다.
(물론 익숙해지면 그러려니 하고 쓰게 되지만… ㅠㅠ)

이런 단점을 해결하기 위한 사막의 오아시스 같은 툴이 등장했는데
바로 예전에 소개한 바 있는 PEDA 이다.

이전 자료 링크 :  Linux Exploit을 손쉽게 – peda 디버거 활용

Cap 2014-12-09 14-31-45-091[이 좋은 걸 만들어 준 Long(?) 씨에게 다시 한번 감사를]

그러나 PEDA는 Intel CPU 기반의 32/64비트 환경만 지원하기 때문에
ARM, SPARC 등의 시스템에서는 사용이 불가하다.

이번에 소개할 GEF – GDB Enhanced Features는 이러한 문제점을 단번에 해결해 줄 수 있다.
ARM, PowerPC, SPARC 등의 시스템을 모조리 지원하는 GDB 확장 도구 GEF를 만나보자.

 

1. 설치 – Installation

설치 과정은 PEDA와 마찬가지로 매우 간단하다.  다음 3줄이면 설치 후 바로 사용이 가능하다.

$ git clone https://github.com/hugsy/gef.git
$ echo source /gef Downloaded Dir/gef.py > ~/.gdbinit
$ gdb -q /path/to/my/bin //바이너리 위치//

위 기본 사항만으로도 대부분의 기능을 사용할 수 있지만,
ROP공격이나, 디스어셈블 기능을 강화하기 위해 다음 두가지 모듈을 추가로 설치할 것을 권장한다.

 

1) Capstone

Disassembly 프레임워크로써, 다양한 아키텍쳐 환경을 지원한다.
github (https://github.com/aquynh/capstone)를 통해 다운로드 받거나, pip 를 통해 바로 설치가 가능하다.

root@ubuntu:~# pip install capstone

 

2) ROPGadget

ROP 공격시 코드 내에서 ROP 조각들을 쉽게 찾을 수 있게 도와준다.
마찬가지로 github(https://github.com/JonathanSalwan/ROPgadget) 또는 pip를 통해 설치할 수 있다.

root@ubuntu:~# pip install ropgadget

이제 모든 환경이 갖춰졌으므로, 본격적으로 GEF를 사용해보도록 하자.

 

2. 기본 사용법

PEDA를 사용해본 적이 있다면 GEF 역시 어렵지 않게 다룰 수 있을 것이다.
텍스트 색상이나 표시 방법은 PEDA의 그것과 매우 비슷하며, 나머지 기능들도 대부분
PEDA에서 이미 제공되는 것들이기 때문이다.

 

1) gef 파일 로드

$ echo source /gef Downloaded Dir/gef.py > ~/.gdbinit

“.gdbinit” 파일에 gef 소스코드를 로드시킨 후, 분석 파일을 gdb로 불러 보자.

root@ubuntu:~# gdb -q gef_test 
[+] Failed to load `assemble`: 'radare2 Python bindings could not be loaded'
gef loaded, `gef help' to start, `gef config' to configure
28 commands loaded (10 sub-commands), using Python engine 2.7
Reading symbols from /root/gef_test...(no debugging symbols found)...done.
gef> gef help
====================[ GEF - GDB Enhanced Features ]====================
aslr                      -- View/modify GDB ASLR behavior.
checksec                  -- Checksec.sh (http://www.trapkit.de/tools/checksec.html) port.
context                   -- Display execution context.
cs-dis                    -- Use capstone disassembly framework to disassemble code.
ctf-exploit-templater     -- Generates a ready-to-use exploit template for CTF.
deref                     -- Dereference recursively an address and display information
dump-memory               -- Dump chunks of memory into raw file on the filesystem. Dump file
                             name template can be defined in GEF runtime config
elf-info                  -- Display ELF header informations.
entry-break               -- Tries to find best entry point and sets a temporary breakpoint on it.
fd                        -- Enumerate file descriptors opened by process.
fmtstr-helper             -- Exploitable format-string helper (experimental)
gef-alias                 -- GEF defined aliases
heap                      -- Get some information about the Glibc heap structure.
inspect-stack             -- Exploiter-friendly top-down stack inspection command (peda-like)
invoke                    -- InvokeCommand: invoke an external command and display result.
ksymaddr                  -- Get kernel address
pattern                   -- Metasploit-like pattern generation/search
ps                        -- List and filter process.
reg                       -- Display full details on one, many or all registers value from current architecture.
reset-cache               -- Reset cache of all stored data.
ropgadget                 -- ROPGadget (http://shell-storm.org/project/ROPgadget) plugin
shellcode                 -- ShellcodeCommand uses @JonathanSalwan simple-yet-awesome shellcode API to
                             download shellcodes
trace-run                 -- Create a runtime trace of all instructions executed from $pc to LOCATION specified.
vmmap                     -- Display virtual memory mapping
xd                        -- Display arranged hexdump (according to architecture endianness) of memory range.
xfiles                    -- Shows all libraries (and sections) loaded by binary (Truth is out there).
xinfo                     -- Get virtual section information for specific address
xor-memory                -- XOR a block of memory.
gef> 

“gef help” 를 입력하면, gef에서 제공하는 기능들에 대한 설명들을 볼 수 있다.
help 결과로만 보아도, 이 gdb 확장도구가 일반 디버깅이 아닌 해킹을 위한 도구란 것을 알 수 있을 것이다.

 

2) context – 레지스터, 스택, 코드 정보 확인

메인 함수에 브레이크 포인트를 설정한 후, 프로그램을 실행하면(run),
다음과 같이 레지스터, 스택, 코드 영역이 깔끔하게 정리되어 출력되는 것을 볼 수 있다.

gef> b main
Breakpoint 1 at 0x8048417
gef> r
--------------------------------------------------------------------------------[regs]
$eax     0x00000001 $ecx     0xbffff4d4 $edx     0xbffff464 $ebx     0xb7fc6ff4 
$esp     0xbffff438 $ebp     0xbffff438 $esi     0x00000000 $edi     0x00000000 
$eip     0x08048417 $cs      0x00000073 $ss      0x0000007b $ds      0x0000007b 
$es      0x0000007b $fs      0x00000000 $gs      0x00000033 $eflags  [ PF ZF IF ] 

--------------------------------------------------------------------------------[stack]
0xbffff438: 0xbffff438 -> 0x0
0xbffff43c: 0xbffff43c -> 0xb7e3a4d3 -> 0xb7e3a4d3 <__libc_start_main+243>: mov DWORD PTR [esp],eax
0xbffff440: 0xbffff440 -> 0x1
0xbffff444: 0xbffff444 -> 0xbffff4d4 -> 0xbffff649 -> "/root/gef_test"
0xbffff448: 0xbffff448 -> 0xbffff4dc -> 0xbffff658 -> "SSH_AGENT_PID=2836"
0xbffff44c: 0xbffff44c -> 0xb7fdc858 -> 0xb7e21000 -> 0xb7e21000: jg 0xb7e21047
0xbffff450: 0xbffff450 -> 0x0
0xbffff454: 0xbffff454 -> 0xbffff41c -> 0xb7e53e55 -> 0xb7e53e55 <__cxa_atexit+53>: add esp,0x18
0xbffff458: 0xbffff458 -> 0xbffff4dc -> 0xbffff658 -> "SSH_AGENT_PID=2836"
0xbffff45c: 0xbffff45c -> 0x0
--------------------------------------------------------------------------------[code]
=> 0x8048417 <main+3>:	and    esp,0xfffffff0
   0x804841a <main+6>:	sub    esp,0x20
   0x804841d <main+9>:	mov    DWORD PTR [esp+0x1c],0x8048520
   0x8048425 <main+17>:	mov    DWORD PTR [esp],0x8048529
   0x804842c <main+24>:	call   0x8048330 <puts@plt>
   0x8048431 <main+29>:	mov    eax,0x804853a
--------------------------------------------------------------------------------[trace]
#0  0x08048417 in main ()

Breakpoint 1, 0x08048417 in main ()
gef> 

X86 환경뿐만 아니라 ARM에서도 다음 그림과 같이 깔끔하게 출력이 된다.

arm

 

3) Capstone 디스어셈블러 사용

앞서 “Capstone Disassembly Framework”를 추가로 설치한것을 기억할 것이다.
만약 GDB가 아닌 Capstone의 디스어셈블 결과를 보고 싶다면 “cs-dis” 명령어를 사용한다.
(일반 x86 환경에서 큰 차이를 보이지는 않는 듯 하다)

gef> cs-dis
0x08048417		and	esp, 0xfffffff0
0x0804841a		sub	esp, 0x20
0x0804841d		mov	dword ptr [esp + 0x1c], 0x8048520
0x08048425		mov	dword ptr [esp], 0x8048529
0x0804842c		call	0x8048330
0x08048431		mov	eax, 0x804853a
0x08048436		mov	edx, dword ptr [esp + 0x1c]
0x0804843a		mov	dword ptr [esp + 4], edx
0x0804843e		mov	dword ptr [esp], eax
0x08048441		call	0x8048320
0x08048446		leave	
0x08048447		ret	
0x08048448		nop	
0x08048449		nop	
0x0804844a		nop	
0x0804844b		nop	
gef> 

 

4) inspect-stack : 스택 정보만 확인하기

코드가 아닌 스택 영역만 자세하게 확인하고 싶다면 “inspect-stack” 명령어를 사용한다.
출력되는 형태는 PEDA 와 매우 흡사하며, 포인터의 경우 값을 추적하여 보여주므로
매우 활용도가 높다. (이 도구를 써야하는 가장 첫번째 이유…적어도 내겐)

gef> inspect-stack 20
0xbffff438: 0xbffff438 -> 0x0
0xbffff43c: 0xbffff43c -> 0xb7e3a4d3 -> 0xb7e3a4d3 <__libc_start_main+243>: mov DWORD PTR [esp],eax
0xbffff440: 0xbffff440 -> 0x1
0xbffff444: 0xbffff444 -> 0xbffff4d4 -> 0xbffff649 -> "/root/gef_test"
0xbffff448: 0xbffff448 -> 0xbffff4dc -> 0xbffff658 -> "SSH_AGENT_PID=2836"
0xbffff44c: 0xbffff44c -> 0xb7fdc858 -> 0xb7e21000 -> 0xb7e21000: jg 0xb7e21047
0xbffff450: 0xbffff450 -> 0x0
0xbffff454: 0xbffff454 -> 0xbffff41c -> 0xb7e53e55 -> 0xb7e53e55 <__cxa_atexit+53>: add esp,0x18
0xbffff458: 0xbffff458 -> 0xbffff4dc -> 0xbffff658 -> "SSH_AGENT_PID=2836"
0xbffff45c: 0xbffff45c -> 0x0
0xbffff460: 0xbffff460 -> 0x0804822c -> 0x804822c: add BYTE PTR [edi+0x5f],bl
0xbffff464: 0xbffff464 -> 0xb7fc6ff4 -> 0x1a5d7c
0xbffff468: 0xbffff468 -> 0x0
0xbffff46c: 0xbffff46c -> 0x0
0xbffff470: 0xbffff470 -> 0x0
0xbffff474: 0xbffff474 -> 0x68d81d8e
0xbffff478: 0xbffff478 -> 0x5079b99e
0xbffff47c: 0xbffff47c -> 0x0
0xbffff480: 0xbffff480 -> 0x0
0xbffff484: 0xbffff484 -> 0x0
gef> 

 

5) 기타 기능들

“Checksec” 명령어를 사용하면 Security 관련 설정을 한번에 확인할 수 있다.

gef> checksec
[+] checksec for '/root/gef_test'
Canary:                                           No
NX Support:                                       Yes
PIE Support:                                      No
RPATH:                                            No
RUNPATH:                                          No
Partial RelRO:                                    Yes
Full RelRO:                                       No
gef> 

그외 “shellcode”, “pattern” 등의 나머지 기능들은 PEDA에서 제공되는 것과 큰 차이가 없으므로
사용 환경에 따라 PEDA / GEF를 선택하여 사용하면 되겠다.

 

GEF 마무리

지금까지 GEF – GDB Enhanced Feature에 대해 간단하게 알아보았다.
물론 이미 기존 GDB에 완벽하게 적응을 마친 Old Boys 들에게는 오히려 이런 도구들이
불편하게 느껴질 수도 있을 것이다.

하지만 워게임을 풀거나 리눅스 환경에서의 리버스 엔지니어링을 시작하는 이들에게는
단비와 같은 존재가 아닐까 싶다.

적어도 GDB 때문에 그만두고 싶다는 생각은 하지 않게 될 것이라 확신한다 🙂

 

Site Footer