VS 2022 17.11.5버전 기준

1. 최신 NDK 다운로드

2. 원본 C:\Program Files (x86)\Android\AndroidNDK\android-ndk-r23c 백업 및 해당 경로에 최신 NDK 덮어 씌우기

3. 텍스트 편집기를 관리자 권한으로 실행 후, 아래 경로를 로드

C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Application Type\Android\3.0\Android.Common.props

isystem 문자열 검색 후, 아래 파란 라인을 삭제

VS 프로젝트 -> 속성페이지 -> C/C++ -> 명령줄 -> 모든 옵션에서 -isystem이 사라진 것을 확인

(최신 NDK와 호환되지 않는 경로 설정을 삭제)

4. 텍스트 편집기를 관리자 권한으로 실행 후, 아래 두 개의 경로를 로드

C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Application Type\Android\3.0\Platforms\ARM\PlatformToolsets\Clang_5_0\toolset.props

C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Application Type\Android\3.0\Platforms\ARM64\PlatformToolsets\Clang_5_0\toolset.props

lib64 문자열 검색 후, 아래처럼 lib\clang\18로 변경 (경로마다 각각 변경)

6. 빌드

'Windows > Dev' 카테고리의 다른 글

windows + mac 동시 개발 시 주의 사항  (0) 2024.10.15
[C++] 함수 const 선언 정리  (0) 2024.09.12
[MSVC] 클래스 고찰 & 디컴파일  (0) 2024.08.08
[VC++] 문자열 복사, 이동  (0) 2024.05.09
detours 빌드 및 적용  (0) 2024.04.11

1. windows에서 CRLF를 사용한다면, 맥에서도 CRLF로 변경해야함.

Xcode -> Settings -> Text Editing -> Editing -> Default Line Endings을 CRLF로 변경

2. 맥에서는 UTF8(BOM)을 지원하지 않으므로, windows에서 UTF8(BOM)으로 작업하고 있었다면 UTF8로 변경해줘야 함

이 두가지를 맞추지 않으면, git 작업 시 애로사항이 꽃 핀다.

const 선언할 경우 해당 함수의 this는 const가 된다.

즉, 수정 불가능한 상태가 된다. 따라서, this의 모든 멤버 변수에 접근할 수 없다.

또한, 해당 함수에서는 비 const 함수를 호출할 수 없다. 왜냐면 비 const함수에서는 멤버 변수가 수정될 수 있기 때문이다.

class AA {
public:
    AA() = default;
    ~AA() = default;

    void printData(int value) const
    {
        std::cout << this->data;
        this->data = value; // 에러 
        changeData(); // 에러
    }

    void changeData(int value) 
    {
        this->data = value;
    }

private:
    int data = 0;
};
int main()
{
    std::cout << "Hello World!\n";
}

 

 

환경: c++20, 최적화 끔(-O0), 릴리즈 빌드

테스트 1

class A
{
public:
    void foo()
    {
        printf("hello %d\n", var);
    }
    void set(int a)
    {
        this->var = a;  
    }
private:
    int var = 100;
};

int main()
{
    A a;
    a.foo();
    A b;
    b = a;
    b.foo();
 }

아래는 IDA 디컴파일

int __fastcall main(int argc, const char **argv, const char **envp)
{
  A a; // [rsp+20h] [rbp-18h] BYREF
  A b; // [rsp+24h] [rbp-14h] BYREF

  A::A(&a);
  A::foo(&a);
  A::A(&b);
  b.var = a.var;
  A::foo(&b);
  return 0;
}

void __fastcall A::A(A *this)
{
  this->var = 100;
}

void __fastcall A::foo(A *this)
{
  printf("hello %d\n", (unsigned int)this->var);
}

스택에 a, b 각 4바이트씩 할당함 (멤버변수 사이즈)

클래스의 함수는 일반적인 함수로 취급 (함수명이 A::foo)

= 연산자에서 대입이 발생

테스트 2

private 변수만 늘리고 컴파일

private:
    int var = 100;
    int var2 = 200;
    int var3 = 300;

아래는 IDA 디컴파일

int __fastcall main(int argc, const char **argv, const char **envp)
{
  A a; // [rsp+20h] [rbp-48h] BYREF
  A b; // [rsp+30h] [rbp-38h] BYREF

  A::A(&a);
  A::foo(&a);
  A::A(&b);
  qmemcpy(&b, &a, sizeof(b));
  A::foo(&b);
  return 0;
}

멤버 변수가 많으면 memcpy로 복사함

테스트 3

class A
{
public:
    A& operator=(const A& a)
    {
        this->var = a.var;
        return *this;
    }
    void foo()
    {
        printf("hello %d\n", var);
    }
    void set(int a)
    {
        this->var = a;
  
    }
private:
    int var = 100;
};

아래는 IDA 디컴파일

int __fastcall main(int argc, const char **argv, const char **envp)
{
  A a; // [rsp+20h] [rbp-18h] BYREF
  A b; // [rsp+24h] [rbp-14h] BYREF

  A::A(&a);
  A::foo(&a);
  A::A(&b);
  A::operator=(&b, &a);
  A::foo(&b);
  return 0;
}

A *__fastcall A::operator=(A *this, const A *a)
{
  this->var = a->var;
  return this;
}

기본 = 연산자가 내가 재정의한 operator=로 대체됨

operator=는 일반적인 함수로 취급 (함수명이 A::operator=)

테스트 4

class A
{
public:
    A& daeip(const A& a)
    {
        this->var = a.var;
        return *this;
    }
    A& operator=(const A& a)
    {
        this->var = a.var;
        return *this;
    }
    void foo()
    {
        printf("hello %d\n", var);
    }
    void set(int a)
    {
        this->var = a;
  
    }
private:
    int var = 100;
};
int main()
{
    A a;
    a.foo();
    A b;
    b = a;
    b.foo();
    A c;
    c.daeip(a);
 }

아래는 IDA 디컴파일

