정확한 원리가 무엇인가요?

cpy 함수의 스택 프레임에 buf - ebp가 가르키는 부분(프레임 맨 밑 부분) - 리턴 주소 인 것은 확인 하였습니다. 그래서 ebp 가 가르키는 부분의 첫 바이트를 변조할 수 있다는 것 까지는 이해에 성공 했습니다. 그런데 궁금한게 이러한 조작이 메인함수의 리턴 주소에 어떤 과정을 통해 영향을 끼치는 것인가요? ㅠㅠ

또 궁금한게 대부분 풀이는 64라는 숫자를 이용하여 풀었는데 이 값을 곧바로 구할 수 있는건가요? 제 로컬에서는 50대의 숫자가 나왔는데 작동하지 않아 포문을 돌렸습니다.

#pwnable
작성자 정보
답변 2
avatar
snwo
2024 Invitational Contenders

rbp 첫바이트가 \x00 으로 변조되어서 $ebp-0x100 영역을 가리키게 됩니다.
리턴후에 main 함수에서 leave (mov ebp,esp; pop ebp; ret) 명령어로 ebp+4 로 리턴하게 되는데,
ebp+4 의 위치를 알 수 없으니 $ebp-0x100 영역을 get_shell 함수 주소로 채워넣는거죠

2020.11.13. 20:44
avatar
Sechack
2024 Invitational Contenders

64라는 숫자는 256 / 4 입니다. 일단 이문제는 FPO(ebp를 1바이트 변조시켜서 최종적으로는 eip를 조작)기법을 이용해서 푸는겁니다.

정확한 원리는 https://hackstoryadmin.tistory.com/entry/FPO-Frame-Pointer-Overflow 여기에 자세히 설명되어 있습니다. 여기에 최대한 쉽게 풀어써져 있으니 읽어보시면 메인함수의 리턴주소에 어떠한 영향을 미치는지 이해가실겁니다.

정확한 원리와 64라는 숫자에 대해 조금만 더 말을 해보자면 배열은 256바이트입니다. 근데 입력받을 size를 지정할때 NULL을 고려해서 크기를 255바이트로 지정해야하지만 문제에서는 256바이트으로 지정했습니다. 따라서 ebp의 첫 바이트가 NULL문자인 \x00으로 변조됩니다. 위에 제가 소개한 글을 읽어보시면 아시겠지만 정상적인 상황에서는 ebp는 leave를 하면서 이전 함수의 SFP를 가리키게 됩니다. 하지만 우리는 ebp의 첫바이트를 \x00로 바꿨습니다.(정확히 말하면 ebp가 아닌 이전 함수의 SFP인데 함수 에필로그에서 leave(mov esp, ebp; pop ebp)를 하게 되면서 ebp에 저장된다.) 따라서 leave를 하게되면 gdb로 확인해보면 아시겠지만 첫 바이트가 \x00으로 변조되어서 이전 함수의 SFP가 아닌 buf의 어딘가를 가리키게 됩니다. 따라서 우리는 그 주소를 정확히 계산하여 거기에 get_shell의 주소를 넣으면 됩니다. 하지만 정확히 계산할 필요 없이 그냥 배열에다가 get_shell의 주소로 도배하면 간 ㅡ 단 합니다. (ASLR보호기법이 걸린 환경에서 문제를 풀려면 이러한 방법을 사용해야됨) 자 그래서 get_shell의 주소로 버퍼를 떡칠해봅시다. 근데 32비트 elf파일이므로 get_shell의 주소는 4바이트입니다. 따라서 버퍼의 크기인 256 / 4를 해서 get_shell을 64번 집어넣으면 버퍼가 get_shell로 도배되게 됩니다. 이때 ebp첫바이트가 \x00으로 변조되고 함수 에필로그가 두번 호출되면서 버퍼의 어딘가로 점프하게 됩니다. 버퍼는 get_shell의 주소로 떡칠되어 있으므로 어디로 점프를 뛰던간에 get_shell이 호출될겁니다.

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