Вызов напрямую winapi

Тема в разделе "WASM.BEGINNERS", создана пользователем piligmindo, 12 июл 2022.

  1. Research

    Research Active Member

    Публикаций:
    1
    Регистрация:
    6 янв 2024
    Сообщения:
    538
    Прикольно если на основе таких функций самому реализовать обертки под CreateFileA/W с теми же самыми параметрами и типами переменных, не уходя в юзермодные dll. Только ntdll.dll только хардкор. Чтобы все эти обертки работали как оригинальные функции и подключались в виде отдельного файла "brain_fuck.h" или "this_is_sparta.h".
     
  2. k3rnl

    k3rnl Member

    Публикаций:
    0
    Регистрация:
    28 янв 2021
    Сообщения:
    74
    Уже делал такое много лет назад (без инклудов) https://www.cyberforum.ru/blogs/172954/5635.html
    Переопределяем PEB и сопутствующие структуры, читаем регистр, и получаем адрес ntdll.dll
    А дальше полет фантазии.
    Код конечно не идеальный, давно это было, и переписывать лень.
     
    Mikl___ нравится это.
  3. Marylin

    Marylin Active Member

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

    Research Active Member

    Публикаций:
    1
    Регистрация:
    6 янв 2024
    Сообщения:
    538
    Это же около-малварный кодинг? А зачем это нужно в совр. мире?
    Кроме хайда exe есть еще проблемы uac, передачи инфы и т.д.
     
  5. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    346
    Всё, кроме легальных GetProcAddress() является около-малварным,
    а uac здесь вообще ни при делах - это будет работать даже под обычным юзером.
     
  6. Research

    Research Active Member

    Публикаций:
    1
    Регистрация:
    6 янв 2024
    Сообщения:
    538
    Это гипотетически будет малварь без связи с внешним миром?
     
  7. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    346
    Нет, это не вещь в себе - просто всё либы загружаешь динамически или через LoadLibrary() из kernel32 (база ведь есть уже), или из ntdll через альтернативу LdrLoadDll().
     
  8. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    899
    Вот кстати такой метод я тут делал, правда там kernel32 получался.
     
  9. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    346
    Да.. это древний приём, но здесь интересно другое.
    Как оказалось, если вскормить аверам на VirusTotal версию х64 этой фишки, то всего 2/70 что-то там подозревают. А вот на версию х32 ругаются уже 9/70. Видимо сторожа х64 вырезали сигнатуры трюка из своих баз (как устаревшие), хотя паттерны остались для кода х32. Таким образом, нестандартные/старые техники только плюс в наше время.
    Код (ASM):
    1. start:
    2. ;// Поиск базы Kernel32
    3.         mov     eax,[esp]        ; линк на kernel32
    4.         and     eax,not 0xfff    ; выравнивание на 4К-страницу
    5. @@:     cmp     word[eax],'MZ'
    6.         je      @f
    7.         sub     eax,0x1000       ; шагаем назад..
    8.         jmp     @b
    9.  
    10. ;// EAX = база в памяти
    11. @@:    cinvoke  printf,<10,' KernelBase:  %08x',0>,eax
    12.