Last Updated on 6월 14th, 2023, By
 In 앱실링 블로그

대부분의 사람들이 이미 알고 있듯이, 리버스 엔지니어링은 작업이 정확히 어떻게 수행되는지에 대한 인사이트 없이, 종종 소스코드에 액세스 할 수 없는 상태에서 시스템이 어떻게 작동하는지에 대해 이해하려는 시도에 기반합니다.

안티 리버스 엔지니어링이란?

안티 리버스 엔지니어링(Anti-reverse Engineering)은 애플리케이션을 리버스 엔지니어링(역설계) 하기 어렵게 만드는 기술입니다. 안타깝게도 이 리버스 엔지니어링 기술들은 해커가 탐지를 방지하기 위해 악용하는 경우가 많습니다. 이는 해커들이 향후 공격을 수행할 수 있는 특정 애플리케이션에 대한 액세스 권한이나 지식을 확보하고 이를 기반으로 향후 공격을 수행할 수 있는 좋은 도구입니다. 그러나, 공격자들에게 좋은 도구는 기업에게는 나쁜 소식일 수 있습니다. 그래서 저희는 여러분의 이해를 돕기 위해 리버스 엔지니어링 방지에 대한 간단한 강좌를 준비했습니다. 일반적으로 사용하는 리버스 엔지니어링 방지 기술들에 대해 확인해보세요!

인라인 함수

사이버 보안 전문가의 역할은 해커가 시스템을 이해하기 어렵게 만드는 것이며, 인라인 함수를 사용하면 바로 이러한 목표를 달성할 수 있습니다. 함수가 인라인으로 표시되면 실행파일이 비대해지면서 해커에게 혼란을 줄 수 있습니다.

타이밍 공격

일반적으로 코드 섹션을 실행하는 데는 일정 시간이 소요됩니다. 작은 섹션일 수록 소요 시간은 훨씬 더 짧을 것입니다. 만약 특정 세션이 예상보다 더 오랜 시간이 걸리는 것으로 관찰되는 경우, 디버거가 연결되어 있을 가능성이 높습니다.

가장 일반적으로 사용되는 함수 예시로는 IA-32 RDTSC 명령어(실시간 타임 스탬프 카운터)로, GetTickCount, timeGetTime, 그리고 QueryPerformanceCounter 등이 있습니다. 개발자는 타이밍 공격 전략을 통해 보호해야 할 함수를 결정하고, 다른 코드 블록을 타이밍 블록으로 둘러싸고 이를 프로그래머가 설정한 한계값과 비교하면 됩니다. 그런 다음 시간 제한을 초과하면 프로그램을 종료할 수 있습니다.

Windows 내부

Windows 운영체제의 독특한 특성을 이용하여 개발자가 해커로부터 코드를 보호하는데 도움이 되는 몇 가지 특정 안티 리버스 엔지니어링 방지 방법이 있습니다. 일부 주요 기능은 다음과 같습니다.

  1. ProcessDebugFlags: 이 값은 EPROCESS->NoDebugInherit의 반대값을 반환하는 NtQueryProcessInformation 함수에 전달됩니다. 디버거가 있는 경우, 이 함수는 FALSE 값을 반환합니다.

  2. 디버그 오브젝트 대처법: 프로세스가 디버깅되면, 일반적으로 디버그 객체가 생성됩니다. NtQueryInformationProcess를 사용하여 유사한 핸들(대처법)이 생성되고 쿼리됩니다. 이 핸들 (대처법)은 존재하고 있는 디버거를 보여줍니다.
    샘플 코드:

  3. 스레드 숨기기: HideThreadFromDebugger로 알려진 이 클래스는, 디버거가 HideThreadFromDebugger 클래스가 호출된 NtSetInformationThread를 포함한 스레드에서 이벤트를 수신하지 못하도록 합니다. 중단점과 프로그램 종료가 가장 흔하게 쓰입니다.
    샘플 코드:
  4. OutputDebugString: 이는 활성화된 디버거가 없는 경우에만 발생하는 오류를 감지합니다.
    샘플코드:
  5. BlockInput: 이는 마우스나 키보드 메세지가 해당 애애플리케이션과 상호 작용하는 것을 차단하고 방지합니다.
    샘플 코드:

프로세스 악용

그들은 보호 기능을 구현하기 위해 윈도우즈 프로세스 환경과 관리 시스템을 악용합니다. 일부 기술에는 다음과 같은 것들이 있습니다:

  1. Open Process: 프로세스 권한을 악용하여 디버거를 탐지합니다. 만약 디버거에 의해 프로세스 권한이 올바르게 재설정되지 않은 경우, 프로세스는 SeDebugPrivilege set을 받습니다.
  2. Parent Process: 상위 프로세스(Explorer.exe)의 프로세스 ID를 얻어 하위 프로세스와 비교합니다.
  3. Self-debugging: 이 메인 프로세스는 상위 프로세스를 디버깅하는 하위 프로세스를 만듭니다. 추가적인 장점은 다른 디버거가 해당 프로세스에 접근하기 더 어려워진다는 것입니다.
  4. UnhandleExceptionFilter: 이는 다른 핸들러가 없을 때 호출됩니다. 만약 디버거가 발견되면, 해당 작업을 재개하는 대신 프로세스가 종료됩니다.
  5. NtQueryObject: 호스트 시스템과 운영중인 프로세스에 대한 여러 가지 중요한 정보를 반환합니다.

 

덤프 방지

이 기술은 보호된 실행파일의 스냅샷이 메모리에서 덤프되는 것을 방지하는 기술입니다. 아래와 같은 방법으로 덤핑을 방지 할 수 있습니다.

  1. Nanomites: 이 기술은 이 기술은 분기 명령어와 JCC 명령어를 INT 3 중단점으로 대체하는 동시에 점프 대상(Jump Destination), CPU 플래그, 점프의 크기와 같은 정보를 암호화된 테이블에 저장합니다. 명령어는 코드에서 접근할 수 없는 부분에 배치되고 항목은 나노마이트 테이블에 배치됩니다.
  2. SizeOfImage: 런타임에 PEB의 필드 사이즈가 늘어나게 되면, 애플리케이션의 이미지베이스(ImageBase) 페이지부터 시작하여 MEM_IMAGE 플래그가 있는 모든 페이지를 열거하는 프로세스를 통해 애플리케이션을 리버싱(역으로 공격)하여 무효화합니다.
  3. 바이트 도난 (코드 도난): 원본 프로세스에서 코드 또는 바이트가 추출되어 패킹 코드의 임의의 위치에 암호화된 상태로 배치됩니다. 바이트가 배치된 영역은 원본 코드에서 훔친 암호가 해독된 바이트를 보유한 동적으로 할당된 버퍼로 점프(Jump)하는 코드로 대체됩니다. 이런 이유로로 “도난”이라는 용어가 사용됩니다.
  4. 가상 머신: 이 기술은 모든 보호된 각 실행 파일마다다 고유한 가상 머신을 생성하여 일반적인 공격을 방지하는데 중점을 둡니다.

IA-32 명령 악용

디버거는 종종 IA-32 명령어를 처리하는데 문제가 있으며 이 기능은 이런 기술들에 의해 악용됩니다. 일부 기술 목록은 다음과 같습니다.

  • Interrupt 2D: 디버거가 존재하는 경우 예외가 발생하지 않는 범용 디버거 입니다.
  • 스택 세그먼트: Push SS와 Pop SS를 통해 스택 세그먼트를 조작합니다.
  • 명령어 접두사: 여기에서 디버거는 _try 접두사를 건너뛰고 INT 1을 처리합니다.

WinDBG Specific

이 기술은 WinDBG가 백그라운드에서 실행 중인지 확인하는데 사용되는 기술이며, 아직은 초기 단계입니다.

위에서 볼 수 있듯이, 리버스 엔지니어링 방지 기술은 해커의 애플리케이션 접근 권한을 제한하는데  굉장히 유용합니다. 단, 유일한 문제는 해커들의 공격이 점점 정교해지고 있다는 점입니다. 그들은 기업이 대응하는 속도보다 훨씬 빠르게 트릭을 익히고 있습니다. 따라서 사이버보안에 대한 강력한 사전 예방적 접근 방식이 수동적인 방식보다 낫습니다. 물론 위에 언급된 기술들도 유용하지만, 모바일 애플리케이션에 특히 초점을 맞춘 애플리케이션 보안 전략을 잘 수립하는 것이 더욱 더 현명한 선택이 될 수 있습니다. 그리고, 저희가 확실히 도움을 드릴 수 있습니다. 지금 바로 문의하여 자세히 알아보세요!

Dustin Hong
Dustin Hong
Dustin은 잉카엔트웍스의 앱실링 비즈니스 개발을 이끌고 있습니다. 그는 사이버 보안, IT, 컨텐츠 및 애플리케이션 보안 분야의 소프트웨어 개발과 혁신에 많은 관심을 가지고 있습니다. 또한 사이버 보안 세계에서 주요 사건의 대상, 이유 및 방법에 대해 다양한 사람들에게 공유하고 토론하는 것을 좋아합니다. 업계 동향 및 모범 사례에 대한 그의 견해는 기사, 백서에 실려있으며, 여러 보안 행사에서 유사 주제로 발표를 하였습니다.