My Study/Reversing2012.05.25 02:21

자기전에 문서를 뒤적거리다. 또 재미있는 안티 디버깅 기법이 보여서 정리합니다 ^^


방법은 Prefetch queue라는 기법인데.. 먼저 코드를 보고 이야기를 하겠습니다.


소스코드입니다.



Anti라는 함수를 만들었습니다.


함수 내부에 있는 어셈블리를 설명해보면


Anti 함수 처음(0x00401000)부터 총 14Byte 만큼 0x00을 덮어씌우라는 명령입니다.

OllyDbg로 Hex Dump값도 보도록 하죠.


총 14Byte 이므로 0x40100C 위치에 있는 REP 명령어 까지 0x00으로 덮어씌워지게 될 것입니다.

뭔가 이상하지 않습니까? 덮어 씌움을 행하는 명령어는 REP인데 해당 명령어가 0x00으로 덮어 씌워진다면?


바로 이 부분에서 Anti-Debugging 트릭이 생기는 것입니다.


여기서 prefetch queue는 명령어를 미리 읽어 넣어두는 캐쉬 메모리 같은 건데 그림을 보겠습니다.

이런식으로 오른쪽 하단에 있는 놈입니다.


아무튼 prefetch queue 안에 저장된 값과 일치하는 주소에 쓰기가 발생할 경우 자동으로 flush 되지 않습니다.

하지만 쓰기가 아닌 예외가 발생할 경우엔 flush가 됩니다.


이 기능을 사용해 안티디버깅 트릭을 사용하면 됩니다.


프로그램을 그냥 실행시킬 때는 아무런 예외가 발생하지 않으므로 Prefetch queue에 있는 오리지널 명령어가 수행이 됩니다.

그렇기 때문에 Anti 함수 내부에 있는 RETN을 제외한 나머지 명령어는 전부 0x00으로 덮어씌워지게 되고 rep명령어가 끝났기 때문에 유유히 RETN을 수행하고 빠져나오는 것입니다. 이것이 가능한 이유는 rep가 Prefetch queue에 있는 값으로 수행되고 있기 때문이죠.


실행결과입니다.

뻑나지 않고 잘 실행됨을 확인할 수 있습니다.


반대의 경우를 보겠습니다.

대부분의 디버거는 트레이스 할 때 single-step 예외를 사용합니다. 예외 예외 예외!!

즉, 위 Anti 함수를 single-step 을 사용해 트레이스 할 때 rep 부분이 0x00으로 덮어씌워지면서 flush가 발생하게 되고 결국 이상한 명령어를 수행해 프로그램이 죽어버리는 것입니다. 그림으로 보겠습니다.


보시면 원래 rep명령부분이 f3 aa 인데 앞 f3이 0x00으로 덮어씌워지면서 명령어가 이상하게 바뀌어버렸고 prefetch queue는 single-step예외가 발생했기 때문에 flush를 하게됩니다. 저 이상한 명령어를 가지고 말이죠... 결국... 뻑뻑뻑!


이해가 가시려나요??

Posted by Ezbeat