Прикольно если на основе таких функций самому реализовать обертки под CreateFileA/W с теми же самыми параметрами и типами переменных, не уходя в юзермодные dll. Только ntdll.dll только хардкор. Чтобы все эти обертки работали как оригинальные функции и подключались в виде отдельного файла "brain_fuck.h" или "this_is_sparta.h".
Уже делал такое много лет назад (без инклудов) https://www.cyberforum.ru/blogs/172954/5635.html Переопределяем PEB и сопутствующие структуры, читаем регистр, и получаем адрес ntdll.dll А дальше полет фантазии. Код конечно не идеальный, давно это было, и переписывать лень.
Найти базу Ntdll можно ещё и через стек - имхо это проще, чем парсить РЕВ.Ldr Суть в том, что на каком-то этапе загрузчик образов зовёт RtlUserThreadStart() из Ntdll, и её адрес остаётся в стеке - это видно в любом отладчике: Код (Text): 0:000> bp @$exentry <-------- OEP 0:000> g Breakpoint 0 hit 00000000`00401000 4883ec08 sub rsp,8 0:000> dqs rsp 00000000`0006ff58 00000000`76de556d kernel32!BaseThreadInitThunk+0xd 00000000`0006ff60 00000000`00000000 00000000`0006ff68 00000000`00000000 00000000`0006ff70 00000000`00000000 00000000`0006ff78 00000000`00000000 00000000`0006ff80 00000000`00000000 00000000`0006ff88 00000000`76f4372d ntdll!RtlUserThreadStart+0x1d <-------- 00000000`0006ff90 00000000`00000000 00000000`0006ff98 00000000`00000000 00000000`0006ffa0 00000000`00000000 00000000`0006ffa8 00000000`00000000 00000000`0006ffb0 00000000`00000000 00000000`0006ffb8 00000000`00000000 00000000`0006ffc0 00000000`00000000 00000000`0006ffc8 00000000`00000000 00000000`0006ffd0 00000000`00000000 Остаётся шагая по страницам назад, найти сигнатуру 'MZ'. Не знаю как в Win10/11, но на Win7 фишка вроде работает. Здесь я загрузил msvcrt чтобы просто показать результат, хотя в реальном коде секция-импорта вообще не нужна, т.к. поиск функций из Ntdll осуществляется через её секцию-экспорта. Аналогичным образом можно получить и базу Kernel32: Код (ASM): format pe64 console include 'win64ax.inc' entry start ;//------------- section '.text' code readable executable start: sub rsp,8 mov rsi,rsp add rsi,16 ;// Поиск ntdll.RtlUserThreadStart() в стеке @@: lodsq or rax,rax jz @b push rax ;// Покажем найденное значение mov ebx,eax shr rax,32 cinvoke printf,<10,' Ntdll stack: %08x`%08x',0>,eax,ebx ;// Поиск базы Ntdll по сигнатуре 'MZ' pop rax and eax,not 0xfff ;// выравнивание на 4К-страницу @@: cmp word[rax],'MZ' je @f sub rax,0x1000 ;// шагаем назад.. jmp @b ;// RAX = база Ntdll в памяти @@: mov ebx,eax shr rax,32 cinvoke printf,<10,' Ntdll base : %08x`%08x',0>,eax,ebx cinvoke getch cinvoke exit,0 ;//------------------------- section '.idata' import data readable writeable library msvcrt,'msvcrt.dll' import msvcrt,printf,'printf',getch,'_getch', exit, 'exit' Код (Text): 0:000> !peb PEB at 000007fffffdd000 InheritedAddressSpace: No ReadImageFileExecOptions: No BeingDebugged: Yes ImageBaseAddress: 0000000000400000 Ldr 0000000077022e40 Ldr.Initialized: Yes Ldr.InInitOrderModuleList: 00000000001e2bb0 . 00000000001e4150 Ldr.InLoadOrderModuleList: 00000000001e2a80 . 00000000001e4130 Ldr.InMemoryOrderModuleList: 00000000001e2a90 . 00000000001e4140 Base TimeStamp Module 400000 6a18c906 May 29 04:00:22 2026 D:\Install\DEBUG\ASM\CODE\stack.exe -----> 76ef0000 5e0eb67f Jan 03 08:35:27 2020 C:\Windows\SYSTEM32\ntdll.dll 76dd0000 5e0eb6bc Jan 03 08:36:28 2020 C:\Windows\system32\kernel32.dll 7fefcd80000 5e0eb6bd Jan 03 08:36:29 2020 C:\Windows\system32\KERNELBASE.dll 7fefd160000 4eeb033f Dec 16 13:37:19 2011 C:\Windows\system32\msvcrt.dll ............
Это же около-малварный кодинг? А зачем это нужно в совр. мире? Кроме хайда exe есть еще проблемы uac, передачи инфы и т.д.
Всё, кроме легальных GetProcAddress() является около-малварным, а uac здесь вообще ни при делах - это будет работать даже под обычным юзером.
Нет, это не вещь в себе - просто всё либы загружаешь динамически или через LoadLibrary() из kernel32 (база ведь есть уже), или из ntdll через альтернативу LdrLoadDll().
Да.. это древний приём, но здесь интересно другое. Как оказалось, если вскормить аверам на VirusTotal версию х64 этой фишки, то всего 2/70 что-то там подозревают. А вот на версию х32 ругаются уже 9/70. Видимо сторожа х64 вырезали сигнатуры трюка из своих баз (как устаревшие), хотя паттерны остались для кода х32. Таким образом, нестандартные/старые техники только плюс в наше время. Код (ASM): start: ;// Поиск базы Kernel32 mov eax,[esp] ; линк на kernel32 and eax,not 0xfff ; выравнивание на 4К-страницу @@: cmp word[eax],'MZ' je @f sub eax,0x1000 ; шагаем назад.. jmp @b ;// EAX = база в памяти @@: cinvoke printf,<10,' KernelBase: %08x',0>,eax