Windows 7 (& Vista) 에 맞는 InjectDll.exe 를 개발하고 소스 코드를 살펴보겠습니다.

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


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



지난 내용 정리


시작하기 전에 먼저 지난 시간에 소개해 드린 내용을 짧게 정리해 보겠습니다.

Windows 7 (or Vista) 에서는 Session 관리 정책이 변경됨에 따라서 kernel32!CreateRemoteThread() API 내부 구현이 변경되었습니다. 

☞ 참고 : Session in Windows 7

그 결과 CreateRemoteThread() 를 사용한 DLL Injection 기술이 Windows 7 (or Vista) 의 서비스 프로세스(Session 0) 에게는 정상적으로 동작하지 않습니다. 

Kernel32!CreateRemoteThread() 를 디버깅 한 결과 원인은 API 내부에서 리모트 스레드를 생성할 때 suspend 모드로 생성하는데, 만약 리모트 프로세스가 Session 0 라면 resume 시키지 않고 그냥 에러를 리턴하기 때문이었습니다. 

* 참고!
리모트 스레드를 생성할 때 일단 suspend 모드로 생성시킨 후 resume 시키는 구현 방법은 예전 XP 때부터 사용되던 방식입니다.

Kernel32!CreateRemoteThread() API 내부에서 호출되는 ntdll!ZwCreateThreadEx() API 의 파라미터를 조작 하거나 에러 조건 분기를 강제로 변경하면 정상적으로 리모트 스레드가 생성되면서 DLL Injection 이 성공하는 것을 확인 하였습니다.



InjectDll.exe


Windows 7 에서는 kernel32!CreateRemoteThread() 를 호출하는 것보다는 ntdll!ZwCreateThreadEx() API 를 직접 호출하는 것이 더 좋은 방법임을 알게 되었습니다.


* 주의!
ntdll!ZwCreateThreadEx() API 는 Vista 이후부터 추가된 API 이므로 XP 이하에서는 계속 CreateRemoteThread() 를 사용해야 합니다.

새로 알게 된 지식을 바탕으로 InjectDll.exe 프로그램을 새롭게 만들었습니다.

새롭게 프로그래밍한 InjectDll() 함수를 살펴보겠습니다.

typedef DWORD (WINAPI *PFNTCREATETHREADEX)
    PHANDLE                 ThreadHandle,
    ACCESS_MASK             DesiredAccess,
    LPVOID                  ObjectAttributes,
    HANDLE                  ProcessHandle,
    LPTHREAD_START_ROUTINE  lpStartAddress,
    LPVOID                  lpParameter,
    BOOL                    CreateSuspended,
    DWORD                   dwStackSize,
    DWORD                   dw1, 
    DWORD                   dw2, 
    LPVOID                  Unknown 
); 

BOOL IsVistaOrLater()
{
    OSVERSIONINFO osvi;

    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

    GetVersionEx(&osvi);

    // 커널 버전이 6 이상인지 확인!
    if( osvi.dwMajorVersion >= 6 )
        return TRUE;

    return FALSE;
}

BOOL MyCreateRemoteThread
(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
{
    HANDLE      hThread = NULL;
    FARPROC     pFunc = NULL;

    // OS 가 Vista 이상인지 확인!
    if( IsVistaOrLater() )    // Vista, 7, Server2008
    {
        pFunc = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCreateThreadEx");
        if( pFunc == NULL )
        {
            printf("GetProcAddress(\"NtCreateThreadEx\") failed!!! [%d]\n",
                   GetLastError());
            return FALSE;
        }

        // NtCreateThreadEx() 호출
        ((PFNTCREATETHREADEX)pFunc)(&hThread,
                                    0x1FFFFF,
                                    NULL,
                                    hProcess,
                                    pThreadProc,
                                    pRemoteBuf,
                                    FALSE,
                                    NULL,
                                    NULL,
                                    NULL,
                                    NULL);
        if( hThread == NULL )
        {
            printf("NtCreateThreadEx() failed!!! [%d]\n", GetLastError());
            return FALSE;
        }
    }
    else                    // 2000, XP, Server2003
    {
        hThread = CreateRemoteThread(hProcess, 
                                     NULL, 
                                     0, 
                                     pThreadProc, 
                                     pRemoteBuf, 
                                     0, 
                                     NULL);
        if( hThread == NULL )
        {
            printf("CreateRemoteThread() failed!!! [%d]\n", GetLastError());
            return FALSE;
        }
    }

    if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )
    {
        printf("WaitForSingleObject() failed!!! [%d]\n", GetLastError());
        return FALSE;
    }

    return TRUE;
}

BOOL InjectDll(DWORD dwPID, char *szDllName)
{
    HANDLE hProcess = NULL;
    LPVOID pRemoteBuf = NULL;
    FARPROC pThreadProc = NULL;
    DWORD dwBufSize = strlen(szDllName)+1;

    if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
    {
        printf("OpenProcess(%d) failed!!! [%d]\n", 
                dwPID, GetLastError());
        return FALSE;
    }

    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, 
                                MEM_COMMIT, PAGE_READWRITE);

    WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName, 
                       dwBufSize, NULL);

    pThreadProc = GetProcAddress(GetModuleHandle(L"kernel32.dll"), 
                                 "LoadLibraryA");

    if( !MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pThreadProc, pRemoteBuf) )
    {
        printf("CreateRemoteThread() failed!!! [%d]\n", GetLastError());
        return FALSE;
    }

    VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);

    CloseHandle(hProcess);

    return TRUE;
}


InjectDll() 함수의 변경된 사항은 바로 kernel32!CreateRemoteThread() 를 직접 호출하지 않고MyCreateRemoteThread() 사용자 함수를 호출 한다는 것입니다.

MyCreateRemoteThread() 함수 내부에서 OS 버전을 구해서 Vista 이상이라면 ntdll!NtCreateThreadEx() 를 호출하고, XP 이하라면 kernel32!CreateRemoteThread() 를 호출하도록 하였습니다.

간단한 코드이므로 쉽게 이해하실 수 있으실 겁니다.


* 참고!
유저 모드에서 ntdll.dll 라이브러리의 NtCreateThreadEx() 와 ZwCreateThreadEx() API 는 사실 같은 함수입니다. (두 함수의 시작 주소는 동일합니다.) 커널 모드(ntoskrnl.exe) 에서는 두 함수가 서로 틀려집니다. 향후 커널 모드 디버깅을 설명할 때 다시 설명 드리겠습니다. 일단 유저 모드에서는 NtXXX() 와 ZwXXX() 는 같다는 것만 기억해 주시기 바랍니다.



