날먹을 위한 몸부림/Driver

HamsterHide dll v0.1.0

프로그래밍하는 지팡이 2022. 8. 2. 03:52

SSDT 후킹을 지원하는 드라이버

 

프로그램 스텔스를 위한 dll임

dll 내부에 커널 드라이버와 일부 유틸이 포함되어 있음

 

dll을 사용해서 드라이버를 설치, 제거 할 수 있음

dll에서 내보낸 함수를 사용해서 원하는 프로세스를 숨길 수 있음


지원하는 기능은 

 

프로세스  (NtQuerySystemInformation)

핸들 테이블에서 핸들 필터링 (NtQuerySystemInformation)

프로세스 오픈 방지 (NtOpenProcess)

 

 


다운로드는 여기서

 

 

데모 GUI 프로그램 : https://www.dropbox.com/s/utixqy05bh9il1o/HamsterHide.zip?dl=0 

 

HamsterHide.zip

Dropbox를 통해 공유함

www.dropbox.com

 

빌드된 DLL : https://www.dropbox.com/s/6ahukarci4sah4k/HamsterHideDLL_v0.1.0.zip?dl=0 

 

HamsterHideDLL_v0.1.0.zip

Dropbox를 통해 공유함

www.dropbox.com

 

소스코드 : 지인 공유


데모 GUI 사용 방법

 

 


모듈을 사용한 예제 

 

python

 

파일명 : hamster_hide.py

import os
from ctypes import POINTER, cast, pointer, byref, c_bool, c_wchar, c_wchar_p, windll, c_int, Structure


HH_OK                      = 0
HH_FAIL                    = 1
HH_FILE_SAVE_ERROR         = 2
HH_PATCH_GUARD_OFF_ERROR   = 3
HH_DRIVER_SCM_OPEN_FAIL    = 4
HH_DRIVER_CREATE_OPEN_FAIL = 5
HH_DRIVER_START_STOP_FAIL  = 6
HH_DRIVER_DELETE_FAIL      = 7
HH_DRIVER_STATUS_FAIL      = 8
HH_DRIVER_HANDLE_OPEN_FAIL = 9
HH_DRIVER_READ_WRITE_FAIL  = 10
HH_DRIVER_DATA_SIZE_FAIL   = 11
HH_INVALID_PARAMETER       = 12
HH_BUFFER_SIZE_MISMATCH    = 13
HH_BUFFER_TO_SMALL         = 14


class HamsterHideBaseException(Exception):
    pass


class ProcessInfo(Structure):
    _fields_ = [("process_name", c_wchar * 100)]


class HamsterHide:
    def __init__(self, dll_path : str) -> None:
        self.hide_dll = windll.LoadLibrary(dll_path)

        self._install_driver = self.hide_dll["install_driver"]
        self._install_driver.argtypes = None
        self._install_driver.restype = c_int

        self._uninstall_driver = self.hide_dll["uninstall_driver"]
        self._uninstall_driver.argtypes = None
        self._uninstall_driver.restype = c_int

        self._is_run_driver = self.hide_dll["is_run_driver"]
        self._is_run_driver.argtypes = None
        self._is_run_driver.restype = c_bool

        self._hide_process_name = self.hide_dll["hide_process_name"]
        self._hide_process_name.argtypes = (c_wchar_p, )
        self._hide_process_name.restype = c_int

        self._unhide_process_name = self.hide_dll["unhide_process_name"]
        self._unhide_process_name.argtypes = (c_wchar_p, )
        self._unhide_process_name.restype = c_int

        self._get_hide_process_list = self.hide_dll["get_hide_process_list"]
        self._get_hide_process_list.argtypes = (POINTER(ProcessInfo), POINTER(c_int))
        self._get_hide_process_list.restype = c_int

    def install_driver(self) -> None:
        code = self._install_driver()
        if code != HH_OK:
            raise HamsterHideBaseException("드라이버를 설치하는데 실패했습니다", code)

    def uninstall_driver(self) -> None:
        code = self._uninstall_driver()
        if code != HH_OK:
            raise HamsterHideBaseException("드라이버를 제거하는데 실패했습니다", code)

    def is_run_driver(self) -> bool:
        return self._is_run_driver()

    def hide_process_name(self, process_name : str) -> None:
        code = self._hide_process_name(c_wchar_p(process_name))
        if code != HH_OK:
            raise HamsterHideBaseException("프로세스를 숨기는데 실패했습니다", code)

    def unhide_process_name(self, process_name : str) -> None:
        code = self._unhide_process_name(c_wchar_p(process_name))
        if code != HH_OK:
            raise HamsterHideBaseException("숨겨진 프로세스를 복구하는데 실패했습니다", code)

    def get_hide_process_list(self) -> list[str]:
        count = c_int(0)
        code = self._get_hide_process_list(POINTER(ProcessInfo)(), byref(count))
        if code != HH_BUFFER_TO_SMALL:
            raise HamsterHideBaseException("버퍼의 크기를 구하는데 실패했습니다", code)

        process_list = (ProcessInfo * count.value)()
        code = self._get_hide_process_list(cast(pointer(process_list), POINTER(ProcessInfo)), byref(count))
        if code != HH_OK:
            raise HamsterHideBaseException("데이터를 가져오는데 실패했습니다", code)

        return [proc.process_name for proc in process_list]

 

