
NtSetInformationThread는 ntdll.dll에 존재하는 API다.

이전과 같은 방법으로 OllyDbg를 이용해 ntdll.dll에 익스포트 된 API를 찾아보려고 한 결과 Unknown identifier라고 뜨는 것을 볼 수 있었다.
이는 Windows Native API는 보통 ntdll.dll에 존재하지만 직접 익스포트 되지 않는 경우가 있다고 한다.
그리하여 ida를 통해 찾아 보았다.

ida에서 ntdll.dll파일을 열고,
ctrl+l입력시 함수 명들을 확인 가능합니다. 여기서 NtSetInformationThread를 찾아서 더블 클릭하면 함수동작 부분을 볼 수 있다.

동작을 간단히 설명하면 NtSetInformationThread의 syscall 번호인 0Dh를 eax에 저장하고 그 다음 window 32비트 환경인지 확인하여 32비트 환경이면 분기하며 아닌 경우 syscall을 수행한다.
32비트 환경에서 분기하면

해당 위치로 분기하고 int 2Eh를 통해 시스템 호출을 하게 된다.
이는 32비트, 64비트 각 시스템 호출 방식이 다르기 때문이다.
사용 방법에 대해서 살펴보면

MS공식 문서이며, 첫 번째 인자는 쓰레드 개체 핸들이고
두 번째 인자는

THREADINFOCLASS 열거형 이다.

공식 문서에는 위의 사진처럼 나와 있는데 실제로는
typedef enum _THREAD_INFORMATION_CLASS {
ThreadBasicInformation,
ThreadTimes,
ThreadPriority,
ThreadBasePriority,
ThreadAffinityMask,
ThreadImpersonationToken,
ThreadDescriptorTableEntry,
ThreadEnableAlignmentFaultFixup,
ThreadEventPair,
ThreadQuerySetWin32StartAddress,
ThreadZeroTlsCell,
ThreadPerformanceCount,
ThreadAmILastThread,
ThreadIdealProcessor,
ThreadPriorityBoost,
ThreadSetTlsArrayAddress,
ThreadIsIoPending,
ThreadHideFromDebugger //0x11
} THREAD_INFORMATION_CLASS, *PTHREAD_INFORMATION_CLASS;
이렇게 존재한다.
그 이유는 Windows Native API를 공개할 때, 보안 관련 값이나 커널 내부 API 일부를 문서화하지 않기 때문이라고 한다.
0x11(17)번째 값은 ThreadHideFromDebugger이고 말 그대로 Thread를 Debugger로 부터 숨기는 기능이다.
API 사용 방법의 예시는
NtSetInformationThread(GetCurrentThread(), 0x11, 0, 0);
GetCurrentThread()는 현재 모든 쓰레드를 구하는 함수이며, 두 번째 인자로 0x11을 넣게 되면 현재 모든 쓰레드를 디버거로 부터 숨기는 동작을 하게 된다.
해당 API는 VMProtect의 Debugger Detection 옵션을 사용하면 동작하는 API이다.
감사합니다.