[GDB] gdb에서 입력 함수에 호출 지점 찾고 싶을 때

GDB를 사용하다 보면 입력을 받는 함수인 read에서 breakpoint를 걸고 싶을 때가 있다.

이때 함수 목록에서 해당 입력을 수행하는 함수에 모두 breakpoint를 거는 것보다 더 유용한 기술을 소개하려고 한다.

명령어

catch syscall read

catch syscall 이후 read 외에도 여러 이벤트에 브레이크 포인트를 걸 수 있는데, 해당 OS의 unistd.h 헤더파일을 참조하면 된다.

예). i686-linux-android : https://github.com/EdgeApp/android-ndk-linux/blob/master/sysroot/usr/include/i686-linux-android/asm/unistd_64.h

List up

#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4
#define __NR_fstat 5
#define __NR_lstat 6
#define __NR_poll 7
#define __NR_lseek 8
#define __NR_mmap 9
#define __NR_ioctl 16
#define __NR_socket 41
#define __NR_sendto 44
#define __NR_recvfrom 45
#define __NR_sendmsg 46
#define __NR_recvmsg 47
#define __NR_fork 57
#define __NR_exit 60

** [0] Read

ssize_t read(int fd, void buf[count], size_t count);

해당 read 함수의 원형이다.

read 함수에 브레이크 포인트를 걸었을 때 buf와 count에 집중하기보다는 콜스택을 통해 해당 함수를 호출한 프로그램 내부의 주소가 더 중요하다. 이때 catch syscall read함수를 통해 브레이크 포인트가 걸리면 bt를 통해 콜스택을 보고 하나하나 들어가서 확인해보면 된다. 나는 주로 ghidra의 codeBrowser를 통해 해당 코드가 프로그램의 코드인지 같이 판별한다.

실제 해보면 read함수에 브레이크 포인트가 걸리기 전에 read_nocancel.c처럼 read와 관련된 함수에서 걸리기도 하는데 그럴때는 쭈욱 continue를 해주면 된다. bt를 했을 때, 사용자의 코드를 한번에 찾아가는법은 libc의 호출주소와 다른게 눈에 딱 보인다.

bt 명령어 입력시

여기서 프로그래머가 작성한 코드 위치는 0x55로 시작하는 주소이고, 0x7f로 시작하는 주소는 공유 라이브러리 주소이다.

0x0000555555555516a 주소에 가보면 아래 이미지처럼 되어있다.

read함수를 호출하는 사용자의 함수

여기서 ghidra의 codeBrowser의 Decompiler를 이용하기 위해서는 해당 주소로 가야 하는데,

ImageBase를 실행중인 프로그램의 ImageBase와 동일하게 맞춰야 한다. (아니면 직접 계산도 가능함)

먼저 info proc mappings를 통해 offset이 0x0의 Start Addr 주소를 구한다. (이는 ImageBase와 동일하다.)

Ghidra-Window-Set Image Base에서 위에서 구한 ImageBase 주소값으로 설정한다.

gdb와 Ghidra Code Browser Imagebase 맞추기

** 참고자료

https://sourceware.org/gdb/current/onlinedocs/gdb.html/Set-Catchpoints.html

https://github.com/EdgeApp/android-ndk-linux/blob/master/sysroot/usr/include/i686-linux-android/asm/unistd_64.h

https://man7.org/linux/man-pages/man2/read.2.html


게시됨

카테고리

작성자

태그:

댓글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다