2017년 11월 11일 토요일

MBR 공부 정리 II - MBR 접근 C코드 사본

다음은 MBR의 부트코드에 어떤식으로 ASM코드를 쓰는지(Overwrite)하는지에 대해 코드를 보고 예제 코드이 API의 사용법에 대해 새새하게 정리해본다.


우선 MBR을 공부하게된 Petya 랜섬웨어를 예로 들면 다음과 같인 API을 대표적으로 사용하는 것을 확인할 수 있다.

CreateFileA - 파일에 접근하기 위해 사용되는 API
DeviceIoControl - MBR 섹터에 대한 정보를 확인하는데 이용
SetFilePointEx - 파일의 포인터를 이동 시기킄데 사용
WriteFile / ReadFile - MBR 섹터에 암호화된 데이터를 쓸 때 사용되는 API

이들 중 다음 세개 API에 대해서 좀 더 자세히 알아보고 들어가 보자.
CreateFile / DeviceIoControl / SetFilePointEx

CreateFile API - MSDN

해당 API의 함수 형태는 다음과 같은 형태를 갖고 있다.

HANDLE WINAPI CreateFile(
  _In_     LPCTSTR               lpFileName,    #생성하고자 하는 파일
  _In_     DWORD                 dwDesiredAccess,    #파일에 대한 엑세스 권한 지정
  _In_     DWORD                 dwShareMode,    #파일의 공유 모드 지정
  _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,    #보안속성 지정, SECRITY_ATTRITUBES 구조체 포인터
  _In_     DWORD                 dwCreationDisposition,    #파일을 생성할 것인지 열것인지 지정
  _In_     DWORD                 dwFlagsAndAttributes,    #생성 파일의 속성을 지정
  _In_opt_ HANDLE                hTemplateFile    #생성된 파일의 속성을 제공할 탬블릿
);


보통 해당 함수는 다음과 같은 형태로 사용되며 목적은 PhysicalDrvie0에 접근하기 위해 사용된다. (MBR Handle 획득)

CreateFileA("\\\.\\PhysicalDrvie0", 0x40000000, 0x3, 0, 0x3, 0, 0)

    FileName : "\\\.\\PhysicalDrvie0"
    DesiredAccess : 0x40000000 => GENERIC_WRITE
        0x00000001 => CREATE_ALWAYS
        0x80000000 => GENERIC_READ
    ShareMode : 0x3 = 0x00000003 => FILE_SHARE_WRITE(0x01) | FILE_SHARE_READ(0x02)
        0x00000000 => NULL = File 또는 Device에 delete, read, write 접근이 가능
        0x00000004 = FILE_SHARE_DELETE => DELETE 가능
        0x00000001 = FILE_SHARE_READ => READ 가능
        0x00000002 = FILE_SHARE_WRITE => Write 가능
    SecurityAttributes : 0
    CreationDisposition : 0x3 = > OPEN_EXISTING
        0x2 : CREATE_ALAWAYS => 새로운 파일을 항상 만들 수 있음, Error code = 183
        0x1 : CREATE_NEW => 같은 파일이 존재하지 않은 경우, 새로운 파일을 만듬. Error code = 80
        0x4 : OPEN_SLAWAYS => 파일을 염, Error code = 183
        0x3 : OPEN_EXISTING => 파일이나 디바이스에 아무 접근 없을 시, 파일을 염, Error code = 2
        0x5 : TRUNACATE_EXISITING 
    FlagAndAttributes : 0
        0x20(32) : FILE_ATTRIBUTE_ARCHIVE
        0x4000(16384) : FILE_ATTRUBYTE_ENCRYPTED
        0x2(2) : FILE_ATTRIBUTE_HIDDEN
        0x80(128) : FILE_ATTRIBUTE_NORMAL
        0x1000(4096) : FILE_ATTRIBUTE_OFFLINE
        0x1(1) : FILE_ATTRUBYTE_READONLY
        0x4(4) : FILE_ATTRIBUTE_SYSTEM
        0x100(256) : FILE_ATTRIBUTE_TEMPORARY
        0x02000000 : FILE_FLAG_BACKUP_SEMANTICS
        0x04000000 : FILE_FLAG_DELETE_ON_CLOSE
        0x20000000 : FILE_FLAG_NO_BUFFERING
        0x00100000 : FILE_FLAG_OPEN_NO_RECALL
        0x00200000 : FILE_FLAG_OPEN_REPARSE_POINT
        0x40000000 : FILE_FLAG_OVERLAPPED
        0x01000000 : FILE_FLAG_POSIX_SEMANTICS
        0x10000000 : FILE_FLAG_RANDOM_ACCESS
        0x00800000 : FILE_FLAG_SESSION_AWARE
        0x08000000 : FILE_FLAG_SEQUENTIAL_SCAN
        0x80000000 : FILE_FLAG_WRITE_THROUGN
    TemplateFile : 0

