rop.c 파일을 컴파일한 후 libc 종류를 직접 찾아내는 걸 한 번 해 보고 싶었는데... 뭔가 잘 안 돼서 질문 드립니다.
- 환경
Ubuntu: 22.04.4 LTS
gcc: gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
===========================================================
- 과정
(1) rop.c 파일 생성(해당 워게임에서 제공해준 파일과 동일하게 생성)
(2) gcc -o rop rop.c -fno-PIE -no-pie 으로 rop.c 컴파일
(3) readelf -d rop 결과

(4) ldd rop 결과

=> 위의 readelf와 ldd 결과를 보고, rop에서는 libc.so.6 라이브러리를 사용한다고 생각하여 다음과 같이 readelf 명령어로 해당 라이브러리 파일에서 printf와 puts 함수를 찾았습니다.
puts의 마지막 12비트는 e50이며, printf의 경우는 6f0입니다.
-
readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep "puts"

-
readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep "printf"

=> 그런데 gdb rop을 실행한 후 p puts/p printf로 확인해 보았을 때는 마지막 12비트가 위의 라이브러리 파일에서 확인한 것과 다릅니다.

제가 이해한 바로는 마지막 12비트가 동일하여 그것을 이용하여 libc base도 계산하고 libc 버전도 알아낼 수 있는 것으로 알고 있는데, 혹시 제가 잘못 알고 있는 것이 있는지 문의 드립니다...
안녕하십니까. 선생님께서 올리신 마지막 캡쳐본에서 p puts 및 p printf는 libc의 puts와 printf가 아닙니다. 바이너리 내부에 있는 plt 코드의 주소입니다. 나중에 GOT overwrite 등의 기법을 공부하신다면 더 깊게 배울 기회가 있으실건데, plt는 libc 파일 내부에 있는 것이 아닌 실행 파일에 있는 코드이며, 실행 파일 내부에서 libc의 코드를 실행하기 위해 libc와 연결해주는 코드라고 이해하시면 편할 것 같습니다. 실행 파일에서 처음 puts 혹은 printf를 호출했을 시에 puts@plt와 printf@plt가 실행되게 되고 아직은 libc의 코드가 실행되지 않습니다. plt에서는 실제 libc의 puts함수 혹은 printf함수 주소를 먼저 알아낸 뒤 해당 주소로 jmp하는 방식의 코드가 수행되고 있습니다. 여기서는 자세한 부분은 생략하겠습니다.
정리하자면, 잘못 알고 계신 것은 아니며, gdb rop에서 찾은 주소가 libc의 puts printf함수의 주소가 아닌 plt 코드의 주소였기에 혼동을 겪으신 것 같습니다.