테스트

dummy.dll 파일은 지난 시간에 사용된 것과 동일한 파일로써 인젝션이 성공하면 디버그 로그를 출력하는 기능을 가지고 있습니다.

테스트를 위해서 적당한 서비스 프로세스를 골라 봅니다.


<Fig. 1>

그리고 아래와 같이 InjectDll.exe 를 실행시켜 주세요.


<Fig. 2>

Process Explorer 로 svchost.exe (PID:612) 를 확인해 보시면 dummy.dll 이 인젝션 되어 있는 걸 확인 하실 수 있습니다.


<Fig. 3>

이제 서비스 프로세스(Session 0) 에도 무리 없이 DLL Injection 을 할 수 있게 되었습니다. 

* 참고!
ntdll!NtCreateThreadEx() API 는 undocument API 입니다. 따라서 MicroSoft 에서 사용을 권장하지 않을뿐더러 시스템의 안정성을 보장할 수 없습니다. 제가 테스트 해본 바로는 잘 동작하였지만 언제든지 MS 에서 패치를 시킬 가능성도 있습니다. 따라서 업무용으로 이 방법을 따라 하시는 분들께서는 꼭 이러한 사항을 염두에 두시기 바랍니다.

이상으로 Windows 7 에서 DLL Injection 하는 방법에 대한 설명을 마치도록 하겠습니다.


