10.8(월) 실습-1

2007/10/14 12:18

1. TEB에서 값 얻어오기
[ more.. | less.. ]
// GetLastError() 함수의 원리 - 스레드당 1개의 에러코드를 얻는 함수.(TEB에 있다.)
int get_last_error()
{
    int err = 0;

    __asm
    {
        // TEB의 0x34번째 값을 얻는다.
        mov        eax,    FS:[0x34]

        mov        err,    eax
    }
    return err;
}
// 현재 프로세스가 디버깅 중인지 알아낸다. - Anti hack 프로그램의 원리
int AntiHack()
{
    char bRet = 0;
   
    __asm
    {
        // PEB의 주소를 알아낸다.
        mov        eax,    FS:[0x30]
        // PEB에서 2byte 이동한다.
        add        eax,    2

        // 디버깅 중인지를 알아낸다.
        mov        bl,        byte ptr[eax]
        mov        bRet,    bl
    }
    return bRet;
}
// 현재 쓰레드의 Id를 알아낸다.
int MyGetCurrentThreadId()
{
    int tid = 0;
        __asm
        {
            mov eax, FS:[0x24]
            mov tid, eax
        }
    return tid;
}
// 현재 스택의 시작주소를 알아낸다.
PVOID MyGetStackBase()
{
    PVOID tid = 0;
    __asm
    {
        mov eax, FS:[0x04]

        mov tid, eax
    }
    return tid;
}
// TLS의 주소를 알아온다.
PVOID MyGetThreadLocalStorage()
{
    PVOID tid = 0;
    __asm
    {
        mov eax, FS:[0x2c]

        mov tid, eax
    }
    return tid;
}

2. 커널 상속( 콘솔 창에 출력을 edit박스로 받기 )
[ more.. | less.. ]

//-------------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static HWND hEdit;
    switch( msg )
    {   
    case WM_CREATE:
        {
            hEdit = CreateWindow( "edit", "",
                WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE,
                10, 10, 500, 500, hwnd, (HMENU)1, 0, 0 );
        }
        return 0;
    case WM_LBUTTONDOWN:
        {
            PROCESS_INFORMATION pi;
            STARTUPINFO si = { sizeof(si) };

            // 화일을 생성해서 ping의 표준 출력을 redirect 한다.
            HANDLE hFile = CreateFile(
                "a.txt", GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                0,
                CREATE_ALWAYS,
                FILE_ATTRIBUTE_NORMAL,
                0 );

            // 모든 KO는 기본적으로 상속 불가능
            // 특정 KO를 상속 가능하게 변경한다.
            SetHandleInformation( hFile, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );

            si.hStdOutput = hFile;    // 표준 출력과 연결할 파일 핸들을 지정한다.
            si.dwXSize = 100;
            si.dwYSize = 100;        // 자식이 만드는 윈도우의 크기를 지정한다.
            si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE;
            //----------------------------------------------------------------           

            char cmd[256] = "ping www.dblab.co.kr";
            BOOL b = CreateProcess(
                0, cmd, 0, 0, TRUE,
                CREATE_NO_WINDOW, // 콘솔에서 만들지 말라.//우선순위 | 플래그
                0, 0, &si, &pi );

            if( b )
            {
                // ping이 종료될 때까지 대기한다.
                WaitForSingleObject( pi.hProcess, INFINITE );

                // 이제 파일에서 읽어 온다.
                char buf[8096] = { 0 };    // 8k 버퍼   
       
                // 파일 포인터를 처음으로 옮기고. 4G가 보다 클수 있으므로 크기를 알려준다.
                SetFilePointer( hFile, 0, 0, FILE_BEGIN );

                DWORD len;
                ReadFile( hFile, buf, 8096, &len, 0 );

                // EditBox에 출력해준다.
                SetWindowText( hEdit, buf );
               
                CloseHandle( pi.hProcess );
                CloseHandle( pi.hThread );
            }
        }
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc( hwnd, msg, wParam, lParam);
}

3. Pipe를 사용한 콘솔창 출력을 에디트 박스로~( 한줄 씩 읽어보기 )
[ more.. | less.. ]
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static HWND hEdit;
    switch( msg )
    {   
    case WM_CREATE:
        {
            hEdit = CreateWindow( "edit", "",
                WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE,
                10, 10, 500, 500, hwnd, (HMENU)1, 0, 0 );
        }
        return 0;

    case WM_LBUTTONDOWN:
        {
            PROCESS_INFORMATION pi;
            STARTUPINFO si = { sizeof(si) };

            HANDLE hRead, hWrite;
            CreatePipe( &hRead, &hWrite, 0, 1024 );

            SetHandleInformation( hWrite, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );

            si.hStdOutput = hWrite;    // 쓰기 위한 Pipe 핸들을 전달한다.
            si.dwFlags = STARTF_USESTDHANDLES;

            char cmd[256] = "ping www.dblab.co.kr";

            BOOL b = CreateProcess( 0, cmd, 0, 0, TRUE, CREATE_NO_WINDOW, 0, 0, &si, &pi );

            if( b )
            {
                CloseHandle( hWrite );    // 이제 쓰기 위한 핸들은 필요없다.
               
                while( 1 )
                {
                    char buf[2048] = { 0 }; // 2k 버퍼
                   
                    DWORD len;
                    BOOL b = ReadFile( hRead, buf, 2048, &len, 0 );    // 파이프로 결국 파일

                    if( len <= 0 )    // 에러 발생이거나 파이프가 닫힌 경우
                        break;

                    // 에디트에 한줄 씩 추가한다.
                    SendMessage( hEdit, EM_REPLACESEL, 0, (LPARAM)buf );
                }
                CloseHandle( hRead );
                CloseHandle( pi.hProcess );
                CloseHandle( pi.hThread );
            }
        }
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc( hwnd, msg, wParam, lParam);
}

