출처: http://huammmm1.tistory.com/494
http://cr3denza.blogspot.kr/2014/12/gdb-gnu-project-debuger-command.html
GDB (The GNU Project Debugger)
GDB는 컴퓨터 프로그램의 실행을 추적하고 수정할 수 있는 많은 기능들을 제공한다. 사용자는 프로그램의 내부 변수들의 값을 주시하거나 변경할 수 있으며, 프로그램의 일반적인 실행 과정과 독립적으로 함수를 호출할 수도 있다.
시스템 해킹에서 gdb를 사용할 경우 분석해야 하는 바이너리는 디버깅을 위해 컴파일 된 바이너리가 아니기 때문에 변수 이름이나 메인 함수 같은 디버깅을 위한 심볼이 없는 경우가 많다. 그렇기 때문에 심볼이 있어야만 사용 가능한 명령어들은 제외하고 자주 쓰이는 명령어를 잘 숙지해두는 것이 gdb에 익숙해지는데 도움이 된다.
1. gdb file
명시한 file을 gdb로 로드한다.
1-1. gdb -q file
-q 혹은 --quiet 옵션을 주면 gdb를 시작할 때 버전 정보 등을 출력하지 않도록 한다.
1-2. gdb --args file arg1 arg2
gdb 실행 시 --args 옵션을 주면 file과 함께 인자를 전달할 수 있다. (위 예에서는 arg1, arg2 전달)
2. run(r)
gdb로 로드한 프로그램을 실행한다.
참고로 run arg1 arg2 형태로 프로그램을 시작할 때 인자값을 넘길 수 있다.
아니면 처음에 gdb --args file arg1 arg2 이런식으로도 인자값을 전달할 수 있다.
3. disas(disassemble) function
function에 대한 disassemble을 수행 한다.
4. break *address
break *address 명령어는 address 위치에 브레이크 포인트를 설정한다
직접 주소값을 명시하거나 *main+3 이런식으로 사용할 수 있다
또는 break main
이렇게 사용할 수도 있다.
Break(b) func
Break(b) *func+5
Break(b) *0x8040000
Info break (I b) : 현재 걸려있는 모든 break point를 확인한다
Cl func : func함수에 걸린 브레이크포인트 지우기
Delete(d) : 브레이크포인트 모두 지우기
5. x
x 명령어는 주어진 주소 내의 메모리 값이 무엇인지를 확인하는 용도로 사용한다.
그리고 x 명령어에 addr이나 /nfu addr 등의 옵션을 줄 수 있다.
x/”범위”“출력형식”“범위의단위” “메모리주소 또는 함수명”
범위 : 범위의단위 * 범위byte 출력
출력형식 : x (16진수), s (문자열) , I (명령어)
범위의단위 : b (1byte), h(2byte), w(4byte), g(8byte)
EX)
x/20wx $esp : esp가 가리키는 메모리로부터 높은 주소 쪽으로 4byte씩 20개를 출력다.
x/10i $eip : 현재 eip의 명령어로부터 10줄의 어셈블리어를 출력한다.
x/s 0x8040000 : 0x8040000에서 시작하는 문자열을 출력한다.
- n (repeat count)
몇 개의 메모리 유닛을 보여줄건지 지정한다. n은 decimal integer로 지정되며 디폴트 값은 1이다. 메모리 유닛은 u로
지정된다.
- f (display format)
읽은 메모리 값을 어떻게 해석할 것인지를 지정한다. 디폴트 값은 x(hexadecimal)이고, 이 외에도 o(octal),
d(decimal), s(string), i(machine instruction) 등이 있다
- u(unit size)
읽을 메모리 유닛의 사이즈를 지정한다. 지정할 수 있는 옵션은 b(byte), h(two bytes), w(four bytes), g(eightbytes)
가 있다.
ex) x/x $esp
esp레지스터의 값(주소)이 가리키는 메모리 값을 16진수로 나타내라는 의미이다
위의 그림에서 현재 esp레지스터의 값은 0xbfffdccc이고, 0xbfffdccc 주소 내의 메모리 값은 0x42015574임을 확인할
수 있다.
한 가지 헷갈리는 점은, AT&T 문법에서는 레지스터의 값을 나타낼 때 레지스터 앞에 %를 붙이고, 상수를 나타낼 때
상수 앞에 $를 붙이는데(ex. %esp, $0x03), gdb에서 x/x 명령어를 사용할 때에는 레지스터 앞에 $를 붙여야 한다는
점이다. (왜그럴까)
ex) x/x $ebp+0xffffffd8
이런식으로 주소 위치에 expression이 들어갈 수도 있다.
해석하면 x/x $ebp+0xffffffd8은 ebp 레지스터가 들고 있는 값에 0xffffffd8을 더한 값을 주소로 명시하고, 해당 주소에
저장된 값을 16진수로 해석하라는 의미가 된다.
명령 수행의 결과에서 왼쪽 0xbfffdca0은 ebp값에 0xffffffd8을 더한 값이고, 오른쪽 0x42130ef8은 해당 주소에 저장
되있었던 값을 16진수로 표현한 결과이다.
ex) x/s
0x8048680 주소에 저장된 값을 string format으로 읽는다.
5-1. print variable
variable에 저장된 값을 출력 한다.
ex) print main
ex) print system
6. continue(c)
다음 브레이크포인트 전까지 코드를 실행한다.
Run(r) : 프로그램을 수행한다.
Run argv[1] argv[2] 형식으로 인자를 전달할 수 있다.
Kill(k) : 프로그램을 종료한다
Si : 다음 인스트럭션(명령어)을 실행하는데 만약 함수라면 함수 안으로 들어간다.
Ni : 다음 인스트럭션(명령어)을 실행한다. 함수 안으로 진입하지 않는다.
7. ni(nexti) [n]
라인 하나를 실행 하되 함수 호출문은 건너 뛴다. n을 명시 하면 n개 만큼 코드를 실행한다.
8. si(stepi) [n]
라인 하나를 실행 하되 함수 호출 시 해당 함수로 들어 간다. n을 명시 하면 n개 만큼 코드를 실행 한다.
9. delete [n]
설정했던 모든 브레이크 포인트들을 삭제한다. n을 명시해서 특정 브레이크 포인트만 삭제할 수도 있다.
10. info registers [register name]
레지스터들의 값들을 출력한다. register name을 지정해서 특정 레지스터에 대한 값만
확인할 수도 있다.
-AT&T 어셈블리어 명령어를 Intel 어셈블리어 명령어로 바꾸기
Set disassembly-flavor intel
- 특정 메모리에 원하는 값 넣기
Set {타입}”주소 또는 레지스터” = “값”
Set {int}0x8040000 = 123
Set {int}$edx = 123
- 매 실행 시 특정 명령어 반복하기
Disp/5I $eip : 매 명령마다 eip에서부터 5줄의 어셈블리어 코드를 출력한다.
Disp/4x $esp : 매 명령마다 esp에서부터 16byte의 스택을 출력한다.
Disp는 명령어를 쌓아서 명령 시 원하는 출력이 보기게 할 수 있다.
- shell 실행하기
!명령어 : !뒤에 shell 명령어를 입력하여 실행할 수 있다.
!ps : 현재 돌고 있는 프로세스를 볼 수 있다.
!cat /proc/$pid/maps : $pid의 프로세스의 전체적인 메모리 상태를 볼 수 있다.
11. quit (혹은 q)
gdb를 종료한다.
'IT기술 관련 > 리눅스' 카테고리의 다른 글
linux 환경에서의 메모리 보호기법을 알아보자(1) (0) | 2016.09.30 |
---|---|
쉘코드 뒤에 여유 공간이 필요한 경우 by ORANG (0) | 2016.09.30 |
리눅스 각 기본계정별 설명입니다. (0) | 2016.09.27 |
/bin/false, /sbin/nologin 의 차이점 (0) | 2016.09.27 |
[Linux] 리눅스 열린 포트 및 프로세스 확인 (0) | 2016.09.26 |