Life of a WinAPI: from user-mode to kernel-mode

در این پست قراره مراحلی رو که یک Win API از زمان فراخوانی تا زمان رسیدن به Kernel Mode و تفسیرش توسط Kernel طی می‌کنه با هم بررسی کنیم.

برای شروع، تکه کد زیر رو (که طی اون با استفاده از CreateFile که یک Win API هست یک فایل ایجاد می شود) در نظر بگیرید:

#include "pch.h"
#include <windows.h>
#include <iostream>
int main(void)
{
	HANDLE hFile = CreateFile(L"7erom.txt",
		GENERIC_WRITE,          // open for writing
		0,                      // do not share
		NULL,                   // default security
		CREATE_NEW,             // create new file only
		FILE_ATTRIBUTE_NORMAL,  // normal file
		NULL);                  // no attr. template
	if (hFile == INVALID_HANDLE_VALUE)
	{
		std::cout << "Unable to open file!" << std::endl;
		return -1;
	}
	return 0;
}

کد فوق رو با نام ntdll_test به صورت x86 و x64 کامپایل می کنیم. در ادامه به بررسی هر دو مورد در سیستم‌عامل Windows 10 x64 می‌پردازیم. بهتره که اعلام کنم، debuggerای که استفاده می‌کنیم windbg preview (نسخه جدید windbg) هست. پیشنهاد میشه شما هم به جای استفاده از windbg قدیمی، از این debugger استفاده کنید. تفاوتش رو حتما احساس می‌کنید.

x64 in Windows 10 x64

نسخه x64 از ntdll_test رو با استفاده از windbg preview اجرا می‌‌کنیم و با استفاده از bu ntdll_test!main بر روی تابع main آن breakpoint میذاریم.

زمانی که برنامه بر روی تابع main متوقف شد، با استفاده ازعملیات Trace and Watch Data (که دستور wt این کار رو برای ما انجام میده) از فراخوانی‌های داخل تابع main پروفایل می‌سازیم.

در زیر، بخش مهمی از نتایج این دستور رو می‌بینیم:

0:000> wt
Tracing ntdll_test!main to return address 00007ff6`f64c2f34
   83     0 [  0] ntdll_test!main
    8     0 [  1]   ntdll_test!main
    1     0 [  2]     KERNEL32!CreateFileW
   20     0 [  2]     KERNELBASE!CreateFileW
   44     0 [  3]       KERNELBASE!CreateFileInternal
   44     0 [  4]         ntdll!RtlInitUnicodeStringEx
   62    44 [  3]       KERNELBASE!CreateFileInternal
   52     0 [  4]         ntdll!RtlDosPathNameToRelativeNtPathName_U_WithStatus
   48     0 [  5]           ntdll!RtlpDosPathNameToRelativeNtPathName
   58     0 [  6]             ntdll!RtlGetFullPathName_Ustr
   88     0 [  7]               ntdll!memset
   65    88 [  6]             ntdll!RtlGetFullPathName_Ustr
    9     0 [  7]               ntdll!RtlpIsDosDeviceName_Ustr
   20     0 [  8]                 ntdll!RtlDetermineDosPathNameType_Ustr
  144    20 [  7]               ntdll!RtlpIsDosDeviceName_Ustr
   69   252 [  6]             ntdll!RtlGetFullPathName_Ustr
   20     0 [  7]               ntdll!RtlDetermineDosPathNameType_Ustr
   93   272 [  6]             ntdll!RtlGetFullPathName_Ustr
   13     0 [  7]               ntdll!RtlpReferenceCurrentDirectory
   10     0 [  8]                 ntdll!RtlEnterCriticalSection
   20    10 [  7]               ntdll!RtlpReferenceCurrentDirectory
   19     0 [  8]                 ntdll!RtlLeaveCriticalSection
   33    29 [  7]               ntdll!RtlpReferenceCurrentDirectory
  105   334 [  6]             ntdll!RtlGetFullPathName_Ustr
    3     0 [  7]               ntdll!RtlpComputeBackupIndex
   25     0 [  8]                 ntdll!RtlDetermineDosPathNameType_Ustr
    8    25 [  7]               ntdll!RtlpComputeBackupIndex
  110   367 [  6]             ntdll!RtlGetFullPathName_Ustr
    9     0 [  7]               ntdll!RtlUnicodeStringCopy
   11     0 [  8]                 ntdll!RtlUnicodeStringValidateDestWorker
   14     0 [  9]                   ntdll!RtlUnicodeStringValidateWorker
   28    14 [  8]                 ntdll!RtlUnicodeStringValidateDestWorker
   17    42 [  7]               ntdll!RtlUnicodeStringCopy
    6     0 [  8]                 ntdll!RtlUnicodeStringValidateSrcWorker
   14     0 [  9]                   ntdll!RtlUnicodeStringValidateWorker
   17    14 [  8]                 ntdll!RtlUnicodeStringValidateSrcWorker
   26    73 [  7]               ntdll!RtlUnicodeStringCopy
  196     0 [  8]                 ntdll!RtlWideCharArrayCopyWorker
   33   269 [  7]               ntdll!RtlUnicodeStringCopy
  547   669 [  6]             ntdll!RtlGetFullPathName_Ustr
    6     0 [  7]               ntdll!_security_check_cookie
  556   675 [  6]             ntdll!RtlGetFullPathName_Ustr
   61  1231 [  5]           ntdll!RtlpDosPathNameToRelativeNtPathName
   25     0 [  6]             ntdll!RtlDetermineDosPathNameType_Ustr
   88  1256 [  5]           ntdll!RtlpDosPathNameToRelativeNtPathName
   22     0 [  6]             ntdll!RtlAllocateHeap
   59     0 [  6]             ntdll!RtlpAllocateHeapInternal
   37     0 [  7]               ntdll!RtlpAllocateHeap
   17     0 [  8]                 ntdll!RtlDebugAllocateHeap
   12     0 [  9]                   ntdll!RtlpCheckHeapSignature
   41    12 [  8]                 ntdll!RtlDebugAllocateHeap
   10     0 [  9]                   ntdll!RtlEnterCriticalSection
   47    22 [  8]                 ntdll!RtlDebugAllocateHeap
   18     0 [  9]                   ntdll!RtlpValidateHeap
   14     0 [ 10]                     ntdll!RtlpValidateHeapHeaders
   37    14 [  9]                   ntdll!RtlpValidateHeap
   51    73 [  8]                 ntdll!RtlDebugAllocateHeap
   22     0 [  9]                   ntdll!RtlAllocateHeap
   59     0 [  9]                   ntdll!RtlpAllocateHeapInternal
  103     0 [ 10]                     ntdll!RtlpAllocateHeap
   10     0 [ 11]                       ntdll!RtlpGetLFHContext
  266    10 [ 10]                     ntdll!RtlpAllocateHeap
   66     0 [ 11]                       ntdll!RtlpHeapRemoveListEntry
  289    76 [ 10]                     ntdll!RtlpAllocateHeap
   70     0 [ 11]                       ntdll!RtlCompareMemoryUlong
  404   146 [ 10]                     ntdll!RtlpAllocateHeap
   16     0 [ 11]                       ntdll!RtlpFindEntry
  122     0 [ 12]                         ntdll!RtlpHeapFindListLookupEntry
   23   122 [ 11]                       ntdll!RtlpFindEntry
  447   291 [ 10]                     ntdll!RtlpAllocateHeap
   43     0 [ 11]                       ntdll!RtlpHeapAddListEntry
  523   334 [ 10]                     ntdll!RtlpAllocateHeap
    7     0 [ 11]                       ntdll!RtlpGetExtraStuffPointer
  562   341 [ 10]                     ntdll!RtlpAllocateHeap
   88   903 [  9]                   ntdll!RtlpAllocateHeapInternal
   56  1086 [  8]                 ntdll!RtlDebugAllocateHeap
   14     0 [  9]                   ntdll!RtlpValidateHeapHeaders
   75  1100 [  8]                 ntdll!RtlDebugAllocateHeap
    7     0 [  9]                   ntdll!RtlpGetExtraStuffPointer
  103  1107 [  8]                 ntdll!RtlDebugAllocateHeap
   19     0 [  9]                   ntdll!RtlLeaveCriticalSection
  113  1126 [  8]                 ntdll!RtlDebugAllocateHeap
   48  1239 [  7]               ntdll!RtlpAllocateHeap
   88  1287 [  6]             ntdll!RtlpAllocateHeapInternal
  114  2653 [  5]           ntdll!RtlpDosPathNameToRelativeNtPathName
   18     0 [  6]             ntdll!memcpy
  146  2671 [  5]           ntdll!RtlpDosPathNameToRelativeNtPathName
   59     0 [  6]             ntdll!memcpy
  177  2730 [  5]           ntdll!RtlpDosPathNameToRelativeNtPathName
   13     0 [  6]             ntdll!RtlpReferenceCurrentDirectory
   10     0 [  7]               ntdll!RtlEnterCriticalSection
   20    10 [  6]             ntdll!RtlpReferenceCurrentDirectory
   19     0 [  7]               ntdll!RtlLeaveCriticalSection
   39    29 [  6]             ntdll!RtlpReferenceCurrentDirectory
  185  2798 [  5]           ntdll!RtlpDosPathNameToRelativeNtPathName
  139     0 [  6]             ntdll!RtlPrefixUnicodeString
  212  2937 [  5]           ntdll!RtlpDosPathNameToRelativeNtPathName
    6     0 [  6]             ntdll!_security_check_cookie
  222  2943 [  5]           ntdll!RtlpDosPathNameToRelativeNtPathName
   54  3165 [  4]         ntdll!RtlDosPathNameToRelativeNtPathName_U_WithStatus
  165  3263 [  3]       KERNELBASE!CreateFileInternal
   48     0 [  4]         ntdll!SbSelectProcedure
   53     0 [  5]           ntdll!memset
   69    53 [  4]         ntdll!SbSelectProcedure
   49     0 [  5]           ntdll!memset
   92   102 [  4]         ntdll!SbSelectProcedure
    6     0 [  5]           ntdll!_security_check_cookie
   99   108 [  4]         ntdll!SbSelectProcedure
  170  3470 [  3]       KERNELBASE!CreateFileInternal
    1     0 [  4]         KERNELBASE!guard_dispatch_icall_nop
    1     0 [  4]         KERNELBASE!AfpAdminDisconnect
  187  3472 [  3]       KERNELBASE!CreateFileInternal
   61     0 [  4]         apphelp!InsHook_NtCreateFile
   99     0 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!wcsnicmp
   48     0 [  6]             ntdll!wcsnicmp
  109    49 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!wcsnicmp
   48     0 [  6]             ntdll!wcsnicmp
  119    98 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!wcsnicmp
   48     0 [  6]             ntdll!wcsnicmp
  129   147 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!wcsnicmp
   48     0 [  6]             ntdll!wcsnicmp
  139   196 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!wcsnicmp
   48     0 [  6]             ntdll!wcsnicmp
  149   245 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!wcsnicmp
   48     0 [  6]             ntdll!wcsnicmp
  159   294 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!wcsnicmp
   48     0 [  6]             ntdll!wcsnicmp
  169   343 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!wcsnicmp
   48     0 [  6]             ntdll!wcsnicmp
  179   392 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!wcsnicmp
   48     0 [  6]             ntdll!wcsnicmp
  190   441 [  5]           apphelp!Insp_ExtensionMatch
   82   631 [  4]         apphelp!InsHook_NtCreateFile
    1     0 [  5]           apphelp!guard_dispatch_icall_nop
    6     0 [  5]           ntdll!NtCreateFile
...

همونطور که دیدیم، ابتدا توابع مربوط به تبدیل آدرس فایل صدا زده شد و در ادامه تابع مهم ntdll!NtCreateFile.

نکته: تمامی فراخوانی‌ها به ماژول ntdll ختم میشن. ntdll رابط بین user mode و kernel mode هست.

خوب، حالا وقتشه که بررسی ‌کنیم قراره داخل ntdll!NtCreateFile چه اتفاقاتی بیفته! به همین خاطر، اول میایم این تابع رو disassemble می‌‌کنیم:

0:000> uf ntdll!NtCreateFile
ntdll!NtCreateFile:
00007ff8`040bcb50 4c8bd1          mov     r10,rcx
00007ff8`040bcb53 b855000000      mov     eax,55h
00007ff8`040bcb58 f604250803fe7f01 test    byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007ff8`040bcb60 7503            jne     ntdll!NtCreateFile+0x15 (00007ff8`040bcb65)  Branch
ntdll!NtCreateFile+0x12:
00007ff8`040bcb62 0f05            syscall
00007ff8`040bcb64 c3              ret
ntdll!NtCreateFile+0x15:
00007ff8`040bcb65 cd2e            int     2Eh
00007ff8`040bcb67 c3              ret</code>

در خط چهارم، عدد 55h رو می‌بینیم که به رجیستر eax ریخته میشه. این عدد چیه؟!

هر تابع در ntdll یک شماره منحصر به فرد داره. این عدد نمایانگر شماره syscall اون تابع هست. از طریق این عدد، Kernel متوجه میشه چه تابعی فراخوانی شده و خودش باید چه روتینی رو فراخوانی کنه. در مورد تفسیر این عدد، بعدا بیشتر صحبت می کنیم.

در ادامه می‌بینیم که میشه از دو طریق sycall و int 2eh به cpu بگیم که می‌خوایم بریم به Kernel Mode و بقیه‌ش رو تو Handle کن. اما این که این دو تا instruction (منظورم sycall و int 2eh هست) چه تفاوتی با همدیگه دارن یه بحث جداگانه‌ای رو می‌طلبه. فقط به این نکته بسنده کنم که در نسخه‌های قدیمی‌تر ویندوز، از int 2eh استفاده میشد و در نسخه‌های امروزی، syscall هم اضافه شده.

بر ابتدای تابع ntdll!NtCreateFile یه bp می‌ذاریم تا call stack رو با هم بررسی کنیم:

0:000> kc
 # Call Site