3. 실행중인 프로세스 열거해보기
[ more.. | less.. ]
#include <tlhelp32.h>
// TOOL Help API : process, thread, module, heap 등을 열거 할때 사용하는 API의 모음
//                kernel32.dll 에 있다.

BOOL EnablePrimary( HANDLE    hProcess, // 권한을 부여할 프로세스
                    char*    pri,      // 권한을 나타내는 문자열
                    BOOL    bEnable   // 가능/불가능 여부
                    )
{

    HANDLE hToken;
    OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken );

    // 문자열로 되어 있는 권한ID( LUID, 64비트 정수 )로 변경한다.
    LUID luid;
    LookupPrivilegeValue(
        ".", // PC이름
        pri, // 권한이름
        &luid ); // luid를 담을 변수

    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount = 1;    // 갯수
    tp.Privileges[0].Luid = luid;    // 권한 ID
    tp.Privileges[0].Attributes= bEnable ? SE_PRIVILEGE_ENABLED : 0;

    return AdjustTokenPrivileges( hToken, 0, &tp, sizeof(tp), 0, 0 );
}

int main()
{
    if ( EnablePrimary(
        GetCurrentProcess(),    // 현재 프로세스의 핸들(-1이 나온다. -1은 자신을의미)
        SE_SHUTDOWN_NAME, TRUE )        // PC를 종료할수 있는 특권.
        == FALSE )
    {
        printf("can't Get Privieges\n");
        return 0;
    }

    // 프로세스의 목록을 메모리 어딘가에 보관(snapshot)해 둔다.
    HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );

    PROCESSENTRY32 pe32 = { 0 };
    pe32.dwSize = sizeof( pe32 );

    BOOL b = Process32First( hSnap, &pe32 );

    while( b )
    {
        printf( "%04d %04d %s\n",
            pe32.th32ProcessID,
            pe32.th32ParentProcessID,
            pe32.szExeFile );

        b = Process32Next( hSnap, &pe32 );
    }
    CloseHandle( hSnap );
}

4. pid 를 사용한 모듈 열거
[ more.. | less.. ]
#include <tlhelp32.h>

int main( int argc, char** argv ) { if ( argc != 2 )
    {
        printf( "usage : %s <pid> \n", argv[0] );
        return 0;
    }
    DWORD pid = atoi( argv[1] );

    HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pid );

    MODULEENTRY32 me32 = { sizeof(me32) };

    BOOL b = Module32First( hSnap, &me32 );

    while( b )
    {
        printf( "%08x : %s\n", me32.modBaseAddr, me32.szModule );

        b = Module32Next( hSnap, &me32 );
    }
    CloseHandle( hSnap );
}

5. PC끄는 권한 얻어 와서 종료시키기
[ more.. | less.. ]
// 특정 프로세스에 특정 권한을 부여한다. - 이 함수 역시 관리자 모드이어야만 실행이 성공.
BOOL EnablePrimary( HANDLE    hProcess, // 권한을 부여할 프로세스
                    char*    pri,      // 권한을 나타내는 문자열
                    BOOL    bEnable   // 가능/불가능 여부
                    )
{
    HANDLE hToken;
    OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken );

    // 문자열로 되어 있는 권한ID( LUID, 64비트 정수 )로 변경한다.
    LUID luid;
    LookupPrivilegeValue(
        ".", // PC이름
        pri, // 권한이름
        &luid ); // luid를 담을 변수

    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount = 1;    // 갯수
    tp.Privileges[0].Luid = luid;    // 권한 ID
    tp.Privileges[0].Attributes= bEnable ? SE_PRIVILEGE_ENABLED : 0;

    return AdjustTokenPrivileges( hToken, 0, &tp, sizeof(tp), 0, 0 );
}
                     
int main()
{
    // PC를 끌수 있는 권한을 부여한다.
    if ( EnablePrimary(
        GetCurrentProcess(),    // 현재 프로세스의 핸들(-1이 나온다. -1은 자신을의미)
        SE_SHUTDOWN_NAME, TRUE )        // PC를 종료할수 있는 특권.
        == FALSE )
    {
        printf("can't Get Privieges\n");
        return 0;
    }


    // 컴퓨터를 종료 하는 함수
    BOOL b = ExitWindowsEx( EWX_POWEROFF, 0 );

    if( b == FALSE )
    {
        printf( "실패 : %d\n", GetLastError() );
    }
}

Tags

System, 실습