심플스 - 프로그램과 책 이야기로 가득한 곳, (Simples.Kr)

  


   심플스 배너



 

어떤 보안 프로그램( nProtect, 키보드보안 ) 이나 SPTD를 사용하는 가상 시디 소프트웨어 ( Daemon, Alchol 120% ) 에 경우에는 드라이버가 설치되어 있지만 윈도우즈 탐색기에 \\system32\\drivers\\에 가보면 해당 드라이버 파일들이 존재하지 않는다는 것을 알 수 있습니다.

데몬을 예로 들자면 다음과 같이 설치가 완료되면 장치 관리자에 저장소 컨트롤러가 추가되게 됩니다.


b0072382_4971b1f3078e5.png 


그러나 그림에서 보는 경로에 파일은 존재하지 않으며 gmer과 같은 루트킷 체크프로그램으로 파일 시스템을 직접적으로 읽어도 파일이 존재하지 않습니다.

이러한 방식은 드라이버 파일을 숨기는 방식이 아니며 실제로 하드 디스크에 존재하지 않는 경우입니다.
드라이버를 로드하면 로드 후 바로 파일을 하드 디스크상에 삭제함으로 메모리상에만 존재하게 되는 것입니다.

이렇게 드라이버 파일을 바로 삭제하는 이유는 리버스 엔지니어링을 방지하기 위함인데
이러한 경우 어떻게 해당 드라이버 파일을 가져올 수 있는지에 대한 방법에 대해 소개할까합니다.

사실 방법은 매우 간단하며 다음과 같은 시스템에서 제공해주는 함수를 이용하면 쉽게 드라이버 파일인 .sys를 흭득 할 수 있습니다.


PsSetLoadImageNotifyRoutine

NTSTATUS
  PsSetLoadImageNotifyRoutine(
    IN PLOAD_IMAGE_NOTIFY_ROUTINE  NotifyRoutine
    );


훅킹쪽에 관심이 있으신 분이라면 거의 알만한 함수죠..
이 함수는 하나의 콜백함수를 인자로 받으며 이 콜백함수는 "시스템에서 어떠한 모듈이 로드 될 때 ( Dll, Sys )" 호출되게 됩니다.

이쯤이면 거의 답이 나왔다시피 합니다.

한 번 실제 구현코드를 보겠습니다.


