✨컴공주✨ [1052682] · MS 2021 (수정됨) · 쪽지

2025-12-16 14:09:11
조회수 231

컴공 일기279

게시글 주소: https://orbi.kr/00076405203

보안 솔루션 개발에서 빼놓을 수 없는 Api Hook 기법의 예제입니다. 강의를 지금 수강하고 있는데, 예제를 돌려보면서 감을 잡는 중이네요. Hook은 상당히 위험한 기술입니다. 잘 쓰면 보안이지만, 그릇되게 사용하면 해킹 기법이기도 하거든요. 안성재 셰프님이 사시미 칼을 가지고 계신다면 맛있는 방어회를 기대할 수 있지만, 인천 조폭 오빠야들이 사시미 칼을 들고 있다면 그건 살인 도구가 됩니다.


hooking도 마찬가지입니다. 영어 표현이 넌지시 암시하듯이, 함수의 흐름을 멋대로 갈취해서, 자기만의 흐름으로 바꿔버리는 기술이지요. 프로그램을 열어주는 OpenProcess()라는 함수를 갈취해서, MyOpenProcess()로 실행되도록 한 것입니다. 원래의 OpenProcess()는 커널 수준의 프로그램을 제외한 유저모드 수준의 프로그램을 다 조회할 수 있도록 지원하지만, MyOpenProcess()의 경우 메모장 프로그램의 정보를 blind처리 시키는 구조를 가집니다.


예, 원래 함수가 다 보여주는 기능이라면 커스터마이징된 함수에서는 메모장의 정보 조회를 막고 있지요.

그러니까 원래 함수의 흐름에서 커스터마이징된 함수 즉 MyOpenProcess()로 함수의 흐름을 바꿔채기만 한다면 메모장의 정보 조회를 막는 보안 솔루션이 됩니다. 



#include <iostream>

#include <windows.h>

#include <Psapi.h>


using namespace std;



#pragma pack(push, 1)

typedef struct JUMP_CODE {

    BYTE opCode;

    LPVOID targetAddr;

}JUMP_CODE;

#pragma pack(pop)


void* g_pOpenProcess;

BYTE g_codesBeforeHook[sizeof(JUMP_CODE)] = { 0 };


BOOL hookOpenProcess(void);

void unhookOpenProcess(void);    


HANDLE MyOpenProcess(

    DWORD dwDesiredAccess, BOOL bInheritHandle,

    DWORD dwProcessId

)

{

    //여기에서 unHook을 해야지만 무한루프에 빠지는 것을 방지할 수 있다.

    unhookOpenProcess(); 


    HANDLE(WINAPI * pfOpenProcess)(DWORD, BOOL, DWORD) = NULL;

    pfOpenProcess = (HANDLE(WINAPI*)(DWORD, BOOL, DWORD)) g_pOpenProcess; 


    dwDesiredAccess |= PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;

    HANDLE hProcess = pfOpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);


    TCHAR name[MAX_PATH + _MAX_FNAME] = { 0 };

    ::GetModuleFileNameEx(hProcess, NULL, name, size(name));


    if (wcsstr(name, L"Notepad.exe") != NULL)

    {

        cout << "\tMyOpenProcess()" << endl;

        cout << "\t*******************************************************" << endl;

        cout << "\t***************Block notepad Process!!!****************" << endl;

        cout << "\t*******************************************************" << endl;


        hookOpenProcess();

        return NULL;

    }


    hookOpenProcess();

    return hProcess; 

}



void printProcessList(void)

{

    HMODULE hk32 = ::LoadLibrary(L"Kernel32.dll");

    HANDLE(WINAPI * pfOpenProcess)(DWORD, BOOL, DWORD) = NULL;


    pfOpenProcess = (HANDLE(WINAPI*)(DWORD, BOOL, DWORD)) ::GetProcAddress(hk32, "OpenProcess");


    DWORD aPid[1024] = { 0 };

    DWORD dwNeeded = 0;

    if (::EnumProcesses(aPid, sizeof(aPid), &dwNeeded))

    {

        DWORD count = dwNeeded / sizeof(DWORD); //Process Count

        HANDLE hProcess;


        for (DWORD i = 0; i <= count; ++i)

        {

            hProcess = pfOpenProcess(

                PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aPid[i]);

            

            if (hProcess != NULL)

            {

                TCHAR name[MAX_PATH + _MAX_FNAME] = { 0 };

                ::GetModuleFileNameEx(hProcess, NULL, name, sizeof(name));

                ::wprintf(L"%s [PID: %d]\n", name, aPid[i]);

            }

        }

    }


    ::FreeLibrary(hk32);

}



BOOL hookOpenProcess(void)

{

    HMODULE hk32 = ::GetModuleHandle(L"Kernel32.dll");

    HANDLE(WINAPI * pfOpenProcess)(DWORD, BOOL, DWORD) = NULL;


    pfOpenProcess = (HANDLE(WINAPI*)(DWORD, BOOL, DWORD))::

        GetProcAddress(hk32, "OpenProcess");

    g_pOpenProcess = pfOpenProcess;


    DWORD dwOldProtect = 0;

    BOOL bResult = ::VirtualProtect(

        (LPVOID)pfOpenProcess, 5,

        PAGE_EXECUTE_READWRITE, &dwOldProtect

    );


    memcpy(g_codesBeforeHook, pfOpenProcess, 5);


    //목적지 주소 - 현재 명령어 주소 - 5

    //5는 JMP, CALL 명령어의 크기 만큼 빼주는 것

    JUMP_CODE jmpCode = { 0 };

    jmpCode.opCode = 0xE9; //JMP 

    jmpCode.targetAddr = (void*)((DWORD)MyOpenProcess - (DWORD)pfOpenProcess - 5);


    memcpy(pfOpenProcess, &jmpCode, 5);


    return TRUE;

}


void unhookOpenProcess(void)

{

    if (g_pOpenProcess == NULL)

        return;


    //원상복구

    memcpy(g_pOpenProcess, g_codesBeforeHook, 5);


}


//32bit Windows Api Inline hook

int main()

{

    setlocale(LC_ALL, "");


    hookOpenProcess();

    printProcessList();


    return 0;

}

0 XDK (+0)

  1. 유익한 글을 읽었다면 작성자에게 XDK를 선물하세요.