Global API Hooking 개념과 구현 방법에 대해서 알아보도록 하겠습니다.


<Fig - Global API Hooking>

본 내용은 이전 포스트에서 이어지는 내용입니다.

API Hooking – ‘스텔스’ 프로세스 (3)

* 참고!
모든 소스 코드는 MS Visual C++ 2008 Express Edition 으로 개발 되었으며, Windows XP SP3 & Windows 7 환경에서 테스트 되었습니다.



Global API Hooking


Global API Hooking 이란 1) 현재 실행중인 모든 프로세스2) 앞으로 실행될 모든 프로세스에 대해서 API Hooking 을 시키는 것입니다.

지난번에 설명한 예제 프로그램(HideProc.exe, stealth.dll)은 global hooking 이 아닙니다. 위에서 설명한 2) 번 조건이 만족되지 않기 때문입니다.

HideProc.exe 를 실행 하여 notepad.exe 프로세스를 은폐시켜도 이후에 Process Explorer (혹은 task manager) 를 실행시키면 이들 프로세스에서는 notepad.exe 프로세스를 볼 수 있습니다.

그 이유는 HideProc.exe 실행 이후에 생성된 프로세스들에게는 stealth.dll 파일이 (자동으로) 인젝션 되지 않기 때문입니다.

아래 링크를 참조하여 직접 실습해 보세요.

API Hooking – ‘스텔스’ 프로세스 (2)


이러한 문제를 해결하기 위한 다양한 방법이 있을 수 있습니다.
그 중에서 또 다른 API 를 Hooking 하여 Global API Hooking 을 구현하는 방법에 대해서 설명 드리겠습니다.


 
Kernel32!CreateProcess() API


새로운 프로세스가 생성되려면 kernel32!CreateProcess() API 를 사용해야 합니다. WinExec(), ShellExecute(), system() 등의 API 도 내부적으로는 CreateProcess() 를 호출합니다.

BOOL WINAPI CreateProcess(
  __in_opt     LPCTSTR lpApplicationName,
  __inout_opt  LPTSTR lpCommandLine,
  __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
  __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in         BOOL bInheritHandles,
  __in         DWORD dwCreationFlags,
  __in_opt     LPVOID lpEnvironment,
  __in_opt     LPCTSTR lpCurrentDirectory,
  __in         LPSTARTUPINFO lpStartupInfo,
  __out        LPPROCESS_INFORMATION lpProcessInformation
);

* 출처 : http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx

따라서 현재 실행중인 모든 프로세스에 stealth.dll 을 인젝션 하고, stealth.dll 에서 CreateProcess() API 를 후킹하면 이후 실행되는 프로세스에게도 자동으로 stealth.dll 을 인젝션 시키도록 만들 수 있습니다.

다시 설명 드리면 모든 프로세스는 부모 프로세스에서 (CreateProcess() 를 이용하여) 생성시켜주기 때문에 부모 프로세스의 CreateProcess() API 를 후킹하여 자식 프로세스에게 stealth.dll 을 인젝션 하도록 만들면 됩니다. (보통 부모 프로세스는 explorer.exe 가 될 것입니다.)

어떤가요? 좋은 아이디어 이지요?
이와 같이 Global API Hooking 의 개념은 어렵지 않습니다.

하지만 CreateProcess() API 를 후킹하면 아래와 같이 고려해야 할 사항들이 있습니다.

1) CreateProcess() API 를 후킹할 때는 kernel32!CreateProcessA(), kernel32!CreateProcessW() 두 개의 API 를 각각 후킹해야 합니다. (ASCII 버전과 UniCode 버전)

2) CreateProcessA(), CreateProcessW() 는 각각 내부적으로 CreateProcessInternalA(), CreateProcessInternalW() 를 호출합니다. 실제 MS 제품들 중에서 일부는 CreateProcessInternalA/W 를 직접 호출하기도 하지요. 따라서 좀 더 정확히 Global API Hooking 을 구현하기 위해서는 이 두 함수를 더 후킹해줘야 합니다.

3) 후킹 함수(NewCreateProcess) 는 원본 함수(CreateProcess) 를 호출 한 후 생성된 자식 프로세스에 대해서 API 를 후킹 해야 합니다. 따라서 아주 짧은 시간동안 자식 프로세스가 후킹 되지 않은 채로 실행될 수 있습니다.


많은 리버싱 선배님들에 의하여 kernel32!CreateProcess() 보다 더 후킹하기 좋은 함수가 발견 되었습니다.
바로 ntdll!ZwResumeThread() API 입니다.

NtResumeThread(
    IN    HANDLE    ThreadHandle,
    OUT   PULONG    SuspendCount OPTIONAL
);

* 유저 모드에서는 NtXXX 계열과 ZwXXX 계열은 동일합니다.

* 출처 : http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Thread/NtResumeThread.html


ZwResumeThread() 는 프로세스가 생성 된 후 메인 스레드 실행 직전에 호출되는 함수입니다. 따라서 이 함수 하나만 후킹하면 자식 프로세스의 코드가 하나도 실행되지 않은 상태에서 API 를 후킹시킬 수 있습니다.

