5 코인 payload 중 read를 system으로 덮는 과정

payload 구성단계에 있어서 도저히 이해가 안돼서 질문을 남깁니다ㅠ
설명을 정리하자면 exploit 단계는 다음과 같음을 이해했습니다.

  1. write(1, read_got, ...); 으로 read의 실제 주소를 구해 libc base를 찾는다.
  2. libc base를 구했으니 라이브러리에서의 함수들의 실제 주소를 구할 수 있다. 따라서 system 함수의 주소를 구한다.
  3. read(1, read_got, ...); 에 system함수의 주소를 보내 read_got을 system 함수 주소로 overwrite한다.
  4. read("/bin/sh"); 으로 system("/bin/sh"); 를 실행한다. read_got이 system이므로 read가 아닌 system이 실행된다.

그러나 payload를 구성하면 왜 위 단계의 마지막인 4단계까지 한번에 구성해서 보내는지 이해가 잘 안됩니다.

# 1번 write(1, read_got, ---)
payload += p64(pop_rdi) + p64(1)
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)
payload += p64(write_plt)

# 2번 read(0, read_got, ---)
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)
payload += p64(read_plt)

# 3번 read("/bin/sh") = system("/bin/sh")
payload += p64(pop_rdi)
payload += p64(read_got + 0x8)
payload += p64(ret)
payload += p64(read_plt)

canary 우회 이후에 왜 read(0, read_got, ---)가 있는지 모르겠고, 그 밑에는 왜 이것이 system으로 대체되는지 모르겠습니다.
write에서 read_got를 알아낸 것을 알겠는데 실제로 libc_base를 계산하는 과정은 위 payload 구성 후 buf로 보내고 난 후에 받은 6바이트+ '\x00'*2 를 통해 구하는 것으로 코드가 작성되어있습니다. payload로 이미 보내서 실행이 쭉 될텐데 어떻게 system을 덮을 수 있는건가요?

p.send(p64(system) + b'/bin/sh\x00')
맨 마지막에 이것을 보냄으로써 exploit이 완성되는데 이것도 왜 이렇게 되는지 궁금합니다! system의 주소를 보내는것과 /bin/sh을 보내는게 따로 아닌가요? 두개를 합쳐서 보내는데도 exploit이 되는데 그 이유가 궁금합니다.

질문 정리

  1. payload가 길게 보내져도 1번 write가 먼저 실행되면서 여기서 read의 주소가 노출되고 이것을 통해 system의 주소를 구하는게 맞나요?
  2. 맞다면 이후 2번 과정인 read(0, read_got, --)는 무슨 과정을 의미하는건가요? read_got가 있는 주소값에 입력받을 값을 쓰겠다고 이해하는게 맞나요?
  3. 위가 맞다면 3번이 더더욱 이해가 가지 않습니다. pop_rdi 이후 read_got + 0x8 을 rdi 값에 넣는데 이건 rdi값에 저것을 넣는 이유가 무엇인가요? read_got+0x8이 의미하는게 무엇인지도 궁금합니다
  4. 3번에서 ret은 왜 들어가는 것인가요?
  5. read_plt를 마지막에 호출하는데 이게 read를 실제로 system으로 덮은 이후에 호출하는게 맞나요? 역할이 무엇인지 궁금합니다.
  6. 마지막으로 p.send(p64(system) + b'/bin/sh\x00') 로 보내면 exploit이 왜 되는지 궁금합니다. system주소값과 /bin/sh을 합쳐서 보내는데 이것이 read_got와 read_got+0x8에 각각 들어가는 것으로 이해하는게 맞나요? 만약 그렇다면 system과 '/bin/sh'를 넣은 값을 보냈을 때 이게 어떤 레지스터에 들어가서 어떻게 작동하는지 궁금합니다!

질문이 많아졌네요ㅠㅠㅠ 이해가 너무 힘들어서 질문드립니다!! 부탁드려요ㅠㅠ

