최근 rop 공격을 공부하면서 난항을 겪었다.
#include <stdio.h>
int main(void)
{
char buf[32] = {};
puts("Hello World!");
puts("Hello ASLR!");
scanf("%s", buf);
return 0;
}
gcc -o example4 example4.c -fno-stack-protector -mpreferred-stack-boundary=2 -m32 -no-pie
rop 공격을 테스트하기 위해, 위 c언어 소스 코드를 아래 gcc 명령어를 이용해 실습에 방해되는 보호 기법을 해제해준 상태로 빌드를 했다.
빌드 후 gdb로 파일을 열어 scanf 함수의 plt 코드를 확인해보면 정상적인 plt 코드가 아니라, endbr32 같은 이상한 명령어들이 보이는 것이다.
실행은 잘 되길래 처음에는 gdb가 제대로 디스어셈을 못한다고 생각했다. 왜냐하면 정상적인 결과에서는 0x8048340 ~ 0x8048346까지 총 6byte의 opcode를 해석해서 jmp DWORD PTR ds:0x804a014를 도출해내는 반면, 내 gdb는 4byte만 읽고 endbr32를 도출해냈다.
하지만 objdump, ida로 확인해봐도 gdb와 똑같이 디스 어셈을 하는 것을 보고 gdb 문제는 아닌 거라 생각해 보호 기법 관련해서 찾아봤다.
찾아보니 CET라는 보호 기법 때문이었다. cet 보호기법은 ubuntu 19 버전 이상부터 적용되는 보호 기법인데, 하필 실습환경이 ubuntu 20.04 LTS라서 자동으로 cet 보호 기법이 적용된 것이다.
이 cet 보호기법은 rop, jop를 막기 위해 만들어진 보호 기법으로, 이 보호 기법이 적용되면 rop 공격을 수행하기 어렵다고 한다.(물론 우회 기법은 존재한다.)
그 이유는 확실하진 않지만 shadow stack이라는 일반적인 stack에서 고립된 stack에 함수의 return address, call address를 넣어두고 기존 stack에 들어간 주소 값과 shadow stack에 들어 있는 주소 값을 비교하는데, 만약 다르다면 변조됐다고 여기고 예외를 발생시키는 것이다.
-결론-
endbr 같이 이상한 코드가 plt에 존재하는 이유는 cet라는 보호 기법 때문이고, 이 cet 보호 기법은 ubuntu 19 버전 이상부터 적용되기 때문에, 본인의 실습환경이 ubuntu 19 버전 이상이라면 rop 등 plt, got을 이용한 공격 기법을 실습해볼 때 cet 보호 기법 해제를 해줘야 한다.
-fcf-protection=none // cet 비활성화
빌드 시 위 옵션을 추가해준다면 cet가 비활성화된다.
'Old (2021.01 ~ 2021.12) > Tip' 카테고리의 다른 글
Visual Studio에서 %n, %hn 서식 지정자를 사용하는 방법 (0) | 2021.05.05 |
---|