int __fastcall main(int argc, const char **argv, const char **envp)
{
  A a; // [rsp+20h] [rbp-28h] BYREF
  A b; // [rsp+24h] [rbp-24h] BYREF
  A c; // [rsp+28h] [rbp-20h] BYREF

  A::A(&a);
  A::foo(&a);
  A::A(&b);
  A::daeip(&b, &a);
  A::foo(&b);
  A::A(&c);
  A::daeip(&c, &a);
  return 0;
}

daeip 함수와 operator=는 기능적으로 동일함

최적화에 의해 operator= 가 삭제되고 daeip 함수로 통일됨

테스트 5

class A
{
public:
    void daeip(const A& a)
    {
        this->var = a.var;
    }
    void operator=(const A& a)
    {
        this->var = a.var;
    }
    void foo()
    {
        printf("hello %d\n", var);
    }
    void set(int a)
    {
        this->var = a;
  
    }
private:
    int var = 100;
};

int main()
{
    A a;
    a.foo();
    A b;
    b = a;
    b.foo();
    A c;
    c.daeip(a);
}

아래는 IDA 디컴파일

int __fastcall main(int argc, const char **argv, const char **envp)
{
  A a; // [rsp+20h] [rbp-28h] BYREF
  A b; // [rsp+24h] [rbp-24h] BYREF
  A c; // [rsp+28h] [rbp-20h] BYREF

  A::A(&a);
  A::foo(&a);
  A::A(&b);
  A::daeip(&b, &a);
  A::foo(&b);
  A::A(&c);
  A::daeip(&c, &a);
  return 0;
}

b = a 처럼 단순 대입만 할 경우 operator=의 리턴값을 void로 해도 무방하다.

테스트6

class A
{
public:  
    void foo()
    {
        printf("hello %d\n", var);
    }
    void set(int a)
    {
        this->var = a;  
    }
private:
    int var = 100;
};

int main()
{
    A a;
    a.foo();
    A& b = a;
    b.foo();
}

아래는 IDA 디컴파일

int __fastcall main(int argc, const char **argv, const char **envp)
{
  A a; // [rsp+28h] [rbp-20h] BYREF

  A::A(&a);
  A::foo(&a);
  A::foo(&a);
  return 0;
}

A& b를 A a로 인식함

테스트7

class A
{
public: 
    A& operator=(const A& a)
    {
        this->var = a.var;
        return *this;
    }
    void foo()
    {
        printf("hello %d\n", var);
    }
    void set(int a)
    {
        this->var = a;  
    }
private:
    int var = 100;
};

아래는 IDA 디컴파일

int __fastcall main(int argc, const char **argv, const char **envp)
{
  A a; // [rsp+28h] [rbp-20h] BYREF

  A::A(&a);
  A::foo(&a);
  A::foo(&a);
  return 0;
}

재정의를 해도 참조 연산 기능이 동일하여  바이너리 결과는 같음

'Windows > Dev' 카테고리의 다른 글

windows + mac 동시 개발 시 주의 사항  (0) 2024.10.15
[C++] 함수 const 선언 정리  (0) 2024.09.12
[VC++] 문자열 복사, 이동  (0) 2024.05.09
detours 빌드 및 적용  (0) 2024.04.11
[Visual Studio 2022] curl 빌드  (0) 2023.01.30

 

	string a = "hello man world girl";

	cout << static_cast<void*>(a.data()) << endl;
	cout << a << endl;

	string b = a;
	cout << static_cast<void*>(b.data()) << endl;
	cout << b << endl;

	string c = move(a);
	cout << a << endl;
   	cout << static_cast<void*>(a.data()) << endl;
	cout << static_cast<void*>(c.data()) << endl;
	cout << c << endl;

b = a을 하게 되면 복사가 일어난다. 즉, 객체의 생성 -> 복사 -> 파괴가 두번 발생한다.

move 의 경우, 객체의 생성 후 이동만 발생한다. a의 allocator가 c로 이동되며, 이동 후 a의 allocator에는 빈 값과 빈 버퍼가 들어간다. 

 

 

'Windows > Dev' 카테고리의 다른 글

[C++] 함수 const 선언 정리  (0) 2024.09.12
[MSVC] 클래스 고찰 & 디컴파일  (0) 2024.08.08
detours 빌드 및 적용  (0) 2024.04.11
[Visual Studio 2022] curl 빌드  (0) 2023.01.30
[VC++] string deallocate  (0) 2022.05.23

x64 Native Tools Command Prompt for VS 2022 실행

git clone https://github.com/Microsoft/Detours.git
cd detours
nmake

VS 2022로 Detours\vc\Detours.sln 오픈 후, x64, x86 각각 빌드


VS에서 새 DLL 프로젝트를 만들고, 해당 디렉토리에 아래의 파일을 복사

Detours\lib.X??\*.lib
Detours\include\*.h

속성 -> 링커 -> 입력 -> 추가 종속성에 아래의 파일을 추가

detours.lib
syelog.lib

아래와 같이 후킹 코드를 작성하고 빌드한다.

#include "pch.h"
#include <stdio.h>
#include "detours.h"

HANDLE(WINAPI* OrgCreateFileW)(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE) = CreateFileW;

HANDLE WINAPI MyCreateFileW(
    _In_ LPCWSTR lpFileName,
    _In_ DWORD dwDesiredAccess,
    _In_ DWORD dwShareMode,
    _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    _In_ DWORD dwCreationDisposition,
    _In_ DWORD dwFlagsAndAttributes,
    _In_opt_ HANDLE hTemplateFile
)
{
    wprintf(L"%s\n", lpFileName);    
    return OrgCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}