00 ntdll!NtCreateFile
01 apphelp!InsHook_NtCreateFile
02 KERNELBASE!CreateFileInternal
03 KERNELBASE!CreateFileW
04 ntdll_test!main
05 ntdll_test!invoke_main
06 ntdll_test!__scrt_common_main_seh
07 ntdll_test!__scrt_common_main
08 ntdll_test!mainCRTStartup
09 KERNEL32!BaseThreadInitThunk
0a ntdll!RtlUserThreadStart

اما با فراخوانی syscall یا int 2eh چه اتفاقی در Kernel میفته؟

خوب از اینجا به بعد دیگه دیباگ تو حالت user mode به درد ما نمیخوره. بنابراین وارد kernel mode debugging میشیم.

با اجرای دستورالعمل syscall یا int 2eh وارد Kernel و اجرای عملیات System Service Dispatcher میشیم. طی این عملیات، از جدولی به نام System Service Dispatcher Table یا به اختصار SSDT، آدرس روتینی که باید برای انجام عملیات مربوط به ntdll!NtCreateFile اجرا شود به دست میاریم. اما چطور؟

مقداری که قبل از اجرای دستورالعمل syscall یا int 2eh در رجیستر eax ذخیره می‌کنیم اینجا به درد ما می‌خوره. این مقدار به عنوان index جدول SSDT به کار میاد.

می‌تونیم از طریق nt!KiServiceTable به جدول مذکور دسترسی پیدا کنیم:

11: kd> dd nt!KiServiceTable
fffff807`6a8a35b0  fc7b5904 fc852900 026de402 04538c00
fffff807`6a8a35c0  02a95700 fdb7dc00 027c6f05 02424a06
fffff807`6a8a35d0  027b9605 02407801 02875600 01b1fd00
fffff807`6a8a35e0  01b0fe00 02afce00 02869e00 02a87300
fffff807`6a8a35f0  02230801 027cfc01 02a0ce00 02189002
fffff807`6a8a3600  028bc200 025bcd00 02814301 0281a902
fffff807`6a8a3610  029c5402 01ec8201 01d27901 02751305
fffff807`6a8a3620  01ef4100 019c3003 023b5600 044bd600

هر ۴ بایت، با حذف کم ارزش‌ترین ۴ بیت بیانگر آدرس یک روتین هست. مثلا در مورد 02751305، با حذف کم ارزش‌ترین ۴ بیت (= مقدار 5) برابر با 0275130 خواهد بود. اما این مقدار ۵ چه چیزی رو نشون میده؟

کم ارزش‌ترین ۴ بیت، بیانگرتعداد آرگومان‌های ورودی اون روتین هستند. در مورد مثال قبل، روتین مذکور، 5 آرگومان ورودی داشت. حالا با این دانش، سراغ کار خودمون بریم.

از اونجایی که مقدار eax برابر با 0x55 بود، بنابراین مقدار index روتینش هم 0x55 هست. پس بریم ببنیم آدرس روتین NtCreateFile چیه:

