비트 플래그

from Study/C언어 2007/11/28 21:10 view 33342

1. 기본( &(검사), |(추가),  &= ~(삭제) )

more..


2. 배열을 사용한 비트 플래그

more..


3. 매크로를 이용한 비트 플래그 연산( http://lxr.linux.no/source/include/linux/posix_types.h )

more..


1. PID를 알고 있을 때 작업관리자에서 프로세스 종료시 종료되지 않는 드라이버.

//3. SDT Hooking

#include <ntddk.h>

// 함수 이름(주소)를 가지고 SDT 서비스 번호를 얻어내는 매크로
#define SERIVCE_ID( f )        *(ULONG*)( (char*)f + 1 )

// SDT Table의 각항목을 구성하는 구조체
#pragma pack(1)    // 1 Byte 단위로 align(정렬)하라는 지시어
typedef struct ServiceDescriptorEntry
{
    unsigned int*   ServiceTableBase; // 함수 주소
    unsigned int*   ServiceCounterTableBase;
    unsigned int    NumberOfServices;
    unsigned char*  ParamTableBase;
} ServiceDescriptorTableEntry_t;
#pragma pack()

// ntoskrnl.exe 에서는 SDT Table을 export 하고 있다.
__declspec(dllimport) ServiceDescriptorTableEntry_t
                                            KeServiceDescriptorTable;

// ntoskrnl.exe 가 가진 ZwTerminateProcess를 import 한다.
// Hooking 에 대상이 되는 함수를 import
__declspec(dllimport)
        NTSTATUS __stdcall ZwTerminateProcess( HANDLE handle, NTSTATUS ExitCode);

// 원래 함수의 주소를 보관하고 있어야 한다.
typedef NTSTATUS (__stdcall *FUNC)(HANDLE, NTSTATUS );
FUNC old; // 원래 함수의 주소를 담아둘 변수.

// 새로운 함수
NTSTATUS __stdcall foo( HANDLE handle, NTSTATUS ExitCode )
{
    DbgPrint("TerminateProcess is Called : %x", handle );

    if ( handle != (HANDLE)0 && handle != (HANDLE)-1 )    // 자기 스스로 죽는 ExitProcess 일 경우 제외
    {
        PVOID pEprocess = 0;    // 계산기의 EPROcESS의 주소를 담을 변수
        OBJECT_HANDLE_INFORMATION obj_handle;    // 핸들의 관한 정보(상속여부등)를 얻어 올 변수

        // User Level 에서 사용하던 핸들을 가지고 커널메모리에 있는 구조체의 주소를 직접 얻는다.
        // 이때 참조 개수가 증가한다.
        NTSTATUS status = ObReferenceObjectByHandle(
            handle,
            GENERIC_ALL,
            NULL,
            KernelMode,
            &pEprocess,
            &obj_handle );

        if( pEprocess != 0 )
        {
            // ObjectTable에 등록된 주소(물리주소)의 0x84에(xp,2003) PID값이 저장되어 있다.
            int id = *((int*)((char*)pEprocess + 0x84));

            if( id == 2648 ) // PID 값을 조사
            {
                DbgPrint("no kill");
                return STATUS_SUCCESS;
            }
            // 구조체를 다 사용했으므로 참조개수를 줄인다.
            ObDereferenceObject( pEprocess );
        }
    }
    // 기존의 함수로 다시 보낸다.
    return old( handle, ExitCode );
}

// 실제 SDT 훅을 하는 함수.
void InstallSDTHook()
{
    // 함수의 서비스 번호를 구한다.
    int id = SERIVCE_ID(ZwTerminateProcess);
   
    DbgPrint("ZwTerminateProcess service ID : %d", id );

    // 원래 함수의 주소를 보관해 둔다.
    old = (FUNC)KeServiceDescriptorTable.ServiceTableBase[ id ];

    __asm { CLI }   // interrupt 중지 - 다른 스레드가 실행흐름을 중지시키지 못하게 한다.(커널모드만 가능)

    // SDT Table을 수정(Hooking) 한다.
    KeServiceDescriptorTable.ServiceTableBase[ id ] = (unsigned int)foo;

    __asm { STI }    // interrupt 다시 시작 - 다른 스레드로의 전환(Context Switch) 를 가능하게 한다.
}

void UninstallSDTHook()
{
    int id = SERIVCE_ID(ZwTerminateProcess);
   
    __asm { CLI }   // interrup 중지

    // SDT 를 다시 원래대로 변경해 놓는다.
    KeServiceDescriptorTable.ServiceTableBase[ id ] = (unsigned int)old;

    __asm { STI }
}

VOID DriverUnload( PDRIVER_OBJECT pDrvObj )
{
    UninstallSDTHook();
    DbgPrint( "Driver Unload" );
}

NTSTATUS DriverEntry( PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath )
{
    DbgPrint("DriverEntry");

    pDrvObj->DriverUnload = DriverUnload;
    InstallSDTHook();
    return STATUS_SUCCESS;
}
Tag |

WDM 실습 - 작업관리자 흉내내기

from Study/WDM 2007/11/28 20:14 view 32235

1. 작업관리자 흉내내기. ( 서비스의 시작과 스톱을 신중히 하지 않는다면 블루스크린 )

// 프로세스의 생성/파괴를 감시하는 드라이버

#include <ntddk.h>

VOID foo( HANDLE ParentID, HANDLE ProcessID, BOOLEAN Create )
{
    if( Create == TRUE )
    {
        DbgPrint( "Process Created : %d, %d", ProcessID, ParentID );
    }
    else
    {
        DbgPrint( "Process Terminated : %d, %d", ProcessID, ParentID );
    }
}

VOID DriverUnload( PDRIVER_OBJECT pDrvObj )
{
    DbgPrint( "Driver Unload" );

    // 반드시 Callback 함수를 제거하고 unload 되어야 한다.
    PsSetCreateProcessNotifyRoutine( foo, TRUE );
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj            // DRIVER_OBJECT 객체의 주소
                     , PUNICODE_STRING pRegPath )    // 설치된 레지스트리 경로
{
    DbgPrint( "DriverEntry : %p", pDrvObj );

    // 드라이버가 unload 될때 호출될 함수를 등록한다.
    pDrvObj->DriverUnload = DriverUnload;

    // 프로세스 감시 함수를 등록한다.
    PsSetCreateProcessNotifyRoutine( foo, FALSE );

    return STATUS_SUCCESS;
}

WDM 기본 - 빌드

from Study/WDM 2007/11/28 20:10 view 57309
1. 기본 동작방식
 1) 소스제작 -> 빌드 -> 설치 -> 시동 -> 중지 -> 제거

  - 소스제작