BOOL Start()
{
    AllocConsole();
    FILE* fp;
    freopen_s(&fp, "CONOUT$", "w", stdout);
 
    DetourRestoreAfterWith();
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourAttach(&(PVOID&)OrgCreateFileW, MyCreateFileW);
    DetourTransactionCommit();
    return TRUE;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        Start();
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

아래의 DLL Injector로 테스트가 가능하다.

 

GitHub - TarekExister/UWP-Dll-Injector-32bit-64bit: universal windows platform (uwp) apps Dll injector [32bit-64bit]

universal windows platform (uwp) apps Dll injector [32bit-64bit] - TarekExister/UWP-Dll-Injector-32bit-64bit

github.com

 

'Windows > Dev' 카테고리의 다른 글

[MSVC] 클래스 고찰 & 디컴파일  (0) 2024.08.08
[VC++] 문자열 복사, 이동  (0) 2024.05.09
[Visual Studio 2022] curl 빌드  (0) 2023.01.30
[VC++] string deallocate  (0) 2022.05.23
get EIP (gcc / vc)  (0) 2019.04.11

0. Windows 11 에서 정상적인 실행이 되지 않으므로, hyper-V 등을 통해서 windows 10에서 실행하는 것을 권장한다.

1. 다운로드 : Python3, Visual studio 2022, DynamoRIO(https://github.com/DynamoRIO/dynamorio/releases)

2. 적절한 경로에 DynamoRIO 압축 해제

3. config.h 에서 input 파일 최대 사이즈 수정  (1*1024*1024 를 아래와 같이 수정)

/* Maximum size of input file, in bytes (keep under 100MB): */

#define MAX_FILE            (100 * 1024 * 1024)

4. x64 Native Tools Command Prompt for VS 2022 열기

git clone https://github.com/googleprojectzero/winafl
cd winafl
git submodule update --init --recursive
mkdir build64
cd build64
cmake -G"Visual Studio 17 2022" -A x64 .. -DDynamoRIO_DIR=I:\DynamoRIO\cmake -DTINYINST=1 -DUSE_DRSYMS=1 -DINTELPT=1 -DUSE_COLOR=1
cmake --build . --config Release

5. harness 작성

#include <iostream>
#include <windows.h>

typedef int(__stdcall* _OHMYGOD)(const char* data); 
_OHMYGOD func;

extern "C" __declspec(dllexport) __declspec(noinline) int fuzzme(const char* path)
{   
    int result = func(path);
    return result;
}

int main(int argc, char *argv[])
{    
    HMODULE hMod = GetModuleHandle(0);
   
    hMod = LoadLibrary(L"I:\\victim\\x64\\Release\\victim.dll");
    if (NULL == hMod)
    {
        printf("dll load error\n");
        return 0;
    }
   
    func = (_OHMYGOD)GetProcAddress(hMod, "ohmygod");
    fuzzme(argv[1]);    
}

6. victim 작성 (타겟 DLL)

#include "pch.h"
#include <iostream>

extern "C" __declspec(dllexport) int ohmygod(const char* path)
{
    std::cout << path << std::endl;
    char data[40] = { 0, };
    char buf[30] = { 0, };
    
    HANDLE hFile = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (hFile)
    {
        DWORD dwRead;
       
        ReadFile(hFile, data, sizeof(data), &dwRead, NULL);
        std::cout << "read : " << dwRead << std::endl;
        if (dwRead)
        {
            memcpy(buf, data, dwRead+40);
            std::cout << buf;
        }
        CloseHandle(hFile);
    }
    return 0;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

원활한 crash 발생을 위해 각각 Release 로 빌드한다.

7. 입출력 디렉토리 설정

afl은 사용자가 지정한 입력 디렉토리에 있는 파일들을 퍼징 데이터로 사용한다. 

crash를 유발하지 않는 정상 입력 데이터이어야 첫 실행 시 에러가 발생하지 않는다.

아래 데이터를 1.txt로 저장한다.

abcd

8. 공격

afl-fuzz.exe -D I:\\dynamorio\\bin64  -i "d:\\fuzz_input" -o "d:\\fuzz_output" -t 1000 -- -coverage_module victim.dll -target_module harness.exe -target_method fuzzme -fuzz_iterations 10 -nargs 1 -- I:\\harness\\x64\\Release\\harness.exe @@

실행은 반드시 afl-fuzz.exe 디렉토리에서 하여야 한다. 그렇지 않다면 아래와 같은 에러가 발생한다.

주의 : -coverage_module 및 -target_module 에는 파일명만 기입한다.

아래와 같은 화면이 나오면 실행 성공이다.

crash가 발생할 경우, i:\fuzz_output\crashes 경로에 상세 정보가 저장된다.

만약 CPU가 인텔인 경우, -D 옵션 대신 -P옵션을 사용하도록 하자. 속도가 압도적으로 빠르다. (내 PC에서는 5배 이상 차이가 났다.)

afl-fuzz.exe -P -i "d:\\fuzz_input" -o "d:\\fuzz_output" -t 1000 -- -coverage_module victim.dll -target_module harness.exe -target_method fuzzme -fuzz_iterations 10 -nargs 1 -- I:\\harness\\x64\\Release\\harness.exe @@

 

x64 Native Tools Command Prompt for VS 2022 프롬프트 실행

git clone https://github.com/curl/curl.git
cd curl
buildconf.bat
Set RTLIBCFG=static
cd winbuild
nmake /f MakeFile.vc mode=static vc=17

빌드는 아래 경로에 생성 됨

curl\builds\libcurl-vc17-x64-release-static-ipv6-sspi-schannel

curl.zip
1.25MB

프로젝트 설정

#include <curl.h>
int main()
{
    CURL* curl = curl_easy_init();
    CURLcode res;
}

 

'Windows > Dev' 카테고리의 다른 글

[VC++] 문자열 복사, 이동  (0) 2024.05.09
detours 빌드 및 적용  (0) 2024.04.11
[VC++] string deallocate  (0) 2022.05.23
get EIP (gcc / vc)  (0) 2019.04.11
C용 초경량 XML 파서 : Mini-XML 소개 및 사용법  (0) 2017.06.29

deallocate시 문자열 길이 단위는 0x10이며, 문자열 길이가 0x10이하면 _Count 에는 1이 들어가고, _Deallocate를 호출하면서 0x10 * 1하여 0x10 사이즈로 deallocate를 하게 된다.

예시)  string abc = "this is";

_Ptr은 이중 포인터이며, &abc의 주소를 담고 있다.

길이가 0x10을 초과하는 경우 param에 블록단위(0x10의 배수)가 들어간다.

예시) string abc = "live a live is not fun"; // 22바이트

 

긴 사이즈에서 짧은 사이즈로 리사이즈 하는 경우, 최초에 할당한 길이로 deallocate가 한 번만 수행된다.

string abc = "live a live is not fun";
abc = "papa";

vc++에서는 문자열의 길이를 deallocate의 인자로 확인할 수 없으므로, deallocate 재정의를 통한 memory wipe는 수행할 수 없다.

namespace secure
{
    template <class T> class allocator : public std::allocator<T>
    {
    public:

        template<class U> struct rebind { typedef allocator<U> other; };
        allocator() throw() {}
        allocator(const allocator&) throw() {}
        template <class U> allocator(const allocator<U>&) throw() {}

        void deallocate(T* const p, size_t _Count)
        {            
            memset((void*)p, 0, _Count); // _Count가 문자열 길이를 뜻하는 것이 아니다                    
            std::allocator<T>::deallocate(p, _Count);
        }
    };

    typedef std::basic_string<char, std::char_traits<char>, allocator<char> > string;
}

 

'Windows > Dev' 카테고리의 다른 글

detours 빌드 및 적용  (0) 2024.04.11
[Visual Studio 2022] curl 빌드  (0) 2023.01.30
get EIP (gcc / vc)  (0) 2019.04.11
C용 초경량 XML 파서 : Mini-XML 소개 및 사용법  (0) 2017.06.29
x86 __usercall 함수 후킹하기  (0) 2017.05.11

테스트 환경 : windows 10 x64 build 19041

이 방식은 DRIVER_OBJECT -> OBJECT_HEADER_NAME_INFO ->  OBJECT_DIRECTORY -> OBJECT_DIRECTORY_ENTRY 순서대로 구조체를 얻어온 뒤 ENTRY 체인을 끊어 목록에서 제거하는 방식입니다.

이를 위해 먼저 최상위 OBJECT_DIRECTORY 부터 살펴봅니다.

lkd> !object ffffcb83e84023c0
Object: ffffcb83e84023c0  Type: (ffffdc8a4aa9c4e0) Directory
    ObjectHeader: ffffcb83e8402390 (new version)
    HandleCount: 0  PointerCount: 58
    Directory Object: 00000000  Name: \

    Hash Address          Type                      Name
    ---- -------          ----                      ----
     01  ffffdc8a4ccfe450 Mutant                    PendingRenameMutex
         ffffcb83e8451ad0 Directory                 ObjectTypes
     02  ffffdc8a4f6ec6e0 FilterConnectionPort      storqosfltport
     04  ffffdc8a55ba1c20 FilterConnectionPort      TsFltScanPort_V3LITE40
     05  ffffdc8a55ba1670 FilterConnectionPort      TsFltCheckPort_V3LITE40
         ffffcb83e84b6520 SymbolicLink              SystemRoot
     06  ffffcb83e8cfba20 Directory                 Sessions
     08  ffffcb83e848fb80 Directory                 ArcName
     09  ffffdc8a4f6ec9a0 FilterConnectionPort      WcifsPort
         ffffcb83e84ec060 Directory                 NLS
     10  ffffdc8a4fa27760 Event                     LanmanServerAnnounceEvent
         ffffdc8a4f86baa0 ALPC Port                 ThemeApiPort
         ffffdc8a4ce59d40 Device                    UdfsCdRom
         ffffcb83e8ba5380 Directory                 Windows
         ffffcb83e8467c50 Directory                 GLOBAL??
     11  ffffcb83e8cfb2a0 Directory                 RPC Control
         ffffdc8a4c3596a0 ALPC Port                 PdcPort
     13  ffffdc8a55b87400 FilterConnectionPort      MEDSRVPOSTPORT_V3LITE40_2.13.1.63
         ffffdc8a4cd7a4e0 Event                     EFSInitEvent
     14  ffffcb83e8c68930 SymbolicLink              Dfs
         ffffdc8a4c53c870 Device                    clfs
     15  ffffdc8a4c22dc90 Event                     CsrSbSyncEvent
         ffffdc8a4c62a790 ALPC Port                 SeRmCommandPort
     16  ffffcb83e8445830 SymbolicLink              DosDevices
     17  ffffdc8a55b92450 FilterConnectionPort      MEDSRVPENDINGPORT_V3LITE40_2.13.1.63
         ffffcb83e8cfbc00 Directory                 KnownDlls32
     18  ffffdc8a55b88fa0 FilterConnectionPort      MEDSRVSENDPORT_V3LITE40_2.13.1.63
         ffffcb83e849ad20 Key                       \REGISTRY
     19  ffffcb83e8836c00 Directory                 BaseNamedObjects
     20  ffffcb83e8ec49d0 Section                   Win32kCrossSessionGlobals
         ffffdc8a4ab13df0 ALPC Port                 PowerPort
     21  ffffdc8a4f412a10 ALPC Port                 SmSsWinStationApiPort
         ffffdc8a4c22b7b0 Event                     UniqueInteractiveSessionIdEvent
         ffffcb83e84ec920 Directory                 UMDFCommunicationPorts
     22  ffffcb83e8cfb840 Directory                 KnownDlls
         ffffdc8a4cc52d40 Device                    FatCdrom
         ffffdc8a4cc53d40 Device                    Fat
         ffffdc8a4ab46df0 ALPC Port                 PowerMonitorPort
     23  ffffdc8a4c626b50 Device                    Ntfs
         ffffcb83e84ec3e0 Directory                 FileSystem
         ffffcb83e8441cc0 Directory                 KernelObjects
     26  ffffdc8a4ebebd40 ALPC Port                 SeLsaCommandPort
         ffffcb83e8451ca0 Directory                 Callback
     28  ffffdc8a4f6ec580 FilterConnectionPort      BindFltPort
         ffffdc8a4c23dc30 Event                     DSYSDBG.Debug.Trace.Memory.2bc
         ffffcb83e84588d0 Directory                 Security
     29  ffffdc8a4ce31e00 Device                    UdfsDisk
     30  ffffcb83e8490060 Directory                 Device
     32  ffffcb83e84f8190 SymbolicLink              DriverData
     34  ffffcb83ebcfe610 Section                   LsaPerformance
         ffffdc8a4c8aec70 ALPC Port                 SmApiPort
     35  ffffdc8a4f6ec4d0 FilterConnectionPort      CLDMSGPORT
         ffffcb83e84b66d0 SymbolicLink              OSDataRoot
     36  ffffdc8a4c23e9f0 Event                     SAM_SERVICE_STARTED
         ffffcb83e84ec220 Directory                 Driver
         ffffcb83e8489820 Directory                 DriverStores

저의 windows의 windbg 화면으로, OBJECT_DIRECTORY 구조체는 타입과 이름을 가지고 있습니다. 최상위 구조체라서 타입은 HANDLE을 가지고 있습니다.

우리에게 필요한 것은 드라이버 목록인데, 이는 각각 23번, 36번 인덱스 2번째에 속해 있습니다. (FileSystem, Driver) 

일반적으로 드라이버를 로딩하면 Driver의 OBJECT_DIRECTORY에 연결되므로, 36번 인덱스의 Driver만 보도록 하겠습니다. 

위 주소를 다시 구조체로 표현해봅니다.

lkd> dt !_OBJECT_DIRECTORY  ffffcb83e84023c0
nt!_OBJECT_DIRECTORY
   +0x000 HashBuckets      : [37] (null) 
   +0x128 Lock             : _EX_PUSH_LOCK
   +0x130 DeviceMap        : (null) 
   +0x138 ShadowDirectory  : (null) 
   +0x140 NamespaceEntry   : (null) 
   +0x148 SessionObject    : (null) 
   +0x150 Flags            : 0
   +0x154 SessionId        : 0xffffffff

HashBucket은 37개의 배열로 구성되어 있으며, 각각 OBJECT_DIRECTORY_ENTRY로 표현됩니다. 각 OBJECT_DIRECTORY_ENTRY체인으로 연결되어 있습니다. 

운영체제는 각각의 Name에서 Hash Index 를 계산해 각 배열에 삽입하는 방식입니다. 따라서 연결된 Entry의 갯수는 일정하지 않습니다. 

보시면 00, 03번 인덱스는 존재하지 않고, 10번의 경우 5개의 오브젝트가 존재하는데 Name에서 동일한 Hash Index가 계산된 결과입니다. (Hash인덱스를 어떻게 구하는지는 모르겠습니다. 만약 알게되면 기술하도록 하겠습니다.)

HashBucket을 눌러보면 아래와 같이 나옵니다.

lkd> dx -id 0,0,ffffdc8a4aa96040 -r1 (*((ntkrnlmp!_OBJECT_DIRECTORY_ENTRY * (*)[37])0xffffcb83e84023c0))
(*((ntkrnlmp!_OBJECT_DIRECTORY_ENTRY * (*)[37])0xffffcb83e84023c0))                 [Type: _OBJECT_DIRECTORY_ENTRY * [37]]
    [0]              : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [1]              : 0xffffcb83e8ca8b10 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [2]              : 0xffffcb83ec36c2e0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [3]              : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [4]              : 0xffffcb83f4a17c00 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [5]              : 0xffffcb83f4a17b70 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [6]              : 0xffffcb83e8caca10 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [7]              : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [8]              : 0xffffcb83e84b5060 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [9]              : 0xffffcb83ebf53e70 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [10]             : 0xffffcb83ec371200 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [11]             : 0xffffcb83e8ca8d20 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [12]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [13]             : 0xffffcb83ece2c4c0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [14]             : 0xffffcb83e8b80690 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [15]             : 0xffffcb83e8caec90 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [16]             : 0xffffcb83e84af0c0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [17]             : 0xffffcb83ece2c430 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [18]             : 0xffffcb83ece2c400 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [19]             : 0xffffcb83e854c2e0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [20]             : 0xffffcb83e85439d0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [21]             : 0xffffcb83e8845930 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [22]             : 0xffffcb83e8ca8d80 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [23]             : 0xffffcb83e855f600 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [24]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [25]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [26]             : 0xffffcb83e8841160 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [27]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [28]             : 0xffffcb83ec36cca0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [29]             : 0xffffcb83e8cad460 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [30]             : 0xffffcb83e84b5630 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [31]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [32]             : 0xffffcb83e8545a00 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [33]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [34]             : 0xffffcb83e8841250 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [35]             : 0xffffcb83ec36c430 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [36]             : 0xffffcb83e8842420 [Type: _OBJECT_DIRECTORY_ENTRY *]

36번 인덱스의 주소를 구조체로 확인해봅니다.

lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83e8842420
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e8568920 _OBJECT_DIRECTORY_ENTRY
   +0x008 Object           : 0xffffdc8a`4c23e9f0 Void
   +0x010 HashValue        : 0x9b5074d

2번째에 위치해있으니 ChainLink를 따라가봅니다.

lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83e8568920
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e84b5b10 _OBJECT_DIRECTORY_ENTRY
   +0x008 Object           : 0xffffcb83`e84ec220 Void
   +0x010 HashValue        : 0x80a0801

해당 OBJECT_DIRECTORY_ENTRY에 0xffffcb83e84ec220 오브젝트가 있음을 확인할 수 있습니다. (!object 한 것과 값을 비교해보세요) 이 주소는 OBJECT_DIRECTORY 구조체로 표현됩니다.(그래서 Type명이 Directory입니다.) 이를 다시 !object로 확인해봅니다.

lkd> !object 0xffffcb83e84ec220
Object: ffffcb83e84ec220  Type: (ffffdc8a4aa9c4e0) Directory
    ObjectHeader: ffffcb83e84ec1f0 (new version)
    HandleCount: 0  PointerCount: 124
    Directory Object: ffffcb83e84023c0  Name: Driver

    Hash Address          Type                      Name
    ---- -------          ----                      ----
     00  ffffdc8a50e1eb20 Driver                    kldbgdrv
         ffffdc8a4c9a2e20 Driver                    fvevol
         ffffdc8a4c356d70 Driver                    vdrvroot
     01  ffffdc8a4cd2ee00 Driver                    usbuhci
         ffffdc8a4cc9dd40 Driver                    GpuEnergyDrv
         ffffdc8a4ca4b9e0 Driver                    NetBT
         ffffdc8a4aa3fd00 Driver                    acpiex
         ffffdc8a4aa8bde0 Driver                    Wdf01000
     02  ffffdc8a4faabb70 Driver                    mpsdrv
         ffffdc8a4c53a060 Driver                    storahci
     03  ffffdc8a51c56540 Driver                    BthEnum
         ffffdc8a4fd73e20 Driver                    MMCSS
         ffffdc8a4f924e30 Driver                    lltdio
         ffffdc8a4cbdeb40 Driver                    bam
         ffffdc8a4cc63d80 Driver                    Psched
         ffffdc8a4cb8ae40 Driver                    BasicRender
         ffffdc8a4c9c28f0 Driver                    disk
     04  ffffdc8a4facadf0 Driver                    HTTP
         ffffdc8a4c382d80 Driver                    stornvme
     05  ffffdc8a4cdbe5b0 Driver                    e1i65x64
         ffffdc8a4cb9acb0 Driver                    WscVReg
     06  ffffdc8a4f641a70 Driver                    monitor
         ffffdc8a4cdb7b50 Driver                    usbehci
         ffffdc8a4cb9a6c0 Driver                    ahcache
         ffffdc8a4cafae40 Driver                    vmrawdsk
         ffffdc8a4c9c1dc0 Driver                    iorate
         ffffdc8a4c53b640 Driver                    pcw
     07  ffffdc8a4fcd4df0 Driver                    AMonCDW8
         ffffdc8a4cde8060 Driver                    Ucx01000
         ffffdc8a4cde7060 Driver                    USBXHCI
         ffffdc8a4c359dc0 Driver                    partmgr
     08  ffffdc8a52b98e50 Driver                    AntiStealth_V3LITE40
         ffffdc8a4fd83a10 Driver                    PEAUTH
         ffffdc8a4ab88e40 Driver                    MsLldp
         ffffdc8a4cc6fa30 Driver                    Vid
         ffffdc8a4ab0cd80 Driver                    ACPI_HAL
     09  ffffdc8a4c372850 Driver                    spaceport
     10  ffffdc8a4cf1ae00 Driver                    HidUsb
         ffffdc8a4cc62dd0 Driver                    vwififlt
     11  ffffdc8a50ea0e10 Driver                    condrv
         ffffdc8a4cb9be40 Driver                    DXGKrnl
         ffffdc8a4ab35e20 Driver                    PnpManager
     12  ffffdc8a4c9c9740 Driver                    Null
         ffffdc8a4c35ca80 Driver                    vsock
         ffffdc8a4ab3be20 Driver                    intelpep
     13  ffffdc8a506c4e30 Driver                    MeDCoreD_V3LITE40
         ffffdc8a4aa81e20 Driver                    Telemetry
         ffffdc8a4aae6de0 Driver                    SoftwareDevice
     14  ffffdc8a52e98a70 Driver                    RFCOMM
         ffffdc8a4ca57e10 Driver                    Serenum
         ffffdc8a4c8ae0a0 Driver                    CLFS
         ffffdc8a4ab28e20 Driver                    WindowsTrustedRTProxy
     15  ffffdc8a4ccdae20 Driver                    Serial
         ffffdc8a4cc59d40 Driver                    NdisCap
         ffffdc8a4c8b3d30 Driver                    KSecDD
         ffffdc8a4c35bda0 Driver                    volmgr
         ffffdc8a4aaced80 Driver                    DeviceApi
     16  ffffdc8a4fcd3c90 Driver                    VMMemCtl
         ffffdc8a4ccd6e20 Driver                    umbus
         ffffdc8a4aad9c10 Driver                    MsSecFlt
         ffffdc8a4abd8cc0 Driver                    CNG
     17  ffffdc8a4ce72e20 Driver                    Win32k
         ffffdc8a4cce0dc0 Driver                    i8042prt
         ffffdc8a4cc96d70 Driver                    npsvctrig
         ffffdc8a4c9bed90 Driver                    volume
         ffffdc8a4c8b6e00 Driver                    KSecPkg
     18  ffffdc8a4cca25b0 Driver                    mouclass
     19  ffffdc8a4ea59e00 Driver                    X58a84jzGG36Q
         ffffdc8a4c53d350 Driver                    msisadrv
     20  ffffdc8a4fd79e10 Driver                    Ndu
         ffffdc8a4ccdddb0 Driver                    kbdclass
     21  ffffdc8a4c8b8e00 Driver                    mouhid
         ffffdc8a4c9bf8f0 Driver                    volsnap
     22  ffffdc8a567efe30 Driver                    MeDVpDrv_V3LITE40
         ffffdc8a4cc71dd0 Driver                    nsiproxy
         ffffdc8a4c944bd0 Driver                    AhnRghNt
         ffffdc8a4aaddd80 Driver                    WMIxWDM
     23  ffffdc8a528188f0 Driver                    BthPan
         ffffdc8a4fac3e30 Driver                    MsQuic
         ffffdc8a4cb6f9a0 Driver                    tdx
         ffffdc8a4c360a90 Driver                    vmci
     24  ffffdc8a5102ae30 Driver                    AntiStealth_V3LITE40F
         ffffdc8a52f8b570 Driver                    BTHUSB
         ffffdc8a4ab32e20 Driver                    WindowsTrustedRT
     25  ffffdc8a4cd2fde0 Driver                    HDAudBus
         ffffdc8a4cbbde40 Driver                    BasicDisplay
     26  ffffdc8a4cd62e00 Driver                    rdpbus
     27  ffffdc8a50eaca70 Driver                    Cdm2DrNt
         ffffdc8a4fcd3a70 Driver                    DBGV
         ffffdc8a4c358dc0 Driver                    pdc
     28  ffffdc8a4f92de20 Driver                    rspndr
         ffffdc8a4e14fe00 Driver                    vmusbmouse
     29  ffffdc8a4ce59670 Driver                    HdAudAddService
         ffffdc8a4cc98d60 Driver                    mssmbios
         ffffdc8a4cc97de0 Driver                    CSC
         ffffdc8a4c372d90 Driver                    volmgrx
         ffffdc8a4c536060 Driver                    pci
     30  ffffdc8a545d5e50 Driver                    ArtDrv
         ffffdc8a4cd67ce0 Driver                    NdisVirtualBus
         ffffdc8a4cdeb300 Driver                    CmBatt
         ffffdc8a4cce1e00 Driver                    vm3dmp_loader
         ffffdc8a4ccd8e20 Driver                    kdnic
         ffffdc8a4c9c1ba0 Driver                    cdrom
         ffffdc8a4c8b54e0 Driver                    NDIS
     31  ffffdc8a4cd65dc0 Driver                    swenum
     32  ffffdc8a4ce6ee30 Driver                    usbhub
         ffffdc8a4c9bfb00 Driver                    rdyboost
         ffffdc8a4c997e30 Driver                    WFPLWFS
         ffffdc8a4c8b7e00 Driver                    Tcpip
         ffffdc8a4aad9e20 Driver                    SgrmAgent
     33  ffffdc8a543a7750 Driver                    TSFltDrv_V3LITE40
         ffffdc8a4ce66cb0 Driver                    USBHUB3
         ffffdc8a4cdec940 Driver                    intelppm
         ffffdc8a4cd2fb20 Driver                    gencounter
         ffffdc8a4c162e40 Driver                    Beep
         ffffdc8a4c374410 Driver                    atapi
     34  ffffdc8a4cf18e00 Driver                    usbccgp
         ffffdc8a4cb6b9a0 Driver                    AFD
         ffffdc8a4c373c40 Driver                    mountmgr
         ffffdc8a4c365e30 Driver                    intelide
     35  ffffdc8a4e156410 Driver                    ATamptNt_V3LITE40
         ffffdc8a52bb1b70 Driver                    BTHPORT
         ffffdc8a4fd83e30 Driver                    tcpipreg
         ffffdc8a4ce32060 Driver                    ksthunk
         ffffdc8a4ccd9e30 Driver                    vmmouse
         ffffdc8a4cb6c9a0 Driver                    afunix
     36  ffffdc8a55296750 Driver                    asc_kbc_V3LITE40
         ffffdc8a4ca547b0 Driver                    vm3dmp
         ffffdc8a4cca4db0 Driver                    CompositeBus
         ffffdc8a4caf99a0 Driver                    ws2ifsl
         ffffdc8a4c64edd0 Driver                    EhStorClass
         ffffdc8a4aa954c0 Driver                    ACPI

로딩된 드라이버 목록이 나오는 것을 확인할 수 있습니다. 

위에서 언급했듯이, 각각의 Entry(1줄당 하나의 Entry, 여기서는 드라이버를 의미)는 체인으로 연결되어 있습니다. 아래 그림처럼 특정 Entry를 제거한 후 체인을 이을 수 있습니다.

33번 인덱스의 2번째인 USBHUB3를 목록에서 숨겨본다고 가정하겠습니다. 

우선 위 주소를 구조체로 표현해봅니다.

lkd> dt _OBJECT_DIRECTORY 0xffffcb83e84ec220
nt!_OBJECT_DIRECTORY
   +0x000 HashBuckets      : [37] 0xffffcb83`f16ee960 _OBJECT_DIRECTORY_ENTRY
   +0x128 Lock             : _EX_PUSH_LOCK
   +0x130 DeviceMap        : (null) 
   +0x138 ShadowDirectory  : (null) 
   +0x140 NamespaceEntry   : (null) 
   +0x148 SessionObject    : (null) 
   +0x150 Flags            : 0
   +0x154 SessionId        : 0xffffffff

HashBucket을 눌러보면 아래와 같이 나옵니다.

lkd> dx -id 0,0,ffffdc8a4aa96040 -r1 (*((ntkrnlmp!_OBJECT_DIRECTORY_ENTRY * (*)[37])0xffffcb83e84ec220))
(*((ntkrnlmp!_OBJECT_DIRECTORY_ENTRY * (*)[37])0xffffcb83e84ec220))                 [Type: _OBJECT_DIRECTORY_ENTRY * [37]]
    [0]              : 0xffffcb83f16ee960 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [1]              : 0xffffcb83e8ca9a10 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [2]              : 0xffffcb83ec3710b0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [3]              : 0xffffcb83f2246b20 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [4]              : 0xffffcb83ec370900 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [5]              : 0xffffcb83e8ca9e30 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [6]              : 0xffffcb83f66bb380 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [7]              : 0xffffcb83edd0bf70 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [8]              : 0xffffcb83edd081f0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [9]              : 0xffffcb83e8545490 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [10]             : 0xffffcb83e8568860 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [11]             : 0xffffcb83efa5efd0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [12]             : 0xffffcb83e854c820 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [13]             : 0xffffcb83edd05790 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [14]             : 0xffffcb83f2246ac0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [15]             : 0xffffcb83e8ca8c30 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [16]             : 0xffffcb83ec373fc0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [17]             : 0xffffcb83e8b809c0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [18]             : 0xffffcb83e8ca8a50 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [19]             : 0xffffcb83f2245590 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [20]             : 0xffffcb83ece2d4b0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [21]             : 0xffffcb83e8cae4e0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [22]             : 0xffffcb83edd05c10 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [23]             : 0xffffcb83f2246eb0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [24]             : 0xffffcb83edd08c70 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [25]             : 0xffffcb83e8ca9a40 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [26]             : 0xffffcb83e8cab330 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [27]             : 0xffffcb83edd08be0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [28]             : 0xffffcb83ec36f310 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [29]             : 0xffffcb83e8cad760 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [30]             : 0xffffcb83edd0cb10 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [31]             : 0xffffcb83e8cab180 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [32]             : 0xffffcb83e8cacda0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [33]             : 0xffffcb83edd0ced0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [34]             : 0xffffcb83e85686b0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [35]             : 0xffffcb83edd087c0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [36]             : 0xffffcb83edd0cf30 [Type: _OBJECT_DIRECTORY_ENTRY *]

33번 인덱스의 주소를 구조체로 확인해봅니다.

lkd>  dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83edd0ced0
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e8cadac0 _OBJECT_DIRECTORY_ENTRY
   +0x008 Object           : 0xffffdc8a`543a7750 Void // TSFltDrv_V3LITE40 오브젝트
   +0x010 HashValue        : 0x602bada7

2번째에 위치해있으니 ChainLink주소를 따라가봅니다.

lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83`e8cadac0
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e8caa730 _OBJECT_DIRECTORY_ENTRY
   +0x008 Object           : 0xffffdc8a`4ce66cb0 Void // USBHUB3 오브젝트
   +0x010 HashValue        : 0x19f5be6d

해당 OBJECT_DIRECTORY_ENTRY에 USBHUB3인 0xffffdc8a4ce66cb0 오브젝트에 도달한 것을 확인할 수 있습니다. 여기서 이전 Entry의 ChainLink를 USBHUB3 Entry가 가리키는 ChainLink로 변경하면 됩니다. 

이제 중요한 것은 해당 OBJECT_DIRECTORY_ENTRY에 어떻게 도달하느냐인데, DriverEntry함수의 PDRIVER_OBJECT는 Directory 타입의 "Driver"에 속해있는 유형입니다. "Driver"에 속해있는 드라이버라면 OBJECT_DIRECTORY(일종의 부모)가 동일합니다. 따라서 타 드라이버의 DRIVER_OBJECT 등을 구할 필요없이 자신의 드라이버 모듈을 Head로 사용하면 됩니다.

"Driver" 의 OBJECT_DIRECTORY에 접근하기 위해서 우선 ObQueryNameInfo함수로 OBJECT_HEADER_NAME_INFO 구조체 주소를 구해야 합니다. 해당 구조체에 OBJECT_DIRECTORY를 가리키는 필드가 있습니다.

POBJECT_HEADER_NAME_INFO pObjectHeaderNameInfo = ObQueryNameInfo(pDriverObject);
POBJECT_DIRECTORY pObjectDirectory = pObjectHeaderNameInfo->Directory;

OBJECT_DIRECTORY를 구했으면 각각의 ENTRY를 순회한 뒤 이름이 일치하면 ChainLink를 변경하는 코드를 작성합니다.

UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"USBHUB3");
for (int i = 0; i < 37; i++)
{
	POBJECT_DIRECTORY_ENTRY pBlinkObjectDirectoryEntry = NULL; // 이전 노드 저장
	POBJECT_DIRECTORY_ENTRY pObjectDirectoryEntry = pObjectDirectory->HashBuckets[i];

	while (pObjectDirectoryEntry)
	{        
		// 일치하면
		if (RtlEqualUnicodeString(DriverName, &pObjectHeaderNameInfo->Name, TRUE))
		{
			// 체인의 0번째(=헤드)가 자신의 Entry일때
			if (pObjectDirectory->HashBuckets[p] == pObjectDirectoryEntry)
			{			
				pObjectDirectory->HashBuckets[p] = pObjectDirectoryEntry->ChainLink; // 내 Entry의 다음 Entry를 헤드로 만든다.
				pObjectDirectoryEntry->ChainLink = NULL;
			}
			else // 1번째부터
			{			
				pBlinkObjectDirectoryEntry->ChainLink = pObjectDirectoryEntry->ChainLink; // 이전 Entry의 다음 Entry를 내 다음 Entry로 가리킨다.
				pObjectDirectoryEntry->ChainLink = NULL;
			}
		}
	        pBlinkObjectDirectoryEntry = pObjectDirectoryEntry;
		pObjectDirectoryEntry = pObjectDirectoryEntry->ChainLink;
	}
}

