두 가지 질문이 있습니다.

첫 번째 질문으로 카나리를 릭할 때 페이로드 보낸 다음 p.recvuntil(payload)를 했었는데 두 번째 페이로드를 보낼 때는 위 과정을 거치지 않고 바로 read = u64(p.recvn(6) + b"\x00" * 2)합니다. 두 번째 페이로드를 보낸 이후에 페이로드만큼 recvuntil()함수로 출력(?)하고 데이터를 받아야 하는게 아닌가요??

두 번째 질문으로 공격 타겟이 되는 rop.c 소스에서는 입력하는 read()함수가 총 두 곳인데 익스플로잇 코드에서는 두 번의 sendafter()이후에 send()를 한 번 더 입력합니다. 입력 횟수는 상관이 없는건가요??

#pwnable
작성자 정보
답변 3
avatar
wyv3rn
무플 방지 위원회장

전체 페이로드를 보지 못하여서 일단 제 예상만으로 답을 드리자면

첫 번째 질문은 이해하기 어렵습니다만, 첫번째 페이로드의 역할은 (첫번째 read 에 넣는 값은) 카나리 릭, 두번째 페이로드의 역할은 read 함수 재 실행 및 system 함수 호출을 위한 got overwrite, system 함수 인자 전달이 됩니다.

두번째 질문은 위에서도 설명하였지만, 두번째 read 이후 한번의 read가 더 필요하기에 rop으로 read 함수를 재 호출해야하며, 그렇기에 세번의 값 전달이 일어납니다.

2022.08.17. 22:29
avatar
wyv3rn
무플 방지 위원회장

첫번째 질문의 첫번째 질문부터 답변을 드리자면
문제 파일의 코드를 다시 보시면

  // Leak canary
  puts("[1] Leak Canary");
  printf("Buf: ");
  read(0, buf, 0x100);
  printf("Buf: %s\n", buf);

와 같고,
read 함수에 canary leak을 위한 적절한 값을 삽입하고
printf 함수로 돌아오는 값의 형태를 보면
Buf: 문자열 + 입력한 payload + canary
가 될 것입니다.

이제 해당 문자열을 받아오는 페이로드를 보시면

p.sendafter("Buf: ", buf)
p.recvuntil(buf)
cnry = u64(b"\x00"+p.recvn(7))

인데, 그 구조와 동일하게 받아오는 것을 보실 수 있습니다.

두번째, read의 주소를 받기 위한 주소의 경우도 마찬가지로 생각하시면 됩니다.
코드를 보시면

  puts("[2] Input ROP payload");
  printf("Buf: ");
  read(0, buf, 0x100);

와 같고, read 함수 이후에 별다른 문자열은 출력되지 않지만, 페이로드에 의해 puts 함수를 실행시키고, 화면에 바로 주소를 뿌려주기에 해당 값을 받아오기만 하면 되기 때문입니다.

2022.08.18. 08:04
avatar
wyv3rn
무플 방지 위원회장

두번째 질문은 생각하신 것이 맞습니다.

rop이 가능한 케이스에서, 여러번 read 뿐만 아니라 지속적으로 다른 함수를 불러와 실행할 수 있습니다.

위에서 설명 드린 것과 같이, 문제에서는 값 전달이 총 3번 일어나야하는 상황인데, read 함수는 코드 내에 두번밖에 없으니 rop을 통해 한번 더 실행시켜주는 것입니다.

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