Microsoft MVP성태의 닷넷 이야기
VC++: 64. x64 Visual C++에서 TEB 주소 구하는 방법 [링크 복사], [링크+제목 복사],
조회: 21407
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)
(시리즈 글이 5개 있습니다.)
VC++: 64. x64 Visual C++에서 TEB 주소 구하는 방법
; https://www.sysnet.pe.kr/2/0/1387

.NET Framework: 348. .NET x64 응용 프로그램에서 Teb 주소를 구하는 방법
; https://www.sysnet.pe.kr/2/0/1388

.NET Framework: 349. .NET Thread 인스턴스로부터 COM Apartment 유형 확인하는 방법
; https://www.sysnet.pe.kr/2/0/1389

VC++: 91. 자식 스레드에 자동 상속되는 TEB의 SubProcessTag 필드
; https://www.sysnet.pe.kr/2/0/10797

디버깅 기술: 150. windbg - Wow64, x86, x64에서의 커널 구조체(예: TEB) 구조체 확인
; https://www.sysnet.pe.kr/2/0/12097




x64 Visual C++에서 TEB 주소 구하는 방법

다들 아시는 것처럼, x64용의 Visual C++ 컴파일러에서는 인라인 어셈블리가 지원되지 않습니다. 게다가 NtCurrentTeb API도 x64에서는 ntdll.dll 파일에서 export 되어 있지 않습니다.

System32 폴더의 64비트 DLL을 32비트 Depends.exe에서 보는 방법
; https://www.sysnet.pe.kr/2/0/1384

하지만, 네이티브 언어인 C++에서 못할 것이 어디 있겠습니까? ^^

우선, x64에서는 TEB가 FS 레지스터가 아닌 GS 레지스터 쪽으로 바뀌었다는 사실을 알아야 합니다.

Thread Local Storage, part 1: Overview
; http://www.nynaeve.net/?p=180

위의 글에서 보면, x86에서는 fs, x64에서는 gs 레지스터라고 언급되어 있습니다.

The “per-thread” resolution of the TEB is fairly well documented, but for the benefit of those that are unaware, the general idea is that one of the segment registers (fs on x86, gs on x64) is repurposed by the OS to point to the base address of the TEB for the current thread. This allows, say, an access to fs:[0x0] (or gs:[0x0] on x64) to always access the TEB allocated for the current thread, regardless of other threads in the address space.


옵셋은 어떻게 바뀌었을까요?

Mixing x86 with x64 code
; http://blog.rewolf.pl/blog/?p=102#.UMg6zi2wc5c

위의 글에 보면 gs:[0x30]으로 바뀐 것을 알 수 있습니다.

마지막으로, 그럼 어떻게 해야 gs:[0x30] 값을 인라인 어셈블리(asm 키워드) 없이 가져올 수 있을지 알아내야 합니다. 비록 asm 키워드는 없어졌지만, Visual C++에서는 자주 쓰는 어셈블리 코드에 대해 x64 Intrinsics 함수군을 제공합니다.

x64 Intrinsics
; https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/azcs88h2(v=vs.100)

위의 목록에서 GS 레지스터 관련해서 __readgsqword 함수가 제공되는 것을 볼 수 있는데요. 따라서, TEB를 구하는 x86 코드를 x64에서는 다음과 같이 변경할 수 있습니다.

#include "stdafx.h"
#include <intrin.h>

int _tmain(int argc, _TCHAR* argv[])
{
	//int *pTib = NULL;

	//_asm {
	//	mov eax, fs:[18h]
	//	mov pTib, eax
	//}

	unsigned __int64 fsReg = 0;

	fsReg = __readgsqword(0x30);
	printf("%I64x\n", fsReg);

	//::__debugbreak();
	
	return 0;
}

그런데, 정말 0x30 값을 __readgsqword 함수에 넘겨서 반환받은 값이 TEB가 맞을까요? 이를 확인하려면 windbg의 도움을 받아야 합니다.

teb_x64_1.png