코드를 실행하여 체인 연결을 끊은 후 windbg로 확인해보면 TSFltDrv_V3LITE40의 ChainLink가 USBHUB3가 아닌 intelppm을 가리키는 것을 확인할 수 있습니다.

    33  ffffdc8a543a7750 Driver                    TSFltDrv_V3LITE40
        ffffdc8a4cdec940 Driver                    intelppm
        ffffdc8a4cd2fb20 Driver                    gencounter
        ffffdc8a4c162e40 Driver                    Beep
        ffffdc8a4c374410 Driver                    atapi
lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83edd0ced0 // TSFltDrv_V3LITE40 엔트리
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e8caa730 _OBJECT_DIRECTORY_ENTRY // intelpm 엔트리
   +0x008 Object           : 0xffffdc8a`543a7750 Void // TSFltDrv_V3LITE40 오브젝트
   +0x010 HashValue        : 0x602bada7
lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83`e8cadac0
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : (null) // 체인이 끊어짐
   +0x008 Object           : 0xffffdc8a`4ce66cb0 Void // USBHUB3 오브젝트
   +0x010 HashValue        : 0x19f5be6d
lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83e8caa730 // intelppm 엔트리
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e8caaa30 _OBJECT_DIRECTORY_ENTRY
   +0x008 Object           : 0xffffdc8a`4cdec940 Void // intelppm 오브젝트
   +0x010 HashValue        : 0x29f82c1

 

+ Recent posts