왜 BOF로 return address를 덮어 씌울까?
🔥 BOF로 리턴 주소를 덮어씌우는 이유 🔥
💡 왜 굳이 BOF(버퍼 오버플로우)로 리턴 주소를 덮어야 할까?
💡 그냥 rdi에 /bin/sh 주소만 넣으면 안 되는 걸까?
✅ 정답: 프로그램의 흐름을 강제로 변경하려면 return address를 덮어야 하기 때문!
✅ BOF 없이 그냥 주소를 찍으면, 프로그램이 원래 흐름대로 실행되면서 우리가 원하는 system("/bin/sh") 실행이 안 됨!
🚖 1️⃣ 네비게이션 비유로 이해하기
🚕 정상적인 프로그램 실행 흐름
- 원래 프로그램은 함수 실행이 끝나면 **리턴 주소(return address)**로 복귀해야 함.
- ret 명령어가 실행되면, 스택에서 원래 리턴 주소를 꺼내서 이동함.
🚕 BOF 없이 그냥 rdi에 값만 넣으면?
- rdi에 /bin/sh 주소를 넣어도, 원래 리턴 주소로 돌아가버림 ❌
- 즉, 프로그램이 원래 실행되던 곳으로 복귀해서 그냥 종료됨 ❌
🚕 BOF로 리턴 주소를 덮어쓰면?
- 강제로 우리가 원하는 주소(system 함수)로 이동 가능! ✅
- 즉, 택시(프로그램)의 목적지를 우리가 원하는 곳으로 바꿀 수 있음! 🚀
🔍 2️⃣ BOF 없이 그냥 rdi 설정하면 어떻게 될까?
💡 BOF 없이 그냥 rdi에 "/bin/sh" 주소를 넣으면?
- rdi 값을 변경해도, 프로그램은 원래 실행 흐름을 따라 리턴(return address)으로 이동함.
- 즉, system("/bin/sh")을 실행하지 않고 프로그램이 그냥 끝남! 😱
📌 BOF 없이 실행하면 이런 흐름이 됨
pop rdi; ret ; rdi = "/bin/sh"
ret ; 원래 리턴 주소로 복귀 (system 호출 안 됨!)
🚨 결과: system("/bin/sh")이 실행되지 않음!
💡 3️⃣ BOF로 리턴 주소를 덮으면 어떻게 될까?
💡 BOF를 발생시키면 리턴 주소(return address)를 우리가 원하는 값으로 덮을 수 있음!
- 원래 리턴 주소 대신 system()의 주소를 넣어버리면,
- ret이 실행되었을 때 원래 주소로 돌아가는 게 아니라, 강제로 system("/bin/sh")을 실행할 수 있음! 🚀🔥
📌 BOF로 리턴 주소를 덮으면 이런 흐름이 됨
pop rdi; ret ; rdi = "/bin/sh"
ret ; system("/bin/sh") 실행!!
✅ 결과: system("/bin/sh") 실행 & 쉘 획득! 🎯🔥
📌 4️⃣ BOF 없이 할 수 있는 방법이 있을까?
💡 BOF 없이 프로그램이 원래 실행되던 흐름을 유지하면서 system("/bin/sh")을 실행하는 방법이 있을까?
✅ 가능한 경우
- 이미 system("/bin/sh")을 실행하는 코드가 프로그램에 존재하는 경우
→ 특정 기능을 조작해서 실행 가능 - 함수를 Overwrite(함수 포인터 덮어쓰기, GOT Overwrite 등)
→ 실행 흐름을 강제 변경 가능 - JOP / COP 같은 기법 사용
→ ROP가 안 되는 경우, 다른 공격 기법 활용 가능
✅ 하지만 일반적으로 BOF 없이 ROP를 실행할 방법은 거의 없음!
✅ BOF를 이용해야만 system()을 강제로 실행할 수 있음!
🚀 5️⃣ 최종 정리: 왜 BOF로 리턴 주소를 덮어야 할까?
❓ 질문 ✅ 정답
왜 rdi 값만 바꿔서는 안 되나? | 프로그램이 원래 흐름으로 돌아가기 때문에 system("/bin/sh")을 실행할 수 없음. |
BOF로 리턴 주소를 덮으면 뭐가 좋은가? | 우리가 원하는 주소(system())로 강제 이동할 수 있음! |
BOF 없이 다른 방법은 없을까? | 특정 경우에는 가능하지만, 일반적으로 ROP에서는 BOF가 필수! |
결론은? | BOF를 이용해서 리턴 주소를 덮어야 우리가 원하는 코드가 실행됨! |
🎯 최종 결론
🔥 BOF 없이 rdi 값만 바꾸면 프로그램이 원래 실행 흐름으로 돌아가서 우리가 원하는 공격을 할 수 없음!
🔥 BOF로 리턴 주소를 덮어야 ret을 실행할 때 system("/bin/sh")이 실행될 수 있음!
🔥 결론적으로, BOF는 ROP 공격을 성공시키기 위한 핵심적인 기법이다! 🚀🎯
👏 이제 완벽히 이해했어요! 이제 직접 Pwndbg에서 리턴 주소를 덮었을 때와 안 덮었을 때를 비교해보면 더 확실히 알 수 있어요! 🚀🔥