ReverseCore

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

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

  1. Tracked from ♡바다.. 의 일상이야기 2010/08/10 12:02 삭제

    Subject: CopyPwd.exe 파일을 Windows Server 2008 에서도 사용해보자!!

    오랫만에 포스팅을 하는 듯 합니다. 서버 관리자 분들이면 꽤나 많이 사용하시는 소프트웨어가 CopyPwd.exe 파일입니다. 파일명에서도 보듯이 사용자의 패스워드를 해쉬값으로 변환해서 txt 파일로 저장 및 복원해주는 서버 관리자 분들에게는 없어서는 안될 아주 좋은 Command 창 소프트웨어 입니다. CopyPwd.exe 제조사 방문하기 하지만!! 제가 이번에 Windows Server 2008 을 설치하면서 난관에 봉착했습니다. 그것은 이 Cop..
  1. 철이 2010/02/23 04:12 댓글주소 | 수정 | 삭제 | 댓글

    항상 감사합니다.

  2. 늅늅 2010/03/01 12:51 댓글주소 | 수정 | 삭제 | 댓글

    잘 보고 있습니다!!

    혹시 책으로 언제쯤 발간하실 예정이신가요?~

    너무 기대되네요!!

    • reversecore 2010/03/01 23:32 댓글주소 | 수정 | 삭제

      늅늅님, 안녕하세요.

      제 책을 기다리시는 건가요? ^^

      목표는 금년내에 출판하는 것입니다.

      감사합니다.

  3. L4c0 2010/03/11 11:35 댓글주소 | 수정 | 삭제 | 댓글

    와 출간 계획이 있으셨군요. 빨리나오기를.. ^^

    • reversecore 2010/03/11 22:14 댓글주소 | 수정 | 삭제

      L4c0님, 안녕하세요.

      책쓰는게 정말 쉬운일이 아니라는걸 느끼고 있답니다.

      기술 서적을 쓰시는 분들은 정말 존경합니다. ^^

      감사합니다.

  4. 허훈 2010/03/21 04:17 댓글주소 | 수정 | 삭제 | 댓글

    InjectDll 함수에서
    hThread를 왜 선언만 하고 바로
    CloseHandle하셨는지요??

  5. 아이졸려 2010/05/26 13:40 댓글주소 | 수정 | 삭제 | 댓글

    항상 좋은 글 감사합니다.
    정말 많이 배우고 있습니다.
    Window 7 DLL Injection을 실습중인데, 설명하신대로 잘 되지 않아서 문의드립니다.
    일단 Session 0이 아닌 것은 잘 됩니다. 그런데 Session 0일경우는 새로운 방법도 에러가 나고요.
    것도 CreateRemoteThread가 아닌, OpenProcess에서 나고 있습니다.
    그리고 "The token does not have the specified privilage"라는 메시지도 뜨고요.
    무엇이 문제일까요?
    오늘도 좋은 하루 보내세요~

    • reversecore 2010/05/27 01:33 댓글주소 | 수정 | 삭제

      안녕하세요.

      가령 session 0 의 svchost.exe 에 인젝션 시도하면 OpenProcess() 에서 에러가 발생한다는 말씀이시죠?

      제 경우에는 7 - 32bit 버전에서는 문제가 없고, 64bit 버전에서는 NtCreateThreadEx() 에서만 에러가 발생합니다.

      사용하시는 OS 버전, 인젝션 시도하는 프로세스명 등을 알려주시면 답변에 도움이 될것 같습니다.

      감사합니다.

    • 아이졸려 2010/05/28 11:48 댓글주소 | 수정 | 삭제

      문제는 Windows 7 UAC인것 같습니다.
      지금 자세히 그림을 보니, 명령어창을 관리자 권한으로 여셨네요.^^
      저는 일반 사용자 권한으로 열어서 실행하다 보니 이런 문제가 생긴 것 같습니다.
      그런데 일반 사용자모드에서 관리자 권한으로 상승시키고 DLL Injection을 할 수는 없는 것인지 궁금합니다.
      좋은 답변 감사드립니다.
      오늘도 즐거운 하루보내세요.

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

      안녕하세요.

      아~ 그랬군요.
      UAC 를 평소 끄고 사용하는지라 생각도 못하고 있었습니다.
      그리고 전 항상 관리자로만 접속합니다.

      그런 부분에 대해서는 미처 고려해보지 않았네요.
      소중한 정보 감사드립니다. ^^

      그리고 Windows XP/7 에서는 로그인 유저마다 고유 Session 이 있기 때문에 일반적으로는 다른 Session 의 프로세스에게 DLL Injection 시킬 수 없습니다.

      강제로 권한을 상승 시킨후 DLL Injection 을 하면 어찌 될지 모르겠네요. (제가 요즘 차분히 앉아서 테스트를 할 수 있는 상황이 아니라서요... ㅠㅜ 제 대신 해주시면 매우 감사 하겠습니다.)

      감사합니다.

  6. LinkC 2010/06/12 16:19 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요, Reversecore님의 강의는 항상 감사하게 잘 보고 있습니다 :D

    다름이 아니라, XP나 7 32bit 에서는 성공했는데

    64bit에서 NtCreateThreadEx 에서 권한이 없다면서 실패하고 있습니다

    위 덧글을 보면 저만 그런게 아닌 모양인데요

    혹시 원인을 발견하셨는지 여쭙고 싶어서 댓글 답니다

    32bit 와 64bit 정책 적용 방식이 다를거 같진 않은데

    권한이 없다고 뜨는건 의외네요

    물론 관리자 권한으로 실행도 해봤지만 같은 증상이 뜹니다

    • reversecore 2010/06/14 23:58 댓글주소 | 수정 | 삭제

      안녕하세요.

      네, 64bit 에서 잘 안된다고 하신분들이 계신데요.

      제가 64 bit OS 를 설치해서 테스트 해본 후 답변드리겠습니다.

      감사합니다.

    • LinkC 2010/08/03 19:30 댓글주소 | 수정 | 삭제

      계속 미루다 64bit injection 을 해봤습니다

      32bit process 에서는 32 bit dll만

      64bit process 에서는 64 bit dll 만

      injection이 가능하더군요

      64bit os라고 64bit process만 돌아가는게

      아니니까 , global api hooking 을 하고자 할때는

      64bit용, 32bit 용으로 나눠

      32bit injection program, 32bit dll

      64bit injection program, 64bit dll

      이렇게 제작해야 올바르게 작동하는 걸 확인했습니다 :D

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

      안녕하세요.

      와~ 좋은 정보 감사합니다. ^^
      저도 64 bit 를 더 공부한 후 테스트 해보겠습니다.

      감사합니다.

  7. 이남 2011/05/11 12:54 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요...

    강의내용 잘 보았습니다. 저 헌데 csrss에 전혀 inject되지 않는 이유가 무얼까요? 제 체계는 Win7입니다. inject success통보문 뜨는데도 되지 않거던요..
    의견 부탁드립니다.

    • reversecore 2011/05/13 20:23 댓글주소 | 수정 | 삭제

      안녕하세요.

      csrss.exe 프로세스는 시스템 핵심 프로세스로서 DLL Injection 을 안하는 것이 좋습니다.

      위 포스트의 InjectDll.exe 에는 버그가 있어서 csrss.exe 에 인젝션 성공했다고 나타나지만 실제로는 실패한 것입니다.

      http://www.reversecore.com/76 <- 여기서 제공되는 InjDll.exe 를 사용해 보시면 실패라고 정확히 나타납니다.

      아래 API 호출 중 한 군데에서 에러가 발생합니다.

      OpenProcess(), VirtualAllocEx(), WriteProcessMemory(), CreateRemoteThread()

      감사합니다.

  8. 안랩의전설 2011/10/10 16:38 댓글주소 | 수정 | 삭제 | 댓글

    잘 계시죵?

    오홀~ 이런것까정 해 보셨다니.. 써프롸이즈~

    smss.exe 에 인젝션 해보니.. 시스템이 퍽~하며 재부팅하는군요

    시스템 프로세스는 화이트 리스트로 빼 주는 기능도 추가해야 되겠군요

    좀 더 좋은 정보를 위해서 멀티스레드 환경에서는 JMP 패치시에 코드 크래쉬가 일어날 수 있는데

    윈도우의 핫패치 방법을 이용하는것도 간단히 소개해 주신다면.. 다른 분들께서

    더욱 많은 도움이 될 듯 합니다..

    그럼 이만.. 총총~

    • reversecore 2011/10/28 01:07 댓글주소 | 수정 | 삭제

      안녕하세요. 잘 지내고 있답니다. ^^

      네, 개념 이해용 예제 코드 말고 상업용 프로그램에 사용할 수 있는 전문 DLL Injection 강좌도 기획하고 있습니다.

      제 예제 코드를 현업에서 사용하시는 분들이 꽤 많으시더군요. 좀 더 안정적인 코드를 제공해 드려야 할 것 같아요.

      조만간 책이 완료되면 다시 블로그 작업을 진행할 계획입니다.

      감사합니다.

  9. 인젝션 2011/10/13 14:02 댓글주소 | 수정 | 삭제 | 댓글

    잘 보고 갑니다~

    정리 완전 잘 하셨네요 ㅎ

    블로그에 소중한 정보들 잘 보도록 하겠습니다.!

  10. choiks 2011/10/15 20:44 댓글주소 | 수정 | 삭제 | 댓글

    질문이 있습니다!!!제가 OS관에서 완전 초보인데,,,

    SetPrivilege(SE_DEBUG_NAME, TRUE);

    // InjectDll.exe <PID> <dll_path>
    if( argc != 3 )
    {
    printf("usage : %s <PID> <dll_path>\n", argv[0]);
    return 1;
    }
    이부분 까지 시행이 되고
    "usage:argv[0]문이 실행이 되고 되고 그이후 명령문
    if( !InjectDll((DWORD)atoi(argv[1]), argv[2]) )
    {
    printf("InjectDll() failed!!!\n");
    return 1;
    }
    등이 실행이 안되는데 왜그런걸까요??

  11. jinjin 2011/10/16 09:23 댓글주소 | 수정 | 삭제 | 댓글

    choiks님
    안녕하셰요.
    글 보고 싱크되는것 있어 보니 printf다음에 return이 있어 그러는것 같아요.

  12. choiks 2011/10/16 10:36 댓글주소 | 수정 | 삭제 | 댓글

    그래도 안되네여... 제가 정말 왕초본데 ㅠㅠ
    if( argc !=3)
    {
    printf("usage : %s <PID> <dll_path> \n",arg[0]);
    return 1;
    }
    여기 까지 실행이 되서
    usage : DllInjgection.exe <PID> <DLL_PATH>
    이런 문장이 나오는데 PID랑 DLL_PATH를 어떡해 설정해 주면 될까요??

    아그리고 cmd명령오로 제가 컴파일해서 생성한 DLL_Injection.exe를 쳤더니 내부 또는 외부 명령, 실행할수있는 프로그램,또는 배치 파일이 아닙니다 라고 뜨네요 ㅠ.ㅠ

  13. jinjin 2011/10/17 20:24 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요.
    아그멘트값설정하는것이지요.
    컴맨드프롬프트창에서 EXE의 파일경로를 주어야되는데 예를 들어 "D:\test\Dllinjection.exe"라고 주고 space건을 누르고 계속해서 인젝션시킬 프로세스 아이디를 주어야지요.
    PID는 taskmanager에서 볼수 있지요.
    Next로서 DLL_PATH값을 앞에서 처럼주면 되요.
    예제로 "C:\test\Dllinjection.exe" 5764 "C:\test\Me.dll"
    안녕하세요.

  14. eee 2011/10/30 14:59 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요!^^ 정말 왕초보인데 64bit 에서 64 bit 컴파일 해서

    인젝션 성공 메세지까지 받았어요 . 그런데 process explorer 에서 dll을 검색하니까 검색이 안되요

    인젝션에 성공하면 dll 검색하면 인젝션된 프로세스들이 나와야 하는데 안나와요.

    어떻게 된건지 모르겟어요.ㅠㅠ 고수님들 도와주세요! ^^;

  15. 안녕하세요^^. 2011/11/02 18:59 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요.
    덕분에 모든 32비트환경에서 잘작동하는거 확인했어요 ㅎㅎ.
    하지만 윈7 64비트는안되는데
    윗분님들 말씀보시니 64비트 환경에서 컴파일해야하는데
    64비트를 따로 깔수가없는 환경이라 그런데 다른방법은 없나요 ㅜㅠ?

  16. 구미호 2011/11/14 19:53 댓글주소 | 수정 | 삭제 | 댓글

    dll injection 시켜서 인젝션 당한 프로그램을 렉걸리게 하고싶은데 어떻게하지요?
    1초정도 정지시키거든
    1초정도 순간 렉을 발생시키고 싶은데
    sleep 쓰면 dll에만 적용되고 프로세스에는 적용이 안되서...
    어떻게 소스를 짜면될까요?>

    • reversecore 2011/11/18 20:47 댓글주소 | 수정 | 삭제

      안녕하세요.

      Target 프로세스의 실행을 방해하신다구요? 악성코드 수준입니다. ^^~

      실행중인 모든 스레드를 SUSPEND 모드로 바꿔버려도 되구요... 아니면 무한루프 스레드를 1000개쯤 만들어 버리세요. 엄청난 과부하가 걸릴정도로요...

  17. 팔극진 2012/01/03 14:54 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요~
    강의 보다가 궁금한 점이 있어서 이렇게 질문드립니다.

    ((PFNTCREATETHREADEX)pFunc)(인자값....);

    : 위에 보면요 ntcreatethreadex 의 주소값을 다시 함수 형변환하는데요~

    왜 형변환을 해줘야 하는건가요?

    그리고, CreateSuspended 값 0x1fffff 로 바꿀때

    함수만 호출해서 저렇게 형변환 해서 바꾸면 되는건가요?

    저 부분이 헷갈리네요 ㅜㅠ

    너무 초보라서 아무리 찾아도 모르겠습니다.

    조언 좀 부탁드립니다.

    수고하세요~

    • reversecore 2012/01/11 07:47 댓글주소 | 수정 | 삭제

      안녕하세요.

      형변환은 C 언어의 특징이고요.
      컴파일 에러를 피하기 위해서 넣어주는 겁니다.
      개발자를 돕기 위해서 저렇게 엄격한 타입 체크를 해주는 거랍니다. 고마운거죠.

      어셈블리라면 형변환 자체가 필요없습니다. 다만 모든 책임은 개발자가 지는 것이죠. 어디서 에러가 발생했는지 찾는게 매우 까다롭죠. ^^

      감사합니다.



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

 DLL Injection in Windows 7 (1)



