본문 바로가기

Layer7/동아리 숙제

gdb를 활용한 간단한 바이너리 분석과 보고서 작성

1. Stack Frame
더보기

Stack Frame: Stack을 관리하는 일종의 기법

어떻게 관리하는가?

Stack Frame은 프링글스 칩처럼 값을 위에서 아래로 집어넣고, 나중에 넣은 순서대로 빼내는

LILO(Last Input Last Outpu)방식을 사용한다.

그래서 다른 함수로 들어갈때는 그자리에 백업할 복귀주소를 넣어준뒤,

모든 함수가 다 끝나면 그 부분의 Stack을 소멸시키고, 복귀주소로 넘어가준다.

 

* Stack Frame 함수 프롤로그

push rbp (rbp를 백업)
mov rbp, rsp (rbp를 rsp의 위치로 이동)

 

* Stack Frame 함수 에필로그

leave :
   mov rsp, rbp (esp의 위치는 ebp로 이동)
   pop rbp (rbp값을 빼감)
ret :
   pop rip (다음에 실행시킬 주소를 빼감)
   jmp rip (다음에 실행시킬 주소로 이동)

 

 

2. PLT & GOT
더보기

프로그램 코드

 

그 후 디버거로 실행시켜보면...

printf@plt 발견

printf함수는 알겠지만, plt는 무엇일까?

우선 용어의 정의와 뜻을 이렇다.

plt : 외부 프로시저를 연결해주는 테이블 / plt를 통해 다른 라이브러리에 있는 프로시저를 호출할 수 있다.

got: plt가 참조하는 테이블 / 프로시저들의 주소가 들어있다.

※프로시저: 프로그램을 여러개의 단위로 분해한 것

 

이제 디버깅을 해보자

디버깅을 하다 이 부분을 실행시키면 "what's your name? : "이 출력된다.

그리고 si로 이 함수를 따라들어가면...

1)

printf@plt는 rip+0x20065a로 jmp한다고 써져있다.

그리고 rip+0x20065a(0x600ba0)는 got의 주소값이다.

2)

0x600ba0의 값은 0x400546을 가르키고 있으므로 다시 0x400546(plt)로 이동한다.

3)

plt에서 0x400520(got)으로 jmp한다.

4)

got에서 rip+0x200664(_dl_runtime_resolve)으로 jmp한다.

여기에서 실제 함수의 주소가 got에 적힘

그후 si로 적히는 과정을 계속 들어가보면...

_dl_fixup 함수 호출
_dl_lookup_symbol_x 함수 호출
do_lookup_x 함수 호출
check_match 함수 호출

이렇게 계속 호출하고 마지막으로 printf를 호출하고 끝낸다.

 

만약 printf@plt 함수가 또 호출되면

위와 같은 과정을 거치치 않고, 바로 printf를 호출한다.

즉, 맨 처음 라이브러리에 있는 함수를 호출할 떄는

plt와 got를 사용해서 실제 함수의 주소를 got에 저장하지만,

두번째부터는 got의 있는 실제 함수의 주소값을 사용하면 되기 때문에

바로 그 함수를 호출할 수 있다.

 

 

3. 어셈블리 코드 흐름 간단하게 분석
더보기

어셈블리 코드는 직관적으로 위에서 아래로 흘러간다.

이를 디버거로 확인해보자.

다음 코드를 실행 시켜서 rsp값과 rbp값이 서로 같으면

코드가 위에서 아래로 흘러가는 것을 입증할 수 있다.

RBP값과 RSP값이 같음을 register영역에서도 확인할 수 있다.
명령어를 통해 rsp값과 rbp값이 서로 같음을 확인

이로써 어셈블리 코드는 위에서 아래로 흘러감을 증명했다.

 

 

4. 디버거 사용법 (gdb-peda)
더보기

1. 디버거 실행시키기

(실행시킬 소스코드가 있는 폴더에서) gdb 입력

실행 성공

2. 실행 파일 스캔하기

file [실행 파일]

file : getfile [실행 파일]과 profile [실행 파일] 명령어를 동시에 사용

   getfile [실행 파일] : 프로그램에서 디버깅할 프로세스를 해당 실행파일에서 가져옴

   profile [실행 파일] : 프로그램 내 실행 가능한 지시들을 세기 위해서 간단히 자료수집

 

3. 디버깅할 함수 찾기

disassemble [실행 시킬 함수]

그 함수를 어셈블리어로 보여줌
disassemble main의 실행 결과

4. 디버깅을 시작할 부분에 브레이크 포인트 걸어주기

b*[주소값]

함수 첫부분에 브레이크 포인트 걸어주기

- disassemble [함수]를 실행시켰을때 맨 처음 <+0>에 나타나는 주소값

 

5. 디버거 실행시키기

디버거를 재시작 할때도 사용
run의 실행결과

6. 메모리 검사

x/[출력시킬 갯수][출력단위][출력포멧] [레지스터]

- 출력시킬 갯수가 1이면 생략 가능

- 출력단위

b: 1바이트

h: 2바이트

w: 4바이트

g: 8바이트

- 출력포멧

o: 8진법

x: 16진법

u: 10진법

t: 2진법

- 레지스터 앞엔 $필요

 

7. 레지스터값 확인

info register [레지스터]

8. 다음 코드 실행 (함수 건너뛰고)

ni

9. 다음 코드 실행 (함수 포함)

si

10. 디버거 나가기

q

10. Tip

(1) 입력하다가 중간에 Tab을 두번 누르면 사용할 수 있는 명령어들이 출력됨

   ex) disassemble (Tab Tab) : disassemble 할 수 있는 함수들을 보여줌

disassemble 
_DYNAMIC                                _init
_GLOBAL_OFFSET_TABLE_                   _start
_IO_stdin_used                          completed
__FRAME_END__                           data_start
__GNU_EH_FRAME_HDR                      deregister_tm_clones
__JCR_END__                             frame_dummy
__JCR_LIST__                            gets
__TMC_END__                             gets@plt
__bss_start                             main
__data_start                            printf
__do_global_dtors_aux                   printf@plt
__do_global_dtors_aux_fini_array_entry  puts
__dso_handle                            puts@plt
__frame_dummy_init_array_entry          register_tm_clones
__init_array_end                        setup
__init_array_start                      setvbuf
__libc_csu_fini                         setvbuf@plt
__libc_csu_init                         stderr
__libc_start_main                       stderr@@GLIBC_2.2.5
__libc_start_main@plt                   stdin
_edata                                  stdin@@GLIBC_2.2.5
_end                                    stdout
_fini                                   stdout@@GLIBC_2.2.5

 

(2) PuTTy나 Xshell 등에서 복붙

   복사

Host: Ctrl+C

Client: Ctrl+Insert

   붙여넣기

Host: Ctrl+V

Client: Shift+Insert

 

(3) 디버거에서 똑같은 명령어 실행하기

그냥 Enter입력

ex) ni (Enter) (Enter) (Enter) (Enter) ...

'Layer7 > 동아리 숙제' 카테고리의 다른 글

BOF로 쉘따기  (0) 2020.08.16
Dreamhack 공부 내용 정리 및 문제풀이 (Reversing)  (0) 2020.08.07
python과 pwntools 활용법 익히기  (0) 2020.07.08
모두의 코드 C pointer 문제풀이  (0) 2020.07.03
Linux 환경 구축  (0) 2020.06.28