본문 바로가기
코드/kernel

[WDK]커널에서 CurrentDirectory 구하기

by WeZZ 2009. 1. 8.
커널함수중에는 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의 함수 코드이다.


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();

 _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;

 wDirectory = ExAllocatePoolWithTag( NonPagedPool , TotalLength*sizeof(WCHAR) , _POOL_TAG );
 RtlZeroMemory( wDirectory , TotalLength*sizeof(WCHAR));
 RtlCopyMemory( wDirectory , ImagePathName->Buffer , uL );


ExFreePoolWithTag(wDirectory, _POOL_TAG );




바로 접근하지 않고 ZwQueryInformationProcess함수로 풀패스로 구하는 방법을 사용해도 된다.