1: kd> dd nt!KiServiceTable+55*4 L1
fffff807`6a8a3704  02120707

این نشون میده که آدرس تابع برابر با 0212070 هست. بابت چک کردن، این آدرس رو disassemble می‌کنیم:

1: kd> u nt!KiServiceTable+0212070
nt!NtCreateFile:
fffff807`6aab5620 4881ec88000000  sub     rsp,88h
fffff807`6aab5627 33c0            xor     eax,eax
fffff807`6aab5629 4889442478      mov     qword ptr [rsp+78h],rax
fffff807`6aab562e c744247020000000 mov     dword ptr [rsp+70h],20h
fffff807`6aab5636 89442468        mov     dword ptr [rsp+68h],eax
fffff807`6aab563a 4889442460      mov     qword ptr [rsp+60h],rax
fffff807`6aab563f 89442458        mov     dword ptr [rsp+58h],eax
fffff807`6aab5643 8b8424e0000000  mov     eax,dword ptr [rsp+0E0h]

عدد 7 هم بیانگر تعداد آرگومان‌های ورودی روتین هست. اما چرا 7؟ مگه نه اینکه تعداد آرگومان‌های ورودی تابع NtCreateFile برابر 11 هست:

__kernel_entry NTSTATUS NtCreateFile(
  OUT PHANDLE           FileHandle,
  IN ACCESS_MASK        DesiredAccess,
  IN POBJECT_ATTRIBUTES ObjectAttributes,
  OUT PIO_STATUS_BLOCK  IoStatusBlock,
  IN PLARGE_INTEGER     AllocationSize,
  IN ULONG              FileAttributes,
  IN ULONG              ShareAccess,
  IN ULONG              CreateDisposition,
  IN ULONG              CreateOptions,
  IN PVOID              EaBuffer,
  IN ULONG              EaLength
);

فراموش نشه که در فراخوانی‌های ۶۴بیتی، ۴ آرگومان اول در رجیستر و باقی آرگومان‌ها در پشته push می‌شوند. دلیل احتلاف اعداد هم به خاطر همین هست.

x86 in Windows 10 x64 (wow64)

همانطور که می‌دونید، در سیستم‌عامل ۳۲بیتی، Kernel هم ۳۲بیتی است و در سیستم‌عامل ۶۴بیتی، Kernel هم ۶۴بیتی است. اما چطور یک prcoess x86 در یک Kernel x64 کار می‌کنه. برای پاسخ به این سوال، مثال بالا رو این بار برای نسخه x86 از ntdll_test پیش می‌بریم.

به منظور اجرا کردن ntdll_test x86 در windbg preview به صورت wow64 مسیر زیر رو طی کنید:

File > Launch executable (advanced) > Browse...
Set "Target bitness" --> "Use 64-bit"

همانند مثال قبل در تابع main از ntdll_test متوقف می‌شیم ولی این بار، قبل از اجرای دستور wt، دستور lm رو اجرا می‌کنیم:

10:000:x86> lm
start    end        module name
00330000 00352000   ntdll_test C (pdb symbols)          C:\ProgramData\Dbg\sym\ntdll_test.pdb\FEEBEF8A2B32421AAEEDA5640DE8A9AE5\ntdll_test.pdb
608b0000 60a24000   ucrtbased   (deferred)             
60a30000 60ae6000   MSVCP140D   (deferred)             
680a0000 680bb000   VCRUNTIME140D   (deferred)             
711b0000 7124f000   apphelp    (pdb symbols)          C:\ProgramData\Dbg\sym\apphelp.pdb\0D37A746D2E21547F2B11D6457231F8D1\apphelp.pdb
753f0000 754d0000   KERNEL32   (pdb symbols)          C:\ProgramData\Dbg\sym\wkernel32.pdb\7D80824F9CCE7C819044B16FD421C63D1\wkernel32.pdb
757c0000 759be000   KERNELBASE   (pdb symbols)          C:\ProgramData\Dbg\sym\wkernelbase.pdb\B51CE52F863C2F8DF34C736B3D53BDA91\wkernelbase.pdb
77bb0000 77bb9000   wow64cpu   (pdb symbols)          C:\ProgramData\Dbg\sym\wow64cpu.pdb\DEA45E10CDDFECA0DEFADB7905BEC69A1\wow64cpu.pdb
77bc0000 77d5a000   ntdll_77bc0000   (pdb symbols)          C:\ProgramData\Dbg\sym\wntdll.pdb\C426B34E4A17C490B9C8608C500F9F8A1\wntdll.pdb
02270000 022c5000   wow64      (pdb symbols)          C:\ProgramData\Dbg\sym\wow64.pdb\A2E64E5ADC27E0048276806BBEECE2931\wow64.pdb
02c10000 02c8d000   wow64win   (deferred)             
00007ff8`04020000 00007ff8`04210000   ntdll      (pdb symbols)          C:\ProgramData\Dbg\sym\ntdll.pdb\FB60D3E08B5E4960376A4E73BD35F24E1\ntdll.pdb

به خط ۱۱ و ۱۴ دقت کنید. دو تا ntdll لود شده. یکی برای توابع ۳۲ بیتی و دیگری برای توابع ۶۴ بیتی. با این دید وارد بررسی فراخوانی‌های تابع main میشیم.

0:000:x86> wt
Tracing ntdll_test!main to return address 00342ece
   62     0 [  0] ntdll_test!main
    9     0 [  1]   ntdll_test!main
    1     0 [  2]     KERNEL32!CreateFileW
   28     0 [  2]     KERNELBASE!CreateFileW
   47     0 [  3]       KERNELBASE!CreateFileInternal
   65     0 [  4]         ntdll_77bc0000!RtlInitUnicodeStringEx
   66    65 [  3]       KERNELBASE!CreateFileInternal
    9     0 [  4]         ntdll_77bc0000!RtlDosPathNameToRelativeNtPathName_U_WithStatus
   65     0 [  5]           ntdll_77bc0000!RtlInitUnicodeStringEx
   20    65 [  4]         ntdll_77bc0000!RtlDosPathNameToRelativeNtPathName_U_WithStatus
   45     0 [  5]           ntdll_77bc0000!RtlpDosPathNameToRelativeNtPathName
   71     0 [  6]             ntdll_77bc0000!RtlGetFullPathName_Ustr
  158     0 [  7]               ntdll_77bc0000!memset
   80   158 [  6]             ntdll_77bc0000!RtlGetFullPathName_Ustr
  161     0 [  7]               ntdll_77bc0000!RtlpIsDosDeviceName_Ustr
  119   319 [  6]             ntdll_77bc0000!RtlGetFullPathName_Ustr
   12     0 [  7]               ntdll_77bc0000!RtlpReferenceCurrentDirectory
   16     0 [  8]                 ntdll_77bc0000!RtlEnterCriticalSection
   20    16 [  7]               ntdll_77bc0000!RtlpReferenceCurrentDirectory
   25     0 [  8]                 ntdll_77bc0000!RtlLeaveCriticalSection
   29    41 [  7]               ntdll_77bc0000!RtlpReferenceCurrentDirectory
  133   389 [  6]             ntdll_77bc0000!RtlGetFullPathName_Ustr
    4     0 [  7]               ntdll_77bc0000!RtlpComputeBackupIndex
   34     0 [  8]                 ntdll_77bc0000!RtlDetermineDosPathNameType_Ustr
   10    34 [  7]               ntdll_77bc0000!RtlpComputeBackupIndex
  137   433 [  6]             ntdll_77bc0000!RtlGetFullPathName_Ustr
   17     0 [  7]               ntdll_77bc0000!RtlUnicodeStringCopy
   18     0 [  8]                 ntdll_77bc0000!RtlUnicodeStringValidateDestWorker
   21     0 [  9]                   ntdll_77bc0000!RtlUnicodeStringValidateWorker
   37    21 [  8]                 ntdll_77bc0000!RtlUnicodeStringValidateDestWorker
   28    58 [  7]               ntdll_77bc0000!RtlUnicodeStringCopy
   13     0 [  8]                 ntdll_77bc0000!RtlUnicodeStringValidateSrcWorker
   21     0 [  9]                   ntdll_77bc0000!RtlUnicodeStringValidateWorker
   27    21 [  8]                 ntdll_77bc0000!RtlUnicodeStringValidateSrcWorker
   38   106 [  7]               ntdll_77bc0000!RtlUnicodeStringCopy
  210     0 [  8]                 ntdll_77bc0000!RtlWideCharArrayCopyWorker
   48   316 [  7]               ntdll_77bc0000!RtlUnicodeStringCopy
  519   797 [  6]             ntdll_77bc0000!RtlGetFullPathName_Ustr
   11     0 [  7]               ntdll_77bc0000!RtlGetFullPathName_Ustr
  529   808 [  6]             ntdll_77bc0000!RtlGetFullPathName_Ustr
    3     0 [  7]               ntdll_77bc0000!__security_check_cookie
  532   811 [  6]             ntdll_77bc0000!RtlGetFullPathName_Ustr
  101  1343 [  5]           ntdll_77bc0000!RtlpDosPathNameToRelativeNtPathName
   18     0 [  6]             ntdll_77bc0000!RtlAllocateHeap
   65     0 [  7]               ntdll_77bc0000!RtlpAllocateHeapInternal
   45     0 [  8]                 ntdll_77bc0000!RtlpAllocateHeap
    3     0 [  9]                   ntdll_77bc0000!RtlDebugAllocateHeap
   21     0 [ 10]                     ntdll_77bc0000!_SEH_prolog4
   16    21 [  9]                   ntdll_77bc0000!RtlDebugAllocateHeap
   13     0 [ 10]                     ntdll_77bc0000!RtlpCheckHeapSignature
   43    34 [  9]                   ntdll_77bc0000!RtlDebugAllocateHeap
   16     0 [ 10]                     ntdll_77bc0000!RtlEnterCriticalSection
   50    50 [  9]                   ntdll_77bc0000!RtlDebugAllocateHeap
   15     0 [ 10]                     ntdll_77bc0000!RtlpValidateHeap
   16     0 [ 11]                       ntdll_77bc0000!RtlpValidateHeapHeaders
   30    16 [ 10]                     ntdll_77bc0000!RtlpValidateHeap
   54    96 [  9]                   ntdll_77bc0000!RtlDebugAllocateHeap
   18     0 [ 10]                     ntdll_77bc0000!RtlAllocateHeap
   65     0 [ 11]                       ntdll_77bc0000!RtlpAllocateHeapInternal
  274     0 [ 12]                         ntdll_77bc0000!RtlpAllocateHeap
   76     0 [ 13]                           ntdll_77bc0000!RtlpHeapRemoveListEntry
  299    76 [ 12]                         ntdll_77bc0000!RtlpAllocateHeap
   32     0 [ 13]                           ntdll_77bc0000!RtlCompareMemoryUlong
  360   108 [ 12]                         ntdll_77bc0000!RtlpAllocateHeap
   24     0 [ 13]                           ntdll_77bc0000!RtlFillMemoryUlong
  398   132 [ 12]                         ntdll_77bc0000!RtlpAllocateHeap
    3     0 [ 13]                           ntdll_77bc0000!RtlpAllocateHeap
  416   135 [ 12]                         ntdll_77bc0000!RtlpAllocateHeap
   92   551 [ 11]                       ntdll_77bc0000!RtlpAllocateHeapInternal
   22   643 [ 10]                     ntdll_77bc0000!RtlAllocateHeap
   59   761 [  9]                   ntdll_77bc0000!RtlDebugAllocateHeap
   16     0 [ 10]                     ntdll_77bc0000!RtlpValidateHeapHeaders
   79   777 [  9]                   ntdll_77bc0000!RtlDebugAllocateHeap
    6     0 [ 10]                     ntdll_77bc0000!RtlpGetExtraStuffPointer
  110   783 [  9]                   ntdll_77bc0000!RtlDebugAllocateHeap
    5     0 [ 10]                     ntdll_77bc0000!RtlDebugAllocateHeap
   25     0 [ 11]                       ntdll_77bc0000!RtlLeaveCriticalSection
    6    25 [ 10]                     ntdll_77bc0000!RtlDebugAllocateHeap
  119   814 [  9]                   ntdll_77bc0000!RtlDebugAllocateHeap
   54   933 [  8]                 ntdll_77bc0000!RtlpAllocateHeap
   92   987 [  7]               ntdll_77bc0000!RtlpAllocateHeapInternal
   22  1079 [  6]             ntdll_77bc0000!RtlAllocateHeap
  131  2444 [  5]           ntdll_77bc0000!RtlpDosPathNameToRelativeNtPathName
   32     0 [  6]             ntdll_77bc0000!memmove
  169  2476 [  5]           ntdll_77bc0000!RtlpDosPathNameToRelativeNtPathName
   44     0 [  6]             ntdll_77bc0000!memmove
  206  2520 [  5]           ntdll_77bc0000!RtlpDosPathNameToRelativeNtPathName
   12     0 [  6]             ntdll_77bc0000!RtlpReferenceCurrentDirectory
   16     0 [  7]               ntdll_77bc0000!RtlEnterCriticalSection
   20    16 [  6]             ntdll_77bc0000!RtlpReferenceCurrentDirectory
   25     0 [  7]               ntdll_77bc0000!RtlLeaveCriticalSection
   35    41 [  6]             ntdll_77bc0000!RtlpReferenceCurrentDirectory
  216  2596 [  5]           ntdll_77bc0000!RtlpDosPathNameToRelativeNtPathName
  171     0 [  6]             ntdll_77bc0000!RtlPrefixUnicodeString
  252  2767 [  5]           ntdll_77bc0000!RtlpDosPathNameToRelativeNtPathName
    3     0 [  6]             ntdll_77bc0000!__security_check_cookie
  255  2770 [  5]           ntdll_77bc0000!RtlpDosPathNameToRelativeNtPathName
   22  3090 [  4]         ntdll_77bc0000!RtlDosPathNameToRelativeNtPathName_U_WithStatus
  168  3177 [  3]       KERNELBASE!CreateFileInternal
   50     0 [  4]         ntdll_77bc0000!SbSelectProcedure
   60     0 [  5]           ntdll_77bc0000!memset
   60    60 [  4]         ntdll_77bc0000!SbSelectProcedure
   34     0 [  5]           ntdll_77bc0000!SbObtainTraceHandle
   69    94 [  4]         ntdll_77bc0000!SbSelectProcedure
   56     0 [  5]           ntdll_77bc0000!memset
   95   150 [  4]         ntdll_77bc0000!SbSelectProcedure
    3     0 [  5]           ntdll_77bc0000!__security_check_cookie
   98   153 [  4]         ntdll_77bc0000!SbSelectProcedure
  175  3428 [  3]       KERNELBASE!CreateFileInternal
    1     0 [  4]         KERNELBASE!CDPPreShutdown
  176  3429 [  3]       KERNELBASE!CreateFileInternal
    1     0 [  4]         KERNELBASE!AfpAdminDisconnect
  198  3430 [  3]       KERNELBASE!CreateFileInternal
   64     0 [  4]         apphelp!InsHook_NtCreateFile
  116     0 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!_wcsnicmp
   62     0 [  6]             ntdll_77bc0000!_wcsnicmp
  126    63 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!_wcsnicmp
   62     0 [  6]             ntdll_77bc0000!_wcsnicmp
  136   126 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!_wcsnicmp
   62     0 [  6]             ntdll_77bc0000!_wcsnicmp
  146   189 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!_wcsnicmp
   62     0 [  6]             ntdll_77bc0000!_wcsnicmp
  156   252 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!_wcsnicmp
   62     0 [  6]             ntdll_77bc0000!_wcsnicmp
  166   315 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!_wcsnicmp
   62     0 [  6]             ntdll_77bc0000!_wcsnicmp
  176   378 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!_wcsnicmp
   62     0 [  6]             ntdll_77bc0000!_wcsnicmp
  186   441 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!_wcsnicmp
   62     0 [  6]             ntdll_77bc0000!_wcsnicmp
  196   504 [  5]           apphelp!Insp_ExtensionMatch
    1     0 [  6]             apphelp!_wcsnicmp
   62     0 [  6]             ntdll_77bc0000!_wcsnicmp
  207   567 [  5]           apphelp!Insp_ExtensionMatch
   82   774 [  4]         apphelp!InsHook_NtCreateFile
    1     0 [  5]           apphelp!_guard_check_icall_nop
   83   775 [  4]         apphelp!InsHook_NtCreateFile
    3     0 [  5]           ntdll_77bc0000!NtCreateFile
    1     0 [  6]             ntdll_77bc0000!Wow64SystemServiceCall
    2     0 [  6]             wow64cpu!KiFastSystemCall
   13     0 [  6]             wow64cpu!CpupReturnFromSimulatedCode
    3     0 [  6]             wow64cpu!TurboDispatchJumpAddressStart
    3     0 [  6]             wow64cpu!ServiceNoTurbo
   71     0 [  7]               wow64!Wow64SystemServiceEx
   32     0 [  8]                 wow64!whNtCreateFile
   71     0 [  9]                   wow64!Wow64ShallowThunkAllocObjectAttributes32TO64_FNC
   39     0 [ 10]                     wow64!Wow64ShallowThunkAllocSecurityQualityOfService32TO64_FNC
  129    39 [  9]                   wow64!Wow64ShallowThunkAllocObjectAttributes32TO64_FNC
   26     0 [ 10]                     ntdll!RtlAppendUnicodeStringToString
   38     0 [ 11]                       ntdll!memcpy
   42    38 [ 10]                     ntdll!RtlAppendUnicodeStringToString
  134   119 [  9]                   wow64!Wow64ShallowThunkAllocObjectAttributes32TO64_FNC
   26     0 [ 10]                     ntdll!RtlAppendUnicodeStringToString
   34     0 [ 11]                       ntdll!memcpy
   40    34 [ 10]                     ntdll!RtlAppendUnicodeStringToString
  171   193 [  9]                   wow64!Wow64ShallowThunkAllocObjectAttributes32TO64_FNC
   33     0 [ 10]                     wow64!RedirectPath
  103     0 [ 11]                       ntdll!RtlPrefixUnicodeString
   52   103 [ 10]                     wow64!RedirectPath
   42     0 [ 11]                       ntdll!RtlPrefixUnicodeString
    6     0 [ 12]                         ntdll!NLS_UPCASE
   45     6 [ 11]                       ntdll!RtlPrefixUnicodeString
    6     0 [ 12]                         ntdll!NLS_UPCASE
   51    12 [ 11]                       ntdll!RtlPrefixUnicodeString
   62   166 [ 10]                     wow64!RedirectPath
   11     0 [ 11]                       ntdll!RtlEqualUnicodeString
   68   177 [ 10]                     wow64!RedirectPath
   24     0 [ 11]                       ntdll!RtlPrefixUnicodeString
    6     0 [ 12]                         ntdll!NLS_UPCASE
   27     6 [ 11]                       ntdll!RtlPrefixUnicodeString
    6     0 [ 12]                         ntdll!NLS_UPCASE
   33    12 [ 11]                       ntdll!RtlPrefixUnicodeString
   80   222 [ 10]                     wow64!RedirectPath
   73     0 [ 11]                       ntdll!RtlPrefixUnicodeString
  109   295 [ 10]                     wow64!RedirectPath
   24     0 [ 11]                       ntdll!RtlPrefixUnicodeString
    4     0 [ 12]                         ntdll!NLS_UPCASE
   27     4 [ 11]                       ntdll!RtlPrefixUnicodeString
    6     0 [ 12]                         ntdll!NLS_UPCASE
   33    10 [ 11]                       ntdll!RtlPrefixUnicodeString
  122   338 [ 10]                     wow64!RedirectPath
   24     0 [ 11]                       ntdll!RtlPrefixUnicodeString
    4     0 [ 12]                         ntdll!NLS_UPCASE
   27     4 [ 11]                       ntdll!RtlPrefixUnicodeString
    6     0 [ 12]                         ntdll!NLS_UPCASE
   33    10 [ 11]                       ntdll!RtlPrefixUnicodeString
  135   381 [ 10]                     wow64!RedirectPath
   10     0 [ 11]                       ntdll!RtlPrefixUnicodeString
  148   391 [ 10]                     wow64!RedirectPath
   10     0 [ 11]                       ntdll!RtlPrefixUnicodeString
  161   401 [ 10]                     wow64!RedirectPath
   10     0 [ 11]                       ntdll!RtlPrefixUnicodeString
  174   411 [ 10]                     wow64!RedirectPath
   24     0 [ 11]                       ntdll!RtlPrefixUnicodeString
    4     0 [ 12]                         ntdll!NLS_UPCASE
   27     4 [ 11]                       ntdll!RtlPrefixUnicodeString
    6     0 [ 12]                         ntdll!NLS_UPCASE
   33    10 [ 11]                       ntdll!RtlPrefixUnicodeString
  187   454 [ 10]                     wow64!RedirectPath
   24     0 [ 11]                       ntdll!RtlPrefixUnicodeString
    4     0 [ 12]                         ntdll!NLS_UPCASE
   27     4 [ 11]                       ntdll!RtlPrefixUnicodeString
    6     0 [ 12]                         ntdll!NLS_UPCASE
   33    10 [ 11]                       ntdll!RtlPrefixUnicodeString
  207   497 [ 10]                     wow64!RedirectPath
   26     0 [ 11]                       ntdll!RtlAppendUnicodeStringToString
   49     0 [ 12]                         ntdll!memcpy
   42    49 [ 11]                       ntdll!RtlAppendUnicodeStringToString
  210   588 [ 10]                     wow64!RedirectPath
   26     0 [ 11]                       ntdll!RtlAppendUnicodeStringToString
   34     0 [ 12]                         ntdll!memcpy
   42    34 [ 11]                       ntdll!RtlAppendUnicodeStringToString
  213   664 [ 10]                     wow64!RedirectPath
   26     0 [ 11]                       ntdll!RtlAppendUnicodeStringToString
   44     0 [ 12]                         ntdll!memcpy
   42    44 [ 11]                       ntdll!RtlAppendUnicodeStringToString
  222   750 [ 10]                     wow64!RedirectPath
    6     0 [ 11]                       wow64!_security_check_cookie
  232   756 [ 10]                     wow64!RedirectPath
  180  1181 [  9]                   wow64!Wow64ShallowThunkAllocObjectAttributes32TO64_FNC
   15     0 [ 10]                     wow64!Wow64LogPrint
    6     0 [ 11]                       wow64!_security_check_cookie
   17     6 [ 10]                     wow64!Wow64LogPrint
  186  1204 [  9]                   wow64!Wow64ShallowThunkAllocObjectAttributes32TO64_FNC
    6     0 [ 10]                     wow64!_security_check_cookie
  195  1210 [  9]                   wow64!Wow64ShallowThunkAllocObjectAttributes32TO64_FNC
   59  1405 [  8]                 wow64!whNtCreateFile
    6     0 [  9]                   ntdll!NtCreateFile

همانطور که در تصویر هم مشاهده می کنید، از زمان فراخوانی CreateFile تا رسیدن به ntdll!NtCreateFile یک مسیر طولانی طی شده. به همین خاطر بر روی ntdll_77bc0000!NtCreateFile یک bp قرار می‌دهیم. با اجرای روند برنامه و رسیدن به این تابع و disassemble کردن اون، چیز عجیبی می‌بینیم:

0:000:x86> uf ntdll_77bc0000!NtCreateFile
ntdll_77bc0000!NtCreateFile:
77c322c0 b855000000      mov     eax,55h
77c322c5 ba408dc477      mov     edx,offset ntdll_77bc0000!Wow64SystemServiceCall (77c48d40)
77c322ca ffd2            call    edx
77c322cc c22c00          ret     2Ch

اثری از syscall یا int 2eh نمی‌بینیم! پس کجا این مورد اتفاق میفته؟

اگه خاطرتون باشه گفتیم که Kernel سیستم‌عامل ۶۴بیتی طبییعتا ۶۴بیتی هست پس نمیتونه فراخوانی‌های ۳۲بیتی رو Handle کنه. (باز هم) پس باید یک فراخوانی ۳۲بیتی رو به یه فراخوانی ۶۴بیتی تبدیل کنیم.

اگه دوباره به نتیحه instructionهای تابع ntdll_77bc0000!NtCreateFile برگردیم، در خط ۵، یه فراخوانی داریم به تابع ntdll_77bc0000!Wow64SystemServiceCall.

با چندبار زدن t به داخل این فراخوانی میریم تا دستور آن را مشاهده کنیم:

0:000:x86> t
ntdll_77bc0000!Wow64SystemServiceCall:
77c48d40 ff252812ce77    jmp     dword ptr [ntdll_77bc0000!Wow64Transition (77ce1228)] ds:002b:77ce1228={wow64cpu!KiFastSystemCall (77bb6000)}

گویا از اینجا داره عملیات تبدیل فراخوانی ۳۲بیتی یه یک فراخوانی ۶۴بیتی شروع میشه.

اگر این jmp را انجام دهیم وارد یه dll دیگه‌ای با نام wow64cpu میشیم. ما سه ماژول با نام‌های مشابه داریم:

  • wow64.dll مسئول ترجمه فراخوانی‌های سیستمی *Nt است (ntoskrnl.exe / ntdll.dll).
  • wow64win.dll مسئول ترجمه فراخوانی‌های سیستمی *NtGdi و*NtUser و سایر فراخوانی‌های سیستمی مرتبط با GUI است ( (win32k.sys / win32u.dll).
  • wow64cpu.dll مسئول ساپورت کردن اجرای فرآیندهای ۳۲بیتی در سیستم‌عامل ۶۴بیتی است.

این سه مورد رو با هم اشتباه نگیرید.

با زدن t، اجرا رو ادامه میدیم:

0:000:x86> t
wow64cpu!KiFastSystemCall:
77bb6000 ea0960bb773300  jmp     0033:77BB6009

به «دروازه بهشت» خوش آمدید!

Heaven’s Gate یا دروازه بهشت جایی است که طی یک jmp از ۳۲بیت به ۶۴بیت کوچ می‌کنیم. و البته یک دروازه دوست داشتنی برای بدافزارها!

بگذریم، حالا سوال اینطور مطرح میشه که آدرس این jmp اصلا چطور مشخص میشه؟

برای پاسخ به این پرسش نیازمند بررسی TEB هستیم.

0:000:x86> !teb
Wow64 TEB32 at 00dc2000
    ExceptionList:        00f3f8ec
    StackBase:            00f40000
    StackLimit:           00f3d000
    SubSystemTib:         00000000
    FiberData:            00001e00
    ArbitraryUserPointer: 00000000
    Self:                 00dc2000
    EnvironmentPointer:   00000000
    ClientId:             00000ebc . 00003f9c
    RpcHandle:            00000000
    Tls Storage:          00dc202c
    PEB Address:          00dbf000
    LastErrorValue:       0
    LastStatusValue:      c0000034
    Count Owned Locks:    0
    HardErrorMode:        0
Wow64 TEB at 00dc0000
    ExceptionList:        00dc2000
    StackBase:            00e3fd20
    StackLimit:           00e38000
    SubSystemTib:         00000000
    FiberData:            00001e00
    ArbitraryUserPointer: 00000000
    Self:                 00dc0000
    EnvironmentPointer:   00000000
    ClientId:             00000ebc . 00003f9c
    RpcHandle:            00000000
    Tls Storage:          00000000
    PEB Address:          00dbe000
    LastErrorValue:       0
    LastStatusValue:      0
    Count Owned Locks:    0
    HardErrorMode:        0

اگه Wow64 TEB32 رو بررسی کنیم داریم:

0:000:x86> dt _teb 00dc2000
ntdll_77bc0000!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : (null) 
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : (null) 
   +0x02c ThreadLocalStoragePointer : 0x00dc202c Void
   +0x030 ProcessEnvironmentBlock : 0x00dbf000 _PEB
   +0x034 LastErrorValue   : 0
   +0x038 CountOfOwnedCriticalSections : 0
   +0x03c CsrClientThread  : (null) 
   +0x040 Win32ThreadInfo  : (null) 
   +0x044 User32Reserved   : [26] 0
   +0x0ac UserReserved     : [5] 0
   +0x0c0 WOW32Reserved    : 0x77bb6000 Void
   +0x0c4 CurrentLocale    : 0x409
   +0x0c8 FpSoftwareStatusRegister : 0
   +0x0cc ReservedForDebuggerInstrumentation : [16] (null) 
   +0x10c SystemReserved1  : [26] (null) 
   +0x174 PlaceholderCompatibilityMode : 0 ''
   +0x175 PlaceholderHydrationAlwaysExplicit : 0 ''
   +0x176 PlaceholderReserved : [10]  ""
   +0x180 ProxiedProcessId : 0
   +0x184 _ActivationStack : _ACTIVATION_CONTEXT_STACK
   +0x19c WorkingOnBehalfTicket : [8]  ""
   +0x1a4 ExceptionCode    : 0n0
   +0x1a8 ActivationContextStackPointer : 0x00dc2184 _ACTIVATION_CONTEXT_STACK
   +0x1ac InstrumentationCallbackSp : 0
   +0x1b0 InstrumentationCallbackPreviousPc : 0
   +0x1b4 InstrumentationCallbackPreviousSp : 0
   +0x1b8 InstrumentationCallbackDisabled : 0 ''
   +0x1b9 SpareBytes       : [23]  ""
   +0x1d0 TxFsContext      : 0xfffe
   +0x1d4 GdiTebBatch      : _GDI_TEB_BATCH
   +0x6b4 RealClientId     : _CLIENT_ID
   +0x6bc GdiCachedProcessHandle : (null) 
   +0x6c0 GdiClientPID     : 0
   +0x6c4 GdiClientTID     : 0
   +0x6c8 GdiThreadLocalInfo : (null) 
   +0x6cc Win32ClientInfo  : [62] 0
   +0x7c4 glDispatchTable  : [233] (null) 
   +0xb68 glReserved1      : [29] 0
   +0xbdc glReserved2      : (null) 
   +0xbe0 glSectionInfo    : (null) 
   +0xbe4 glSection        : (null) 
   +0xbe8 glTable          : (null) 
   +0xbec glCurrentRC      : (null) 
   +0xbf0 glContext        : (null) 
   +0xbf4 LastStatusValue  : 0xc0000034
   +0xbf8 StaticUnicodeString : _UNICODE_STRING ""
   +0xc00 StaticUnicodeBuffer : [261]  ""
   +0xe0c DeallocationStack : 0x00e40000 Void
   +0xe10 TlsSlots         : [64] (null) 
   +0xf10 TlsLinks         : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0xf18 Vdm              : (null) 
   +0xf1c ReservedForNtRpc : (null) 
   +0xf20 DbgSsReserved    : [2] (null) 
   +0xf28 HardErrorMode    : 0
   +0xf2c Instrumentation  : [9] (null) 
   +0xf50 ActivityId       : _GUID {00000000-0000-0000-0000-000000000000}
   +0xf60 SubProcessTag    : (null) 
   +0xf64 PerflibData      : (null) 
   +0xf68 EtwTraceData     : (null) 
   +0xf6c WinSockData      : (null) 
   +0xf70 GdiBatchCount    : 0xdc0000
   +0xf74 CurrentIdealProcessor : _PROCESSOR_NUMBER
   +0xf74 IdealProcessorValue : 0x2020000
   +0xf74 ReservedPad0     : 0 ''
   +0xf75 ReservedPad1     : 0 ''
   +0xf76 ReservedPad2     : 0x2 ''
   +0xf77 IdealProcessor   : 0x2 ''
   +0xf78 GuaranteedStackBytes : 0
   +0xf7c ReservedForPerf  : (null) 
   +0xf80 ReservedForOle   : (null) 
   +0xf84 WaitingOnLoaderLock : 0
   +0xf88 SavedPriorityState : (null) 
   +0xf8c ReservedForCodeCoverage : 0
   +0xf90 ThreadPoolData   : (null) 
   +0xf94 TlsExpansionSlots : (null) 
   +0xf98 MuiGeneration    : 0
   +0xf9c IsImpersonating  : 0
   +0xfa0 NlsCache         : (null) 
   +0xfa4 pShimData        : (null) 
   +0xfa8 HeapData         : 0
   +0xfac CurrentTransactionHandle : (null) 
   +0xfb0 ActiveFrame      : (null) 
   +0xfb4 FlsData          : 0x0128a498 Void
   +0xfb8 PreferredLanguages : (null) 
   +0xfbc UserPrefLanguages : 0x012870e8 Void
   +0xfc0 MergedPrefLanguages : 0x012898a8 Void
   +0xfc4 MuiImpersonation : 0
   +0xfc8 CrossTebFlags    : 0
   +0xfc8 SpareCrossTebBits : 0y0000000000000000 (0)
   +0xfca SameTebFlags     : 0x620
   +0xfca SafeThunkCall    : 0y0
   +0xfca InDebugPrint     : 0y0
   +0xfca HasFiberData     : 0y0
   +0xfca SkipThreadAttach : 0y0
   +0xfca WerInShipAssertCode : 0y0
   +0xfca RanProcessInit   : 0y1
   +0xfca ClonedThread     : 0y0
   +0xfca SuppressDebugMsg : 0y0
   +0xfca DisableUserStackWalk : 0y0
   +0xfca RtlExceptionAttached : 0y1
   +0xfca InitialThread    : 0y1
   +0xfca SessionAware     : 0y0
   +0xfca LoadOwner        : 0y0
   +0xfca LoaderWorker     : 0y0
   +0xfca SkipLoaderInit   : 0y0
   +0xfca SpareSameTebBits : 0y0
   +0xfcc TxnScopeEnterCallback : (null) 
   +0xfd0 TxnScopeExitCallback : (null) 
   +0xfd4 TxnScopeContext  : (null) 
   +0xfd8 LockCount        : 0
   +0xfdc WowTebOffset     : 0n-8192
   +0xfe0 ResourceRetValue : 0x01287510 Void
   +0xfe4 ReservedForWdf   : (null) 
   +0xfe8 ReservedForCrt   : 0
   +0xff0 EffectiveContainerId : _GUID {00000000-0000-0000-0000-000000000000}

در آفست C0، پارامتر WOW32Reserved به آدرس 0x77bb6000 اشاره می کند. این آدرس، دستورالعمل مذکور رو در خودش نگه می داره. واسه اطمینان با هم دیگه ببینیم:

0:000:x86> u 0x77bb6000
wow64cpu!KiFastSystemCall:
77bb6000 ea0960bb773300  jmp     0033:77BB6009
77bb6007 0000            add     byte ptr [eax],al
77bb6009 41              inc     ecx
77bb600a ffa7f8000000    jmp     dword ptr [edi+0F8h]
77bb6010 0000            add     byte ptr [eax],al
77bb6012 0000            add     byte ptr [eax],al
77bb6014 0000            add     byte ptr [eax],al
77bb6016 0000            add     byte ptr [eax],al

خوب، دوباره برگردیم به کدی که داشت اجرا میشد و با اجرای دستور jmp از دروازه بهشت عبور کنیم:

wow64cpu!KiFastSystemCall+0x9:
00000000`77bb6009 41ffa7f8000000  jmp     qword ptr [r15+0F8h] ds:00000000`77bb3718={wow64cpu!CpupReturnFromSimulatedCode (00000000`77bb1742)}