void CallBackLoadImageNotifyRoutine(__in PUNICODE_STRING FullImageName, __in HANDLE ProcessId, __in PIMAGE_INFO ImageInfo)
{
    HANDLE hReadHandle;
    HANDLE hWriteHandle;
    CHAR pFileBuffer[1024];
    NTSTATUS ntStatus;
    IO_STATUS_BLOCK IoStatusBlock;
    OBJECT_ATTRIBUTES ObjectAttributes;
    LARGE_INTEGER Offset;
    UNICODE_STRING uniWritFileName;
    KdPrint(("모듈이 로드되었습니다. : %ws ( Irql : %#x )\n", FullImageName->Buffer, KeGetCurrentIrql()));
    // 드라이버의 파일은 확장자가 .sys 이므로 확장자가 s로 끝나는 이름이 있는지 확인합니다.
    if ((FullImageName->Buffer[wcslen(FullImageName->Buffer) - 1] == 's')
        || (FullImageName->Buffer[wcslen(FullImageName->Buffer) - 1] == 'S'))
    {
        // 드라이버 파일이 로드되었습니다.
        InitializeObjectAttributes(&ObjectAttributes, FullImageName, OBJ_CASE_INSENSITIVE, NULL, NULL);
        ntStatus = ZwCreateFile(&hReadHandle,
                                GENERIC_READ | SYNCHRONIZE,
                                &ObjectAttributes,
                                &IoStatusBlock, NULL,
                                FILE_ATTRIBUTE_NORMAL,
                                FILE_SHARE_READ | FILE_SHARE_WRITE,
                                FILE_OPEN,
                                FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
                                NULL,
                                0);
        if (NT_SUCCESS(ntStatus) == FALSE)
        {
            KdPrint(("파일을 생성하지 못 하였습니다.\n"));
            return ;
        }
        else
        {
            Offset.LowPart = 0;
            Offset.HighPart = 0;
            RtlInitUnicodeString(&uniWritFileName, L"\\??\\C:\\Output.Sys");
            InitializeObjectAttributes(&ObjectAttributes, &uniWritFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
            ntStatus = ZwCreateFile(&hWriteHandle,
                                    GENERIC_WRITE | SYNCHRONIZE | FILE_APPEND_DATA,
                                    &ObjectAttributes,
                                    &IoStatusBlock,
                                    NULL,
                                    FILE_ATTRIBUTE_NORMAL,
                                    FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_CREATE,
                                    FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
                                    NULL,
                                    0);
            if (NT_SUCCESS(ntStatus) == FALSE)
            {
                KdPrint(("쓰기 파일을 생성 할 수 없음 %#x\n", ntStatus));
                ZwClose(hReadHandle);
                return ;
            }
            while (TRUE)
            {
                ntStatus = ZwReadFile(hReadHandle, NULL, NULL, NULL, &IoStatusBlock, pFileBuffer, 1024, &Offset, NULL);
                if((NT_SUCCESS(ntStatus) == FALSE) || (IoStatusBlock.Information != 1024))
                {
                    ntStatus = ZwWriteFile(hWriteHandle, NULL, NULL, NULL, &IoStatusBlock, pFileBuffer, IoStatusBlock.Information, NULL, NULL);
                    if (NT_SUCCESS(ntStatus) == FALSE)
                    {
                        ZwClose(hWriteHandle);
                        ZwClose(hReadHandle);
                        return ;
                    }
                    KdPrint(("루프를 빠져나갑니다.\n"));
                    // 파일을 모두 작성하였으니 루프를 빠져나갑니다.
                    ZwClose(hWriteHandle);
                    ZwClose(hReadHandle);
                    break;
                }
                else
                {
                    ntStatus = ZwWriteFile(hWriteHandle, NULL, NULL, NULL, &IoStatusBlock, pFileBuffer, 1024, NULL, NULL);
                    if (NT_SUCCESS(ntStatus) == FALSE)
                    {
                        KdPrint(("쓰기 실패...\n"));
                        ZwClose(hWriteHandle);
                        ZwClose(hReadHandle);
                        return ;
                    }
                }
                Offset.LowPart += 1024;
            }
            KdPrint(("완료...\n"));
        }
    }
}

void Hook()
{
    if (NT_SUCCESS(PsSetLoadImageNotifyRoutine(CallBackLoadImageNotifyRoutine)) == TRUE)
    {
        KdPrint(("성공...\n"));
    }
    else
    {
        KdPrint(("실패...\n"));
    }
}

Hook() 이라는 함수는 DriverEntry와 같은 함수에서 호출하거나 또는 다른
PASSIVE_LEVEL에서 호출하면 됩니다.

콜백함수에서는 파일의 이름에서 끝에 이름이 'S' 또는 's'일 경우라면 "Output.sys"라는 파일로 "C:\" 루트에다가 드라이버 파일을 생성하게 됩니다.

실제로 이 드라이버 파일을 컴파일하고 로드를 미리 시켜놓은 다음에 데몬을 설치하고 설치가 완료되면 가상 장치 업데이트
창에서 드라이버를 로드하게 되는데 다음과 같이 DbgView에서 드라이버 파일이 로드됨을 볼 수 있습니다.


b0072382_4971b1f3078e5.png 

완료라는 메세지가 출력되고 C드라이브에 가보면 다음과 같이 Outpup.sys가 생성되게 됩니다.


b0072382_4971b1f3078e5.png 


국내에 보안 프로그램들도 위에서처럼 드라이버를 숨기게 됩니다.
밑에 그림은 특정 은행에 들어갔을 때 키보드 보안 프로그램을 설치하게 되는데 이 때 로드 된 드라이버입니다.


b0072382_4971b1f3078e5.png 

결론은 드라이버가 로드되기전에 PsSetLoadImageNotifyRoutine를 이용하면 로드 후 바로 삭제되는 로딩방식의 드라이버 파일을
가져올 수 있다는 것입니다.


profile

[레벨:3]Lyn

2010.09.04 01:52:42

헐.. 로드 했다는건 핸들 잡고있는거 아닌가요 ㅡ,.ㅡ? 왜 삭제가 되는거지 ;;

profile

[레벨:6]lain

2010.09.04 09:33:46

EXE, DLL같은 경우와 다르게 드라이버파일에 경우에는 삭제가 됩니다.ㅎㅎ


제 개인적인 생각에는 EXE같은 타입에 파일이 삭제가 되지 않는 경우는 EXE가 가상메모리에 매핑이 될 때

윈도우즈 내부적으로 EXE 파일자체를 Memory Mapped File로 사용하기 때문에 그럴까 합니다.

관련 내용은 Windows 실행파일의 구조와 원리라는 책에 43페이지부터 잘 나와있습니다.


sys파일에 경우에는 커널모드에서 실행되고 EXE처럼 PASSIVE_LEVEL에서만 실행되는게 아니라

페이지아웃이 되면 안되는 경우도 있기 때문에 물리적인 메모리에 다 올리는 것 같습니다.

profile

[레벨:3]Lyn

2010.09.04 11:36:55

흠. 드라이버는 전부 NonPaged pool 에 올라가는건가요.


드라이버 많이깔면 성능에 영향미칠수도 있겠네요 `-`;

profile

[레벨:6]lain

2010.09.04 12:01:14

페이지 아웃되는 영역도 있기 때문에 Paged Pool에도 들어갈 수 있습니다.

물론 이런 경우에도 드라이버 파일은 삭제가 됩니다.

처음에 로드 될 때 어떠한 상황이라도 완전히 물리 메모리에 올라가는지에 대해서는

저도 정확하게 확인해보질 않아서 잘은 모르겠습니다.emoticon

profile

[레벨:8]esniper

2010.09.05 22:07:51

최근 바이러스들은 드라이버로 올려놓고 원본 파일은 삭제 되버리니깐 엄청 골치아픈데

그런것들만 따로 모아서 보여주면 편하겠네~

List of Articles
번호 제목 글쓴이 날짜 조회 수
142 Windows Research 디바이스이름으로부터 PDEVICE_OBJECT 얻기 file [레벨:6]lain 2010-09-04 3675
» Windows Research 하드디스크에 존재하지 않는 드라이버 바이너리 가져오기 file [5] [레벨:6]lain 2010-09-03 3627
140 Windows Research DosPathNameToNtPathName file [레벨:6]lain 2010-09-03 2617
139 Windows Research ZwQueryInformationFile을 비동기 파일핸들로 호출 시 STAT... file [레벨:6]lain 2010-09-03 3481
138 Windows Research 커널 디버거 탐지 기법 우회 [레벨:6]lain 2010-09-03 3708
137 Windows Research VMWare 탐지 기법 우회 [2] [레벨:6]lain 2010-09-03 5115
136 Windows Research 커널 모듈 리스트 가져오기 [3] [레벨:6]lain 2010-09-03 2627
135 Windows Research IDA에서 Microsoft 바이너리 파일을 리버싱 할 때 디버그 ... file [1] [레벨:6]lain 2010-09-03 3725
134 Windows Research IDA에 HexRay를 사용할 때의 주의점 [1] [레벨:6]lain 2010-09-03 3347
133 Windows Research 유저 레벨에서 API Hook 2부 file [2] [레벨:6]lain 2010-09-03 2336
132 Windows Research 유저 레벨에서 API Hook 1부 file [1] [레벨:6]lain 2010-09-03 2498
131 Windows Research 윈도우즈 버전이 Windows XP SP2인지 확인하는 다른 방법 [1] [레벨:6]lain 2010-09-03 2728
130 문서자료 Hexray - Failures and troubleshooting [레벨:6]lain 2010-09-03 2130
129 문서자료 Intel i80x86 CPU Architecture [레벨:6]lain 2010-09-03 1981
128 문서자료 Keybaord Scan Codes Demystified [레벨:6]lain 2010-09-03 2058
127 문서자료 Bona Fide OSDev Documents [레벨:6]lain 2010-09-03 1981
126 문서자료 the Operating System resource center [레벨:6]lain 2010-09-03 1543
125 문서자료 Win32 Assembly Tutorials [1] [레벨:6]lain 2010-09-03 1985
124 문서자료 Mozilla - Accessibility/AT-Windows-API [레벨:6]lain 2010-09-03 1984
123 문서자료 Intel® Threading Building Blocks: Documents [레벨:6]lain 2010-09-03 2600

  • 이용약관
  • 개인정보취급방침
  • 사이트맵