디버깅 2


OllyDbg 를 재실행시켜 InjectDll.exe 의 CreateRemoteThread() 호출 코드까지 옵니다. (아래 그림 참조)


<Fig. 1>

스택에 저장된 CreateRemoteThread() API 의 파라미터를 보겠습니다.


<Fig. 2>

위 그림의 중요 파라미터들에 대한 설명은 다음과 같습니다.

(1) svchost.exe (PID : 3148) 의 프로세스 핸들
(2) kernel32!LoadLibraryA() API 주소
(3) svchost.exe 의 프로세스 메모리에 할당한 버퍼 주소 ("c:\work\dummy.dll")

이제 <Fig. 1> 에서 StepIn (F7) 명령으로 kernel32!CreateRemoteThread() API 내부로 들어가 보겠습니다.


<Fig. 3>

Kernel32!CreateRemoteThread() 는 내부적으로 kernelbase!CreateRemoteThreadEx() 를 호출합니다. 

* kernelbase.dll 은 Vista 부터 추가된 DLL 파일로써 kernel32.dll 의 wrapper 역할을 담당합니다.

이때의 스택에 저장된 파라미터를 살펴보겠습니다.


<Fig. 4>

kernelbase!CreateRemoteThreadEx() 의 파라미터들은 kernel32!CreateRemoteThread() 와 거의 동일하고 lpAttributeList 파라미터가 추가되었습니다.

다시 kernelbase!CreateRemoteThreadEx() 코드 내부로 들어갑니다. 스크롤을 조금 내려보면 아래와 같이 ntdll!ZwCreateThreadEx() 호출 코드가 나타납니다.


<Fig. 5>

스택에 저장된 파라미터를 살펴보겠습니다.


<Fig. 6>

파라미터 개수가 더 많아졌습니다. <Fig. 2> 와 <Fig. 6> 을 비교해보면 중요 파라미터 (1) ~ (3) 이 그대로 전달된 것을 확인할 수 있습니다.

ntdll!ZwCreateThreadEx() API 의 내부를 더 파고 들어가면 결국 "SYSENTER" 명령어를 만나서 커널 모드로 진입하게 됩니다. 유저 모드 디버깅으로는 더 이상 진행할 수 없습니다. (커널 모드 디버깅에 대해서는 향후 자세히 설명하도록 하겠습니다.)

사실 kernelbase!CreateRemoteThreadEx() 와 ntdll!ZwCreateThreadEx() 는 모두 Vista 이후에 추가된 API 입니다. (XP 이하에서는 존재하지 않는 API 입니다.)

참고로 XP 에서는 kernel32!CreateRemoteThread() 내부에서 바로 ntdll!ZwCreateThread() 를 호출합니다. XP 와 7 에서 kernel32!CreateRemoteThread() API 의 호출 흐름을 아래 그림에 나타내었습니다.


<Fig. 7>

따라서 새로 추가된 이 API 때문에 Session 0 에서 실행되는 서비스 프로세스들에게 DLL Injection 이 실패한다고 볼 수 있겠습니다.

kernelbase!CreateRemoteThreadEx() 는 kernel32!CreateRemoteThread() 의 wrapper 라고 한다면 문제의 원인은 ntdll!ZwCreateThreadEx() 에 있을 것 같습니다. ntdll!ZwCreateThreadEx() 는 undocumented API 이므로 MSDN 에서는 함수 정의를 찾을 수 없고, Google 검색으로 찾아야 합니다.

typedef struct 
{
    ULONG    Length; 
    ULONG    Unknown1; 
    ULONG    Unknown2; 
    PULONG   Unknown3; 
    ULONG    Unknown4; 
    ULONG    Unknown5; 
    ULONG    Unknown6; 
    PULONG   Unknown7; 
    ULONG    Unknown8; 
}UNKNOWN, *PUNKNOWN; 


DWORD ZwCreateThreadEx
    PHANDLE                ThreadHandle,
    ACCESS_MASK            DesiredAccess,
    POBJECT_ATTRIBUTES     ObjectAttributes,
    HANDLE                 ProcessHandle,
    LPTHREAD_START_ROUTINE lpStartAddress,
    LPVOID                 lpParameter,
    BOOL CreateSuspended,
    DWORD                  dwStackSize,
    DWORD                  dw1, 
    DWORD                  dw2, 
    PUNKNOWN               pUnknown 
);

* XP 이하에서는 지원되지 않음

Google 검색을 하던 중에 아래와 같은 글을 발견하였습니다.


글 내용을 요약하면 Vista 이후의 OS 에서 DLL Injection 을 할 때는 CreateRemoteThread() 대신에 ZwCreateThreadEx() 를 직접 호출하면 잘 된다는 것입니다. 제가 테스트 해보니 Session 에 상관없이 성공하였습니다. (관련 소스는 다음편에서 설명합니다.)

이 방법에서 사용된 파라미터와 <Fig. 6> 의 파라미터를 비교하니 바로 7 번째 파라미터인 CreateSuspended 항목에서 차이를 보였습니다. 즉, ZwCreateThreadEx() 를 직접 호출하여 성공한 경우에는 CreateSuspended 파라미터가 FALSE (0) 인데 반해, CreateRemoteThread() API 내부 에서 호출되는 ZwCreateThreadEx() 호출에서는 CreateSuspended 파라미터가 TRUE (1) 입니다.

* XP 이전부터 CreateRemoteThread() API 의 내부 구현 알고리즘은 일단 suspend 모드로 thread 를 생성한 후 resume 시키는 방법을 사용해 왔습니다. (CreateSuspended = 1)



CreateRemoteThread() 성공 시키는 방법 #1


위와 같이 ZwCrateThreadEx() API 의 CreateSuspended 파라미터의 차이점을 이용한다면 Windows 7 의 서비스 프로세스에 CreateRemoteThread() API 호출도 성공 시킬 수 있을 것 같습니다.

다시 디버깅을 새로 시작하여 위의 <Fig. 5> 까지 진행한 후 스택에 저장된 CreateSuspended 파라미터 값을 1 에서 0 으로 변경합니다.


<Fig. 8>

이 상태로 ZwCreateThreadEx() 호출을 StepOver(F8) 로 넘어가면 아래 그림과 같이 dummy.dll 이 인젝션 됩니다.


<Fig. 9>

DbgView 로 보면 아래 그림과 같이 dummy.dll 의 DllMain() 함수에서 찍은 디버깅 로그가 나타납니다.


<Fig. 10>



CreateRemoteThread() 성공 시키는 방법 #2


kernelbase!CreateRemoteThreadEx() 를 좀 더 디버깅 해보면 몇 가지 사실을 더 알 수 있습니다.

<Fig. 5> 에서 ZwCreateThreadEx() 를 그대로(CreateSuspended 수정 안함 = TRUE) StepOver(F8) 하면 아래 그림과 같이 첫 번째 파라미터 pThreadHandle 에 값이 세팅됩니다. 


<Fig. 11>

스레드 핸들이 생성되었다는 말은 스레드가 정상적으로 생성되었다는 얘기입니다. 즉, CreateRemoteThread() 호출에서도 리모트 스레드 "생성"만큼은 성공했다고 볼 수 있습니다.

하지만 이 리모트 스레드가 정상 동작하지 않았던 이유는 이후에 호출될 ntdll!ZwResumeThread() API 가 실패했거나, 아니면 아예 호출되지 못했거나 둘 중의 하나가 될 것입니다. (suspend 모드로 생성하였으니 resume 해줘야 스레드가 정상적으로 실행됩니다.)

디버깅을 더 진행해서 ZwResumeThread() API 호출 부분까지 따라가 보겠습니다. 아래 그림은 kernelbase!CreateRemoteThreadEx() API 코드의 끝 부분입니다.


<Fig. 12>

위 그림을 보시면 758EBD33 주소의 ntdll!CsrClientCallServer() API 가 호출된 이후에 그 아래쪽의 조건 분기 명령어(CMP/JL)에 의해 ZwResumeThread() API 가 호출되지 않고 점프하는 것을 확인할 수 있습니다. 

디버거에서 ntdll!CsrClientCallServer() API 호출 후에 저 조건 분기를 조작해서 ZwResumeThread() 를 호출하도록 해주면 DLL Injection 이 성공합니다.

Intel IA-32 Reference 에 의하면 JL 명령어는 SF != OF 인 경우 점프하도록 되어 있으므로 아래 그림과 같이 S Flag 를 마우스 더블 클릭하여 변경합니다. 


<Fig. 13>

DLL 인젝션이 정상적으로 되었는지 직접 확인해 보시기 바랍니다.


+---+

지금까지 Windows 7 에서 서비스 프로세스에 DLL Injecion 할 때 kernel32!CreateRemoteThread() API 호출이 왜 실패하는지 알아보았습니다. 또한 kernel32!CreateRemoteThread() API 를 디버깅해서 결국 DLL Injection 이 성공하도록 실습해봤습니다. (디버깅을 이용하는 방법이라서 범용적으로 사용하기에는 불편합니다.)

다음 시간에는 Windows 7 (or Vista) 뿐만 아니라 XP 에서도 범용적으로 사용할 수 있는 InjectDll.exe 를 만들어 보도록 하겠습니다.