به آدرس دستوراالعمل دقت کنید! بله، دیگه وارد دنیای ۶۴بیت شدیم.

از اونجایی که trace کردن و رسیدن به ntdll!NtCreateFile خیلی طول میکشه، با گذاشتن bp بر روی این تابع، مستقیم وارد ntdll از نوع ۶۴بیت میشیم.

با توقف روی ابتدای این تابع، دستوراالعمل‌هایش رو بررسی می‌کنیم:

0:000> u
ntdll!NtCreateFile:
00007ff8`040bcb50 4c8bd1          mov     r10,rcx
00007ff8`040bcb53 b855000000      mov     eax,55h
00007ff8`040bcb58 f604250803fe7f01 test    byte ptr [Sh1aredUserData+0x308 (00000000`7ffe0308)],1
00007ff8`040bcb60 7503            jne     ntdll!NtCreateFile+0x15 (00007ff8`040bcb65)
00007ff8`040bcb62 0f05            syscall
00007ff8`040bcb64 c3              ret
00007ff8`040bcb65 cd2e            int     2Eh
00007ff8`040bcb67 c3              ret

به نتایج مشابه اون چیزی که در تحلیل فراخوانی‌ ۶۴بیتی در سیستم‌عامل ۶۴بیتی بود رسیدیم. حالا نگاه کنیم لیست ۱۱ فراخوانی اخیر تا قبل از رسیدن به ntdll!NtCreateFile چه بود:

0:000> kc
 # Call Site
00 ntdll!NtCreateFile
01 wow64!whNtCreateFile
02 wow64!Wow64SystemServiceEx
03 wow64cpu!ServiceNoTurbo
04 wow64cpu!BTCpuSimulate
05 wow64!RunCpuSimulation
06 wow64!Wow64LdrpInitialize
07 ntdll!LdrpInitializeProcess
08 ntdll!_LdrpInitialize
09 ntdll!LdrpInitialize
0a ntdll!LdrInitializeThunk

هر کدوم از این توابع نقشی رو ایفا میکنه و من نمیخوام وارد جزئیات هر کدوم از این توابع بشم. فقط به عنوان نمونه، یکی از وظایف تابع wow64!whNtCreateFile (وبه صورت کی، همه توابع *wow64!wh)، تبدیل استاندارد پاس دهی آرگومان‌های تابع از قالب ۳۲بیتی به ۶۴بیتی هست. همونطور که می‌دونید، در فرآیندهای ۳۲بیتی، هنگام فراخوانی یک تابع، آرگومان‌های اون از راست به چپ در پشته push میشن ولی درفرآیندهای ۶۴بیتی، از راست به چپ، چهار آرگومان اول به ترتیب در رجیسترهای rcx و rdx و r8 و r9 قرار داده میشن و باقی آرگومان‌ها در پشته push میشن.

