둘둘리둘둘리둘둘리둘둘리둘둘리둘
.plt .got 동작과정 본문
#include <stdio.h>
int main(){
printf("hello\n");
printf("rekcah\n");
return 0;
}
위의 소스를 예로 들어 설명함.
먼저 간략하게 설명하자면 main에서 printf 호출시 printf@plt를 호출하고 plt가 got에서 함수의 주소를 찾고 그 함수가 없으면 _dl_runtime_resolve를 통해서 함수를 찾는다.(_dl_runtime_resolve에서 got에 함수 주소를 입력해 이후로는 함수를 쉽게 찾을 수 있도록 한다)
소스 코드를 보면 <main+36>과 <main+52>에서 호출하는 0x080482b0 <_init+56>이 printf임을 짐작할 수 있다. main+36부터 따라가 보자.
_init을 disassamble하고 <main+36>에서 호출한 <_init+56>부터 보면
ds:0x08049590으로 jump한다 그럼 ds:0x08049590을 보자.
(gdb) x/x 0x08049590
0x8049590 <_GLOBAL_OFFSET_TABLE_+16>: 0x080482b6
0x080482b6이고.. 0x080482b6은 <_init+62>d이다 .. 위에 보이듯이 0x08049590은 global offset table 즉 got영역이다. 앞서 설명했듯이 함수 호출순서가 plt -> got -> printf 니까 got이전에서 참조한 0x080482b0이 plt영역이다.
그런데 plt에서 got영역을 참조하고 다시 plt영역으로 돌아왔다(정확하게는 init+56 -> got -> init+62) 이는 got에서 printf 주소를 찾지 못했음을 뜻하고 다시 init+56을 따라가보면 0x08을 push하고 init+24로 돌아가 ds:0x08049584(GOT+4)를 push하고 ds:0x08049588(GOT+8:_dl_runtime_resolve)로 jump한다..
그 후 _dl_runtime_resolve를 수행하며 아래와 같이 got+16에 실제 printf의 주소를 입력하고 printf를 수행한다.
(gdb) x/x 0x08049590
0x8049590 <_GLOBAL_OFFSET_TABLE_+16>: 0x0075e660
(gdb) x/20i 0x0075e660
0x75e660 <printf>: push ebp
0x75e661 <printf+1>: mov ebp,esp
0x75e663 <printf+3>: lea eax,[ebp+12]
0x75e666 <printf+6>: push ebx
0x75e667 <printf+7>: sub esp,0xc
0x75e66a <printf+10>: mov ecx,DWORD PTR [ebp+8]
0x75e66d <printf+13>: call 0x730c71 <__i686.get_pc_thunk.bx>
0x75e672 <printf+18>: add ebx,0xe0982
0x75e678 <printf+24>: mov DWORD PTR [esp+8],eax
0x75e67c <printf+28>: mov edx,DWORD PTR [ebx-416]
0x75e682 <printf+34>: mov DWORD PTR [esp+4],ecx
0x75e686 <printf+38>: mov eax,DWORD PTR [edx]
0x75e688 <printf+40>: mov DWORD PTR [esp],eax
0x75e68b <printf+43>: call 0x755f80 <vfprintf>
0x75e690 <printf+48>: add esp,0xc
0x75e693 <printf+51>: pop ebx
0x75e694 <printf+52>: pop ebp
0x75e695 <printf+53>: ret
이 다음 printf를 호출할 경우 아래와 같이 plt에서 got+16이 가지고있는 printf의 실제 주소를 바로 호출할 수 있게 된다,
(gdb) b *main+52
Breakpoint 2 at 0x804839c
(gdb) c
Continuing.
Breakpoint 2, 0x0804839c in main ()
(gdb) si
0x080482b0 in ?? ()
'Linux > Reversing' 카테고리의 다른 글
gdb-peda 설치 (0) | 2016.02.28 |
---|---|
IDA를 이용한 리눅스 원격 디버깅 (0) | 2015.12.30 |
ROPeMe (ROP Exploit Made Easy) (0) | 2015.11.17 |
64비트 elf 인자전달방식 (0) | 2015.10.07 |
칼리 리눅스에 버추얼박스 게스트 확장 설치 (0) | 2015.10.07 |