파일명 : main.py

from hamster_hide import *

try:
    #dll 로드
    hide_dll = HamsterHide("HamsterHideDLL.dll")

    #드라이버 설치(패치가드도 같이 꺼짐)
    hide_dll.install_driver()
    #프로세스를 숨김(메모장)
    hide_dll.hide_process_name("notepad.exe")

    #프로세스 이름 가져오기
    process_list = hide_dll.get_hide_process_list()
    for process in process_list:
        print(process)
        #output : notepad.exe


    input("엔터 누르면 드라이버 언로드함")


    #드라이버 삭제
    hide_dll.uninstall_driver()
except HamsterHideBaseException:
    pass

 

c/c++

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

int main()
{
	try
    {
    	//드라이버 설치(패치가드도 같이 꺼짐)
    	hamster::install_driver();
        
        //프로세스 숨김
        hamster::hide_process_name("notepad.exe");
        
        //숨겨진 프로세스 리스트 가져오기
        auto process_list = hamster::get_hide_process_list();
        for(const auto& process : process_list)
        	std::wcout << process << std::endl;
        
        std::cout << "엔터 누르면 언로드함";
        std::cin.get();
        
        //드라이버 언로드
        hamster::uninstall_driver();
    }
    catch (const hamster::HamsterHideBaseException& e)
    {
    
    }
	
    return 0;
}

문제점

 

  • 윈도우 디펜더를 끄고 해야함(꺼도 일정 시간 후에 다시 켜짐)
  • 패치가드를 끈다고 껐는데 어느 시점에 다시 트리거 될 수 있음(Shark 프로젝트 참조)
  • 하이퍼바이저 기반 백신이 설치된 경우 하이퍼바이저를 종료하거나 백신을 삭제한 뒤 실행

계획

 

  • 드라이버를 설치할 때 다른 방식으로 패치가드를 끌 수 있도록 지원
  • 드라이버를 언로드하지 않고 프로세스 하이드를 등록취소할 수 있도록 지원
  • 하이퍼바이저 기반 후킹 지원

개인 목적으로 사용은 무료입니다
타인에게 재배포를 허용하지 않습니다
타인에게 배포가 필요시 저장소 또는 블로그 링크를 공유하는 방식으로 전달해야합니다

블로그 링크를 공유하는 방식으로 이루어지지 않는 배포는 라이선스를 구매해서 진행해야합니다(댓글 문의)


사용된 서브모듈 또는 다른 프로젝트는
해당 프로젝트의 라이센스를 따릅니다

Shark : 런타임에 패치가드 off (https://github.com/9176324/Shark)
PySide6 (Qt) : 데모 UI작성용 (https://www.qt.io/)
PyInstaller : 파이썬 번들 프로그램 작성 (https://github.com/pyinstaller/pyinstaller)

 


수정사항

220802 : c/c++ 예제에서 누락된 네임스페이스 추가

220802 : 파이썬 예제 수정(누락된 모듈)

220914 : 배포 관련 세부 내용 추가