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는 무엇일까?
우선 용어의 정의와 뜻을 이렇다.
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로 적히는 과정을 계속 들어가보면...




이렇게 계속 호출하고 마지막으로 printf를 호출하고 끝낸다.
만약 printf@plt 함수가 또 호출되면

즉, 맨 처음 라이브러리에 있는 함수를 호출할 떄는
plt와 got를 사용해서 실제 함수의 주소를 got에 저장하지만,
두번째부터는 got의 있는 실제 함수의 주소값을 사용하면 되기 때문에
바로 그 함수를 호출할 수 있다.
3. 어셈블리 코드 흐름 간단하게 분석
어셈블리 코드는 직관적으로 위에서 아래로 흘러간다.

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




다음 코드를 실행 시켜서 rsp값과 rbp값이 서로 같으면
코드가 위에서 아래로 흘러가는 것을 입증할 수 있다.


이로써 어셈블리 코드는 위에서 아래로 흘러감을 증명했다.
4. 디버거 사용법 (gdb-peda)
1. 디버거 실행시키기
(실행시킬 소스코드가 있는 폴더에서) gdb 입력


2. 실행 파일 스캔하기
file [실행 파일]

file : getfile [실행 파일]과 profile [실행 파일] 명령어를 동시에 사용
getfile [실행 파일] : 프로그램에서 디버깅할 프로세스를 해당 실행파일에서 가져옴
profile [실행 파일] : 프로그램 내 실행 가능한 지시들을 세기 위해서 간단히 자료수집
3. 디버깅할 함수 찾기
disassemble [실행 시킬 함수]


4. 디버깅을 시작할 부분에 브레이크 포인트 걸어주기
b*[주소값]

- disassemble [함수]를 실행시켰을때 맨 처음 <+0>에 나타나는 주소값
5. 디버거 실행시키기


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 |