단점은 ZwResumeThread() 는 undocumented API 라서 언제 바뀔지 알 수 없으며, 그만큼 안정성을 보장 할 수 없습니다. 따라서 ZwResumeThread() 같은 undocumented API 를 후킹 할 때는 OS 가 패치되면서 변경될 수 있다는 것을 항상 염두에 두어야 합니다. 하위 버전에서는 잘 되던 후킹이 최신 버전에서는 갑자기 안 되는 일이 많기 때문입니다.



실습




* 참고
위 stealth2.dll 는 CreateProcess 후킹 버전입니다.
ZwResumeThread 후킹 버전을 원하시는 분께서는 따로 요청해 주시면 보내드리겠습니다.

실습을 간단히 하기 위해서 은폐 프로세스를 notepad.exe 로 고정하였습니다. 참고하시기 바랍니다.

#1. stealth2.dll 파일 -> %SYSTEM% 폴더에 복사


<Fig. 1>

실행 중인 모든 프로세스에 stealth2.dll 파일을 인젝션 시킬 예정입니다. 따라서 모든 프로세스에서 공통적으로 인식할 수 있는 path 인 %SYSTEM% 폴더에 stealth2.dll 파일을 복사합니다.

#2. HideProc2.exe –hide 실행


<Fig. 2>

기존 HideProc.exe 와 비교해서 실행 파라미터가 변경되었습니다. 은폐 프로세스 이름이notepad.exe 로 하드코딩 되어있습니다.
HideProc2.exe 를 –hide 옵션으로 실행시키면 이제부터 글로벌 후킹이 시작됩니다.

#3. ProcExp.exe & notepad.exe 실행

Process Explorer(혹은 작업관리자) 와 notepad 를 여러 개 실행 해 주세요.

 
<Fig. 3>

위 그림을 보시면 ProcExp.exe 와 notepad.exe 프로세스가 각각 2개씩 실행되고 있습니다.
하지만 ProcExp.exe 에서는 notepad.exe 프로세스가 은폐되어 있습니다.

추가로 ProcExp.exe 를 몇 개 더 실행해 보시기 바랍니다. 마찬가지로 새로 생성된 ProcExp.exe 프로세스에서도 notepad.exe 프로세스가 은폐되어서 보이지 않을 것입니다.

이것이 바로 Global API Hooking 의 효과입니다.

#4. HideProc2.exe –show 실행

Global API Hooking 을 해제 합니다.

 
<Fig. 4>

이제 Process Explorer(혹은 작업관리자) 에서 notepad.exe 프로세스가 보일 것입니다.



소스 코드


# HideProc2.cpp


HideProc2.cpp 는 기존 HideProc.cpp 에서 실행 파라미터를 줄인 것뿐이므로, 기존 설명을 참고하시면 되겠습니다.

API Hooking – ‘스텔스’ 프로세스 (3)


# stealth2.cpp


stealth2.cpp 는 기존 stealth.cpp 에서 은폐 프로세스 이름을 "notepad.exe" 로 하드 코딩 하였고, global hooking 을 위해서 CreateProcessA() API 와 CreateProcessW() API 를 후킹 하는 코드가 추가 되었습니다.


DllMain()

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    char            szCurProc[MAX_PATH] = {0,};
    char            *p = NULL;

    // HideProc2.exe 프로세스에는 인젝션 되지 않도록 예외처리

    GetModuleFileName(NULL, szCurProc, MAX_PATH);
    p = strrchr(szCurProc, '\\');
    if( (p != NULL) && !_stricmp(p+1, "HideProc2.exe") )
        return TRUE;

    // change privilege
 
   SetPrivilege(SE_DEBUG_NAME, TRUE);

    switch( fdwReason )
    {
        case DLL_PROCESS_ATTACH :
            // hook
            hook_by_code("kernel32.dll", "CreateProcessA",
                         (PROC)NewCreateProcessA, g_pOrgCPA);
            hook_by_code("kernel32.dll", "CreateProcessW",
                         (PROC)NewCreateProcessW, g_pOrgCPW);
            hook_by_code("ntdll.dll", "ZwQuerySystemInformation",
                         (PROC)NewZwQuerySystemInformation, g_pOrgZwQSI);
            break;

        case DLL_PROCESS_DETACH :
            // unhook
            unhook_by_code("kernel32.dll", "CreateProcessA",
                           g_pOrgCPA);
            unhook_by_code("kernel32.dll", "CreateProcessW",
                           g_pOrgCPW);

            unhook_by_code("ntdll.dll", "ZwQuerySystemInformation",
                           g_pOrgZwQSI);
            break;
    }

    return TRUE;
}

위 DllMain() 함수를 보시면 CreateProcessA, CreateProcessW 를 후킹하는 코드가 추가되었습니다.


NewCreateProcessA()

CreateProcessA() API 의 후킹 함수인 NewCreateProcessA() 코드를 살펴 보겠습니다. (NewCreateProcessW() 코드도 거의 동일합니다.)

