got.c 코드는 아래 처럼 강의와 똑같이 했습니다.
// Name: got.c
// Compile: gcc -o got got.c
#include <stdio.h>
int main() {
puts("Resolving address of 'puts'.");
puts("Get address from GOT");
}
컴파일도 별다른 옵션을 주지 않고
gcc -o got got.c
로 했습니다.
다음은 gdb입니다.
gdb-peda$ start
gdb-peda$ disass main
Dump of assembler code for function main:
=> 0x0000555555555149 <+0>: endbr64
0x000055555555514d <+4>: push rbp
0x000055555555514e <+5>: mov rbp,rsp
0x0000555555555151 <+8>: lea rdi,[rip+0xeac] # 0x555555556004
0x0000555555555158 <+15>: call 0x555555555050 puts@plt
0x000055555555515d <+20>: lea rdi,[rip+0xebd] # 0x555555556021
0x0000555555555164 <+27>: call 0x555555555050 puts@plt
0x0000555555555169 <+32>: mov eax,0x0
0x000055555555516e <+37>: pop rbp
0x000055555555516f <+38>: ret
End of assembler dump.
gdb-peda$ b *main+15
gdb-peda$ c
0x55555555514d <main+4>: push rbp
0x55555555514e <main+5>: mov rbp,rsp
0x555555555151 <main+8>: lea rdi,[rip+0xeac] # 0x555555556004
=> 0x555555555158 <main+15>: call 0x555555555050 puts@plt
0x55555555515d <main+20>: lea rdi,[rip+0xebd] # 0x555555556021
0x555555555164 <main+27>: call 0x555555555050 puts@plt
0x555555555169 <main+32>: mov eax,0x0
0x55555555516e <main+37>: pop rbp
gdb-peda$ si
0x555555555040 __cxa_finalize@plt: endbr64
0x555555555044 <__cxa_finalize@plt+4>: bnd jmp QWORD PTR [rip+0x2fad] # 0x555555557ff8
0x55555555504b <__cxa_finalize@plt+11>: nop DWORD PTR [rax+rax1+0x0]
=> 0x555555555050 puts@plt: endbr64
0x555555555054 <puts@plt+4>: bnd jmp QWORD PTR [rip+0x2f75] # 0x555555557fd0 puts@got.plt
0x55555555505b <puts@plt+11>: nop DWORD PTR [rax+rax1+0x0]
0x555555555060 <_start>: endbr64
0x555555555064 <_start+4>: xor ebp,ebp
gdb-peda$ ni
0x555555555044 <__cxa_finalize@plt+4>: bnd jmp QWORD PTR [rip+0x2fad] # 0x555555557ff8
0x55555555504b <__cxa_finalize@plt+11>: nop DWORD PTR [rax+rax1+0x0]
0x555555555050 puts@plt: endbr64
=> 0x555555555054 <puts@plt+4>: bnd jmp QWORD PTR [rip+0x2f75] # 0x555555557fd0 puts@got.plt
0x55555555505b <puts@plt+11>: nop DWORD PTR [rax+rax1+0x0]
0x555555555060 <_start>: endbr64
0x555555555064 <_start+4>: xor ebp,ebp
0x555555555066 <_start+6>: mov r9,rdx
puts 함수 첫번째 호출이지만 밑줄로 안 보내고 다른 곳으로 날려버립니다.
gdb-peda$ ni
0x7ffff7e4f40f <_IO_new_popen+143>: jmp 0x7ffff7e4f3e4 <_IO_new_popen+100>
0x7ffff7e4f411: nop WORD PTR cs:[rax+rax1+0x0]
0x7ffff7e4f41b: nop DWORD PTR [rax+rax1+0x0]
=> 0x7ffff7e4f420 <__GI__IO_puts>: endbr64
0x7ffff7e4f424 <__GI__IO_puts+4>: push r14
0x7ffff7e4f426 <__GI__IO_puts+6>: push r13
0x7ffff7e4f428 <__GI__IO_puts+8>: push r12
0x7ffff7e4f42a <__GI__IO_puts+10>: mov r12,rdi
###그럼 갑자기 __GI__IO_puts라는 함수(?) 가 시작됩니다.
gdb-peda$ disass __GI__IO_put 해보면 다음과 같습니다.
0x00007ffff7e4f420 <+0>: endbr64
0x00007ffff7e4f424 <+4>: push r14
0x00007ffff7e4f426 <+6>: push r13
=> 0x00007ffff7e4f428 <+8>: push r12
0x00007ffff7e4f42a <+10>: mov r12,rdi
0x00007ffff7e4f42d <+13>: push rbp
0x00007ffff7e4f42e <+14>: push rbx
0x00007ffff7e4f42f <+15>: call 0x7ffff7ded460 *ABS*+0x9f630@plt
0x00007ffff7e4f434 <+20>: mov r13,QWORD PTR [rip+0x167b0d] # 0x7ffff7fb6f48
0x00007ffff7e4f43b <+27>: mov rbx,rax
0x00007ffff7e4f43e <+30>: mov rbp,QWORD PTR [r13+0x0]
0x00007ffff7e4f442 <+34>: mov edx,DWORD PTR [rbp+0x0]
0x00007ffff7e4f445 <+37>: and edx,0x8000
0x00007ffff7e4f44b <+43>: jne 0x7ffff7e4f4b0 <__GI__IO_puts+144>
0x00007ffff7e4f44d <+45>: mov r8,QWORD PTR [rbp+0x88]
0x00007ffff7e4f454 <+52>: mov r14,QWORD PTR fs:0x10
0x00007ffff7e4f45d <+61>: cmp QWORD PTR [r8+0x8],r14
0x00007ffff7e4f461 <+65>: je 0x7ffff7e4f570 <__GI__IO_puts+336>
0x00007ffff7e4f467 <+71>: mov eax,DWORD PTR fs:0x18
0x00007ffff7e4f46f <+79>: test eax,eax
0x00007ffff7e4f471 <+81>: jne 0x7ffff7e4f5b0 <__GI__IO_puts+400>
0x00007ffff7e4f477 <+87>: mov edx,0x1
0x00007ffff7e4f47c <+92>: cmpxchg DWORD PTR [r8],edx
0x00007ffff7e4f480 <+96>: mov r8,QWORD PTR [rbp+0x88]
0x00007ffff7e4f487 <+103>: mov rdi,QWORD PTR [r13+0x0]
0x00007ffff7e4f48b <+107>: mov QWORD PTR [r8+0x8],r14
0x00007ffff7e4f48f <+111>: mov eax,DWORD PTR [rdi+0xc0]
0x00007ffff7e4f495 <+117>: add DWORD PTR [r8+0x4],0x1
0x00007ffff7e4f49a <+122>: test eax,eax
0x00007ffff7e4f49c <+124>: je 0x7ffff7e4f4bd <__GI__IO_puts+157>
0x00007ffff7e4f49e <+126>: cmp eax,0xffffffff
0x00007ffff7e4f4a1 <+129>: je 0x7ffff7e4f4c7 <__GI__IO_puts+167>
0x00007ffff7e4f4a3 <+131>: mov r8d,0xffffffff
0x00007ffff7e4f4a9 <+137>: jmp 0x7ffff7e4f52f <__GI__IO_puts+271>
0x00007ffff7e4f4ae <+142>: xchg ax,ax
0x00007ffff7e4f4b0 <+144>: mov rdi,rbp
0x00007ffff7e4f4b3 <+147>: mov eax,DWORD PTR [rdi+0xc0]
0x00007ffff7e4f4b9 <+153>: test eax,eax
0x00007ffff7e4f4bb <+155>: jne 0x7ffff7e4f49e <__GI__IO_puts+126>
0x00007ffff7e4f4bd <+157>: mov DWORD PTR [rdi+0xc0],0xffffffff
0x00007ffff7e4f4c7 <+167>: mov r14,QWORD PTR [rdi+0xd8]
0x00007ffff7e4f4ce <+174>: lea rdx,[rip+0x1643cb] # 0x7ffff7fb38a0 <_IO_helper_jumps>
0x00007ffff7e4f4d5 <+181>: lea rax,[rip+0x16512c] # 0x7ffff7fb4608
0x00007ffff7e4f4dc <+188>: sub rax,rdx
0x00007ffff7e4f4df <+191>: mov rcx,r14
0x00007ffff7e4f4e2 <+194>: sub rcx,rdx
0x00007ffff7e4f4e5 <+197>: cmp rax,rcx
0x00007ffff7e4f4e8 <+200>: jbe 0x7ffff7e4f580 <__GI__IO_puts+352>
0x00007ffff7e4f4ee <+206>: mov rdx,rbx
0x00007ffff7e4f4f1 <+209>: mov rsi,r12
0x00007ffff7e4f4f4 <+212>: call QWORD PTR [r14+0x38]
0x00007ffff7e4f4f8 <+216>: cmp rbx,rax
0x00007ffff7e4f4fb <+219>: jne 0x7ffff7e4f4a3 <__GI__IO_puts+131>
0x00007ffff7e4f4fd <+221>: mov rdi,QWORD PTR [r13+0x0]
0x00007ffff7e4f501 <+225>: mov rax,QWORD PTR [rdi+0x28]
0x00007ffff7e4f505 <+229>: cmp rax,QWORD PTR [rdi+0x30]
0x00007ffff7e4f509 <+233>: jae 0x7ffff7e4f590 <__GI__IO_puts+368>
0x00007ffff7e4f50f <+239>: lea rdx,[rax+0x1]
0x00007ffff7e4f513 <+243>: mov QWORD PTR [rdi+0x28],rdx
0x00007ffff7e4f517 <+247>: mov BYTE PTR [rax],0xa
0x00007ffff7e4f51a <+250>: add rbx,0x1
0x00007ffff7e4f51e <+254>: mov r8d,0x7fffffff
0x00007ffff7e4f524 <+260>: cmp rbx,0x7fffffff
0x00007ffff7e4f52b <+267>: cmovbe r8,rbx
0x00007ffff7e4f52f <+271>: test DWORD PTR [rbp+0x0],0x8000
0x00007ffff7e4f536 <+278>: jne 0x7ffff7e4f561 <__GI__IO_puts+321>
0x00007ffff7e4f538 <+280>: mov rdi,QWORD PTR [rbp+0x88]
0x00007ffff7e4f53f <+287>: mov eax,DWORD PTR [rdi+0x4]
0x00007ffff7e4f542 <+290>: sub eax,0x1
0x00007ffff7e4f545 <+293>: mov DWORD PTR [rdi+0x4],eax
0x00007ffff7e4f548 <+296>: jne 0x7ffff7e4f561 <__GI__IO_puts+321>
0x00007ffff7e4f54a <+298>: mov QWORD PTR [rdi+0x8],0x0
0x00007ffff7e4f552 <+306>: mov edx,DWORD PTR fs:0x18
0x00007ffff7e4f55a <+314>: test edx,edx
0x00007ffff7e4f55c <+316>: jne 0x7ffff7e4f5d0 <__GI__IO_puts+432>
0x00007ffff7e4f55e <+318>: sub DWORD PTR [rdi],0x1
0x00007ffff7e4f561 <+321>: pop rbx
0x00007ffff7e4f562 <+322>: mov eax,r8d
0x00007ffff7e4f565 <+325>: pop rbp
0x00007ffff7e4f566 <+326>: pop r12
0x00007ffff7e4f568 <+328>: pop r13
0x00007ffff7e4f56a <+330>: pop r14
0x00007ffff7e4f56c <+332>: ret
0x00007ffff7e4f56d <+333>: nop DWORD PTR [rax]
0x00007ffff7e4f570 <+336>: mov rdi,rbp
0x00007ffff7e4f573 <+339>: jmp 0x7ffff7e4f48f <__GI__IO_puts+111>
0x00007ffff7e4f578 <+344>: nop DWORD PTR [rax+rax1+0x0]
0x00007ffff7e4f580 <+352>: call 0x7ffff7e58b60 <_IO_vtable_check>
0x00007ffff7e4f585 <+357>: mov rdi,QWORD PTR [r13+0x0]
0x00007ffff7e4f589 <+361>: jmp 0x7ffff7e4f4ee <__GI__IO_puts+206>
0x00007ffff7e4f58e <+366>: xchg ax,ax
0x00007ffff7e4f590 <+368>: mov esi,0xa
0x00007ffff7e4f595 <+373>: call 0x7ffff7e5c9e0 <__GI___overflow>
0x00007ffff7e4f59a <+378>: cmp eax,0xffffffff
0x00007ffff7e4f59d <+381>: jne 0x7ffff7e4f51a <__GI__IO_puts+250>
0x00007ffff7e4f5a3 <+387>: jmp 0x7ffff7e4f4a3 <__GI__IO_puts+131>
0x00007ffff7e4f5a8 <+392>: nop DWORD PTR [rax+rax1+0x0]
0x00007ffff7e4f5b0 <+400>: mov ecx,0x1
0x00007ffff7e4f5b5 <+405>: mov eax,edx
0x00007ffff7e4f5b7 <+407>: lock cmpxchg DWORD PTR [r8],ecx
0x00007ffff7e4f5bc <+412>: je 0x7ffff7e4f480 <__GI__IO_puts+96>
0x00007ffff7e4f5c2 <+418>: mov rdi,r8
0x00007ffff7e4f5c5 <+421>: call 0x7ffff7e5f5a0 <__lll_lock_wait_private>
0x00007ffff7e4f5ca <+426>: jmp 0x7ffff7e4f480 <__GI__IO_puts+96>
0x00007ffff7e4f5cf <+431>: nop
0x00007ffff7e4f5d0 <+432>: xchg DWORD PTR [rdi],eax
0x00007ffff7e4f5d2 <+434>: cmp eax,0x1
0x00007ffff7e4f5d5 <+437>: jle 0x7ffff7e4f561 <__GI__IO_puts+321>
0x00007ffff7e4f5d7 <+439>: xor r10d,r10d
0x00007ffff7e4f5da <+442>: mov edx,0x1
0x00007ffff7e4f5df <+447>: mov esi,0x81
0x00007ffff7e4f5e4 <+452>: mov eax,0xca
0x00007ffff7e4f5e9 <+457>: syscall
0x00007ffff7e4f5eb <+459>: jmp 0x7ffff7e4f561 <__GI__IO_puts+321>
0x00007ffff7e4f5f0 <+464>: endbr64
0x00007ffff7e4f5f4 <+468>: mov r8,rax
0x00007ffff7e4f5f7 <+471>: jmp 0x7ffff7dedd5c <__GI__IO_puts.cold>
Address range 0x7ffff7dedd5c to 0x7ffff7deddb3:
0x00007ffff7dedd5c <-399044>: test DWORD PTR [rbp+0x0],0x8000
0x00007ffff7dedd63 <-399037>: jne 0x7ffff7dedd8e <__GI__IO_puts-398994>
0x00007ffff7dedd65 <-399035>: mov rdi,QWORD PTR [rbp+0x88]
0x00007ffff7dedd6c <-399028>: mov eax,DWORD PTR [rdi+0x4]
0x00007ffff7dedd6f <-399025>: sub eax,0x1
0x00007ffff7dedd72 <-399022>: mov DWORD PTR [rdi+0x4],eax
0x00007ffff7dedd75 <-399019>: jne 0x7ffff7dedd8e <__GI__IO_puts-398994>
0x00007ffff7dedd77 <-399017>: mov QWORD PTR [rdi+0x8],0x0
0x00007ffff7dedd7f <-399009>: mov edx,DWORD PTR fs:0x18
0x00007ffff7dedd87 <-399001>: test edx,edx
0x00007ffff7dedd89 <-398999>: jne 0x7ffff7dedd96 <__GI__IO_puts-398986>
0x00007ffff7dedd8b <-398997>: sub DWORD PTR [rdi],0x1
0x00007ffff7dedd8e <-398994>: mov rdi,r8
0x00007ffff7dedd91 <-398991>: call 0x7ffff7def3a0 <_Unwind_Resume>
0x00007ffff7dedd96 <-398986>: xchg DWORD PTR [rdi],eax
0x00007ffff7dedd98 <-398984>: sub eax,0x1
0x00007ffff7dedd9b <-398981>: jle 0x7ffff7dedd8e <__GI__IO_puts-398994>
0x00007ffff7dedd9d <-398979>: xor r10d,r10d
0x00007ffff7dedda0 <-398976>: mov edx,0x1
0x00007ffff7dedda5 <-398971>: mov esi,0x81
0x00007ffff7deddaa <-398966>: mov eax,0xca
0x00007ffff7deddaf <-398961>: syscall
0x00007ffff7deddb1 <-398959>: jmp 0x7ffff7dedd8e <__GI__IO_puts-398994>
계속 넘겨보면
0x7ffff7e4f51e <__GI__IO_puts+254>: mov r8d,0x7fffffff
0x7ffff7e4f524 <__GI__IO_puts+260>: cmp rbx,0x7fffffff
0x7ffff7e4f52b <__GI__IO_puts+267>: cmovbe r8,rbx
=> 0x7ffff7e4f52f <__GI__IO_puts+271>: test DWORD PTR [rbp+0x0],0x8000
0x7ffff7e4f536 <__GI__IO_puts+278>: jne 0x7ffff7e4f561 <__GI__IO_puts+321>
0x7ffff7e4f538 <__GI__IO_puts+280>: mov rdi,QWORD PTR [rbp+0x88]
0x7ffff7e4f53f <__GI__IO_puts+287>: mov eax,DWORD PTR [rdi+0x4]
0x7ffff7e4f542 <__GI__IO_puts+290>: sub eax,0x1
gdb-peda$ n
0x55555555514e <main+5>: mov rbp,rsp
0x555555555151 <main+8>: lea rdi,[rip+0xeac] # 0x555555556004
0x555555555158 <main+15>: call 0x555555555050 puts@plt
=> 0x55555555515d <main+20>: lea rdi,[rip+0xebd] # 0x555555556021
0x555555555164 <main+27>: call 0x555555555050 puts@plt
0x555555555169 <main+32>: mov eax,0x0
0x55555555516e <main+37>: pop rbp
0x55555555516f <main+38>: ret
<__GI__IO_puts+271>에서 메인함수로 넘어옵니다.
그런데 이게 puts 두번째 호출에서도 똑같이 작동합니다.
0x555555555151 <main+8>: lea rdi,[rip+0xeac] # 0x555555556004
0x555555555158 <main+15>: call 0x555555555050 puts@plt
0x55555555515d <main+20>: lea rdi,[rip+0xebd] # 0x555555556021
=> 0x555555555164 <main+27>: call 0x555555555050 puts@plt
0x555555555169 <main+32>: mov eax,0x0
0x55555555516e <main+37>: pop rbp
0x55555555516f <main+38>: ret
0x555555555170 <__libc_csu_init>: endbr64
gdb-peda$ si
0x555555555040 __cxa_finalize@plt: endbr64
0x555555555044 <__cxa_finalize@plt+4>: bnd jmp QWORD PTR [rip+0x2fad] # 0x555555557ff8
0x55555555504b <__cxa_finalize@plt+11>: nop DWORD PTR [rax+rax1+0x0]
=> 0x555555555050 puts@plt: endbr64
0x555555555054 <puts@plt+4>: bnd jmp QWORD PTR [rip+0x2f75] # 0x555555557fd0 puts@got.plt
0x55555555505b <puts@plt+11>: nop DWORD PTR [rax+rax1+0x0]
0x555555555060 <_start>: endbr64
0x555555555064 <_start+4>: xor ebp,ebp
gdb-peda$ ni
0x555555555044 <__cxa_finalize@plt+4>: bnd jmp QWORD PTR [rip+0x2fad] # 0x555555557ff8
0x55555555504b <__cxa_finalize@plt+11>: nop DWORD PTR [rax+rax1+0x0]
0x555555555050 puts@plt: endbr64
=> 0x555555555054 <puts@plt+4>: bnd jmp QWORD PTR [rip+0x2f75] # 0x555555557fd0 puts@got.plt
0x55555555505b <puts@plt+11>: nop DWORD PTR [rax+rax1+0x0]
0x555555555060 <_start>: endbr64
0x555555555064 <_start+4>: xor ebp,ebp
0x555555555066 <_start+6>: mov r9,rdx
gdb-peda$ ni
0x7ffff7e4f40f <_IO_new_popen+143>: jmp 0x7ffff7e4f3e4 <_IO_new_popen+100>
0x7ffff7e4f411: nop WORD PTR cs:[rax+rax1+0x0]
0x7ffff7e4f41b: nop DWORD PTR [rax+rax1+0x0]
=> 0x7ffff7e4f420 <__GI__IO_puts>: endbr64
0x7ffff7e4f424 <__GI__IO_puts+4>: push r14
0x7ffff7e4f426 <__GI__IO_puts+6>: push r13
0x7ffff7e4f428 <__GI__IO_puts+8>: push r12
0x7ffff7e4f42a <__GI__IO_puts+10>: mov r12,rdi
그러고는 첫번쨰 호출이랑 같이 <__GI__IO_puts>로 넘어가서 <__GI__IO_puts+271>에서 메인함수로 넘어옵니다.
gcc 버전을 바꿨을 때도 같은 일이 일어납니다. 뭐가 문제인가요?
요약
이해 안 가는 점
- 강의에서는 첫번째 호출에서 got가 plt 바로 다음 줄을 가리켜 plt에서 puts의 위치를 찾는 과정과 그 위치를 got에 등록하는 과정을 거치고 두번째 호출에서는 got가 puts함수를 가르켜 puts 함수가 바로 실행될 수 있음으로 이해했으나 제가 컴퓨터로 돌려봤을때는 puts의 첫번째와 두번째 호출 모두 <__GI__IO_puts>라는 함수로 바로 넘어간다는 것입니다. 강의에서와 달리 dl_runtime_resolve_xsavec라는 함수도 실행된 적 없고 심지어는 <puts>도 실행되지 않습니다.
질문
- 왜 이런 차이가 생기는가?
- <__GI__IO_puts>는 무엇인가?
- 강의와 같은 방법으로 돌아가게 하려면 어떻게 해야하는 가?
첫번째 호출에서 si를 이용해도 바로 <__GI__IO_puts>로 넘어가네요... 얘는 어떻게 puts 함수 주소를 알고 있는 것일까요...? ㅠㅠㅠ 컴파일 할 때 특별한 옵션을 줘야하나요?
file 명령어로 살펴봐도 dynamically linked라고 나와있는데... 영문을 모르겠네요
$ file got
got: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e62a150c7279955b4dbd05222114d2ecc161fa48, for GNU/Linux 3.2.0, not stripped
checksec으로 살펴보면 다음과 같습니다.
$ checksec got
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
0x555555555044 <__cxa_finalize@plt+4>: bnd jmp QWORD PTR [rip+0x2fad] # 0x555555557ff8
0x55555555504b <__cxa_finalize@plt+11>: nop DWORD PTR [rax+rax1+0x0]
0x555555555050 puts@plt: endbr64
=> 0x555555555054 <puts@plt+4>: bnd jmp QWORD PTR [rip+0x2f75] # 0x555555557fd0 puts@got.plt
0x55555555505b <puts@plt+11>: nop DWORD PTR [rax+rax1+0x0]
0x555555555060 <_start>: endbr64
0x555555555064 <_start+4>: xor ebp,ebp
0x555555555066 <_start+6>: mov r9,rdx
gdb-peda$ si
0x7ffff7e4f40f <_IO_new_popen+143>: jmp 0x7ffff7e4f3e4 <_IO_new_popen+100>
0x7ffff7e4f411: nop WORD PTR cs:[rax+rax1+0x0]
0x7ffff7e4f41b: nop DWORD PTR [rax+rax1+0x0]
=> 0x7ffff7e4f420 <__GI__IO_puts>: endbr64
0x7ffff7e4f424 <__GI__IO_puts+4>: push r14
0x7ffff7e4f426 <__GI__IO_puts+6>: push r13
0x7ffff7e4f428 <__GI__IO_puts+8>: push r12
0x7ffff7e4f42a <__GI__IO_puts+10>: mov r12,rdi
아니 왜 그런진 모르겠는데 -no-pie 옵션을 주면 main -> puts@plt -> puts@plt 조금 앞의 주소 -> _dl_runtime_resolve_xsave -> __GI__IO_puts -> main 순으로 넘어갑니다...
아니 근데 이건 또 왜 그러죠.. ㅠㅠ
- -no-pie 옵션이 도대체 왜 이런 거에 영향을 주는 건가요?
- -no-pie 옵션을 안 줬을 때는 어떻게 처음부터 puts 함수의 위치를 알고 있는 건가요?
- -no-pie 옵션을 줬을 경우에도 코드를 살펴보면 의문이 생깁니다.
첫번째 호출일 때
=> 0x401044 <puts@plt+4>: bnd jmp QWORD PTR [rip+0x2fcd] # 0x404018 <puts@got.plt>
에서는 si하면
=> 0x401030: endbr64
로 넘어가는데
두번째 호출일 때는
=> 0x401044 <puts@plt+4>: bnd jmp QWORD PTR [rip+0x2fcd] # 0x404018 <puts@got.plt>
에서 si 하면
=> 0x7ffff7e4f420 <__GI__IO_puts>: endbr64
로 넘어갑니다. 같은 bnd jmp QWORD PTR [rip+0x2fcd] 명령인데 왜 둘이 다른 곳으로 넘어가버리는 거죠?
아니 근데 심지어 rip+0x2fcd를 구해 보면
gdb-peda$ print $rip+0x2fcd
$4 = (void (*)()) 0x404011
입니다...
그럼..
jmp하면 0x404011로 넘어가야 하는 거 아닌가요?
수준 낮은 질문 죄송합니다.
아닙니다 ㅎㅎ 첫 댓글에서 말씀 드렸듯 plt와 got에 대해서 조금 공부해보시면 바로 이해되실 것 같습니다.
아래 링크 참고하시면 좋을 것 같아요 ㅎㅎ
https://bpsecblog.wordpress.com/2016/03/09/about_got_plt_2/