본문으로 건너뛰기

20. ptrace 안티디버깅 우회 메모

안티디버깅은 공격자를 막는 주문이 아니라 관찰 조건을 바꾸는 코드다. 승인된 CTF 또는 자기 소유 샘플에서만 분석하고, 우회보다 먼저 어떤 신호를 검사하는지와 그 검사가 보호하려는 자산을 기록한다. Linux의 ptrace(PTRACE_TRACEME, ...)는 호출 성공 여부만으로 디버거 존재를 추정할 수 있지만, 모든 안티디버깅이 ptrace인 것은 아니다.

관찰 가능한 사실

strace는 시스템콜 순서를 보여주지만 추적 자체가 대상의 관찰 상태를 바꿀 수 있다. 따라서 한 번의 출력으로 로직을 확정하지 말고, 일반 실행·디버거 실행·격리된 테스트 실행을 비교한다. ELF가 PIE인지, RELRO와 서명이 있는지, 자체 무결성 검사가 있는지도 함께 확인한다.

file ./sample
readelf -h -l ./sample
strace -f -o trace.log ./sample

자기 소유 동적 테스트 프로그램에서는 LD_PRELOAD 래퍼로 호출과 반환값을 로깅할 수 있다. 그러나 정적 링크, setuid 실행, 보안 정책, 심볼 직접 호출에서는 적용되지 않으며, “항상 0 반환”은 정상적인 오류 처리까지 망가뜨릴 수 있다. 관찰 목적의 최소 래퍼를 우선 사용한다.

#define _GNU_SOURCE
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request req, ...) {
return 0; /* 로컬 테스트 전용: 실제 ABI와 호출을 검증할 것 */
}

바이너리 패치는 마지막 수단이다. 조건 분기 하나를 NOP 처리하면 뒤의 무결성 검사나 오류 경로가 달라질 수 있으므로, 변경 오프셋·원본 해시·재현 명령을 남기고 복사본에서만 시험한다. PIE에서는 파일 오프셋, 가상 주소, 런타임 베이스를 혼동하지 않는다.

설계에 대한 결론

안티디버깅은 비밀을 보호하는 경계가 아니다. 키와 권한 결정을 클라이언트에 두지 않고, 관찰 가능한 이벤트를 서버 측에서 탐지·대응하며, 정상 사용자를 해치지 않는 실패 모드를 설계하는 편이 강하다. 분석자의 목표도 “우회 성공”보다 보호가 실제로 제공하는 비용과 한계를 측정하는 데 있어야 한다.