디스어셈블 주소지 질문
글쓴이: 송파구최고존엄 / 작성시간: 월, 2021/04/12 - 9:24오후
특정 파일을 디스어셈으로 보던 도중 나타나는 주소지와 실제 파일의 오프셋이 다른것으로 확인됩니다.
아래를 보면 main의 주소지가 04 라는 값이 붙어있는데 이게 주소 방식 차이때문이라고 알고있습니다.
(실제 파일주소지 620)
aarch64 gcc 컴파일러를 사용했는데 이것을 실제 파일 offset과 동일한 주소지로 사용될수 있도록
처리가능한 명령어가 있을까요 ?
0000000000400620 :
400620: d10043ff sub sp, sp, #0x10
400624: b9000fe0 str w0, [sp, #12]
400628: f90003e1 str x1,
40062c: 12800000 mov w0, #0xffffffff
400630: 910043ff add sp, sp, #0x10
400634: d65f03c0 ret
400638: d503201f nop
40063c: d503201f nop
Forums:
"main의 주소지가 04 라는 값이 붙어있다" 가
"main의 주소지가 04 라는 값이 붙어있다" 가 무슨말인가요?
400620 주소 코드가 스택 확장하는거 보니까 main 시작점 아닌가요?
왜 0x400000 오프셋에 로드되는지 물으시는 것
왜 0x400000 오프셋에 로드되는지 물으시는 것 같은데요. "Computing offset of a function in memory" 질문에 대한 누군가의 답변이 힌트가 될 지도 모르겠습니다. 저는 aarch64 시스템이 없어서 그냥 Ubuntu-20.04 x86_64 환경에서 따라해봤습니다.
https://stackoverflow.com/a/37932094
-pie 는 position independent executable로 만드는 옵션이라고 하고, 제 시스템의 gcc는 -pie 가 기본옵션인지 굳이 -no-pie 옵션을 줘야 fixed load address 바이너리가 만들어졌습니다. -no-pie 바이너리는 0x400000 오프셋이 추가돼있고, -pie 바이너리는 그렇지 않은 것이 보이죠.
실행해보면 아래와 같이 -no-pie 바이너리는 늘 고정된 가상주소에 로드되고, -pie 바이너리는 매번 다른 오프셋으로 로드됩니다 (랜덤으로 로드위치가 정해지는건 해킹을 어렵게 하기 위함인 것으로 압니다. 그래서 -pie가 기본값이 된건가 싶네요)
지금 쓰시는 시스템에서는 기본값이 -no-pie 이거나 해당 바이너리가 -no-pie로 빌드된 것이 아닌가 싶고, -pie 옵션을 줘서 position independent executable로 만들면 0x400000 오프셋이 사라질수도 있겠습니다.
호기심이 생겨 좀 더 찾아보니, 베이스오프셋 적용은
호기심이 생겨 좀 더 찾아보니, 베이스오프셋 적용은 링커에 의해 이뤄지며 /usr/lib/x86_64-linux-gnu/ldscripts/ 에 있는 링커 스크립트들에서 볼 수 있군요. 각 스크립트에서 __executable_start 문자열을 grep해봐도 되고, 아래와 같이 ld 명령을 통해 확인해볼수도 있네요.
PIE(Position Independent Executable)가 아닌 바이너리를 만들때는 x86(gcc -m32), x86_64(-m64), x32(-mx32) 상황에 따라 각각 아래와 같이 미리 정해진 베이스 오프셋이 적용되고 실행시에도 이렇게 정해진 동일한 가상주소로 매번 로드되는 반면,
-pie 옵션을 주어 PIE를 만들때는 아래와 같이 링크시에 따로 베이스 오프셋이 적용되지 않으며, 이렇게 만들어진 바이너리는 실행시마다 ASLR(Address Space Layout Randomization)에 의해 랜덤선택된 베이스주소로 로드되는 식이군요. PIE 바이너리에 대한 ASLR은 오래된 centos5에도 적용돼 있었습니다.
아래의 페이지를 보니 aarch64의 링커 스크립트도 비슷하군요. x86_64 시스템처럼 기본 베이스 오프셋이 0x400000이네요.
https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/+/master/aarch64-linux-android/lib/ldscripts/aarch64elf.x
https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/+/master/aarch64-linux-android/lib/ldscripts/aarch64elf.xd
os에서 실행파일을 그냥 load하고 call 하지
os에서 실행파일을 그냥 load하고 call 하지 않습니다.
relocation이라고 해서 실행파일 올린 뒤에 실행파일이 올라간 base address에 따라 실행파일 내부의 코드에 적혀있는 address를 실제 load된 address에 맞게 변환하는 작업이 있습니다.
Written By the Black Knight of Destruction
댓글 달기