보시는 것처럼, __readgsqword로 구해온 값과 windbg의 !teb 명령어 결괏값이 같군요. ^^




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 3/14/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 31  32  33  [34]  35  36  37  38  39  40  41  42  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
12816정성태8/30/202116094스크립트: 24. 파이썬 - tensorflow 2.6 NVidia GPU 사용 방법 [2]
12815정성태8/30/20219129개발 환경 구성: 602. WSL 2 - docker-desktop-data, docker-desktop (%LOCALAPPDATA%\Docker\wsl\data\ext4.vhdx) 파일을 다른 디렉터리로 옮기는 방법
12814정성태8/30/202111706.NET Framework: 1110. C# 11 - 인터페이스 내에 정적 추상 메서드 정의 가능 (DIM for Static Members) [2]파일 다운로드1
12813정성태8/29/20219654.NET Framework: 1109. C# 10 - (11) Lambda 개선파일 다운로드1
12812정성태8/28/20219400.NET Framework: 1108. C# 10 - (10) 개선된 #line 지시자
12811정성태8/27/20219529Linux: 44. 윈도우 개발자를 위한 리눅스 fork 동작 방식 설명 (파이썬 코드)
12810정성태8/27/20218274.NET Framework: 1107. .NET Core/5+에서 동적 컴파일한 C# 코드를 (Breakpoint도 활용하며) 디버깅하는 방법 - #line 지시자파일 다운로드1
12809정성태8/26/20218968.NET Framework: 1106. .NET Core/5+에서 C# 코드를 동적으로 컴파일/사용하는 방법 [1]파일 다운로드1
12808정성태8/25/202110194오류 유형: 758. go: ...: missing go.sum entry; to add it: go mod download ...
12807정성태8/25/202110252.NET Framework: 1105. C# 10 - (9) 비동기 메서드가 사용할 AsyncMethodBuilder 선택 가능파일 다운로드1
12806정성태8/24/20217799개발 환경 구성: 601. PyCharm - 다중 프로세스 디버깅 방법
12805정성태8/24/20219099.NET Framework: 1104. C# 10 - (8) 분해 구문에서 기존 변수의 재사용 가능파일 다운로드1
12804정성태8/24/20219717.NET Framework: 1103. C# 10 - (7) Source Generator V2 APIs
12803정성태8/23/20219535개발 환경 구성: 600. pip cache 디렉터리 옮기는 방법
12802정성태8/23/20219794.NET Framework: 1102. .NET Conf Mini 21.08 - WinUI 3 따라해 보기 [1]
12801정성태8/23/20219234.NET Framework: 1101. C# 10 - (6) record class 타입의 ToString 메서드를 sealed 처리 허용파일 다운로드1
12800정성태8/22/20219457개발 환경 구성: 599. PyCharm - (반대로) 원격 프로세스가 PyCharm에 디버그 연결하는 방법
12799정성태8/22/20219590.NET Framework: 1100. C# 10 - (5) 속성 패턴의 개선파일 다운로드1
12798정성태8/21/202110998개발 환경 구성: 598. PyCharm - 원격 프로세스를 디버그하는 방법
12797정성태8/21/20218641Windows: 197. TCP의 MSS(Maximum Segment Size) 크기는 고정된 것일까요?
12796정성태8/21/20219220.NET Framework: 1099. C# 10 - (4) 상수 문자열에 포맷 식 사용 가능파일 다운로드1
12795정성태8/20/20219894.NET Framework: 1098. .NET 6에 포함된 신규 BCL API - 스레드 관련
12794정성태8/20/20219327스크립트: 23. 파이썬 - WSGI를 만족하는 최소한의 구현 코드 및 PyCharm에서의 디버깅 방법 [1]
12793정성태8/20/202110121.NET Framework: 1097. C# 10 - (3) 개선된 변수 초기화 판정파일 다운로드1
12792정성태8/19/202110552.NET Framework: 1096. C# 10 - (2) 전역 네임스페이스 선언파일 다운로드1
12791정성태8/19/20218724.NET Framework: 1095. C# COM 개체를 C++에서 사용하는 예제 [3]파일 다운로드1
... 31  32  33  [34]  35  36  37  38  39  40  41  42  43  44  45  ...