GCC에서 실행 가능한 스택 없이 중첩 함수를 간접 호출하는 방법
Indirect Calling of Nested Functions on GCC Without Executable Stack
GCC 17 이전 버전에서 중첩 함수를 콜백으로 사용하려면 실행 가능한 스택이 필요했습니다. 이 글에서는 트램펄린에서 코드 주소와 정적 체인을 추출해 `__builtin_call_with_static_chain`으로 직접 호출하는 해킹을 소개합니다. 이 방법을 사용하면 `patchelf --clear-execstack`으로 스택을 다시 실행 불가능하게 만들어 보안 문제를 해결할 수 있습니다. 또한 트램펄린을 함수 디스크립터로 해석하는 아이디어도 제시합니다. 실험적 라이브러리 noplate에서 구현된 내용을 바탕으로 설명합니다.
트램펄린을 호출하는 대신, 호출 지점에서 트램펄린의 코드를 해석한다고 말할 수 있습니다. 이는 매우 간단한 인터프리터를 사용하는 것과 같으며, 이 인터프리터는 특정 코드 시퀀스만 해석할 수 있고 인라인될 수 있을 정도로 단순합니다.
HN 토론
60- inigyou
자기 수정 코드는 멋지다. 보안 때문에 그걸 비활성화해야 했던 게 아쉽다.
- mananaysiempre
관련 글: 시리즈의 이전 기사, https://news.ycombinator.com/item?id=49308685 (103점, 댓글 47개)
- gue5t
처음에는 AT&T 문법을 읽어야 한다는 게 짜증났다. 그러다 다음 코드 조각이 레지스터에 '%' 기호 없이 AT&T 문법이라는 걸 깨닫고 혼란스러웠다. 하지만 그 기법은 멋지다.
- Dwedit
실행 가능한 스택이 왜 필요한가? 함수 포인터로 호출하는데, 함수 포인터를 사용하는 데는 실행 가능한 읽기/쓰기 메모리가 관여하지 않는다.