4 thoughts to “Life of a WinAPI: from user-mode to kernel-mode”

  1. با سلام و تشکر از آموزش هاتون. چنتا سوال داشتم.
    وقتی bu ntdll_test!main رو وارد میکنم با ارورو
    ^ Operation not supported by current debuggee error in ‘bu ntdll_test!main’
    مواجه میشم و وقتی wt رو میزنم با ارور
    ^ No runnable debuggees error in ‘wt’
    مواجه میشوم. میشه کمی راهنمایی کنید …..

    1. سلام
      خواهش می‌کنم
      این جوری بررسی کردن شاید یه خرده سحت باشه ولی
      چیزی که به ذهنم می‌رسه (و البته واسه دبل جک کردن) اینه که
      فایل اجرای کد ++C بالا به اسم ntdll_test.exe هست. آیا اسم فایل اجرایی شما هم همین هست؟
      و دوم این که (بر مبنای متن خود ارورها) به نظر می‌رسه فایل اجرای مدنظر به درستی برای دیباگ کردن انتخاب یا متصل به دیباگر نشده باشه.
      این موارد رو چک کردین؟

      1. بله با همین نام هست.
        بنظرم متصل هست. entrypoint رو تشخیص میده.

  2. سلام و عرض خسته نباشید مجدد.
    من موقع دیس اسمبل کردن ntdll!NtCreateFile ، syscall و int 2eh رو میبینم ولی وقتی از تابع ntdll!NtCreateFile تریس میکنم بهشون نمیرسم و میرم داخل توابع دیگه داخلی ویندوز. مشکل از کجا میتونه باشه ؟

پاسخ دادن به Amid لغو پاسخ

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *