gdb

보안/드림핵 / / 2020. 7. 17. 23:32
반응형

ELF의 동적 분석을 위한 도구로는 gdb, strace, ltrace, IDA 등이 있습니다. 이 코스에서는 가장 유명한 ELF 디버거인 gdb(GNU Debugger)를 사용하여 ELF 바이너리를 동적 디버깅하는 방법에 대해 알아보겠습니다.


-------------------------------------------------------------------------------------------------------------------

설정


gdb의 디스어셈블리 문법에는 AT&T와 intel 두 종류가 있습니다. 이 중 널리 쓰이는 디스어셈블리 문법은 intel 입니다. gdb 기본 설정에서의 디스어셈블리 문법은 AT&T이기 때문에, 디버깅 실습을 하기 전에 gdb의 디스어셈블리 문법을 intel로 바꾸어 주어야 합니다.


.gdbinit는 gdb를 시작할 때 자동적으로 실행할 gdb 명령어들을 저장하고 있는 파일입니다.


echo "set disassembly-flavor intel" >> ~/.gdbinit

명령어를 통해 gdb 실행시 자동으로 디스에셈블리 문법을 intel로 바꾸어주자


다음 명령어를 통해 .gdbinit에 gdb의 디스어셈블리 문법을 intel로 바꾸어 주는 명령어인 set disassembly-flavor intel을 추가할 수 있습니다.

-----------------------------------------------------------------------------------------------------------------


명령어

example0파일 gdb 실행

gdb ./example0


함수의 디스어셈블리 결과를 출력해주는 명령어

disas or disassemble

ex)main함수 디스어셈블리 결과 

disas main


 gdb에서 브레이크포인트를 설정하는 명령어

break or b 

ex)0x804842e주소에 브레이크 포인트를 설정하기

b *0x804842e


break 포인트 설정 확인하기

info break


브레이크 포인트가 설정된 지점까지 실행

r


프로세스가 멈추어 있는 상태에서 프로세스를 이어서 실행시켜주는 명령어

continue or c



스택메모리 살펴보기

x

x명령어는 또한 출력 타입을 지정해 줄수 있습니다.


ex)esp레지스터의 메모리를 word 타입으로 2개만큼 출력해보기

x/2wx $esp

ex)문자열의 주소 0x80484d0을 문자열 형태로 출력

x/s 0x80484d0



함수의 다음 인스트럭션(명령) 까지 실행해주는 명령어

nexti or ni



-------------------------------------------------------------------------------------------------------------------



Process Attach


gdb를 이용하면 실행중인 프로세스를 디버깅 할 수 있습니다.


./read_write를 실행시키고 다른 터미널을 열어줍니다.


gdb에  -p PID  or --pid=PID를 인자로 전달하면 PID에 해당하는 프로세스에 gdb를 attach할수 있습니다.




실행중인 프로세스의 PID를 확인하는 여러가지 방법


-ps프로그램을 이용하는방법

ps -aux | grep read_write 를 실행하면 출력되는 두번째 인자가 해당 프로그램에 PID입니다.


-pidof or pgrep프로그램을 사용하여 프로세스의 PID를 구하는 방법

pidof read_write

pgrep read_write




알아낸 PID를 통해 gdb를 프로세스에 attach 시키기

gdb -q -p <PID>





명령어



함수의 이름과 주소를 출력

info functions


main함수의 디스어셈블리를 출력

disas main


주소에 breakpoint를 설정

b


breakpoint 정보출력

info b


프로그램 처음부터 실행

r


매 실행시 인자로 전달된 값을 출력

display

display [변수명]  : 변수 값을 매번 화면에 디스플레이

display/[출력형식] [변수명] : 변수 값을 출력 형식으로 디스플레이

undisplay [디스플레이번호] : 디스플레이 설정을 없앤다

disable display [디스플레이번호] : 디스플레이를 일시 중단한다.

enable display [디스플레이번호] : 디스플레이를 다시 활성화한다.


다음 브레이크포인트까지 설정

c


명령어 1개 실행

si(step instruction)

ni(next instruction)

stepi nexti 차이

nexti를 하자 call을 따라 가는 것이 아니라 다음 명령으로 넘어간 것을 볼 수 있다

stepi 는 call 한 명령어를 따라가서 수행하는 것을 볼 수 있다.

참고

https://terrorjang.tistory.com/6



현재 함수를 모두 실행

finish


레지스터 정보 출력

info reg


지정된 메모리 영역을 특정 단위로 표현

x/


print,인자로 전달된 값을 출력

p


브레이크포인트 번호에 해당하는 브레이크포인트 삭제

delete [break number]


gdb종료

quit


---------------------------------------------------------------------------------------------------------------------

NOP Sled 계산시 주소 계산하기

p/x 주소 + 주소


NX bit 적용 확인을 위한 메모리맵 확인

shell cat /proc/`pidof <프로그램명>`/maps


--NX bit가 설정되어 있는지 확인하는 방법 

바이너리의 NX bit적용 여부를 알아내는 것은 스택 메모리의 권한을 검사하는 것으로도 충분합니다.

ELF 바이너리 분석 도구인 readelf를 사용하면 NX bit 적용 여부를 쉽게 확인할 수 있습니다.

readelf -a ./example1 | grep STACK

readelf -a ./example1 | grep STACK

NX bit가 적용된 것과 NX bit가 적용되지 않은 것을 확인해보면

적용되지 않을경우 STACK에 권한이 RWE 이지만 적용되어있는경우 RW(읽기,쓰기)만 있는것을 알수 있습니다.



NX bit가 적용되어 있을경우 libc.so.6라이브러리 코드영역 주소 확인

info proc map


pritf 주소 확인

p printf


system 주소 확인

p system



"/bin/sh " 찾기


-메모리맵 확인

info proc map

0xf7e03000 0xf7fb3000   0x1b0000        0x0 /lib/i386-linux-gnu/libc-2.23.so

0xf7fb3000 0xf7fb5000     0x2000   0x1af000 /lib/i386-linux-gnu/libc-2.23.so

0xf7fb5000 0xf7fb6000     0x1000   0x1b1000 /lib/i386-linux-gnu/libc-2.23.so


-system 함수의 주소 확인

p system

$1 = {<text variable, no debug info>} 0xf7e3dda0 <system>


-system함수가 있는 메모리 범위에서 "/bin/sh" 착기

find 0xf7e03000, 0xf7fb3000, "bin/sh"

0xf7f5ea0b



"/bin/sh"주소 확인해보기

x/s 0xf7f5ea0b






드림핵참조

https://dreamhack.io/learn/2

반응형

'보안 > 드림핵' 카테고리의 다른 글

셸코드  (1) 2020.07.20
시스템해킹(취약점 종류)  (0) 2020.07.13
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기