//1. 가장 가단한 드라이버
#include <ntddk.h>

VOID DriverUnload( PDRIVER_OBJECT pDrvObj )
{
    DbgPrint( "Driver Unload" );    // 이 메세지는 커널 디버거에게 전달된다.
                                              // 이 메세지를 보려면 winDbg 또는 softice 또는 DebugView 가 필요
}

// 드라이버의 EntryPoint - 반드시 C 맹글링 규칙을 따라야 한다.
NTSTATUS DriverEntry( PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath )
{
    DbgPrint( "DriverEntry" );

    pDrvObj->DriverUnload = DriverUnload;    // 드라이버가 unload 될 때 호출 될 함수 등록

    return STATUS_SUCCESS;
}

 - 빌드
1. 설치된 DDK의 Windows XP Checked Build Environment 프롬프트를 사용하여 빌드한다.
2. MakeFile 과 Sources 파일이 필요하며 Sources만 편집하여 빌드 'build' 하면 된다.
3. 주의 해야 할점은 소스는 .c 로 되어야 하며 한글경로가 포함 되어 있으면 build가 되지 않는다.

- 설치, 시동, 중지, 제거
1. 레지스토리 편집기(regedit)에서 HKEY_LOCAL_MACHINE\SYSTEM 경로에 레지스토리를 등록한다.
  1) 직접 수정해서 등록한다.
  2) 서비스 API 함수를 사용하는 프로그램을 제작하여 등록한다.(Software 드라이버)
  3) inf 파일을 제작하여 등록한다.(Hardware 드라이버)
  4) Setup API를 사용한다.
2. 서비스의 설치 시작 정지 삭제는 나중에 알아보고 일단 EnumService.exe를 사용한다.

Tag |

DDK 설치

from Study/WDM 2007/11/28 19:38 view 37777

1. DDK

1) 다운 - http://www.microsoft.com/whdc/devtools/ddk/default.mspx
2) VC++ 디렉토리 경로
  - 포함파일에서(include)  DDK 설치폴더의 inc\wxp 와 inc\ddk\wxp 추가

3) 그외 필요한 파일.
 - DbgView.exe : 디버그 출력 DbgPrint 를 보기위한 파일 .
 - EnumService.exe : 빌드한 *.sys 를 서비스등록 시작을 간편하게 하기 위한 파일.

 - Makefile : 빌드시 필요한 파일
 - Sources : 빌드시 수정해야 하는 파일 파일의 명과 파일 경로를 알려준다.!



2. Detours ( MS 연구소가 만든 API HOOKING 라이브러리. )

1) 다운   -  http://research.microsoft.com/sn/detours/
2) Detours 설치 디렉토리에서 nmake  하면 빌드 됩니다.( cmd 말고 VC++ 명령 프롬프트 )
3) bin  폴더에 가면 detour 관련 실행파일및..dll 있습니다.

4) test 하는 법.
 - VC++ 명령 프롬프트 창을 2개 실행
 - 1번 프롬프트에서 bin으로 오세요 한후..  'syelogd > trace.txt'
 - 2번 프롬프트에서 'withdll -d:traceapi.dll  응용프로그램이름'

Tag |