#pwnable
작성자 정보
답변 2
질문자가 채택한 답변입니다. 좋은 지식을 공유해줘서 고마워요!
avatar
z3rodae0
시니어

최대한 답변을 해드리겠습니다.

  1. payload가 길게 보내져도 1번 write가 먼저 실행되면서 여기서 read의 주소가 노출되고 이것을 통해 system의 주소를 구하는게 맞나요?
    -> 넵 맞습니다.

  2. 맞다면 이후 2번 과정인 read(0, read_got, --)는 무슨 과정을 의미하는건가요? read_got가 있는 주소값에 입력받을 값을 쓰겠다고 이해하는게 맞나요?
    -> read의 got에 system 함수의 주소를 Overwrite 하기 위해, ROP를 통해 입력을 한번 더 할 수 있도록 페이로드를 구성하는 것입니다.

  3. 위가 맞다면 3번이 더더욱 이해가 가지 않습니다. pop_rdi 이후 read_got + 0x8 을 rdi 값에 넣는데 이건 rdi값에 저것을 넣는 이유가 무엇인가요? read_got+0x8이 의미하는게 무엇인지도 궁금합니다
    -> read(0, read_got, --)로 입력을 한 번 더 받을 수 있는 실행흐름이 되었다면, 두번째 입력에서는 p64(system) + b"/bin/sh\x00"을 입력할 것입니다. 이때 read_got에 입력을 받으므로, system 주소는 8바이트이므로, read_got + 0x8에는 b"/bin/sh\x00" 문자열이 쓰여져있습니다. 그리고 이 문자열을 pop rdi를 통해 rdi 레지스터가 가리키고도록 하는 것입니다.

  4. 3번에서 ret은 왜 들어가는 것인가요?
    -> system 함수 내부에서 movaps 라는 명령어가 실행되는데 이 명령어는 x64 환경에서 스택이 0x10 바이트 단위로 정렬되어있지 않으면, 에러가 발생하기때문에 ret 명령어를 하나 넣어줌으로써 ret 명령어 내부에서는 pop rip를 하기때문에, rsp가 8 증가하면서 0x10으로 정렬할 수 있습니다.

  5. read_plt를 마지막에 호출하는데 이게 read를 실제로 system으로 덮은 이후에 호출하는게 맞나요? 역할이 무엇인지 궁금합니다.
    -> 넵 맞습니다.

    # 3번 read("/bin/sh") = system("/bin/sh")
    payload += p64(pop_rdi)
    payload += p64(read_got + 0x8)
    payload += p64(ret)
    payload += p64(read_plt)
    

    위 페이로드 이전에 read(0, read_got, --)을 통해서 read_got를 system 함수의 주소로 덮었기때문에, read@plt를 호출하면 got에는 system 함수가 덮혀져있으므로, 최종적으로 system 함수가 호출됩니다.

  6. 마지막으로 p.send(p64(system) + b'/bin/sh\x00') 로 보내면 exploit이 왜 되는지 궁금합니다. system주소값과 /bin/sh을 합쳐서 보내는데 이것이 read_got와 read_got+0x8에 각각 들어가는 것으로 이해하는게 맞나요? 만약 그렇다면 system과 '/bin/sh'를 넣은 값을 보냈을 때 이게 어떤 레지스터에 들어가서 어떻게 작동하는지 궁금합니다!
    -> 넵 이해하신게 맞습니다. system의 주소와 "/bin/sh\x00"이라는 문자열을 read_got에 Write한 것뿐입니다. 이게 어떤 레지스터에 들어가서 어떻게 작동할지는 정확히 알 수 없습니다.

2024.09.12. 09:56
worldescortshub
대표 업적 없음

Yangın Bapsı Kanadı ve kasası arasında açılıp - kapanma sürecinin kabahatsiz şekilde yerine getirilmesini sağlayıcı mekanizmalara Yangın Bapsı Menteşesi denir. https://www.worldescortshub.com

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