OLD 2018 ~ 2021/BASIC → Hacking
[System Hacking ] PLT / GOT 영역
pogn
2018. 7. 10. 21:40
이론적 배경 |
Linking
: 실행파일이 호출하는 라이브러리의 API 함수를 정상적으로 실행시킬 수 있도록
라이브러리의 printf 오브젝트 파일을 서로 연결시켜 주는 과정이다.
Static Link
: 파일 생성시에 라이브러리 파일을 실행파일에 포함하기 때문에
따로 라이브러리를 설치할 필요가 없으며
실행 시에도 라이브러리 연동과정이 필요없다.
Dynamic Link
: 메모리에 로딩시킨 라이브러리를 여러 프로그램이 공유한다.
이 때에, PLT와 GOT는
다이나믹 링킹과정에서 프로그램이 해당 라이브러리의 위치를 찾아가기 위해 쓰이는 영역이다.
PLT/GOT 함수 호출과정 |
junior@catpwn:~/System_Hacking$ gdb -q ./plt_got
Reading symbols from ./plt_got...(no debugging symbols found)...done.
(gdb) disas main
Dump of assembler code for function main:
0x08048444 <+0>: push %ebp
0x08048445 <+1>: mov %esp,%ebp
0x08048447 <+3>: push $0x8048521
0x0804844c <+8>: call 0x80482e0 <puts@plt>
0x08048451 <+13>: add $0x4,%esp
0x08048454 <+16>: push $0x804852e
0x08048459 <+21>: call 0x80482e0 <puts@plt>
0x0804845e <+26>: add $0x4,%esp
0x08048461 <+29>: push $0x8048536
0x08048466 <+34>: call 0x80482e0 <puts@plt>
0x0804846b <+39>: add $0x4,%esp
0x0804846e <+42>: call 0x804840b <func1>
0x08048473 <+47>: call 0x804841e <func2>
0x08048478 <+52>: mov $0x0,%eax
0x0804847d <+57>: leave
0x0804847e <+58>: ret
End of assembler dump.
|
먼저, puts 함수 부분을 보면 call하는 함수명이 puts@plt로 되어있다.
(gdb) b *main+8
Breakpoint 1 at 0x804844c
(gdb) r
Starting program: /home/junior/System_Hacking/plt_got
Breakpoint 1, 0x0804844c in main ()
(gdb) disas main
Dump of assembler code for function main:
0x08048444 <+0>: push %ebp
0x08048445 <+1>: mov %esp,%ebp
0x08048447 <+3>: push $0x8048521
=> 0x0804844c <+8>: call 0x80482e0 <puts@plt>
0x08048451 <+13>: add $0x4,%esp
0x08048454 <+16>: push $0x804852e
0x08048459 <+21>: call 0x80482e0 <puts@plt>
0x0804845e <+26>: add $0x4,%esp
0x08048461 <+29>: push $0x8048536
0x08048466 <+34>: call 0x80482e0 <puts@plt>
0x0804846b <+39>: add $0x4,%esp
0x0804846e <+42>: call 0x804840b <func1>
0x08048473 <+47>: call 0x804841e <func2>
0x08048478 <+52>: mov $0x0,%eax
0x0804847d <+57>: leave
0x0804847e <+58>: ret
End of assembler dump.
|
이부분에 브레이크 포인트를 걸고 실행시켜 함수를 puts바로 직전까지 실행시켰다.
(gdb) x/3i 0x80482e0
0x80482e0 <puts@plt>: jmp *0x804a00c
0x80482e6 <puts@plt+6>: push $0x0
0x80482eb <puts@plt+11>: jmp 0x80482d0
(gdb) x/wx 0x804a00c
0x804a00c: 0x080482e6
|
"함수명"@plt의 어셈코드는 세 줄이며,
puts가 처음 실행되는 순간에는 *0x804a00c에 0x80482e6 , 즉 그냥 다음 실행코드가 들어있다 .
(gdb) x/2i 0x80482d0
0x80482d0: pushl 0x804a004 // 링크맵 구조체 포인터
0x80482d6: jmp *0x804a008
(gdb) x/xw 0x804a008
0x804a008: 0xf7fee000
(gdb) x/10i 0xf7fee000
0xf7fee000 <_dl_runtime_resolve>: push %eax
0xf7fee001 <_dl_runtime_resolve+1>: push %ecx
0xf7fee002 <_dl_runtime_resolve+2>: push %edx
0xf7fee003 <_dl_runtime_resolve+3>: mov 0x10(%esp),%edx
0xf7fee007 <_dl_runtime_resolve+7>: mov 0xc(%esp),%eax
0xf7fee00b <_dl_runtime_resolve+11>: call 0xf7fe77e0 <_dl_fixup>
0xf7fee010 <_dl_runtime_resolve+16>: pop %edx
0xf7fee011 <_dl_runtime_resolve+17>: mov (%esp),%ecx
0xf7fee014 <_dl_runtime_resolve+20>: mov %eax,(%esp)
0xf7fee017 <_dl_runtime_resolve+23>: mov 0x4(%esp),%eax
(gdb) b *0xf7fee00b
Breakpoint 6 at 0xf7fee00b: file ../sysdeps/i386/dl-trampoline.S, line 43.
(gdb) c
Continuing.
Breakpoint 6, _dl_runtime_resolve () at ../sysdeps/i386/dl-trampoline.S:43
43 ../sysdeps/i386/dl-trampoline.S: 그런 파일이나 디렉터리가 없습니다.
(gdb) x/10i 0xf7fee000
0xf7fee000 <_dl_runtime_resolve>: push %eax
0xf7fee001 <_dl_runtime_resolve+1>: push %ecx
0xf7fee002 <_dl_runtime_resolve+2>: push %edx
0xf7fee003 <_dl_runtime_resolve+3>: mov 0x10(%esp),%edx
0xf7fee007 <_dl_runtime_resolve+7>: mov 0xc(%esp),%eax
=> 0xf7fee00b <_dl_runtime_resolve+11>: call 0xf7fe77e0 <_dl_fixup>
0xf7fee010 <_dl_runtime_resolve+16>: pop %edx
0xf7fee011 <_dl_runtime_resolve+17>: mov (%esp),%ecx
0xf7fee014 <_dl_runtime_resolve+20>: mov %eax,(%esp)
0xf7fee017 <_dl_runtime_resolve+23>: mov 0x4(%esp),%eax
|
0x80482d0를 따라가 보면 _dll_runtime_resolve 함수가 시작된다.
_dll_fixup 함수를 call 하는 것을 볼 수 있다.
이 부분에 브레이크 포인트를 걸고 따라 들어가면
(gdb) x/100i 0xf7fe77e0
0xf7fe77e0 <_dl_fixup>: push %ebp
0xf7fe77e1 <_dl_fixup+1>: push %edi
0xf7fe77e2 <_dl_fixup+2>: mov %eax,%edi
0xf7fe77e4 <_dl_fixup+4>: push %esi
0xf7fe77e5 <_dl_fixup+5>: push %ebx
0xf7fe77e6 <_dl_fixup+6>: call 0xf7ff276d <__x86.get_pc_thunk.si>
0xf7fe77eb <_dl_fixup+11>: add $0x15815,%esi
0xf7fe77f1 <_dl_fixup+17>: sub $0x2c,%esp
0xf7fe77f4 <_dl_fixup+20>: mov 0x7c(%edi),%ecx
0xf7fe77f7 <_dl_fixup+23>: mov 0x34(%eax),%eax
0xf7fe77fa <_dl_fixup+26>: mov %esi,0x8(%esp)
0xf7fe77fe <_dl_fixup+30>: add 0x4(%ecx),%edx
0xf7fe7801 <_dl_fixup+33>: mov 0x4(%eax),%eax
0xf7fe7804 <_dl_fixup+36>: mov 0x38(%edi),%ecx
0xf7fe7807 <_dl_fixup+39>: mov %eax,0xc(%esp)
0xf7fe780b <_dl_fixup+43>: mov %edx,%ebp
0xf7fe780d <_dl_fixup+45>: mov 0x4(%edx),%edx
0xf7fe7810 <_dl_fixup+48>: mov 0x0(%ebp),%eax
0xf7fe7813 <_dl_fixup+51>: mov %edx,%esi
0xf7fe7815 <_dl_fixup+53>: shr $0x8,%esi
0xf7fe7818 <_dl_fixup+56>: mov %esi,%ebx
0xf7fe781a <_dl_fixup+58>: shl $0x4,%ebx
0xf7fe781d <_dl_fixup+61>: add 0x4(%ecx),%ebx
0xf7fe7820 <_dl_fixup+64>: mov (%edi),%ecx
0xf7fe7822 <_dl_fixup+66>: add %ecx,%eax
0xf7fe7824 <_dl_fixup+68>: cmp $0x7,%dl
0xf7fe7827 <_dl_fixup+71>: mov %ebx,0x1c(%esp)
0xf7fe782b <_dl_fixup+75>: jne 0xf7fe796f <_dl_fixup+399>
0xf7fe7831 <_dl_fixup+81>: testb $0x3,0xd(%ebx)
0xf7fe7835 <_dl_fixup+85>: mov %eax,%ebp
0xf7fe7837 <_dl_fixup+87>: jne 0xf7fe7910 <_dl_fixup+304>
0xf7fe783d <_dl_fixup+93>: mov 0xe4(%edi),%edx
0xf7fe7843 <_dl_fixup+99>: test %edx,%edx
0xf7fe7845 <_dl_fixup+101>: je 0xf7fe78f0 <_dl_fixup+272>
---Type <return> to continue, or q <return> to quit---
0xf7fe784b <_dl_fixup+107>: mov 0x4(%edx),%edx
0xf7fe784e <_dl_fixup+110>: movzwl (%edx,%esi,2),%edx
0xf7fe7852 <_dl_fixup+114>: and $0x7fff,%edx
0xf7fe7858 <_dl_fixup+120>: shl $0x4,%edx
0xf7fe785b <_dl_fixup+123>: add 0x170(%edi),%edx
0xf7fe7861 <_dl_fixup+129>: mov 0x4(%edx),%ecx
0xf7fe7864 <_dl_fixup+132>: test %ecx,%ecx
0xf7fe7866 <_dl_fixup+134>: mov $0x0,%ecx
0xf7fe786b <_dl_fixup+139>: cmove %ecx,%edx
0xf7fe786e <_dl_fixup+142>: mov %gs:0xc,%ecx
0xf7fe7875 <_dl_fixup+149>: test %ecx,%ecx
0xf7fe7877 <_dl_fixup+151>: mov $0x1,%esi
0xf7fe787c <_dl_fixup+156>: jne 0xf7fe7950 <_dl_fixup+368>
0xf7fe7882 <_dl_fixup+162>: mov 0xc(%esp),%eax
0xf7fe7886 <_dl_fixup+166>: add (%ebx),%eax
0xf7fe7888 <_dl_fixup+168>: lea 0x1c(%esp),%ecx
0xf7fe788c <_dl_fixup+172>: sub $0xc,%esp
0xf7fe788f <_dl_fixup+175>: push $0x0
0xf7fe7891 <_dl_fixup+177>: push %esi
0xf7fe7892 <_dl_fixup+178>: push $0x1
0xf7fe7894 <_dl_fixup+180>: push %edx
0xf7fe7895 <_dl_fixup+181>: mov %edi,%edx
0xf7fe7897 <_dl_fixup+183>: pushl 0x1cc(%edi)
0xf7fe789d <_dl_fixup+189>: call 0xf7fe2a60 <_dl_lookup_symbol_x>
(gdb) b *0xf7fe789d
Breakpoint 7 at 0xf7fe789d: file dl-runtime.c, line 111.
(gdb) c
Continuing.
Breakpoint 7, 0xf7fe789d in _dl_fixup (l=0xf7ffd918, reloc_arg=<optimised out>)
at dl-runtime.c:111
111 dl-runtime.c: 그런 파일이나 디렉터리가 없습니다.
(gdb) i r $eax
eax 0x8048236 134513206
(gdb) x/s 0x8048236
0x8048236: "puts"
(gdb) x/10wx 0xf7e1ba48
0xf7e1ba48: 0x00000edc 0x0005fca0 0x000001d0 0x000d0022
0xf7e1ba58: 0x00001522 0x000eb2b0 0x0000007a 0x000d0012
0xf7e1ba68: 0x00001e86 0x0002f100
|
위와 같이 _dl_lookup_symbol_x라는 함수를 발견할 수 있다.
이부분에도 역시 브레이크포인트를 걸어서 해당 부분까지 실행시킨다음에
반환된 레지스터 값은 strtab에 들어있는 puts 라는 문자열의 주소이다.
그리고, symtab에는 실제 심볼들의 offset이 들어있는데,
이 곳에서 공유라이브러리의 시작주소와 실제 puts 함수의 구현 코드 사이의 거리를 알 수 있다.
따라서
>>> hex(0x5fca0+0xf7597000)
'0xf75f6ca0'
값이 puts 함수 코드의 위치임을 알수 있다.
두 번째 puts 함수 호출부터는 아까 다음코드를 가리키던 어셈블리어쪽에
plt 주소가 들어가 있어서 조금 더 빠른 호출이 가능하다.
PLT / GOT |