4

example4_leak.py 코드 부분 질문...

payload = “A”*36 # buf padding
payload += p32(0x8048326) # ret addr (puts@plt + 6)
payload += p32(0xdeadbeef) # ret after puts
payload += p32(0x804a014) # scanf@got

puts를 통해 어떻게 scanf@got의 주소를 어떻게 출력하도록구성한건가요??
puts@plt+6을 실행하면 push 0x0와 jmp 0x8048310 등 리턴이 아닌 코드를 계속 실행하는건데…
이 부분이 이해가 잘 안됩니다… 중간 과정이 많이 생략된거 같습니다.

답변 2개
5

라이브러리 함수를 처음 호출할 때와 두번째 호출할 때가 다릅니다. 처음 호출할 때는 puts@plt 에 puts@plt+6의 주소가 들어가 있습니다. puts@plt+6부터 실행하는 코드들은 dynamic linker를 호출해 puts 함수의 주소를 찾아내 puts를 호출하면서 puts의 got 상의 주소를 puts@plt에 저장합니다. 두번째 호출할 때는 puts@plt에 저장된 got상의 puts의 절대 주소를 불러와서 puts를 호출합니다. 그러니까 puts@plt+6을 리턴 주소에 덮어쓰면 결국 puts 함수를 호출하는 것과 같지요

쉽게 말하면 puts@plt+6을 실행하면 puts를 실행하는 것과 같다는 말입니다. 예제에서는 함수의 리턴주소를 puts@plt+6으로 덮어써서 puts를 호출하게 만든다는 거구요.

5

저도 공부하는 입장이지만 제가 이해한대로 설명해보면 puts@plt로 들어온 상황에서 이미 스택에는 puts가 끝난 후 리턴할 주소와 puts를 통해 출력될 문자열이 들어있는 상황인거고…

해당 리턴주소와 출력할 값을 각각
payload += p32(0xdeadbeef) # ret after puts
payload += p32(0x804a014) # scanf@got

요 값들로 덮어씌우는 것이니 출력은 scanf@got의 주소값이 나오게 되는 걸로 이해했습니다!

본래 리턴주소가 0x0804848a 라고 가정하면, 해당 값이 0xdeadbeef 로 덮어 씌워지고
출력 문자열인 Hello World! 이 저장된 주소를 0x804a014로 덮어씌우는거죠