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 코드의 주소였기에 혼동을 겪으신 것 같습니다.