در این پست قراره مراحلی رو که یک 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 میشن.
با سلام و تشکر از آموزش هاتون. چنتا سوال داشتم.
وقتی bu ntdll_test!main رو وارد میکنم با ارورو
^ Operation not supported by current debuggee error in ‘bu ntdll_test!main’
مواجه میشم و وقتی wt رو میزنم با ارور
^ No runnable debuggees error in ‘wt’
مواجه میشوم. میشه کمی راهنمایی کنید …..
سلام
خواهش میکنم
این جوری بررسی کردن شاید یه خرده سحت باشه ولی
چیزی که به ذهنم میرسه (و البته واسه دبل جک کردن) اینه که
فایل اجرای کد ++C بالا به اسم ntdll_test.exe هست. آیا اسم فایل اجرایی شما هم همین هست؟
و دوم این که (بر مبنای متن خود ارورها) به نظر میرسه فایل اجرای مدنظر به درستی برای دیباگ کردن انتخاب یا متصل به دیباگر نشده باشه.
این موارد رو چک کردین؟
بله با همین نام هست.
بنظرم متصل هست. entrypoint رو تشخیص میده.
سلام و عرض خسته نباشید مجدد.
من موقع دیس اسمبل کردن ntdll!NtCreateFile ، syscall و int 2eh رو میبینم ولی وقتی از تابع ntdll!NtCreateFile تریس میکنم بهشون نمیرسم و میرم داخل توابع دیگه داخلی ویندوز. مشکل از کجا میتونه باشه ؟