TL;DR
- Windows는 AArch64 함수에도 패치 지점을 두며, 고정 길이 명령어 덕분에 x86보다 단순한 핫패칭 방식을 사용함.
- AArch64의 명령어 포인터는 항상 4의 배수 위치에 있어 명령어 중간에 놓이지 않음.
- 함수 첫 명령어에 별도 제약이 없으며, 모든 명령어는 명령어 포인터가 내부에 있는 위험 없이 원자적으로 갱신할 수 있음.
- 각 함수 앞의 12바이트 패치 공간은 대체 함수로 분기하는 세 명령어 트램펄린에 사용됨.
- 함수 진입점의 첫 명령어는 대개 반환 주소에 서명하는 포인터 인증 명령어인
pacibsp임.
AArch64의 패치 지점
- x86-32와 x86-64용 Windows는 각 함수 시작 부분에 패치 지점을 두는 것으로 알려져 있으며, AArch64(Windows에서
arm64로 부름)도 함수에 패치 지점을 둠. - AArch64는 명령어 길이가 고정되어 있어 명령어 포인터가 바이트 시퀀스 중간에 있을 때 명령어를 패치하는 상황을 고려할 필요가 없음. 명령어 포인터는 항상 4의 배수 위치에 있음.
- 따라서 함수의 첫 명령어에는 특별한 제한이 없으며, 모든 명령어를 명령어 포인터가 명령어 내부에 놓일 위험 없이 원자적으로 갱신할 수 있음.
트램펄린과 레지스터 사용
- 각 함수 앞에는 12바이트의 패치 공간이 있으며, 대체 함수 주소를 구성해 그곳으로 분기하는 세 명령어 트램펄린을 수용함.
- 트램펄린은
adrp로 대체 함수의 페이지 주소를 구하고,add로 페이지 내 오프셋을 더한 뒤,br로 해당 주소에 분기하는 방식임. - 함수 진입점의 한 명령어는 패치 공간으로 되돌아가는 분기 명령어로 덮어씀.
xip0는 프로시저 내부 호출용 임시 레지스터 두 개 중 하나이며, 모든 분기 명령어가 이 레지스터를 변경할 수 있다는 규약이 적용됨.- 호출자는 원래 분기 명령어를 사용해 함수 진입점에 도달하므로
xip0를 다른 용도로 사용할 수 없음. 따라서 트램펄린에서xip0를 변경해도 문제가 없음.
함수 진입점의 포인터 인증
- 함수 진입점의 첫 명령어는 거의 확실히
pacibsp임. pacibsp는 반환 주소에 서명하는 포인터 인증(pointer authentication) 명령어로, 반환 주소를 덮어쓰는 공격과 ROP 공격에 대한 코드의 저항성을 높임.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요