На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Все статьи должны быть оформлены согласно Правил оформления статей.
2. Любые обсуждения должны происходить в специальной теме, обсуждение в любых других темах раздела запрещены.
3. Запрещается писать статьи о создании и распространении вирусов, троянов и других вредоносных программ!
4. За грамотно написанные и правильно оформленные статьи авторы награждаются DigiMoney.

Дополнительные ссылки:
Желаю творческих успехов! ;)
Модераторы: Jin X
  
    > Пишем простейший загрузчик PE файлов, FASM, Win, Zen
       
      Пишем простейший загрузчик PE файлов

      ВНИМАНИЕ статья рассчитана на читателя, который знает формат PE файлов или по крайней мере держит в руках доку.
      И так, чтобы не влезать в систему, и не громоздить в коде функции для работы с потоками и создания процессов, мы будем догружать PE файл в своё адресное пространство.
      Теперь по порядку о том, что нам нужно будет сделать:
      1) Нужно будет изменить у нашего PE загрузчика базовый адрес загрузки, в FASM для этого используется специальная директива(смотри код).
      2) Прочитать в память PE файл
      3) Разобрать PE заголовок, определить Image Base, адрес таблицы секций
      4) Разобрать таблицу секций, скопировать секции по адресам, указанным в таблице
      5) Определить адрес таблицы импорта, заполнить таблицу импорта
      6) Поставить заглушку на завершение программы.
      7) Желательно поставить заглушку на GetModuleHandle чтобы корректно работали ресурсы.
      Сразу прошу прощения за плохо комментированный код :( Программе уже не один год, и вспомнить смысл каждой строчки сложно….
      ExpandedWrap disabled
        format PE GUI 4.0 at  0500000h   ; базовый адрес загрузки проги теперь 0500000h
        ; стандартно проги грузятся на 0400000h
        include 'win32ax.inc'
        ; секция данных
        .data
        h                dd 0
        hfile            dd 0h
        fsize            dd 0h
        buffer           rd 512
        hmem             dd 0h
        PEa              dd 0h
        Vsize            dd 0h
        Vadr             dd 0h
        Psize            dd 0h
        Padr             dd 0h
        Iadr             dd 0h
        Isize            dd 0h
        BaseAdr          dd 400000h
        nums             dd 0
        hdll             dd 0h
        fname            dd 0
        EDIs             dd 0
        ECXs             dd 0
        ERMSG            db 'Ошибка при загрузку файла. Код ошибки <<'
        ERC              dw 3030h
                         db '>>. '
        ;Здесь таблица с функциями, которые загрузчик перенаправит на свои заглушки
        HOOKTABLE:
                         dd ExitCode1
        ep               db 'ExitProcess',0
                         dd GetMH
        gmh              db 'GetModuleHandleA',0
         
        .code
        start:
        ; для начала разберём параметры из командной строки
        invoke  GetCommandLine
        cmp eax,0
        mov [ERC],'01'
        je ERRORs
        mov edi,eax
        mov [EDIs],eax
        invoke  lstrlen,edi
        cmp eax,0
        mov [ERC],'02'
        je ERRORs
        cld
        inc edi
        mov ecx,eax
        mov [ECXs],eax
        mov al,22h
        repnz scasb
        jnz OSm2
        inc edi
        jmp CRF
        OSm2:
        mov edi,[EDIs]
        mov ecx,[ECXs]
        mov al,20h
        repnz scasb
        mov [ERC],'03'
        jnz ERRORs
         
        CRF:
        ; теперь в fname имя файла из командной строки
        mov [fname],edi
         
        ; открываем файл
        invoke  CreateFile,[fname],GENERIC_ALL,FILE_SHARE_READ,0,OPEN_EXISTING,0,0
        mov [hfile],eax
        cmp eax,0
        mov [ERC],'04'
        je ERRORs
        ; определяем размер
        invoke  GetFileSize,[hfile],0
        mov [fsize],eax
        cmp eax,0
        mov [ERC],'05'
        je ERRORs
        ;выдиляем память
        invoke    GlobalAlloc, GMEM_FIXED OR GMEM_ZEROINIT, eax
        mov [hmem],eax
        cmp eax,0
        mov [ERC],'06'
        je ERRORs
        ; соответственно читаем файл в память :)))
        invoke  ReadFile,[hfile],[hmem],[fsize],buffer,0
        cmp eax,0
        mov [ERC],'07'
        je ERRORs
         
        mov edx,[hmem]
        ; edx- указатель на начало прочитанного файла в памяти
        ; разбираем PE заголовок
        mov eax,[edx+3ch]
        add edx,eax ; edx- PE offset
        mov [PEa],edx
        add edx,0f8h; edx- Table offset   size 2ch
         
        mov eax,[PEa]
        mov eax,[eax+34h]
        mov [BaseAdr],eax  ; базовый адрес загрузки
         
        mov eax,[PEa]
        mov ax,[eax+06h]
        and eax,0ffffh
        mov [nums],eax  ; количество обьектов  (Num of Objects)
         
        mov eax,[PEa]
        mov eax,[eax+50h] ; виртуальный размер в байтах всего загружаемого образа
        add eax,100h
        ; выдиляем память под образ, но адресу ImageBase
        invoke VirtualAlloc,[BaseAdr],eax,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE
        cmp eax,0
        mov [h],eax
        mov [ERC],'08'
        je ERRORs
        ; читаем в память PE ФАЙЛ
        invoke  SetFilePointer,[hfile], 0,0, FILE_BEGIN
        invoke  ReadFile,[hfile],[BaseAdr],[fsize],buffer,0
        cmp eax,0
        mov [ERC],'12'
        je ERRORs
        ; цикл по таблице секций
        NEXTs:
        dec [nums]
        mov edx,[PEa]
        add edx,0f8h
                push edx
                mov eax,[nums]
                mov ebx,28h
                mul ebx
                pop edx
                add edx,eax
                mov eax,[edx+08h] ;Virtual Size
                mov [Vsize],eax
                mov eax,[edx+0ch] ;Section RVA
                mov [Vadr],eax
                mov eax,[edx+10h] ;Physical Size
                mov [Psize],eax
                mov eax,[edx+14h] ;Physical Offset
                add eax,[hmem]
                mov [Padr],eax
        ; копируем секцию на место
        mov esi,[Padr]
        mov edi,[Vadr]
        add edi,[BaseAdr]
        mov ecx,[Psize]
        rep movsb
        cmp [nums],0
        jne NEXTs
        ;*********************************
        mov eax,[PEa]
        mov eax,[eax+80h] ; RVA адрес таблицы импорта
        mov [Iadr],eax
        mov eax,[PEa]
        mov eax,[eax+84h] ; размер таблицы импорта
        mov [Isize],eax
        mov edi,[Iadr]
        add edi,[BaseAdr]
        cmp dword[edi+0ch],0
        ;Ссылка на библиотеку с которой нам необходимо поиметь вызовы представлена в виде ASCIZ.
        cmp dword[edi+10h],0
        ;Ссылка на табличку адресов импорта, заполняется системой при связывании
        mov [ERC],'09'
        je ERRORs
        ; цикл по таблице импорта
        NXTO:
        ; цикл по именам библиотек
        mov eax,[edi+0ch]
        add eax,[BaseAdr]
        ; загрузили необходимую библиотеку
        invoke  LoadLibrary,eax
        cmp eax,0
        mov [ERC],'10'
        je ERRORs
        mov [hdll],eax
        mov esi,[edi+10h]
        add esi,[BaseAdr]
        ;*****************
        NXTF:
        ; цикл по именам функций
        mov eax,[esi]
        add eax,[BaseAdr]
        add eax,2
        ;********
        ; сравним имя функции с именами для перхвата
        stdcall  XSCAN,gmh
        stdcall  XSCAN,ep
        ;********
        ;опредиляем адрес функции
        invoke  GetProcAddress,[hdll],eax
        cmp eax,0
        mov [ERC],'11'
        je ERRORs
         
        mov [esi],eax
        OKXSCAS:
        add esi,4h
        cmp dword[esi],0
        ; переход на следующее имя функции
        jne NXTF
        ;*****************
        add edi,14h
        cmp dword[edi+0ch],0
        je Iok
        cmp dword[edi+10h],0
        je Iok
        jmp NXTO
        ; переход на следующую библиотеку
        Iok:
        ;*********************************
        ;Таблица импорта  заполнена
        mov edx,[PEa]
        add edx,28h
        mov eax,[edx]
        add eax,[BaseAdr]
        ; установим перехват на выход в кернел
        mov dword[esp+40],ExitCode2
        ; переход на EP
        jmp eax
        ; Заглушки
         ExitCode1:
          invoke  MessageBox,HWND_DESKTOP,'<<ExitProcess>>',"Win32 PE Loader",MB_OK
          invoke  ExitProcess,0
         ExitCode2:
          invoke  MessageBox,HWND_DESKTOP,'Kernel return offset esp+40',"Win32 PE Loader",MB_OK
          invoke  ExitProcess,0
         GetMH:
          pop ebx
          pop eax
          push ebx
          mov eax,[BaseAdr]
          ret
         ERRORs:
          invoke  MessageBox,HWND_DESKTOP,ERMSG,"Win32 PE Loader",MB_OK
          invoke  ExitProcess,0
        ;*************************************
        proc XSCAN,.XSTEMP
         pushad
          mov esi,[.XSTEMP]
          mov edi,eax
          invoke  lstrlen,eax
          mov ecx,eax
          repe cmpsb
         popad
         jnz NOXSCAS
        ;***
         mov eax,[.XSTEMP]
         sub eax,4
         mov eax,[eax]
         mov [esi],eax
         mov dword[esp+4],OKXSCAS
         NOXSCAS:
         ret
        endp
        ;*************************************
        .end start

      Прикреплённый файлПрикреплённый файлPELoad.rar (3.71 Кбайт, скачиваний: 825)
      Что чайнику - варежка с дырками, то мастеру - перчатка без пальцев.
        Вы гений. Это отличный код. Неточность - при открытии файла сравнивать eax нужно не с нулем, а с -1.
        hxxp://dizzie.narod.ru
        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
        0 пользователей:


        Рейтинг@Mail.ru
        [ Script Execution time: 0,0769 ]   [ 17 queries used ]   [ Generated: 18.08.18, 00:36 GMT ]