강의노트를 보며 rop를 풀다 궁금한점이 생겨 질문드립니다.

payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)
payload += p64(read_plt)

우선 이 코드가 이해가 잘 가지 않습니다.
첫번째로는 p64(0)을 뒤에 붙여주는 부분입니다. 어떤 이유로 함수의 인자 뒤에 이것이 붙었는지 잘 모르겠습니다.
두번쨰로는 read함수는 dx가 정해지지 않을 경우 실행이 되지 않는 것으로 알고있는데, 위에 코드에서는 dx가 생략되어 있는 것으로 보입니다.
pop dx를 찾기 힘들다는 내용은 강의를 통해 파악했는데 설정해주지 않으면 0x10 이 defalut value로 들어가게 되는건지 여쭙고 싶습니다.

두번째로는
payload += p64(pop_rdi)
payload += p64(read_got+0x8)
payload += p64(read_plt) 와
p.send(p64(system)+b"/bin/sh\x00")
부분에서 제가 제대로 알고있는지 파악하고 싶은 부분이 있습니다.
제가 이해하기로는 이전에 read함수에서 read_got에 system함수의 실제 주소를 넣어야 하고, 8바이트가 꽉 차기 때문에 p.send(p64(system)+b"/bin/sh\x00")를 통해 read_got와 read_got+0x8을 채워주고, system함수의 인자는 rdi를 통해 받기 때문에
payload += p64(pop_rdi)
payload += p64(read_got+0x8)
을 하고, read_plt를 이용하여 system함수로 실행하는 것으로 이해했습니다.
근데 이미 payload에 +해서 전체를 첫 read함수(read(buf, 0x100)에 전달하는거고, 그러면 입력버퍼에 전부 들어가게 되는 것으로 알고 있습니다.
중간에 다시 read_plt에서 read함수를 호출하여 read_got에 입력해주는 구조인거 같은데,
그렇다면 여기서 입력한 값들은 입력버퍼의 뒤에서 부터 채우게 되어 제대로 입력이 되지 않을 것이라고 생각이 됩니다.
제가 제대로 이해하지 못하여 가독성이 떨어지게 쓴것 같습니다. 그래도 답변해주시면 감사하겠습니다.

#pwnable
작성자 정보
답변 1
avatar
Sechack
CTF First Place

첫번째 : pop_rsi_r15가젯은 pop rsi; pop r15; ret입니다. rsi말고도 r15에도 pop을 하니까 r15에는 0을 넣어준겁니다.

두번째 : gdb로 동적 디버깅을 해보시면 rdx에 모종의 이유로 인해서 0이 아닌 다른 충분히 큰 수가 들어가 있습니다. 따라서 따로 설정을 안해줘도 동작할 수 있습니다. 물론 read를 부르는 시점에서 rdx에 작은 값이 들어가있다면 따로 설정을 해줘야합니다.

세번째 : 입력버퍼의 뒤에서부터 채우게 된다는 말이 뭔진 잘 모르겠습니다. read를 한번 부르고 또 부르면 그냥 C언어로 따지면 read가 2번 호출된 효과가 납니다. 입력은 rsi로 전달한 주소에 들어가고요.

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