最近我一直在搞乱Windows,我在ntdll.dll
中遇到了这个功能。
我尝试过搜索,但似乎根本没有文档
。有人可以提示我查询了哪种环境变量吗?
答案 0 :(得分:2)
看到我最有可能得到一些奇怪的东西(或者更确切地说,我不耐烦),我决定自己做一些研究。
这里有一些我用来理解功能的伪代码:(向下滚动TL; DR)
// Credits to:
// -> http://filelog.net/func/RtlQueryEnvironmentVariable
// For helping with the arguments' names and types
// -> IDA Pro
// -> NirSoft for the RTL_CRITICAL_SECTION structure
// http://www.nirsoft.net/kernel_struct/vista/RTL_CRITICAL_SECTION.html
// https://msdn.microsoft.com/en-us/library/cc704588.aspx
#ifndef STATUS_VARIABLE_NOT_FOUND
#define STATUS_VARIABLE_NOT_FOUND 0xC0000100
#endif
NTSTATUS __stdcall RtlQueryEnvironmentVariable(PVOID Environment, PWSTR Name, size_t NameLength, PWSTR Value, size_t ValueLength, PSIZE_T ReturnLength){
// Here happens some exception stuff
// ...
// Return variable
NTSTATUS ret;
// PEB environment
PVOID pEnv = &teb->ProcessEnvironmentBlock->ProcessParameters->Environment;
// mov ebx, [ebp+ReturnLength]
// xor esi, esi
// mov [ebx], esi
*ReturnLength = 0;
// Sanity check
if ( !NameLength )
return STATUS_VARIABLE_NOT_FOUND;
// Here happens some exception stuff
// ...
// Check the variable
NTSTATUS envVar = RtlpCheckPseudoEnvironmentVariable(Name, NameLength, Value, ValueLength, ReturnLength);
// If the variable exists, fail.
if ( envVar >= 0 ) {
goto sehReturn;
}
/* Only process variables that haven't been set as pseudo.
I could've joined this with the previous if () with ||,
but I'd rather leave it as is for easier comprehension.
Do note that this is a signed comparison, and it's why
this doesn't always simply jump to 'sehReturn'.
P.S. typedef long NTSTATUS; 'long' is signed by default */
if ( envVar != (signed int) STATUS_VARIABLE_NOT_FOUND ) {
goto sehReturn;
}
// In case there's no environment supplied, just take it from TEB->PEB->ProcessParameters->Environment
if ( !Environment ) {
// Get a pointer to TEB
TEB* teb = __readfsdword(0x18);
// Wait till we get thread-safe access to PEB
RtlEnterCriticalSection(&FastPebLock);
// Exception handling stuff
// ...
// Try to load it from cache
NTSTATUS varFromCache = RtlpQueryEnvironmentCache(
pEnv,
Name, NameLength,
Value, ValueLength,
ReturnLength
);
// Get it from the actual environment if it isn't in the cache
if ( varFromCache == STATUS_VARIABLE_NOT_FOUND ) {
varFromCache = RtlpScanEnvironment(
pEnv,
Name, NameLength,
Value, ValueLength,
ReturnLength,
// I'm not really sure what this argument is for,
// but it's set to FALSE when the environment is not
// the same as the current process or the critical
// section is locked by a thread. mainly corner cases.
TRUE
);
}
// Save return value
ret = varFromCache;
// Exception handling stuff
// ...
RtlLeaveCriticalSection(&FastPebLock);
goto sehReturn;
}
// Try to determine if environment is valid
if ( !*PWORD(Environment) ) {
ret = STATUS_VARIABLE_NOT_FOUND;
goto sehReturn;
}
RTL_CRITICAL_SECTION* pCriticalSection = teb->ProcessEnvironmentBlock->FastPebLock;
BOOL cornerCase;
// Set 'cornerCase' to FALSE if the environment is not our process'
// environment or if it is locked by a thread.
if ( pEnv != Environment || (pCriticalSection != NULL && !RtlIsCriticalSectionLockedByThread(pCriticalSection)) ) {
cornerCase = FALSE;
} else {
// If the variable is in the current process, try to take it from the cache.
NTSTATUS varFromCache = RtlpQueryEnvironmentCache(
Environment,
Name, NameLength,
Value, ValueLength,
ReturnLength
);
if ( varFromCache != STATUS_VARIABLE_NOT_FOUND ) {
ret = varFromCache;
goto sehReturn;
}
cornerCase = TRUE;
}
// Take the variable from the environment
RtlpScanEnvironment(
Environment,
Name, NameLength,
Value, ValueLength,
ReturnLength,
cornerCase
);
// Structured Exception Handler return; does some SEH stuff and returns.
sehReturn:
ms_exc.registration.TryLevel = -2;
return ret;
}
<强> TL; DR 强> 这基本上检查PEB-&gt; ProcessParameters-&gt; Reserved2(Environment)中的环境变量,并在传递的指针中返回它。
检查缓存,并对案例进行规范化。