BOOL WINAPI NewCreateProcessA(
    LPCTSTR lpApplicationName,
    LPTSTR lpCommandLine,
    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    BOOL bInheritHandles,
    DWORD dwCreationFlags,
    LPVOID lpEnvironment,
    LPCTSTR lpCurrentDirectory,
    LPSTARTUPINFO lpStartupInfo,
    LPPROCESS_INFORMATION lpProcessInformation
)
{
    BOOL bRet;
    FARPROC pFunc;

    // unhook

    unhook_by_code("kernel32.dll", "CreateProcessA", g_pOrgCPA);

    // original API 호출

    pFunc = GetProcAddress(GetModuleHandle("kernel32.dll"), "CreateProcessA");
    bRet = ((PFCREATEPROCESSA)pFunc)(lpApplicationName,
                                     lpCommandLine,
                                     lpProcessAttributes,
                                     lpThreadAttributes,
                                     bInheritHandles,
                                     dwCreationFlags,
                                     lpEnvironment,
                                     lpCurrentDirectory,
                                     lpStartupInfo,
                                     lpProcessInformation);

    // 생성된 자식 프로세스에 stealth2.dll 을 인젝션 시킴

    if( bRet )
        InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);

    // hook

    hook_by_code("kernel32.dll", "CreateProcessA",
                 (PROC)NewCreateProcessA, g_pOrgCPA);

    return bRet;

}

코드는 매우 단순합니다.
일단 후킹을 풀고 원본 함수를 실행해서 생성된 자식 프로세스에 stealth2.dll 을 인젝션 시킵니다.
그 후 다음 실행을 위해서 다시 후킹해 줍니다.

제 글을 꾸준히 읽어오셨다면 쉽게 이해하실 수 있으실 겁니다.

한가지 눈여겨 볼 사항은 인젝션 함수인 InjectDll2() 입니다.
기존 InjectDll() 함수는 프로세스 ID (PID) 를 이용하여 프로세스 핸들을 얻어 인젝션 시키는 방법이었습니다. (OpenProcess() API 이용)

하지만 위의 경우는 CreateProcessA() API 를 호출하면서 자연스럽게 자식 프로세스의 핸들(lpProcessInformaiton->hProcess)을 얻을 수 있습니다. 이 내용도 같이 참고하시면 좋을 것 같습니다.



+---+

지금까지 Global API Hooking 에 대해서 알아보았습니다.

시스템 전체 프로세스에 대해서 후킹을 하는 기술이기 때문에 예상치 못한 에러가 발생할 수 있습니다. 따라서 사전에 꼼꼼한 테스트가 필요합니다. 그리고 undocumented API 를 후킹할 때는 현재 OS 버전에서 예상대로 동작하는지 반드시 확인하셔야 합니다.


다음번에는 API Hooking 시리즈의 마지막 테마인 Code Injection 기법에 대해서 설명드리도록 하겠습니다.

많이 기대해 주세요.

ReverseCore

위 글이 도움이 되셨다면 추천(VIEW ON) 부탁 드려요~