ReverseCore

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

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

  1. 늅늅 2010/02/22 17:58 댓글주소 | 수정 | 삭제 | 댓글

    앗 1등!!!
    선리플 후 감상 입니다!!!

  2. 비셔스 2010/02/22 20:50 댓글주소 | 수정 | 삭제 | 댓글

    좋은 정보 감사합니다!!

  3. 철이 2010/02/22 20:55 댓글주소 | 수정 | 삭제 | 댓글

    정말로 실력이 부럽습니다..........
    ㅜㅜ 언제쯤 이런 강의를 적을수있을가요 ㅜㅜ

  4. 철이 2010/02/23 04:40 댓글주소 | 수정 | 삭제 | 댓글

    당연히 칭찬이죠 ㅜㅜ 존경 ㅜㅜ

  5. upx 2010/02/23 17:35 댓글주소 | 수정 | 삭제 | 댓글

    저도 강의보고 놀래고있습니다..
    어떻게 저렇게 설명을 저는 죽었다 깨어나면 할라나요.^^

  6. 허훈 2010/03/21 15:39 댓글주소 | 수정 | 삭제 | 댓글

    음,, 저는 일단 2가지 방법을 수행해도 절대 성공하지 않는군요

    과정은 똑같지만 결과가 다르게 나오네요.

    좀더 분석해봐야겠습니다.

    • reversecore 2010/03/22 09:29 댓글주소 | 수정 | 삭제

      허훈님, 안녕하세요.

      위의 설명대로 해도 잘 안되셨나 보네요.

      각 API 의 리턴값과 에러 코드를 확인해서 저에게 알려주시면 저도 좀 확인해 보겠습니다.

      감사합니다.

  7. 너굴히 2010/09/06 15:27 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요 reversecore님^^
    Vista나 Win7의 경우 최근에는 64bit OS를 많이 사용하고 있는데요.
    이 경우 dll injection 시 고려해야 할 점은 뭐가 있을까요?
    좋은 글 감사합니다~

    @저는 어플 개발만 10년 했는데 low level을 공부하면서 다시금 개발에 흥미를 느끼고 있는 프로그래머입니다 :)

  8. 2011/09/11 22:28 댓글주소 | 수정 | 삭제 | 댓글

    비밀댓글입니다

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

      안녕하세요.

      ZwCreateThreadEx() 의 함수 파라미터를 문의하시는 것인가요?


      DWORD ZwCreateThreadEx
      (
      PHANDLE ThreadHandle,
      ACCESS_MASK DesiredAccess,
      POBJECT_ATTRIBUTES ObjectAttributes,
      HANDLE ProcessHandle,
      LPTHREAD_START_ROUTINE lpStartAddress,
      LPVOID lpParameter,
      BOOL CreateSuspended,
      DWORD dwStackSize,
      DWORD dw1,
      DWORD dw2,
      PUNKNOWN pUnknown
      );

      이걸 참고하시기 바랍니다.


      감사합니다.



Windows 7 (& Vista) 에서 DLL Injection 하는 방법에 대한 설명입니다.
새로 변경된 Session 정책에 의하여 기존 CreateRemoteThread() API 를 이용한 DLL Injection 방법이 일부 프로세스들에게 제대로 동작하지 않습니다. 정확한 증상을 알아보고 문제 발생 원인과 해결 방법에 대하여 알아보도록 하겠습니다.

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



DLL Injection


예전에 DLL Injection 에 대해서 연재를 한 적이 있습니다.


또한 API Hooking 연재를 하면서 DLL Injection 기법을 사용하였습니다.


위에서 소개한 DLL Injection 기법은 CreateRemoteThread() API 를 사용하는 방법으로써 Windows XP, 2000 에서는 아주 정확하게 잘 동작합니다.
하지만 Windows 7 (& Vista) 에서 약간 다르게 동작합니다. 정확하게 말하면 기존 CreateRemoteThread() API 를 이용한 방법으로는 7 (& Vista) 의 서비스(Service) 프로세스에 DLL Injection 이 되지 않습니다. 

그 이유는 7 (& Vista) 에서 적용된 Session 관리 정책의 변경 때문입니다. (아래 링크 참고!)

간단한 프로그램을 사용하여 DLL Injection 실패 상황을 재현해 보도록 하겠습니다.



InjectDll.exe & dummy.dll


실습용 파일과 소스 코드입니다.

InjectDll.cpp 소스 코드에서 핵심 함수인 InjectDll() 를 아래에 표시하였습니다.

BOOL InjectDll(DWORD dwPID, char *szDllName)
{
    HANDLE hProcess = NULL;
    HANDLE hThread = NULL;
    LPVOID pRemoteBuf = NULL;
    FARPROC pThreadProc = NULL;
    DWORD dwBufSize = strlen(szDllName)+1;

    if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
    {
        printf("[ERROR] OpenProcess(%d) failed!!! [%d]\n", 
        dwPID, GetLastError());
        return FALSE;
    }

    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, 
                                MEM_COMMIT, PAGE_READWRITE);

    WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName, 
                       dwBufSize, NULL);

    pThreadProc = GetProcAddress(GetModuleHandle(L"kernel32.dll"), 
                                 "LoadLibraryA");

    hThread = CreateRemoteThread(hProcess, NULL, 0, 
                                 (LPTHREAD_START_ROUTINE)pThreadProc, 
                                 pRemoteBuf, 0, NULL);
    if( hThread == NULL )
    {
        printf("[ERROR] CreateRemoteThread() failed!!! [%d]\n", GetLastError());
        return FALSE;
    }

    WaitForSingleObject(hThread, INFINITE);

    VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);

    CloseHandle(hThread);
    CloseHandle(hProcess);

    return TRUE;
}

지금까지 익히 보아오던 DLL Injection 의 전형적인 소스 코드에다가 리턴값 체크를 추가하였습니다.


그리고 아래는 dummy.dll 파일의 소스 코드(dummy.cpp)입니다.

#include "windows.h"
#include "tchar.h"

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    TCHAR   szPath[MAX_PATH]    = {0,};
    TCHAR   szMsg[1024]         = {0,};
    TCHAR   *p                  = NULL;

    switch( fdwReason )
    {
        case DLL_PROCESS_ATTACH : 
            GetModuleFileName(NULL, szPath, MAX_PATH);
            p = _tcsrchr(szPath, L'\\');
            if( p != NULL )
            {
                _stprintf_s(szMsg, 1024 - sizeof(TCHAR), 
                            L"Injected in %s(%d)", 
                            p + 1,                          // Process Name
                            GetCurrentProcessId());         // PID
                OutputDebugString(szMsg);
            }
            
            break;
    }

    return TRUE;
}

DllMain() 함수는 아주 간단합니다. dummy.dll 파일이 프로세스에 정상적으로 인젝션 되었다면 디버그 메시지(프로세스 이름, 프로세스 ID)를 출력하는 것입니다.



테스트


Process Explorer 를 실행시킨 후 Session 0 의 svchost.exe (PID : 3148) 프로세스와 Session 1 의notepad.exe(PID : 2172) 프로세스에 각각 dummy.dll 파일을 인젝션 시켜보도록 하겠습니다.

 
<Fig. 1>

위에서 첨부한 InjectDll.exe 와 dummy.dll 파일을 적당한 폴더에 다운받은 후 아래 그림과 같이 실행합니다. 

 
<Fig. 2>

Session 1 의 notepad.exe (2172) 프로세스에는 정상적으로 인젝션 되었지만, Session 0 의 svchost.exe (3148) 프로세스에는 인젝션이 실패(error code = 8)하였습니다. 

Process Explorer 에서 dummy.dll 모듈을 검사해봅니다.


<Fig. 3>

위 그림에서 보시는 것처럼 Session 1 의 notepad.exe (2172) 프로세스에게만 정상적으로 dummy.dll 파일이 인젝션 되었습니다.



디버깅


<Fig. 2> 에서 Session 0 의 svchost.exe (3148) 프로세스에 인젝션 할 때 CreateRemoteThread() API 함수 호출에서 실패하였고, 그 때의 에러 코드는 8 입니다.

OllyDbg 를 이용해서 InjectDll.exe 파일을 디버깅 해보겠습니다.
InjectDll.exe 파일을 파라미터("3148 c:\work\dummy.dll")를 입력해서 Open 합니다.


<Fig. 4>

CreateRemoteThread() API 호출 시에 에러가 발생하는 것을 알았으니, Search for \ All intermodular calls 메뉴를 이용해서 해당 API 호출 코드에 바로 BP 를 설치합니다.


<Fig. 5>

* 참고!
Windows 7 에서 InjectDll.exe 프로세스의 Base Address 는 랜덤하게 변경됩니다.

디버거를 Run 시키면 <Fig. 5> 의 BP 에 멈추게 됩니다.


<Fig. 6>

여기서 그대로 F8 (StepOver) 로 진행하면 아래 그림과 같이 LastErr = ERROR_NOT_ENOUGH_MEMORY (8) 가 찍힙니다.


<Fig. 7>

에러 메시지도 낯설고 아직은 뭐가 문제인지 잘 모르겠군요.

다음에 이어지는 글에서 InjectDll.exe 의 CreateRemoteThread() 를 좀 더 디버깅 해보겠습니다.



ReverseCore

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

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

  1. eew 2010/02/20 03:12 댓글주소 | 수정 | 삭제 | 댓글

    기대기대

  2. 철이 2010/02/20 05:20 댓글주소 | 수정 | 삭제 | 댓글

    정말로 많이 배웁니다. 빨리 연재 해주세요..;

  3. 늅늅 2010/02/20 23:11 댓글주소 | 수정 | 삭제 | 댓글

    dll injection 관련해서 새로운 글이 올라왔군요~!
    자주 컴터를 할 수 없어서 감이 팍팍 떨어지는데, 오랫만에 다시 코딩을 해봐야겠네요

    좋은 자료 잘 보고 갑니다 :)

  4. 퉁퉁 2011/10/13 09:29 댓글주소 | 수정 | 삭제 | 댓글

    이번 과제로 dll injection이 나왔는데 너무 어렵네요..ㅠㅠ

    어떤 실행파일을 실행하면 20초후에 어떤 주소값이 나오는데 그 주소에는 멀티쓰레드를 이용하여 만들어진 어떤 문자열이 저장되어있대요..

    저장된 문자열을 탈취하여 확인하기위해 실행중인 다른 process에 thread를 생성하여 dll을 injection 하는 공격으로 문자열을 확인하는 건데..

    위에 설명을 참고해서 짜면되겠..........ㅈ..요..? ㅠㅠㅠㅠㅠㅠㅠ

  5. eee 2011/10/30 03:08 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요^^ 이쪽에는 초보입니다.

    64bit win7 에서 64bit 로 컴파일햇는데 에러 코드 1300 이 나와요 ㅠㅠ

    도와주세요!


Session in Windows 7

study 2010/02/14 14:36

Windows Vista & 7 에서 변경된 Session 관리 정책에 대해서 알아보겠습니다.


Windows 응용 프로그램 개발자라면 (XP 에서 잘 실행되는) 서비스 프로그램이 Vista 혹은 7 에서 정상적으로 동작하지 않는 경험을 해보셨을 것입니다. 이는 주로 사용자와 interactive 하게 동작하는 서비스 프로그램에 해당됩니다. 즉, 사용자 다이알로그를 출력하거나, 사용자 프로그램과 서비스 프로그램간의 메시지 통신 등을 시도할 때 예전(XP) 처럼 잘 되지 않는 것입니다.

그 이유는 7 (혹은 Vista) 에서 적용된 Session 관리 정책이 변되었기 때문입니다.

Windows 7 에서의 Session 관리 정책 변경은 개발 관점에서도 중요한 일이지만, 리버싱 관점에서도 매우 중요한 사건입니다. 왜냐하면 기존부터 널리 사용되던 CreateRemoteThread() API 를 이용한 DLL Injection 방법이 Windows 7 의 서비스 프로세스들에게는 더 이상 먹히지 않기 때문입니다. (일반 프로세스에게는 아직도 잘 됩니다.)



Session


Session 이란 간단히 말해서 로그온 사용자 환경을 의미합니다. 

대부분의 OS 는 동시에 여러 사용자의 로그온을 허가하고 각 로그온에 대해서 독립된 사용자 환경을 제공합니다. Windows 운영체제를 예로 들면 "사용자 전환" 기능으로 로컬 사용자 Session을 생성할 수 있으며, "원격 데스크톱 연결" 기능으로 리모트 사용자 Session을 생성할 수 있습니다.

Process Explorer 의 View 메뉴에서 Session 항목을 선택하면 현재 실행되고 있는 프로세스들이 각각 어떤 Session에 속해있는지 표시해 줍니다.

 
<Fig. 1>

현재 Session을 확인하기 위해서 “사용자 전환” 기능을 이용하여 2 명의 사용자를 로그온 시켰습니다. 로그온 순서대로 Session ID(0, 1, 2, …)가 부여됩니다. 

