Windows Internals 책을 한 번 보면 많은 궁금증이 풀릴 겁니다.
http://www.yes24.com/24/goods/4009506?scode=032&OzSrank=1
인터넷에서 PDF 파일도 구할 수 있지만 워낙 두꺼우니 한글판을 사는게.. 쿨럭..
비스타 위주로 설명되어 있지만 윈도7도 거의 동일하기때문에 문제는 없습니다.
pro 님이 쓰신 글 :
: 안녕하세요 빌더님 답변 감사합니당 ^^
:
: 제가 XP만 쓰다가 Win7 프로그래밍 해보기 시작한지 얼마 안되서
: 모르는게 많습니다. 몇가지 더 여쭈어 볼게요
:
: 쉘인 Explorer는 리모트 스레드가 성공하는데 서비스는 안되는 이유가
: 아직 이해가 안됩니다. 세션 개념도 그렇구요.
:
: CreateRemoteThread API 자체를 Tampoline 방식으로 패치하는 방법을
: 알려주셨는데 임포트 테이블 조작이 아니고 함수코드를 직접 조작하는 거라면
: 윈도에서 실행 속성을 갖는 코드는 변경을 금지하고 있는거로 알고 있는데요
: 어떻게 가능하다는 건지 모르겠습니다.
:
:
:
: 빌더(TWx) 님이 쓰신 글 :
: : pro 님이 쓰신 글 :
: : : 그지같은 C++ 빌더가 64비트를 지원하지 않아서
: : : 비쥬얼 스튜디오 64비트 C++ 컴파일러를 이용해서
: : : 쉘인 Explorer.exe를 후킹 하는데 성공했습니다 ^^
: : :
: : : 이번엔 서비스를 인젝션해서 후킹하려고 하는데요
: : : 서비스를 OpenProcess로 오픈하면 프로세스가 정상적으로 오픈됨에도 불구하고
: : : 리모트 스레드 생성에서 실패하네요.
: : :
: : : XP에선 되는데 Win 7 64비트에선 왜 안되는 건가요.
: : :
: : : 컴파일도 비쥬얼 스튜디오 64비트 C++ 컴파일러로 했거든요.
: :
: :
: :
: :
: : 답변:
: :
: : Protected Mode Context로 실행되고 있는 프로세스(서비스)에 리모트 쓰레드를 생성하기 위해선 Token Access Right 등
: :
: : 충분한 권한이 확보 되어있는 상태라야 하는데, OpenProcess로 프로세스 핸들을 여는데 까진 성공했다는 것은
: :
: : 권한과 관련한 사전작업 들은 이미 처리하고 있는 것으로 보여지네요.
: :
: :
: : 리모트 쓰레드 생성에 실패하는 이유는... 비스타 이후 부터 바뀐 OS 구조 때문 입니다.
: :
: : 비스타 이후 부터 프로세스 들은 Session과 연계 되어 처리되게 되는데... 타겟 대상인 서비스와 Injector 프로세스의 Session이
: :
: : 다르기 때문에 리모트 쓰레드 생성에 실패하고 있을 겁니다.
: :
: :
: : 문제를 해결하기 위한 방법을 찾아 보자면... 대략 세가지 정도 생각해 볼 수 있을텐데...
: :
: :
: : 첫번째 방법...
: :
: : 더미로 서비스를 하나 만들어 주어서, 이 서비스가 Injector 프로세스를 실행하도록 해주는 겁니다.
: :
: : 이 경우 Injector 프로세스가 서비스의 세션으로 실행되기 때문에 리모트 쓰레드 생성이 가능해 집니다.
: :
: : Injector 프로세스가 실행되면 역할을 다한 서비스는 제거해 주면 되고요.
: :
: : 서비스 형태로 실행되어야 해서 관리자 권한이 필요해 지게 됩니다.
: :
: :
: : 두번째 방법...
: :
: : CreateRemoteThread API 자체를 Tampoline 방식으로 패치해서 Session Validation 처리를 하지 않도록 해주는 방법 입니다.
: :
: : API를 디스어셈블링해서 코드를 패치해줘야 하니까 번거롭겠죠.
: :
: :
: : 세번째 방법...
: :
: : 'NtCreateThreadEx'라는 Undocumented API를 직접 이용하는 방법입니다.
: :
: : CreateRemoteThread API가 Session Validataion Check에 성공하면 'NtCreateThreadEx'라는 Undocumented API를
: :
: : 내부적으로 호출하게 되어 있으니까... 이 시스템 API를 직접 이용해서 리모트 쓰레드를 생성해 주는 겁니다.
: :
: : Undocumented API인 'NtCreateThreadEx'는 'NTDLL.DLL'에서 Export 하고 있고, API의 프로토타입은 다음과 같습니다.
: :
: : 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
: : );
: :
: : API를 사용하기 위해선 아래와 같은 식으로 펑션의 주소를 얻어서 사용하면 됩니다.
: :
: : HMODULE hNtDLL = LoadLibraryA("NTDLL.DLL");
: : PFNTCREATETHREADEX pFunc = NULL;
: :
: : pFunc = (PFNTCREATETHREADEX)GetProcAddress(hNtDLL, "NtCreateThreadEx");
: :
: : pFunc( &hRemoteThread,
: : 0x1FFFFF,
: : NULL,
: : hTargetProc,
: : reinterpret_cast< LPTHREAD_START_ROUTINE >( pRemoteFunc ),
: : pRemoteArgs,
: : FALSE,
: : 0,
: : 0,
: : 0,
: : NULL);
: :
: :
: : ...