정리하면, 우선 CreateFile API은 PhysicalDrive에 접근하기 위해 주로 사용된다는 점을 알아두고 가자! 보통은 파일에 접근할 때 사용되지만, PhysicalDrive에 접근한다면, MBR 영역을 의심해보자!

DeviceIoControl - MSDN / EXAMPLE CODE

주로 파티션의 갯수를 확인하고자 할 때 사용된다. API의 형태는 다음과 같은 형태를 가지고 있다.

BOOL WINAPI DeviceIoControl(
  _In_        HANDLE       hDevice,    #CreateFile로 받은 값이 들어가고, 타겟이 된다.
  _In_        DWORD        dwIoControlCode,    #전달된 I/O Control Code가 들어간다.
  _In_opt_    LPVOID       lpInBuffer,    #InBuffer 설정
  _In_        DWORD        nInBufferSize,
  _Out_opt_   LPVOID       lpOutBuffer,    #OutBuffer 설정
  _In_        DWORD        nOutBufferSize,
  _Out_opt_   LPDWORD      lpBytesReturned,
  _Inout_opt_ LPOVERLAPPED lpOverlapped
);

해당 API에서는 IoControlCode에 따라 역할이 달라진다. IoControlCode는 다음과 같이 32bit 구조를 가지고 있다.


해당 API는 PhysicalDrive에 접근해서 PhysicalDrvie 번호를 설정하거나, 파티션의 정보를  읽어오거나 할때 사용된다.

IoControlCode -> 좀 정리되고 정의된 데이터가 있으면 좋겠는데 안보인다. 코드 볼때마다 IoControlCode 값이 어떤걸 의미하는지 검색해봐야겠다.

우선 내가 정의한 코드들은 다음과 같은 역할을 한다.

0x70000 => IOCTL_DISK_GET_DRVIE_GEOMETRY, 디스크 타입, 실런더 갯수, 실린더 당 트랙, 트랙당 섹터, 섹터당 바이트 등
0x90020 => FSCTL_DISMOUNT_VOLUME, FSCTL의 마운트를 해제하는 역할
0x560000 => IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, PhysicalDrvie 번호를 설정할 때 사용
0x70048 => IOCTL_DISK_GET_PARTITION_INFO_EX,  파티션 정보를 읽어옴


이정도 인듯 하다. 위에 사용된 IoControlCode를 보면 알 수 있듯이,  DeviceIoControl API는 MBR의 정보를 획득하기 위해 사용되는 것을 알 수 있다.

SetFilePointerEx - MSDN

개발자 시선에서 의 파일 포인터
- 파일을 열면 초기 파일 포인터는 0이다.
- ReadFile, WriteFile 등의 함수를 이용하면 파일 포인터는 자동으로 증가한다.
- 이러한 파일 포인터를 이동시킬 때 사용되는 API가 SetFilePointer다.
- 오프셋이 32비트 

BOOL WINAPI SetFilePointerEx(
  _In_      HANDLE         hFile,    #File handle
  _In_      LARGE_INTEGER  liDistanceToMove,    #이동할 거리
  _Out_opt_ PLARGE_INTEGER lpNewFilePointer,    #옮겨진 포인터를 확인, 확인할 필요 없을 경우 NULL
  _In_      DWORD          dwMoveMethod    #어디로 이동할 것인지
);

dwMoveMethod Flag
    FILE_BEGIN : 파일 처음부터
    FILE_END : 파일 끝에서
    FILE_CURRENT : 현재 위치에서



댓글 1개: