커널함수중에는 GetCurrentDirectory가 없다.
그래서 _PEB 구조체를 뒤져보았다.
kd> dt _PEB
ntdll!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 SpareBool : UChar
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA
+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
+0x014 SubSystemData : Ptr32 Void
+0x018 ProcessHeap : Ptr32 Void
+0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION
+0x020 FastPebLockRoutine : Ptr32 Void
+0x024 FastPebUnlockRoutine : Ptr32 Void
+0x028 EnvironmentUpdateCount : Uint4B
+0x02c KernelCallbackTable : Ptr32 Void
+0x030 SystemReserved : [1] Uint4B
+0x034 AtlThunkSListPtr32 : Uint4B
+0x038 FreeList : Ptr32 _PEB_FREE_BLOCK
+0x03c TlsExpansionCounter : Uint4B
+0x040 TlsBitmap : Ptr32 Void
+0x044 TlsBitmapBits : [2] Uint4B
+0x04c ReadOnlySharedMemoryBase : Ptr32 Void
+0x050 ReadOnlySharedMemoryHeap : Ptr32 Void
+0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void
+0x058 AnsiCodePageData : Ptr32 Void
+0x05c OemCodePageData : Ptr32 Void
+0x060 UnicodeCaseTableData : Ptr32 Void
+0x064 NumberOfProcessors : Uint4B
+0x068 NtGlobalFlag : Uint4B
+0x070 CriticalSectionTimeout : _LARGE_INTEGER
+0x078 HeapSegmentReserve : Uint4B
+0x07c HeapSegmentCommit : Uint4B
+0x080 HeapDeCommitTotalFreeThreshold : Uint4B
+0x084 HeapDeCommitFreeBlockThreshold : Uint4B
+0x088 NumberOfHeaps : Uint4B
+0x08c MaximumNumberOfHeaps : Uint4B
+0x090 ProcessHeaps : Ptr32 Ptr32 Void
+0x094 GdiSharedHandleTable : Ptr32 Void
+0x098 ProcessStarterHelper : Ptr32 Void
+0x09c GdiDCAttributeList : Uint4B
+0x0a0 LoaderLock : Ptr32 Void
+0x0a4 OSMajorVersion : Uint4B
+0x0a8 OSMinorVersion : Uint4B
+0x0ac OSBuildNumber : Uint2B
+0x0ae OSCSDVersion : Uint2B
+0x0b0 OSPlatformId : Uint4B
+0x0b4 ImageSubsystem : Uint4B
+0x0b8 ImageSubsystemMajorVersion : Uint4B
+0x0bc ImageSubsystemMinorVersion : Uint4B
+0x0c0 ImageProcessAffinityMask : Uint4B
+0x0c4 GdiHandleBuffer : [34] Uint4B
+0x14c PostProcessInitRoutine : Ptr32 void
+0x150 TlsExpansionBitmap : Ptr32 Void
+0x154 TlsExpansionBitmapBits : [32] Uint4B
+0x1d4 SessionId : Uint4B
+0x1d8 AppCompatFlags : _ULARGE_INTEGER
+0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER
+0x1e8 pShimData : Ptr32 Void
+0x1ec AppCompatInfo : Ptr32 Void
+0x1f0 CSDVersion : _UNICODE_STRING
+0x1f8 ActivationContextData : Ptr32 Void
+0x1fc ProcessAssemblyStorageMap : Ptr32 Void
+0x200 SystemDefaultActivationContextData : Ptr32 Void
+0x204 SystemAssemblyStorageMap : Ptr32 Void
+0x208 MinimumStackCommit : Uint4B
dt _RTL_USER_PROCESS_PARAMETERS
ntdll!_RTL_USER_PROCESS_PARAMETERS
+0x000 MaximumLength : Uint4B
+0x004 Length : Uint4B
+0x008 Flags : Uint4B
+0x00c DebugFlags : Uint4B
+0x010 ConsoleHandle : Ptr32 Void
+0x014 ConsoleFlags : Uint4B
+0x018 StandardInput : Ptr32 Void
+0x01c StandardOutput : Ptr32 Void
+0x020 StandardError : Ptr32 Void
+0x024 CurrentDirectory : _CURDIR <-- 이넘의 파라미터
+0x030 DllPath : _UNICODE_STRING
+0x038 ImagePathName : _UNICODE_STRING
+0x040 CommandLine : _UNICODE_STRING
+0x048 Environment : Ptr32 Void
+0x04c StartingX : Uint4B
+0x050 StartingY : Uint4B
+0x054 CountX : Uint4B
+0x058 CountY : Uint4B
+0x05c CountCharsX : Uint4B
+0x060 CountCharsY : Uint4B
+0x064 FillAttribute : Uint4B
+0x068 WindowFlags : Uint4B
+0x06c ShowWindowFlags : Uint4B
+0x070 WindowTitle : _UNICODE_STRING
+0x078 DesktopInfo : _UNICODE_STRING
+0x080 ShellInfo : _UNICODE_STRING
+0x088 RuntimeData : _UNICODE_STRING
+0x090 CurrentDirectores : [32] _RTL_DRIVE_LETTER_CURDIR
포인터 인자는 아래와 같다.
kd> dt _CURDIR
ntdll!_CURDIR
+0x000 DosPath : _UNICODE_STRING
+0x008 Handle : Ptr32 Void
위 포인터를 직접 접근하여 실행중인 프로세스의 디렉토리 루트를 구할 수 있다.
..
..
..
CurrentDirectory라는 말은 사실상 잘못 된듯.
CurrentProcessDirectory가 맞는 말이다.^^
근데 위와 같이 _CURDIR 파라미터를 참조하면 오류가 생긴다.
프로세스(A) -> CreateProcess(B) -> DriverLoad
이떄 참조하는 경로는 프로세스(A)의 경로이다.
물론 같은 루트에 있으면 상관이 없겠지만..
나와 같은 경우는 틀린경우라서..어쩔수 없이..
ImagePathName,
WindowTitle
위 두 인자를 참조하는 방법을 썻다.
아래는 RectOs의 함수 코드이다.
내가 수정한 함수 코드
_peb = (PVOID) *(PULONG) GetPtr( _eprocess, G_EPROCESS_PEB_OFFSET );
_processparmeter = (PVOID) *(PULONG) GetPtr( _peb, PROCESSPARAMETER_OFFSET );
wDirectory = ExAllocatePoolWithTag( NonPagedPool , TotalLength*sizeof(WCHAR) , _POOL_TAG );
RtlZeroMemory( wDirectory , TotalLength*sizeof(WCHAR));
바로 접근하지 않고 ZwQueryInformationProcess함수로 풀패스로 구하는 방법을 사용해도 된다.
그래서 _PEB 구조체를 뒤져보았다.
kd> dt _PEB
ntdll!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 SpareBool : UChar
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA
+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
+0x014 SubSystemData : Ptr32 Void
+0x018 ProcessHeap : Ptr32 Void
+0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION
+0x020 FastPebLockRoutine : Ptr32 Void
+0x024 FastPebUnlockRoutine : Ptr32 Void
+0x028 EnvironmentUpdateCount : Uint4B
+0x02c KernelCallbackTable : Ptr32 Void
+0x030 SystemReserved : [1] Uint4B
+0x034 AtlThunkSListPtr32 : Uint4B
+0x038 FreeList : Ptr32 _PEB_FREE_BLOCK
+0x03c TlsExpansionCounter : Uint4B
+0x040 TlsBitmap : Ptr32 Void
+0x044 TlsBitmapBits : [2] Uint4B
+0x04c ReadOnlySharedMemoryBase : Ptr32 Void
+0x050 ReadOnlySharedMemoryHeap : Ptr32 Void
+0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void
+0x058 AnsiCodePageData : Ptr32 Void
+0x05c OemCodePageData : Ptr32 Void
+0x060 UnicodeCaseTableData : Ptr32 Void
+0x064 NumberOfProcessors : Uint4B
+0x068 NtGlobalFlag : Uint4B
+0x070 CriticalSectionTimeout : _LARGE_INTEGER
+0x078 HeapSegmentReserve : Uint4B
+0x07c HeapSegmentCommit : Uint4B
+0x080 HeapDeCommitTotalFreeThreshold : Uint4B
+0x084 HeapDeCommitFreeBlockThreshold : Uint4B
+0x088 NumberOfHeaps : Uint4B
+0x08c MaximumNumberOfHeaps : Uint4B
+0x090 ProcessHeaps : Ptr32 Ptr32 Void
+0x094 GdiSharedHandleTable : Ptr32 Void
+0x098 ProcessStarterHelper : Ptr32 Void
+0x09c GdiDCAttributeList : Uint4B
+0x0a0 LoaderLock : Ptr32 Void
+0x0a4 OSMajorVersion : Uint4B
+0x0a8 OSMinorVersion : Uint4B
+0x0ac OSBuildNumber : Uint2B
+0x0ae OSCSDVersion : Uint2B
+0x0b0 OSPlatformId : Uint4B
+0x0b4 ImageSubsystem : Uint4B
+0x0b8 ImageSubsystemMajorVersion : Uint4B
+0x0bc ImageSubsystemMinorVersion : Uint4B
+0x0c0 ImageProcessAffinityMask : Uint4B
+0x0c4 GdiHandleBuffer : [34] Uint4B
+0x14c PostProcessInitRoutine : Ptr32 void
+0x150 TlsExpansionBitmap : Ptr32 Void
+0x154 TlsExpansionBitmapBits : [32] Uint4B
+0x1d4 SessionId : Uint4B
+0x1d8 AppCompatFlags : _ULARGE_INTEGER
+0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER
+0x1e8 pShimData : Ptr32 Void
+0x1ec AppCompatInfo : Ptr32 Void
+0x1f0 CSDVersion : _UNICODE_STRING
+0x1f8 ActivationContextData : Ptr32 Void
+0x1fc ProcessAssemblyStorageMap : Ptr32 Void
+0x200 SystemDefaultActivationContextData : Ptr32 Void
+0x204 SystemAssemblyStorageMap : Ptr32 Void
+0x208 MinimumStackCommit : Uint4B
dt _RTL_USER_PROCESS_PARAMETERS
ntdll!_RTL_USER_PROCESS_PARAMETERS
+0x000 MaximumLength : Uint4B
+0x004 Length : Uint4B
+0x008 Flags : Uint4B
+0x00c DebugFlags : Uint4B
+0x010 ConsoleHandle : Ptr32 Void
+0x014 ConsoleFlags : Uint4B
+0x018 StandardInput : Ptr32 Void
+0x01c StandardOutput : Ptr32 Void
+0x020 StandardError : Ptr32 Void
+0x024 CurrentDirectory : _CURDIR <-- 이넘의 파라미터
+0x030 DllPath : _UNICODE_STRING
+0x038 ImagePathName : _UNICODE_STRING
+0x040 CommandLine : _UNICODE_STRING
+0x048 Environment : Ptr32 Void
+0x04c StartingX : Uint4B
+0x050 StartingY : Uint4B
+0x054 CountX : Uint4B
+0x058 CountY : Uint4B
+0x05c CountCharsX : Uint4B
+0x060 CountCharsY : Uint4B
+0x064 FillAttribute : Uint4B
+0x068 WindowFlags : Uint4B
+0x06c ShowWindowFlags : Uint4B
+0x070 WindowTitle : _UNICODE_STRING
+0x078 DesktopInfo : _UNICODE_STRING
+0x080 ShellInfo : _UNICODE_STRING
+0x088 RuntimeData : _UNICODE_STRING
+0x090 CurrentDirectores : [32] _RTL_DRIVE_LETTER_CURDIR
포인터 인자는 아래와 같다.
kd> dt _CURDIR
ntdll!_CURDIR
+0x000 DosPath : _UNICODE_STRING
+0x008 Handle : Ptr32 Void
위 포인터를 직접 접근하여 실행중인 프로세스의 디렉토리 루트를 구할 수 있다.
..
..
..
CurrentDirectory라는 말은 사실상 잘못 된듯.
CurrentProcessDirectory가 맞는 말이다.^^
근데 위와 같이 _CURDIR 파라미터를 참조하면 오류가 생긴다.
프로세스(A) -> CreateProcess(B) -> DriverLoad
이떄 참조하는 경로는 프로세스(A)의 경로이다.
물론 같은 루트에 있으면 상관이 없겠지만..
나와 같은 경우는 틀린경우라서..어쩔수 없이..
ImagePathName,
WindowTitle
위 두 인자를 참조하는 방법을 썻다.
아래는 RectOs의 함수 코드이다.
ULONG NTAPI RtlGetCurrentDirectory_U | ( | ULONG | MaximumLength, | |
PWSTR | Buffer | |||
) |
Definition at line 164 of file path.c.
00166 { 00167 ULONG Length; 00168 PCURDIR cd; 00169 00170 DPRINT ("RtlGetCurrentDirectory %lu %p\n", MaximumLength, Buffer); 00171 00172 RtlAcquirePebLock(); 00173 00174 cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectory.DosPath); 00175 Length = cd->DosPath.Length / sizeof(WCHAR); 00176 if (cd->DosPath.Buffer[Length - 1] == L'\\' && 00177 cd->DosPath.Buffer[Length - 2] != L':') 00178 Length--; 00179 00180 DPRINT ("cd->DosPath.Buffer %S Length %lu\n", 00181 cd->DosPath.Buffer, Length); 00182 00183 if (MaximumLength / sizeof(WCHAR) > Length) 00184 { 00185 memcpy (Buffer, 00186 cd->DosPath.Buffer, 00187 Length * sizeof(WCHAR)); 00188 Buffer[Length] = 0; 00189 } 00190 else 00191 { 00192 Length++; 00193 } 00194 00195 RtlReleasePebLock (); 00196 00197 DPRINT ("CurrentDirectory %S\n", Buffer); 00198 00199 return (Length * sizeof(WCHAR));
내가 수정한 함수 코드
ULONG TotalLength;
PCURDIR cd;
PEPROCESS _eprocess;
PVOID _peb = NULL,_processparmeter = NULL;
PUNICODE_STRING ImagePathName;
WCHAR *wTemp = NULL;
WCHAR *wDirectory = NULL;
ULONG uL = 0;
_eprocess = PsGetCurrentProcess();
PCURDIR cd;
PEPROCESS _eprocess;
PVOID _peb = NULL,_processparmeter = NULL;
PUNICODE_STRING ImagePathName;
WCHAR *wTemp = NULL;
WCHAR *wDirectory = NULL;
ULONG uL = 0;
_eprocess = PsGetCurrentProcess();
_peb = (PVOID) *(PULONG) GetPtr( _eprocess, G_EPROCESS_PEB_OFFSET );
_processparmeter = (PVOID) *(PULONG) GetPtr( _peb, PROCESSPARAMETER_OFFSET );
ImagePathName = (PUNICODE_STRING)GetPtr( _processparmeter , IMAGEPATHNAME_OFFSET );
if( !ImagePathName->Length )
return STATUS_UNSUCCESSFUL;
TotalLength = ImagePathName->Length / sizeof(WCHAR);
wTemp = wcsrchr(ImagePathName->Buffer, L'\\');
uL = (ULONG)wTemp - (ULONG)ImagePathName->Buffer;
if( !ImagePathName->Length )
return STATUS_UNSUCCESSFUL;
TotalLength = ImagePathName->Length / sizeof(WCHAR);
wTemp = wcsrchr(ImagePathName->Buffer, L'\\');
uL = (ULONG)wTemp - (ULONG)ImagePathName->Buffer;
wDirectory = ExAllocatePoolWithTag( NonPagedPool , TotalLength*sizeof(WCHAR) , _POOL_TAG );
RtlZeroMemory( wDirectory , TotalLength*sizeof(WCHAR));
RtlCopyMemory( wDirectory , ImagePathName->Buffer , uL );
ExFreePoolWithTag(wDirectory, _POOL_TAG );
ExFreePoolWithTag(wDirectory, _POOL_TAG );
바로 접근하지 않고 ZwQueryInformationProcess함수로 풀패스로 구하는 방법을 사용해도 된다.