Trackback Address :: http://www.reversecore.com/trackback/68 관련글 쓰기

  1. kuaaan 2010/01/18 09:24 댓글주소 | 수정 | 삭제 | 댓글

    일반적으로 ANSI 타입의 API들은 내부적으로 W타입을 Wrapping하는데요... CreateProcess는 그렇지 않군요. 신기하네요.. ^^a

  2. pico 2010/01/23 16:03 댓글주소 | 수정 | 삭제 | 댓글

    좋은 글 많이 보고 갑니다. 계속 좋은 글 부탁드려요 ^^.. view on 열심히 눌렀습니다. ^^;;

  3. 고기 2010/01/25 11:21 댓글주소 | 수정 | 삭제 | 댓글

    항상 눈팅만 하다가 댓글 남깁니다.
    정말 감사해요~

  4. Ezbeat 2010/04/22 18:33 댓글주소 | 수정 | 삭제 | 댓글

    VS옵션이 다른지.. reversecore님께서 올리신 소스를 제 VS에서 컴파일 시키면 에러가 많이 뜨더군요. 그냥 오류나는것을 보면 hook_by_code의 첫번째 인자를 넘겨줄 때
    "ntdll.dll" 이것을 넘겨주는데 해당 타입은 char* 입니다. 하지만 함수 정의부분에서 보면 자료형을
    LPCTSTR로 받고 있더군요. char*과 TCHAR* 타입이 달라서 오류가 쫘좌작 ;; 뜨네요 ㅜㅜ

    VS에서 옵션을 어떻게 주고 컴파일을 하시는지 ;;

    • reversecore 2010/04/23 23:10 댓글주소 | 수정 | 삭제

      아하~

      제가 블로그 초반에는 VS 6 에서 작성된 예제를 가져다 쓰는 경우가 많아서 multibyte 옵션으로 하다가...

      최근에는 unicode 옵션으로 하고 있습니다.

      위 stealth2.cpp 는 multibyte 용으로 작성되었네요. ^^

      VC++ 2008 의 프로젝트 속성 다이알로그에서 "일반\문자 집합" = "멀티바이트 문자 집합 사용" 으로 변경 후 컴파일 하시면 잘 될 것입니다.

      만약에 잘 안되시면 다시 연락주세요.
      프로젝트 파일을 보내드리겠습니다.

      감사합니다.

  5. Ezbeat 2010/04/24 17:29 댓글주소 | 수정 | 삭제 | 댓글

    아 ^^; 전 유니코드 문자 집합 사용으로 되어있네요.. 음..컴파일은 되는데
    전 이 옵션으로 코딩하는게 습관이 들어서 ..( 윤성우님이 쓰신 시스템 프로그래밍 책을 공부해서;.. ) 유니코드 문자 집합 사용 옵션으로 하고
    소스짜도 큰 상관은 없죠?? ㅠ ㅠ

  6. ohsung 2010/05/10 10:39 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요~ 유용한 정보 감사드립니다. 아직 테스트는 해보지 않았는데요 혹시 이 dll이 전역적으로 훅킹을 한다면 시스템에 부하가 걸리는건 아닌지 궁금해서요. 모든 프로세스가 생성될때마다 dll이 인젝션이 된다면 메모리 사용량도 늘어나는건 아닌지요?

    • reversecore 2010/05/12 12:55 댓글주소 | 수정 | 삭제

      ohsung님, 안녕하세요.

      좋은 질문이십니다. ^^

      모든 후킹은 그만큼의 부하가 걸립니다. 다만 프로그래밍을 잘하면 그 부하가 미미하기 때문에 큰 문제는 없습니다만, 어디까지나 시스템의 안정성과 자원을 잘 고려하셔야 합니다.

      그리고 모든 프로세스에 DLL 이 인젝션 되면 말씀하신 대로 메모리 사용량이 그만큼 증가합니다. DLL 크기 * 인젝션 프로세스 개수 만큼 늘어나는 것은 아니구요. Windows 에서는 같은 DLL 의 경우 한번만 메모리에 전체를 로딩하고 프로세스 들에게는 매핑의 개념을 사용합니다. 쉽게 설명해서 코드 섹션은 다 같은 메모리를 보고 있게 매핑하고요, 데이타 섹션만 해당 프로세스 별로 새로 생성합니다.

      다른 질문 있으시면 올려주세요~

      감사합니다.

  7. booraik 2010/05/19 20:12 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요 정리를 깔끔하게 해놓으셔서 항상 잘보고 있습니다^^

    reversecore님께서는 컴파일을 다 multibyte로 하시나봐요
    저는 unicode를 사용하는데 수정할 일이 한두군데가 아니네요..ㅜㅜ
    이상한데서 버그가 막 튀 나오고 ㅋ
    DllMain에서 DLL_PROCESS_ATTACH, DETACH에 있는
    hook_by_code를 모두 주석처리하면 인젝션까지는 되는데
    주석을 하지 않으면 인젝션조차도 안되네요 ㅎㅎ
    아무래도 이거 multibyte->unicode때문에 그런거 같은데
    혹시 unicode기반으로 작성하신 소스코드는 없으신지요?
    있다면 메일로좀 부탁드릴게요 ㅎㅎ

    • reversecore 2010/05/20 18:09 댓글주소 | 수정 | 삭제

      안녕하세요.

      최신 VC++ 에서는 디폴트 설정이 UniCode 라 몇몇 분들께서 컴파일 과정에 에러가 발생한다고 얘기를 해주셨습니다.

      위 소스에 대해서 조만간 UniCode 버젼도 같이 올려놓도록 하겠습니다.

      감사합니다.

  8. xss 2010/06/24 21:49 댓글주소 | 수정 | 삭제 | 댓글

    좋은글 올려주셔서 감사합니다. 그런데 어떤 경우는 CreateProcess를 이용하지 않고 프로세스 생성이 되는 경우가 있는것 같네요. 예를들어 cmd.exe로 어떤 프로그램을 실행시켰는데 Process Explorer로 보면 그 프로그램에는 stealth.dll 이 로드되지 않는게 관찰되네요. 이후에 올려주신 ZwResumeThread를 이용한 버젼으로도 테스트해보았지만 결과는 마찬가지입니다. 혹시 이점에 대해서 해결책을 알고 계신가요?

    • xss 2010/06/25 18:53 댓글주소 | 수정 | 삭제

      답변 감사드립니다만 말씀해주신대로 ZwResumeThread를 후킹하여도 같은 현상이 일어나고 있습니다.

    • reversecore 2010/06/25 19:12 댓글주소 | 수정 | 삭제

      안녕하세요.

      네, 위에서 언급한 대로 CreateProcess() 함수 내부에서 CreateProcessInternal() 를 호출하는데...
      만약 CreateProcessInternal() 를 직접 호출한다면 그 자식 프로세스에게는 후킹이 되지 않을 것입니다.

      이럴때는 CreateProcessInternal() 까지 후킹을 하시거나 다른 API 를 후킹하시면 됩니다.

      Advanced Global API Hooking (http://www.reversecore.com/77) 를 참고하시면 위 문제에 대한 해결이 가능할 것입니다.

      감사합니다.

    • reversecore 2010/06/26 00:25 댓글주소 | 수정 | 삭제

      cmd.exe 를 간단히 살펴보니 CreateProcessW() 를 사용합니다. 위 stealth2.dll 에서 CreateProcessW() 를 후킹하고 있는데, 버그가 있는지 잘 안되는군요. 좀 더 테스트해본후 수정해야 겠네요...

      ZwResumeThread() 후킹 방식은 잘 됩니다.

      http://www.reversecore.com/79

      위 글에 소개된 InjDll.exe 를 이용해서 모든 프로세스(*)에 redirect.dll 을 인젝션 시켜주세요. 그러면 글로벌 후킹이 걸리게 됩니다. 그리고 cmd.exe 에서 notepad.exe 등을 실행하면 redirect.dll 이 인젝션 되어 있는 것을 확인하실 수 있습니다.

      * ZwResumeThread() 후킹 예제로 만든게 아직 redirect.dll 밖에 없군요.

      잘 안되시면 다시 질문해 주세요~

      감사합니다.

  9. dear 2010/07/30 10:05 댓글주소 | 수정 | 삭제 | 댓글

    질문있습니다.
    언인젝션은 어떻게 하나요?.
    같은방법으로 FreeLibrary를 리모트스레드로 하면되나요?.
    그런데 FreeLibrary는 LoadLibrary하고 프로토타입이 틀린데...

  10. 김성현 2010/08/03 18:40 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요.
    이방법으로 dll인젝션을해 보았는데요.
    explorer.exe에 인젝션을해서 createprocess를 후킹하고있습니다.
    인젝션후에
    opencapture.exe라는 캡쳐 프로그램(델파이로만들어짐)을 실행시키면
    잘못된 연산으로 죽습니다.
    그러나 가끔 실행될때가 있습니다.
    dllmain에 attach/dettach 에 있는 로직을 다 지우고
    시도 해도 opencapture.exe가 실행할떄 잘못된 연산으로 죽네요.

    환경은
    WINDOWSXP SP3 32BIT입니다.
    디버거로 어셈블리를 따라가면,

    콜스택은
    > kernel32.dll!__SEH_prolog() + 0x1a バイト
    OpenCapture.exe!00406120()
    [下のフレームは間違っているか、または見つかりません。OpenCapture.exe に対して読み込まれたシンボルはありません。]
    ntdll.dll!ExecuteHandler2@20() + 0x26 バイト
    0012ffb0()

    그리고 역어셈블은
    ReleaseMutex@4:
    7C8024B7 mov edi,edi
    7C8024B9 push ebp
    7C8024BA mov ebp,esp
    7C8024BC push 0
    7C8024BE push dword ptr [ebp+8]
    7C8024C1 call dword ptr [__imp__NtReleaseMutant@8 (7C8014BCh)]
    7C8024C7 test eax,eax
    7C8024C9 jl _ReleaseMutex@4+19h (7C812891h)
    7C8024CF xor eax,eax
    7C8024D1 inc eax
    7C8024D2 pop ebp
    7C8024D3 ret 4
    __SEH_prolog:
    7C8024D6 push offset __except_handler3 (7C839AD8h)
    7C8024DB mov eax,dword ptr fs:[00000000h]
    7C8024E1 push eax
    7C8024E2 mov eax,dword ptr [esp+10h]
    7C8024E6 mov dword ptr [esp+10h],ebp
    7C8024EA lea ebp,[esp+10h]
    7C8024EE sub esp,eax
    7C8024F0 push ebx
    7C8024F1 push esi
    7C8024F2 push edi
    7C8024F3 mov eax,dword ptr [ebp-8]
    7C8024F6 mov dword ptr [ebp-18h],esp
    7C8024F9 push eax
    7C8024FA mov eax,dword ptr [ebp-4]
    7C8024FD mov dword ptr [ebp-4],0FFFFFFFFh
    7C802504 mov dword ptr [ebp-8],eax
    7C802507 lea eax,[ebp-10h]
    7C80250A mov dword ptr fs:[00000000h],eax
    7C802510 ret
    __SEH_epilog:

    7C8024F0 push ebx 에서 에러가 발생하는것으로 캐치됩니다.

    나중에 zwresumethread를 후킹하는 강좌도 테스트 해보겠지만,
    왜 됬다 안됬다 하는지 이유가 궁금합니다.
    (DLL이 인젝션되어서 실행될떄가 있고, 아예 실행하면 잘못된 연산으로 죽을떄가 있다는뜻입니다.)
    바쁘실텐데, 답변 부탁드립니다.
    그럼이만.

    • reversecore 2010/08/04 22:24 댓글주소 | 수정 | 삭제

      안녕하세요.

      와~ 콜스택까지 올려주셨네요~ ^^

      저도 OpenCapture 를 잘 사용하는데요.
      위의 실습 파일을 가지고 조만간 테스트 해서 결과를 알려드리겠습니다.

      기본적으로 됐다 안됐다 하는 것은 대부분 프로그램 안정성 때문입니다. 유효하지 않은 메모리를 참조할 때 그렇습니다. 콜스택에서kernel32 의 SEH 주소를 가리키는 것을 보면 거의 잘못된 메모리 참조 때문일 것입니다.

      * 사용하시는 OpenCapture 의 정확한 버전을 알면 도움이 되겠습니다.

      * 여담인데요...
      전 처음에 제가 아는 분과 성함이 똑같아서 깜짝 놀랐는데요...
      생각해보니 그 분은 저보다 훨씬 실력이 뛰어나신 분이라서요...
      답변을 달아주시면 몰라도 질문을 올리지는 않으실꺼라 생각했답니다. ㅋ~

      감사합니다.

    • reversecore 2010/08/04 22:31 댓글주소 | 수정 | 삭제

      제가 가진 XP SP3 에서 테스트 결과 충돌 증상은 없네요. (MS VirtualPC 환경입니다.)

      제 OpenCapture 버전은 1.4.3 입니다.

      나중에 리얼 환경에서 다시 테스트 해보도록 하겠습니다.

      * 사실 API 코드 패치 기반의 API 후킹은 그 자체로 좀 위험성이 있습니다. 프로세스 실행중에 동적으로 패치하는 방법이라서... 패치하려는 순간 다른 스레드가 그 코드를 실행하고 있다면??? 바로 충돌 나겠죠. Jeffrey Richter 는 자신의 책에서 이점을 분명히 밝혔죠. ^^

      감사합니다.

  11. WERT 2010/08/26 10:05 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요. 좋은 정보 많이 배우고 갑니다.

    열심히 코딩해서 실행을 시켜 보았는데요. 함수 후킹은 아니구 모든 프로세스에 Injection 까지만 했을 때 일부 프로세스에만 Injection이 되는 현상이 나타납니다.

    제 환경은 Win 7 64bit 또는 Win XP 32bit입니다. 혹시나 권한문제인가해서 둘다해보았지만 같은 현상이었습니다. dll은 dummy.dll을 사용했습니다. 이 포스팅에 있는 코드랑 다른 포스팅에 있는 Win 7 에서 RemoteThreadEx인가 사용하는 코드를 넣었습니다.

    인젝션되는 프로세스는 보면 여기 스텔스 2번포스팅의 Process Explorer에 보이는 것처럼 svchost같은데는 전혀 안들어가구요 비쥬얼스튜디오나 네이트온같은곳에만 인젝션이 들어가네요.. 도대체 왜 이런지 넘 궁금합니다;

    • reversecore 2010/08/28 00:36 댓글주소 | 수정 | 삭제

      WERT 님, 안녕하세요.

      svchost.exe 는 서비스로 동작하는 프로그램이지요.
      문의하신 글을 읽어보니 아마 특권(privilege) 문제가 아닌가 생각됩니다.

      http://www.reversecore.com/76

      위 포스트에 소개된 InjDll.exe 와 dummy.dll 을 가지고 테스트 해보시겠어요?

      InjDll.exe 에 특권을 조정하는 코드를 적용시켜 놓았습니다.

      관련 소스는 http://www.reversecore.com/75 에서 InjDll.cpp 의 SetPrivilege() 함수를 참고하시면 되겠습니다.

      감사합니다.

  12. L4c0 2010/09/03 15:32 댓글주소 | 수정 | 삭제 | 댓글

    여기있는 코드들을 조합해서 Dll Injection을 해보았는데요. 훅을 설치할 경우 JMP코드를 삽입하는데 여기에 있는 hook_by_code에서 사용하는 방식은 32비트 밖에는 안되는 것 같습니다.

    한가지 질문이 있는데 32Bit에서는 Jmp [절대주소] 방식으로 사용이 가능한데 64Bit에서는 Jmp를 쓰기위해서는 rax레지스터를 이용하거나 rsp를 이용하여야 하더라구요. 이런 방식이다보니 아무리 적어도 11byte쯤? 여러가지 방법이 있지만 대충 최소 그 정도 이상의 바이트를 필요로 하게 된다고 하는것 같습니다.

    그래서 뭔가 해볼려고 하는데 혹시 어셈코드에 대응되는 바이너리를 쉽게 만드는 방법이 있는지 궁금합니다; mov rax, 주소; jmp rax <-- 요러한 코드를 만든다고 했을 때 이에 대응되는 바이너리는 어떻게 하면 알 수 있는건가요? Windbg로 Attach시킨다음에 a커맨드를 이용해서 위의 코드를 넣어볼려고 했는데 rax레지스터를 쓰는게 안되더라구요.. eax는 되던데;; 그래서 훅이 되는건지 안되는건지 확인도 못해보고 -_ㅜ;

    하나 더 질문드리면.. 위처럼 훅으로 박아넣는 점프코드가 길어졌는데.. 이때 이 점프코드보다 길이가 짧은함수들은 훅이 절대 불가능한건가요??

  13. dngchn 2010/12/03 16:55 댓글주소 | 수정 | 삭제 | 댓글

    본 컬럼 테스트를 하고 있습니다.
    제가 타겟으로 삼은 프로그램은 실행 하다가 "WinExec"를 통해 다른 프로세스를 생성하고 죽습니다. (즉 자식을 낳고 바로 죽는 부모의 경우)
    위 글에서 보면 "WinExec, ShellExecute... 등 도 내부적으로는 CreateProcess를 호출한다고 하였는데, 제 타겟에 대해 이를 체크해보면 WinExec를 통해 자식 프로세스를 생성하므로, 결과적으로는 CreateProcess에서 훅을 걸어보면 걸리지 않습니다. (WinExec에다 걸면 잘 걸리구요.)
    그래서 제 생각에는 ZwResumeThread를 한번 사용해보고 싶습니다. 코드좀 주시면 감사하겠구요.
    또 하나 걸리는 부분은 부모프로세스가 WinExec를 부르고 바로 죽기때문에 부모프로세스에 훅을 걸어놓은 CreateProcess를 탐지 할 수 없는 것일 수도 있을것 같은데, 이에 대해 관리자님 생각의 어떠신지 조언 부탁드립니다.

    • reversecore 2010/12/10 16:04 댓글주소 | 수정 | 삭제

      안녕하세요. ReverseCore 입니다.

      답변이 늦어서 죄송합니다. @@~

      CreateProcess() 는 내부적으로 CreateProcessInternal() 을 호출합니다. 그리고 CreateProcessInternal() 내부에서 ntdll!ZwResumeThread() 를 호출하는 식입니다.
      (http://www.reversecore.com/78 글의 <Fig. 9> 밑의 설명을 참고하세요)

      WinExec() 는 CreateProcessInternal() 를 바로 호출합니다. 따라서 CreateProcess() 를 후킹해서는 효과가 없습니다.

      ZwResumeThread() 사용 코드는 http://www.reversecore.com/80 글을 참고하시면 될것 같습니다.

      감사합니다.

  14. kmslife 2011/04/15 18:02 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요.
    질문이 있어서 이렇게 글을 올립니다.
    첨부되어 있는 프로그램으로 실행은 잘 되는데요
    문제는 vs2008로 만들어진 프로그램들, 그리고 vs2008 툴 자체는 위 dll을 injection 시키면
    프로그램 자체가 실행되지 않습니다.
    vs2003이나, 그외 프로그램들은 잘 동작하는데 말이죠
    ASLR기능 인가 찾아 보았지만 제 pc의 환경은 xp sp3환경이어서 문제가 되지는 않을 것 같습니다.
    원래 vs2008관련되어서는 dll injection 기능이 동작하지 않는것인가요?
    동작하게 하려면 어떻게 해야 할지요?

    • reversecore 2011/04/20 10:41 댓글주소 | 수정 | 삭제

      안녕하세요.

      지금 제 환경은 Win7 64bit, WinXP SP3 32bit 인데요.

      말씀하신 VS2008 은 없어서 Visual C++ 2008 Express (VCExpress.exe 프로세스)에 테스트 해본 결과 정상동작 하네요.

      VS2008 로 제작된 파일에 인젝션 시키면 동작 안한다고 하셨는데요.
      그 파일을 제게 보내주시면 테스트 해보겠습니다.

      실행 파일을 zip 압축 하신 후 확장자를 zipx 로 변경하셔서 아래 메일로 보내주시기 바랍니다.

      reversecore@gmail.com

      감사합니다.

  15. jjengae 2011/09/28 20:06 댓글주소 | 수정 | 삭제 | 댓글

    스텔스 프로세스(2)에서 올려주셨던 HideProc.exe는 XP기반에서만 작동하는 것 같더라구요

    윈도우 7(Enterprise 32bit)에서 vmware-vmx.exe라는 프로세스를 숨기기 하고 싶은데

    이번에 포스팅에 올려주신 파일은 notepad.exe로 고정되어 있는것 같아서요

    제가 임의의 프로세스를 숨기려면 어떤 부분을 수정해서 어떻게 컴파일 해야 하는건가요?

    .exe와 .dll은 한번도 컴파일해보지 않아서...

    또, 수정하려면 무조건 Visual Studio가 설치되어 있어야 하는건가요?

    기초 지식 없이 이렇게 물어봐서 죄송합니다

    가능하시다면 jjengae@nate.com 으로 메일 부탁드릴게요

    • reversecore 2011/09/28 20:36 댓글주소 | 수정 | 삭제

      안녕하세요.

      위 예제에서 은폐프로세스 이름은 notepad.exe 로 하드코딩 되어 있습니다.

      소스코드에서 "notepad.exe" 문자열을 "vmware-vmx.exe" 문자열로 수정 후 빌드 하시면 됩니다.

      Visual C++ 을 한번도 사용해보지 않으셨다면 조금 어려움이 있을 수 있습니다.

      감사합니다.

  16. jjengae 2011/09/29 23:32 댓글주소 | 수정 | 삭제 | 댓글

    빌드를 해야된다고 하셔서 VS2008 설치했습니다.

    "notepad.exe"를 수정해야 한다고 하시는건 "stealth2.cpp"에 있는 내용을 수정하고 빌드해야 된다는 말씀이시죠?

    "HideProc2.cpp"는 "멀티 바이트 문자 집합" 설정하고 컴파일 했더니 debug폴더에 실행파일이 생성되더군요. 문제는 stealth2.cpp 파일입니다.

    여차여차해서 stealth2.cpp 파일을 컴파일 하려고 프로젝트 생성시에 응용프로그램 종류에서 콘솔 응용프로그램 대신 "DLL"로 셋팅하고 멀티바이트 문자 집합으로 설정했더니 오류가 나지 않더군요.

    근데 컴파일 후에 나타나는 창이 무엇인지 잘 모르겠습니다. "디버그 세션이 사용할 실행 파일"이라는 창이 뜨고 "실행 파일 이름"과 "프로젝트에 액세스할 수 있는 URL"을 입력하라고 하는데 그것을 무엇으로 해야할지 잘 모르겠습니다.

    요약하자면 stealth2.cpp 파일을 어떻게 .dll로 컴파일하는지 좀 알려주시면 감사하겠습니다.

    혹시 .dll로 컴파일하는 포스팅은 없는건가요? 시간 되신다면 vmware-vmx.exe로 적용하여 jjengae@nate.com으로 보내주시면 감사하겠습니다. ㅜㅜ

    도움 주시면 감사하겠습니다.

  17. jjengae_father CPP 2011/09/30 10:47 댓글주소 | 수정 | 삭제 | 댓글

    글 보고 메일 발송하였는데요.

    • jjengae 2011/09/30 11:38 댓글주소 | 수정 | 삭제

      관심 감사합니다.
      그런데 메일을 확인해보니 메일이 도착하질 않았네요..
      죄송하지만 다시한번 메일 보내주셨으면 감사하겠습니다

  18. jjengae 2011/10/01 14:31 댓글주소 | 수정 | 삭제 | 댓글

    제발 누가 stealth2.cpp dll로 빌드하는 방법좀 알려주실 수 없나요 ....

  19. jjengae_father CPP 2011/10/06 22:32 댓글주소 | 수정 | 삭제 | 댓글

    안녕하셰요.
    메일 확인하니 주소가 틀렸어요.
    VS키고 dll프로젝트를 하나 창조하지요.
    다음 dll main에서 stealth2.cpp를 코피하다놓고 빌드하면 되겠지요.

    • jjengae 2011/10/08 00:58 댓글주소 | 수정 | 삭제

      전에 보내셨던 메일이 어떤 내용이었는지는 모르겠지만
      보낸메일함에서 전달로 다시한번 보내주실 수 없나요?

      그리구 제가 일반 콘솔 프로젝트는 많이 해봤는데
      dll은 컴파일을 하면 이상한 창이 하나 뜨더라구요
      "디버그 세션이 사용할 실행 파일"이라고...
      실례가 안된다면 프로젝트 생성부터 과정을 좀 자세하게 설명좀 부탁드릴 수 있을까요?

  20. jjengage_father CPP 2011/10/11 20:20 댓글주소 | 수정 | 삭제 | 댓글

    안녕하셰요.
    VS를 켜시고 File/New/Project/Win32를 선택하시지요.
    dll옵션을 체크하시고 empty를 선택하세요.
    그렇게하군서 stealth2.cpp를 코피하다가 빌드하세요.
    dll컴파일을 하구선 loadlibrary를 사용하셰야 디버그를 할수잇어요.

  21. jjengae 2011/10/13 07:05 댓글주소 | 수정 | 삭제 | 댓글

    드디어 빌드를 완료했습니다.

    그런데 아래와 같은 증상이 나타나면서 프로세스는 사라지지 않는데, 무엇이 문제인가요 ?

    C:\Work>HideProc2.exe -hide stealth.dll
    OpenProcess(968) failed!!!
    OpenProcess(1572) failed!!!
    OpenProcess(2296) failed!!!

  22. jjengage_father CPP 2011/10/13 14:14 댓글주소 | 수정 | 삭제 | 댓글

    와 정말 장하시네요.
    근데 또 에러가 있군요.
    오~~~~그거 권한문제때문같아요.
    안녕하셰요.

  23. jjengae 2011/10/14 04:35 댓글주소 | 수정 | 삭제 | 댓글

    father님 항상 조언 감사합니다.
    덕분에 dll 빌드하는 방법을 알았네요.
    전 항상 컴파일만 돌릴생각만 하고 안된다고 생각했었는데 빌드를 해야했군요.

    reversecore님 이게 권한문제때문에 발생하는 에러인가요?
    만약 권한문제라면 권한 문제는 어떻게 해결해야 하나요?

  24. kimpilgu 2012/05/12 15:36 댓글주소 | 수정 | 삭제 | 댓글

    질문있습니다.
    1. 새로 생성(기존x)되는 하나의 모든 exe 프로세스만 감지(CreatePocess 함수)해서 후킹할려면 어떻게 하나요
    2. 그리고 후킹후에 제가 원하는 프로세스 실행할려면
    무슨 함수가 있어야하나요?
    3. 디바이스 드라이버 파일에 dll파일을 로드시켜 사용할수 있나요??
    ...답변해주시면 정말 감사하겠습니다.


◀ PREV : [1] : ... [26] : [27] : [28] : [29] : [30] : [31] : [32] : [33] : [34] : ... [93] : NEXT ▶