아래 그림은 Windows 7 에서 실행중인 프로세스와 Session을 나타냅니다.

 
<Fig. 2>

이번에는 Windows XP 에서 실행중인 프로세스와 Session을 살펴보겠습니다.

 
<Fig. 3>

* 참고
사용자 로그온을 하면 기본적으로 해당 섹션을 위한 csrss.exe, winlogon.exe, explorer.exe 프로세스가 생성됩니다. 

Windows 7 (<Fig. 2>) 과 Windows XP (<Fig. 3>) 사이에는 하나의 큰 차이점이 있습니다. 둘 다 똑같이 두 명의 사용자가 로그인 하였으나 7 에서는 Session이 총 3 개(0, 1, 2) 인 반면에, XP 에서는 Session이 2 개(0, 1) 입니다.

XP 와 7 에서 시스템 프로세스들과 서비스 프로세스들은 Session ID 0 (시스템 Session) 에서 실행됩니다. 둘 간의 차이점은 바로 첫 번째 로그온 사용자의 Session ID 입니다. XP 는 첫 번째 로그온 사용자의 Session ID 가 0 으로 시스템 Session과 같고, 7 은 첫 번째 로그온 사용자의 Session ID 가 1 로 할당 되어 시스템 Session과 다릅니다.

이 작은 차이로 인해 XP 에서 잘 동작하던 기술들이 7 (Vista 포함) 에서는 비정상적으로 실행되게 됩니다. 



Session 0 Isolation


Windows 커널 버전 6 이후 부터는 보안 강화를 위하여 첫 번째 로그온 사용자 세션을 1 로 주어서 시스템 세션 0 과 구별되도록 하였습니다.

* Windows 커널 버전에 대한 설명은 아래 링크를 참고하세요.


이렇게 시스템 세션과 사용자 세션을 분리시켜 서로에 대한 상호작용을 없애는 정책으로 인해서 비록 부분적으로 하위 호환 문제가 발생하였지만, 그 대신 시스템 보안이 강화되었습니다. 

이러한 정책을 MS 에서는 "Session 0 Isolation" 이라고 부르며, 제가 따로 설명할 필요 없이 아래 Windows Team Blog 링크에 이와 관련된 설명이 아주 자세히 나와 있습니다.


개발/리버싱 관점에서 보면 Windows 7 은 여러모로 향상된 기능이 많습니다.



보안 강화


위와 같은 "Session 0 Isolation" 과 지난번에 소개해 드린 "ASLR" 기술 등은 모두 보안 강화를 위해 추가된 기능들인데요, 의도는 좋았지만 실제적인 보안 강화 측면에는 의문이 남습니다.

Session 0 프로세스들이 완전히 분리된 것은 아니기 때문에 Session 1 의 프로세스(예:Process Explorer)에서 Session 0 의 프로세스들을 종료시킬 수 있으며, ReadProcessMemory(), WriteProcessMemory(), VirtualAllocEx() 등의 디버깅 API 들도 정상적으로 동작합니다. (ASLR 기술의 회피 방법도 쉽지요.)

MS 에서 새로운 기술이 추가되고는 있지만 어디까지나 임시 방편에 지나지 않는다고 생각합니다. 당장은 예전에 사용되던 기초적인 해킹 공격들은 막을 수 있겠지만 곧 그에 대응하는 리버싱 기술도 같이 발전하고 있기 때문에 더 새로운 고차원적인 공격 기법들이 나타날 것입니다. 그야말로 창과 방패의 끝없는 싸움이지요.

이런 경우에 방패(MS)쪽이 절대적으로 불리합니다. 왜냐하면 고려해야 할 사항이 너무 많기 때문입니다. 각종 다양한 종류의 응용 프로그램들이 잘 실행되도록 지원해줘야 하구요, 고객의 편의를 위해서 하위 호환을 신경써야 합니다. 또한 수많은 하드웨어들에 대한 지원은 또 어떻구요. 

결정적으로 너무나 많은 PC 에서 사용된다는 것이 문제입니다. 사용자가 너무 많기 때문에 공격하는 창(해커)쪽에서는 MS Windows 의 특수 환경(예:MS XP SP3 IE8 사용자) 하나만 노려도 됩니다. 전쟁에 비유를 하자면 전선이 너무 길다고 할까요. 공격자 입장에서는 공격할 곳이 너무 많아서 유리한 반면에 수비자 입장에서는 막을 곳이 너무나 많아지는 것이지요.
 
Linux, Mac 등에 악성코드가 없는 이유는 사용자가 상대적으로 적기 때문이지 결코 그 운영체제들의 보안성이 월등해서가 아니랍니다.


다음 시간에는 Session 0 Isolation 기술이 적용된 Windows 7 의 서비스 프로세스(Session 0)에게 DLL Injection 을 시키는 방법에 대해서 자세히 알아보겠습니다. 


ReverseCore

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

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

  1. B8L 2010/02/14 21:57 댓글주소 | 수정 | 삭제 | 댓글

    잘보고 가요. 다음 포스팅도 너무 기대됩니다. ^^
    새해복 많이 받으세요!

  2. 세의 2010/02/15 19:32 댓글주소 | 수정 | 삭제 | 댓글

    매번 훌륭한 글 잘 읽고 갑니다! 새해엔 즐거운 일만 가득하시길 ^^

  3. 비셔스 2010/02/16 13:54 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요~
    설날은 잘 보내셧겠죠? 새해 복 많이 받으세요~
    항상 좋은 글 올려주셔서 감사해요^^

  4. Sun2Day 2010/02/16 16:55 댓글주소 | 수정 | 삭제 | 댓글

    항상 재미있는 이야기 해주셔서 감사합니다 +_+;;

    시스템에서 부여해주는 session이라.. 다음 글이 더욱 기대가 됩니다. +_+

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

    오랜만에 오네요 ^^;;
    공부가 안될때 문서를 읽는 재미에 빠졌습니다.
    항상 좋은 내용 감사드립니다~
    올 한해 복 많이 받으세요 ~!

  6. 철이 2010/02/19 00:43 댓글주소 | 수정 | 삭제 | 댓글

    좋은글 감사합니다. ^^:

  7. 퓨틱 2010/02/25 21:13 댓글주소 | 수정 | 삭제 | 댓글

    잘 보고갑니다~
    세상은 넓고 고수는많네요 역시 -_-ㅋㅋㅋㅋ