질문
-
여기서 카나리 값을 유출 할 때 a를 0x39개 만큼 넣는데 왜 그런지 궁금합니다.
버퍼 크기가 0x30인데 0x39개를 넣으면 카나리 값 까지 a로 변해 버릴 수 도 있는거 아닌가요? -
0x39만큼 넣는데 왜 굳이 0x39인가요 카나리 값은 8바이트인데 왜 0x9만큼 더 넣는지 그 이유가 궁금합니다.
-
공격 코드에서 recvn(7)이라는 명령어가 있는데 recvn(7)에서 받는 값이 왜 카나리 값이 되는지 궁금합니다. recvn(7)에서 받는 값이 버퍼에 들어 있는 a값이 될 수도 있는거 아닌가요?
-
스택의 구조를 버퍼 - 카나리 - 리턴주소 라고 했을 때 카나리에서 눌 바이트는 버퍼 쪽에 있는지 아니면 리턴 주소 쪽에 있는지가 궁금합니다.
이상 긴 질문 들어주셔서 감사합니다.
안녕하세요 답변은 이렇습니다.
1번의 경우 사진을 보시면 해당 read 함수에서 0x100만큼 입력할 수 있기 때문에 버퍼의 위치에서부터 메모리를 확인해보면 0으로 된 값 8바이트 * 7개가 존재하고
이후에 카나리가 존재하는 걸 볼 수 있는데 카나리의 첫번째 값이 널바이트로 되어 있기 때문에 해당 널 바이트 값을 덮어주어야 canary 값이 출력이 됩니다.
- 1번 내용과 동일한데 카나리 값을 유출하려고 하는 것이기 때문에 카나리 값을 덮는 것이 아니라 해당 값을 leak 해 오기 위해 canary의 널바이트만 덮어주게 됩니다.
1번에서 말한대로 a * 57을 넣었습니다.
메모리를 확인해보시면 아까 확인했던 카나리 값의 널바이트만 a가 덮은 걸 확인할 수 있습니다.
(아래 나와있는 값은 원래의 카나리 값입니다)
그 후 printf 함수로 해당 버퍼를 출력해주는데 아까 입력했던 a * 57의 값만 있는 것이 아니라 이상한 값이 출력되는 모습을 볼 수 있는데
해당 값이 canary 값입니다.
- 위의 사진을 보시면 알겠지만 printf로 카나리를 출력해줍니다.
(사진1)
그래서 payload와 출력된 printf를 확인해보면 p.sendafter(b'Buf: ', buf)가 사진 1의 첫번째 빨간 상자의 내용을
이후 내용은 p.recvuntil(buf) (buf = b'A'*0x39) 즉 p.recvuntil(b'A'*0x39)를 통해 사진1의 두 번째 상자의 내용을 이미 읽었습니다.
그럼 카나리 값만 남게 되겠죠 ? 그래서 그 값만 cnry = u64(b'\x00' + p.recvn(7)) 를 통해 읽어오는 겁니다.
앞에 \x00을 붙여주는 이유는 카나리를 leak 할때 저희가 널바이트를 덮었기 때문에 원래 카나리 값인 널바이트를 복구해서 완전한 카나리를 만들어주는 것 입니다.
- 널바이트는 메모리를 통해 봤을 땐 리틀 엔디안으로 저장되기 때문에 ret 쪽에 있는 것 처럼 보이지만 사실상 버퍼쪽이라고 이해하시면 될 것 같습니다.
원래는 카나리의 첫 바이트 값이 널 바이트입니다.
이상입니다. 혹시나 궁금한 게 해결 안되셨다면 디스코드 a_dawn0106로 친추주셔서 여쭤봐주시면 감사하겠습니다.