메모장 입니다2

Windows] Self Creation 본문

Study/리버싱

Windows] Self Creation

Wooum@n 2017. 2. 25. 16:10

0.정의


 -자기 자신을 자식프로세스로 생성하여, 하나의 실행파일을 두 개의 실행흐름으로 나누어 동작.

 -실행 흐름이 나뉘기 때문에 디버깅을 어렵게 함.




1.실행 구조


 -동작 구성도

1) 부모 프로세스 실행

2) 부모 프로세스가 "parent process"를 출력.

3) 부모 프로세스가 자기 자신(SelfCreation.exe)을 *SUSPEND 모드의 자식프로세스로 생성.

4) 부모 프로세스가 자식프로세스의 EIP를 변경(자식 프로세스가 실행할 코드로 EIP 변경)

5) 자식프로세스 Resume.

6) 자식 프로세스가 "child process"를 출력.


*SUSPEND: import DLL은 로딩되고 Main 쓰레드는 정지된 상태.




2.소스코드


 -SelfCreation.exe

#include <windows.h>

#include <tchar.h>

#include <stdio.h>



void ChildProc()    //자식프로세스의 실행코드.

{

    MessageBox(NULL, L"This is a child process!", L"DebugMe2", MB_OK);


    ExitProcess(0);

}



void _tmain(int argc, TCHAR *argv[]) 

{

    TCHAR                   szPath[MAX_PATH] = {0,};

    STARTUPINFO si = {sizeof(STARTUPINFO),};

    PROCESS_INFORMATION pi = {0,};

    CONTEXT                 ctx = {0,};


    _tprintf(L"This is a parent process!\n"); 


    if( !GetModuleFileName(NULL, szPath, sizeof(TCHAR) * MAX_PATH) )

    {

        printf("GetModuleFileName() failed! [%d]\n", GetLastError());

        return;

    }


    // Create Child Process

    if( !CreateProcess(    //자식프로세스 생성.

            szPath,

            NULL,

            NULL,

            NULL,

            FALSE,

            CREATE_SUSPENDED,   //SUSPEND MODE 

            NULL,

            NULL,

            &si,

            &pi) )

    {

        printf("CreateProcess() failed! [%d]\n", GetLastError());

        return;

    }


    // Change EIP

    ctx.ContextFlags = CONTEXT_FULL;    

    if( !GetThreadContext(pi.hThread, &ctx) )    //자식 프로세스의 CONTEXT 정보를 얻어옴.

    {

        printf("GetThreadContext() failed! [%d]\n", GetLastError());

        return;

    }


    ctx.Eip = (DWORD)ChildProc;    //자식 프로세스의 EIP 변경.


    if( !SetThreadContext(pi.hThread, &ctx) )    //변경된 CONTEXT를 적용

    {

        printf("SetThreadContext() failed! [%d]\n", GetLastError());

        return;

    }


    // Resume Main Thread

    if( -1 == ResumeThread(pi.hThread) )    //자식 프로세스 실행.

    {

        printf("ResumeThread() failed! [%d]\n", GetLastError());

        return;

    }


    WaitForSingleObject(pi.hProcess, INFINITE);    //자식프로세스가 종료될 때까지 기다림.


    CloseHandle(pi.hProcess);

    CloseHandle(pi.hThread);

}




3.디버깅


 -자식프로세스의 시작주소부터 디버깅하기 위해선, 별도의 방법이 필요.

>JIT(Just-In-Time) 디버깅

->실행 중인 프로세스에 예외가 발생하였을 때, OS가 설정된 디버거를 해당 프로세스에 Attach 시켜주는 기능.

->예외가 발생한 부분부터 디버깅 가능하다.

 -따라서, 올리디버거를 JIT로 설정한 뒤 자식프로세스 시작주소에 BP를 하드코딩하고 실행하면

 BP예외가 발생하여 해당 지점(자식프로세스 시작주소)부터 올리디버거가 Attach되어 디버깅이 가능해진다.

 -실습

1)JIT 설정

>레지스트리 값 변경

`HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\Current Version\AeDebug\Debugger`

->OLLYDBG 경로로 변경한다.

->확인



2)BP 설정

>자식 프로세스의 EP 주소 확인 //BP를 설정하기 위해.

->부모프로세스가 EIP 변경하는 부분을 디버깅하여 확인. 

:자식 프로세스 시작주소 = 401000


>BP 설정

->401000 = RVA: 1000 = RWA: 400



3)프로그램 실행

->예외 발생


->디버깅


'Study > 리버싱' 카테고리의 다른 글

Windows] TLS 콜백함수  (0) 2017.08.08
Windows] 32bit / 64bit 차이점 - 2  (0) 2017.08.08
Windows] 32bit / 64bit 차이점  (0) 2017.08.08
32bit/64bit 역사  (0) 2017.08.08
어셈블리] TEST, JNZ  (0) 2017.08.08