성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Reordering on an Alpha processor ;...
[정성태] 공유 감사합니다. ^^ 참고로, WPF에서 WindowsF...
[Tom Lee] 답변 감사합니다. 나름의 해결책 연구해보고 여기에도 공유해봅니다...
[정성태] 아래의 글을 보면, MoveWindow 하면 될 듯한데요. ^^...
[Tom Lee] 안녕하세요 올려주신 글 참고하여 WPF 어플리케이션 안에 Uni...
[정성태] A graphical depiction of the steps ...
[정성태] 질문을 주셔서 출판사 측에 문의를 했습니다. 약 한 달 정도 후...
[Thorondor
] @정성태 개인 블로그인데도 거의 커뮤니티 급 인 것 같아요. 요...
[정성태] Roll A Lisp In C - Reading ; https...
[정성태] Java - How to use the Foreign Funct...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>자식 스레드에 자동 상속되는 TEB의 SubProcessTag 필드</h1> <p> "Windows Internals" 책을 보다가,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Windows Internals 제6판 Vol. 1: 마이크로소프트 윈도우 커널 공식 가이드 6판 ; <a target='tab' href='http://www.yes24.com/24/goods/7877539'>http://www.yes24.com/24/goods/7877539</a> </pre> <br /> 469페이지에 실린 "서비스 태그"라는 내용에서 SubProcessTag 필드의 존재를 처음 알게 되었습니다.<br /> <br /> 내용인 즉, 마이크로소프트 측에서 Vista부터 제공하고 있던 기능인데 이 필드의 내용은 하위 스레드에 자동으로 전달된다는 것입니다. 오호~~~ 재미있는 기능이군요. ^^<br /> <br /> 일단, windbg로 x64의 windows 8.1에서 _TEB 구조체를 살펴보면 다음과 같이 0x1720 옵셋에 위치한 것을 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0: kd> dt _TEB nt!_TEB +0x000 NtTib : _NT_TIB +0x038 EnvironmentPointer : Ptr64 Void ...[생략]... +0x1720 SubProcessTag : Ptr64 Void +0x1818 ReservedForWdf : Ptr64 Void </pre> <br /> 실제로 이 값을 확인하려면 다음과 같은 식의 코드를 작성하면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=929&boardid=331301885'>첨부 파일에 Visual Studio 프로젝트로 포함됨</a> #include "stdafx.h" #include <winternl.h> #include <intrin.h> void showSbt() { #if defined WIN32 #define OFFSET_SUBPROCESSTAG 0x0f60 #elif defined _WIN64 #define OFFSET_SUBPROCESSTAG 0x1720 #else #endif // _WIN32 unsigned long subProcessTag = 0; HANDLE hProcess = GetCurrentProcess(); #if defined(_WIN64) // x64 auto pTeb = reinterpret_cast<PTEB>(__readgsqword(reinterpret_cast<DWORD>(&static_cast<NT_TIB*>(nullptr)->Self))); #elif defined(WIN32) // x86 auto pTeb = reinterpret_cast<PTEB>(__readfsdword(reinterpret_cast<DWORD>(&static_cast<NT_TIB*>(nullptr)->Self))); #endif BOOL result = <span style='color: blue; font-weight: bold'>ReadProcessMemory</span>(hProcess, reinterpret_cast<void *>(reinterpret_cast<ULONG_PTR><span style='color: blue; font-weight: bold'>(pTeb)+OFFSET_SUBPROCESSTAG</span>) , reinterpret_cast<void *>(&subProcessTag) , sizeof(subProcessTag), nullptr); if (result == TRUE) { printf("[TID: %d] %d (0x%x)\n", GetCurrentThreadId(), subProcessTag, subProcessTag); // 출력결과: [TID: 10216] 0 (0x0) } CloseHandle(hProcess); } int _tmain(int argc, _TCHAR* argv[]) { showSbt(); return 0; } </pre> <br /> 기본값은 0입니다. 그렇다면 정말 스레드 간에 자동 상속되는지 확인을 해볼까요? ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > #include "stdafx.h" #include <winternl.h> #include <intrin.h> void showSbt(<span style='color: blue; font-weight: bold'>bool setSbt, DWORD newId</span>) { #if defined WIN32 #define OFFSET_SUBPROCESSTAG 0x0f60 #elif defined _WIN64 #define OFFSET_SUBPROCESSTAG 0x1720 #else #endif // _WIN32 unsigned long subProcessTag = 0; HANDLE hProcess = GetCurrentProcess(); #if defined(_WIN64) // x64 auto pTeb = reinterpret_cast<PTEB>(__readgsqword(reinterpret_cast<DWORD>(&static_cast<NT_TIB*>(nullptr)->Self))); #elif defined(WIN32) // x86 auto pTeb = reinterpret_cast<PTEB>(__readfsdword(reinterpret_cast<DWORD>(&static_cast<NT_TIB*>(nullptr)->Self))); #endif DWORD written = 0; if (setSbt == true) { subProcessTag = newId; <span style='color: blue; font-weight: bold'>WriteProcessMemory</span>(hProcess, reinterpret_cast<void *>(reinterpret_cast<ULONG_PTR>(pTeb)+OFFSET_SUBPROCESSTAG) , reinterpret_cast<void *>(&subProcessTag) , sizeof(subProcessTag), &written); } subProcessTag = 0; BOOL result = ReadProcessMemory(hProcess, reinterpret_cast<void *>(reinterpret_cast<ULONG_PTR>(pTeb)+OFFSET_SUBPROCESSTAG) , reinterpret_cast<void *>(&subProcessTag) , sizeof(subProcessTag), nullptr); if (result == TRUE) { printf("[TID: %d] %d (0x%x)\n", GetCurrentThreadId(), subProcessTag, subProcessTag); } CloseHandle(hProcess); } DWORD WINAPI <span style='color: blue; font-weight: bold'>newThreadProc2</span>(PVOID pVoid) { <span style='color: blue; font-weight: bold'>showSbt(false, 0);</span> return 0; } DWORD WINAPI <span style='color: blue; font-weight: bold'>newThreadProc</span>(PVOID pVoid) { <span style='color: blue; font-weight: bold'>showSbt(false, 0);</span> HANDLE newThread = ::<span style='color: blue; font-weight: bold'>CreateThread</span>(nullptr, 0, <span style='color: blue; font-weight: bold'>newThreadProc2</span>, nullptr, 0, nullptr); ::WaitForSingleObject(newThread, INFINITE); ::CloseHandle(newThread); return 0; } int _tmain(int argc, _TCHAR* argv[]) { <span style='color: blue; font-weight: bold'>showSbt(false, 0x100);</span> HANDLE newThread = ::<span style='color: blue; font-weight: bold'>CreateThread</span>(nullptr, 0, <span style='color: blue; font-weight: bold'>newThreadProc</span>, nullptr, 0, nullptr); ::WaitForSingleObject(newThread, INFINITE); ::CloseHandle(newThread); return 0; } </pre> <br /> 주 스레드가 newThreadProc를 가진 2차 스레드를 생성하고, 다시 newThreadProc 내부에서는 newThreadProc2를 가진 3차 스레드를 생성했는데, 결과는 예상한 대로 상속된 것으로 나옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [TID: 12536] 256 (0x100) [TID: 13384] 256 (0x100) [TID: 14884] 256 (0x100) </pre> <br /> 이 기능의 아쉬운 점이 있다면? 스레드 풀에는 적용되지 않는다고 합니다. 즉, 현재 스레드에서 스레드 풀의 스레드에 작업을 던진 경우, 그 동작 간에는 SubProcessTag 값의 전달이 없습니다. 아마도, 스레드 생성 시에 부모 스레드의 SubProcessTag값을 전달하는 식으로 구현된 것이 아닌가 생각됩니다. 그렇기 때문에 이미 생성된 스레드 풀의 스레드에는 영향을 미치지 못하는 것이고!<br /> <br /> <hr style='width: 50%' /><br /> <br /> 이 기능을, 마이크로소프트 측에서는 다중 서비스를 호스팅하는 프로세스 내의 스레드에 적용한다고 합니다. 이에 대해서는 다음의 글을 참고하세요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ScTagQuery: Mapping Service Hosting Threads With Their Owner Service ; <a target='tab' href='http://www.alex-ionescu.com/?p=52'>http://www.alex-ionescu.com/?p=52</a> </pre> <br /> 제가 구현한 예제 코드에서는 단순히 DWORD 값을 넣었지만, 마이크로소프트가 설정한 정보의 구조는 좀 다릅니다. 문서화되지 않은(undocumented) 기능이지만, 다음과 같이 잘 공개(?)되어 있습니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > HOWTO: Use I_QueryTagInformation ; <a target='tab' href='http://wj32.org/wp/2010/03/30/howto-use-i_querytaginformation/'>http://wj32.org/wp/2010/03/30/howto-use-i_querytaginformation/</a> </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1288
(왼쪽의 숫자를 입력해야 합니다.)