Пытаюсь перевести код загрузчика из статьи Запуск файла из памяти. Основная работа сделала ида, но появилось много подводных комней... Вот мой masm вариант: Код (Text): .686p .mmx .model flat,stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib include \masm32\include\user32.inc includelib \masm32\lib\user32.lib externdef _imp__MessageBoxA@16:PTR pr4 externdef _imp__GetProcAddress@8:PTR pr2 externdef _imp__LoadLibraryA@4:PTR pr1 externdef _imp__UnmapViewOfFile@4:PTR pr1 externdef _imp__VirtualAlloc@16:PTR pr4 externdef _imp__VirtualFree@12:PTR pr3 .code alloced_area_start proc local pVA:dword call @F @@: pop ebx sub ebx,offset @B lea esi,[ebx + offset some_file] push esi add esi, [esi+3Ch] mov ecx, [esi+34h] mov edx, [esi+50h] mov edi, ecx push edx push ecx call Allock_Region mov pVA,ecx mov edx, esi pop esi push esi mov ecx, [edx+54h] add ecx, 18h rep movsb lea eax, [edx+0F8h] movzx ecx, word ptr [edx+6] push pVA push eax push ecx call process_sections ;pusha ;push 0 ;push 0 ;push 0 ;push 0 ;call _imp__MessageBoxA@16 ;popa push pVA push dword ptr [edx+80h] call process_imports push 8000h push 0 mov eax, ebx and eax, 0FFFFF000h push eax mov ecx, [edx+28h] add ecx, pVA push ecx jmp _imp__VirtualFree@12 alloced_area_start endp process_imports proc near arg_0 = dword ptr 8 arg_4 = dword ptr 0Ch push ebp mov ebp, esp pusha mov edx, [ebp+arg_0] add edx, [ebp+arg_4] loc_40119D: push edx mov edi, [edx+10h] mov esi, [edx] test edi, edi jz loc_4011F5 test esi, esi jnz short loc_4011AD mov esi, edi loc_4011AD: mov ecx, [ebp+arg_4] add esi, ecx add edi, ecx mov eax, [edx+0Ch] add eax, ecx loc_4011B9: cmp byte ptr [eax],0 jnz loc_4011C1 inc eax jmp loc_4011B9 loc_4011C1: push eax call _imp__LoadLibraryA@4 mov edx, eax loc_4011CA: lodsd test eax, eax jz loc_4011EF bt eax, 1Fh jnb loc_4011DC and eax, 0FFFFh jmp loc_4011E2 loc_4011DC: add eax, [ebp+arg_4] add eax, 2 loc_4011E2: push edx push eax push edx call _imp__GetProcAddress@8 pop edx stosd jmp loc_4011CA loc_4011EF: pop edx add edx, 14h jmp loc_40119D loc_4011F5: pop edx popa leave retn 8 process_imports endp process_sections proc near arg_0 = dword ptr 8 arg_4 = dword ptr 0Ch arg_8 = dword ptr 10h arg_C = dword ptr 14h push ebp mov ebp, esp pusha mov ecx, [ebp+arg_0] mov edx, [ebp+arg_4] loc_401205: push ecx mov edi, [edx+0Ch] add edi, [ebp+arg_8] mov ecx, [edx+10h] mov esi, [ebp+arg_C] add esi, [edx+14h] rep movsb pop ecx add edx, 28h dec ecx jnz loc_401205 popa leave retn 10h process_sections endp Allock_Region proc near arg_0 = dword ptr 8 arg_4 = dword ptr 0Ch push ebp mov ebp, esp pusha mov edi, [ebp+arg_0] mov esi, [ebp+arg_4] add esi, edi loc_40122F: push edi call _imp__UnmapViewOfFile@4 push 8000h push 0 push edi call _imp__VirtualFree@12 push 40h push 3000h push 10000h push edi call _imp__VirtualAlloc@16 test eax, eax jz loc_401265 add edi, 10000h cmp edi, esi jl loc_40122F loc_401265: popa leave retn 8 Allock_Region endp some_file: DB 77,90,0,0,80,69,0,0,76,1,1,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,120,0,15,1,11,1,0,0 DB 0,0,0,0,0,0,0,0,0,0,0,0,188,0,0,0 DB 0,0,0,0,0,0,0,0,0,0,20,19,4,0,0,0 DB 4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0 DB 0,0,0,0,18,1,0,0,188,0,0,0,0,0,0,0 DB 2,0,0,0,0,16,0,0,0,16,0,0,0,16,0,0 DB 0,16,0,0,0,0,0,0,2,0,0,0,0,0,0,0 DB 0,0,0,0,225,0,0,0,49,0,0,0,0,0,0,0 DB 0,0,0,0,46,105,109,112,111,114,116,0,49,0,0,0 DB 188,0,0,0,49,0,0,0,188,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,32,0,0,224,106,0,104,219 DB 0,20,19,106,0,106,0,255,21,252,0,20,19,232,0,0 DB 0,0,106,0,100,137,32,255,100,36,4,72,101,108,108,111 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,245,0,0 DB 0,252,0,0,0,85,83,69,82,51,50,0,4,1,0,0 DB 0,0,0,0,0,0,77,101,115,115,97,103,101,66,111,120 DB 65,0 size_some_file = 274 alloced_area_end: alloced_size equ (offset alloced_area_end - offset alloced_area_start) start proc local pVA:dword mov esi, offset some_file add esi, [esi+3Ch] mov ecx, [esi+34h] mov edx, [esi+50h] lea edi, [edx+ecx] mov esi, alloced_size add esi, 10000h and esi, 0FFFF0000h @@: add edi, 10000h invoke VirtualAlloc,edi,esi,MEM_RESERVE+MEM_COMMIT,PAGE_EXECUTE_READWRITE test eax, eax jz @B mov pVA, eax mov esi, offset alloced_area_start mov edi, pVA mov ecx, alloced_size rep movsb jmp pVA start endp end start Доходит до процедуры process_sections и ругается что "The memory could not be written". Не могу понять в чем дело, помогите пожалуйста.
Вот оригинал: Код (Text): FORMAT PE GUI 4.0 on 'null' entry start FILE_NAME equ 'file.exe' include '%fasminc%\win32a.inc' section '.main' code readable writable executable data import library kernel32,'KERNEL32.DLL',\ user32,'USER32.DLL' include '%fasminc%\apia\user32.inc' include '%fasminc%\apia\kernel32.inc' end data macro xinvoke proc,[arg] { common if ~ arg eq reverse pushd arg common end if call [ebx+_#proc-_delta] } proc start locals pVA dd ? shit dd ? endl mov esi,some_file add esi,[esi+3ch] ;peheader mov ecx,[esi+34h] ;image base mov edx,[esi+50h] ;image size lea edi,[edx+ecx] ;imagebase+imagesize mov esi,alloced_size add esi,10000h and esi,0ffff0000h ;округлить значения. @@: add edi,10000h invoke VirtualAlloc,edi,esi,MEM_RESERVE+MEM_COMMIT,PAGE_EXECUTE_READWRITE ;ищем новое место где-нибудь за imagebase+imagesize, чтоб разместить там загрузчик test eax,eax jz @b mov [pVA],eax ;сохранить mov esi,api_table mov edi,esi @@: lodsd test eax,eax jz @f mov eax,[eax] stosd jmp @b ;так как таблицу импорта мы не переносим, адреса необходимых апи занесем в таблицу. @@: mov esi,alloced_area_start mov edi,[pVA] mov ecx,alloced_size rep movsb ;копирование на новое место загрузчика с образом файла jmp [pVA] ;прыжок на начало кода загрузчика endp ;дальше только базонезависимый код proc alloced_area_start locals pVA dd ? endl call _delta _delta: pop ebx ;ebx=delta lea esi,[ebx+some_file-_delta] push esi add esi,dword[esi+3ch] mov ecx,[esi+34h] ;image base mov edx,[esi+50h] ;image size mov edi,ecx stdcall Allock_Region,ecx,edx ;получим памяти под загрузку файла mov [pVA],ecx ;запомним это значение mov edx,esi ;edx=pointer to PE header pop esi push esi ;последний параметр в process_sections mov ecx,[edx+54h] add ecx,18h ;размер заголовков и таблицы секций rep movsb ;перемещаем их lea eax,[edx+78h+16*8] ;указатель на первый IMAGE_SECTION_HEADER movzx ecx,word[edx+6] ;IMAGE_NT_HEADER.FileHeader.NumberOfSections stdcall process_sections,ecx,eax,[pVA] ;расставляем секции по местам stdcall process_imports,dword[edx+78h+8],[pVA] ;заполняем импорты push MEM_RELEASE ;теперь надо освободить память, занятую загрузчиком push 0 mov eax,ebx and eax,0fffff000h push eax ;адрес mov ecx,dword[edx+28h] ;RVA точки входа add ecx,[pVA] ;VA push ecx ;адрес возврата из VirtualFree jmp [_VirtualFree+ebx-_delta] ;освобождаем память endp proc process_imports pTab,pImageBase ;pTab - RVA таблицы импортов (берем из массива DataDirectory) ;pImageBase - указатель на "память" pusha mov edx,[pTab] add edx,[pImageBase] ;VA таблицы импортов .loop: push edx mov edi,[edx+4*4] ;import address table (её и будем заполнять) mov esi,[edx] ;lookup table (можно сделать просто = import address table, они идентичны) test edi,edi jz .ends ;последний IMAGE_IMPORT_DESCRIPTOR нулевой test esi,esi jnz .ok mov esi,edi .ok: mov ecx,[pImageBase] add esi,ecx add edi,ecx ;VA соответствующих таблиц mov eax,[edx+4*3] add eax,ecx ;VA имени DLL @@: cmp byte[eax],0 jnz @f inc eax jmp @b ;могут быть нули для выравнивания @@: xinvoke LoadLibrary,eax mov edx,eax ;загрузить DLL .po_1_dll: lodsd ;RVA IMAGE_IMPORT_BY_NAME test eax,eax jz .exit_it ;таблица заканчивается нулевым элементом bt eax,31 ;если установлен 31 бит, то импорт по ординалу. jnc .no_ord and eax,0ffffh jmp .getproc .no_ord: add eax,[pImageBase] ;VA IMAGE_IMPORT_BY_NAME add eax,2 ;VA IMAGE_IMPORT_BY_NAME.Name .getproc: push edx xinvoke GetProcAddress,edx,eax ;получить адрес АПИ pop edx stosd ;поместить его на свое место jmp .po_1_dll .exit_it: pop edx add edx,5*4 ;перейти к следующему IMAGE_IMPORT_DESCRIPTOR jmp .loop .ends: pop edx popa ret endp proc process_sections num, pStable,pImageBase,pImage ;num - кол-во секций, берем Number Of Sections из IMAGE_FILE_HEADER ;pStable - указатель на таблицу секций (сразу за массивом DataDirectory) ;pImageBase - указатель на выделенную "память" ;pImage - указатель на образ Б pusha mov ecx,[num] mov edx,[pStable] @@: push ecx mov edi,[edx+0ch] ;Section RVA add edi,[pImageBase] ;Section VA mov ecx,[edx+10h] ;Physical Size mov esi,[pImage] add esi,[edx+14h] ;Physical Offset rep movsb ;копируем секцию на её законное место pop ecx add edx,28h ;следующая dec ecx jnz @b popa ret endp proc Allock_Region pRegion,Size pusha mov edi,[pRegion] mov esi,[Size] add esi,edi ;esi - указатель на конец выделяемой области ;edi - указатель на начало @@: xinvoke UnmapViewOfFile,edi xinvoke VirtualFree,edi,0,MEM_RELEASE ;освободить память xinvoke VirtualAlloc,edi,10000h,MEM_RESERVE+MEM_COMMIT,PAGE_EXECUTE_READWRITE ;зарезервировать test eax,eax jz @f ;без этой проверки функция работает, если параметры в "разумных" пределах add edi,10000h ;память резервируется по 10000h за шаг cmp edi,esi jl @b @@: popa ret endp api_table: _UnmapViewOfFile dd UnmapViewOfFile _VirtualAlloc dd VirtualAlloc _LoadLibrary dd LoadLibrary _GetProcAddress dd GetProcAddress _VirtualFree dd VirtualFree dd 0 ;таблица АПИ, необходимых для работы загрузчика some_file: _bin file FILE_NAME ;файлик, который будем загружать _bin_size = $ - _bin alloced_size=$-alloced_area_start Это не тоже самое что и у меня ? Код (Text): some_file: _bin file FILE_NAME ;файлик, который будем загружать _bin_size = $ - _bin alloced_size=$-alloced_area_start
Flasher > Это не тоже самое что и у меня ? Твое db DB 77,90 ни как не похоже на "MZ" Я проверял так: 1.1) написал подопытного Код (Text): ;; foo1.asm .386 .model flat,stdcall option casemap:none .nolist include windows.inc include kernel32.inc includelib kernel32.lib include user32.inc includelib user32.lib .list .code start: invoke MessageBoxA, 0, 0, 0, 0 invoke ExitProcess, 0 end start 1.2) собрал exe'шник foo1.exe c базой /base:0x10000; 1.3) запустил его - MessageBox есть. 2.1) открыл foo1.exe в HexEdit v1.2 by Catch22; 2.2) выделил все - Edit \ Select All; 2.3) скопировал в буфер обмена для вставки а asm-файл - Edit \ Copy As \ Assembler source; 2.4) закрыл HexEdit. 3.1) открыл текстовый редактор; 3.2) вставил содержимое буфера обмена; 3.3) кое-где добавил нулей, т.е. было ffh сделал 0ffh; 3.4) сохранил файл как foo1.inc. 4.1) взял твой код из #1 и сохранил в foo0.asm; 4.2) внес изменение, было Код (Text): ... some_file: DB 77,90,0,0,80,69,0,0,76,1,1,0,0,0,0,0 ... DB 65,0 size_some_file = 274 ... стало Код (Text): ... some_file: include foo.inc size_some_file = $ - offset some_file ... 4.3) собрал exe'шник foo0.exe; 4.4.) запустил его - - MessageBox есть.
Обрати внимание в fasm варианте код помещён в секцию данных, а в масме у тебя он в секции кода, куда запись по умолчению запрещена.
Y_Mur Обрати внимание, что код переносится в специально зарезервированный блок, имеющий атрибуты PAGE_EXECUTE_READWRITE
а какие проблемы-то собственно ? ну отличается синтаксис на уровне 1)fasm->mov eax,some_variable masm->mov eax,offset some_variable 2)fasm->mov eax,dword [ebx] masm->mov eax,dword ptr ebx есть конечно еще много отличий, но на вскидку в коде отличий мало
Не получается Вставляю Код (Text): some_file: db 04Dh, 05Ah, 000h, 000h, 050h, 045h, 000h, 000h, 04Ch, 001h, 001h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 078h, 000h, 00Fh, 001h, 00Bh, 001h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0BCh, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 014h, 013h, 004h, 000h, 000h, 000h db 004h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 004h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 012h, 001h, 000h, 000h, 0BCh, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 002h, 000h, 000h, 000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h, 000h db 000h, 010h, 000h, 000h, 000h, 000h, 000h, 000h, 002h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 0E1h, 000h, 000h, 000h, 031h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 02Eh, 069h, 06Dh, 070h, 06Fh, 072h, 074h, 000h, 031h, 000h, 000h, 000h db 0BCh, 000h, 000h, 000h, 031h, 000h, 000h, 000h, 0BCh, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 020h, 000h, 000h, 0E0h, 06Ah, 000h, 068h, 0DBh db 000h, 014h, 013h, 06Ah, 000h, 06Ah, 000h, 0FFh, 015h, 0FCh, 000h, 014h, 013h, 0E8h, 000h, 000h db 000h, 000h, 06Ah, 000h, 064h, 089h, 020h, 0FFh, 064h, 024h, 004h, 048h, 065h, 06Ch, 06Ch, 06Fh db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0F5h, 000h, 000h db 000h, 0FCh, 000h, 000h, 000h, 055h, 053h, 045h, 052h, 033h, 032h, 000h, 004h, 001h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 04Dh, 065h, 073h, 073h, 061h, 067h, 065h, 042h, 06Fh, 078h db 041h, 000 size_some_file = $ - offset some_file q_q, попробуй у себя вставить, плиз
Хахах, господа ассемблерщики настолько узко-специализированны, что могут собрать код на xASM'лере и не могут собрать на yASM'лере? а если с x86 пересесть на x64, arm, mips или еще что-нибудь более экзотическое, то вообще труба? =)
Да, скомпилил с /base:0x10000 - заработало. censored, помоему путаешь интуитивное мышление с знаниями статистических данных (про синтаксис языка имею ввиду)
Flasher Хз что там путать, использовал 4 диалекта х86-оссемблера -- никаких проблем перенести с одного на другой не возникало.
Flasher > скомпилил с /base:0x10000 - заработало Это ответ мне? Образ #9 без правки загрузчика #1 не должен заработать. Поясняю Код (Text): ... ;; тут EDX указывает на IMAGE_NT_HEADERS32 (за ним первый IMAGE_SECTION_HEADER), ;; если образ "правильный", то размер IMAGE_NT_HEADERS32 равен 0F8h, lea eax, [edx+0F8h] ;; образ #9 хитрый, у него не шестнадцать IMAGE_DATA_DIRECTORY, а всего три, ;; следовательно, тут EAX не указывает на первый IMAGE_SECTION_HEADER ;; как этого ожидает process_sections movzx ecx, word ptr [edx+6] push pVA push eax push ecx call process_sections ... n1kt0 & censored Imho для того чтобы отвечать по теме не достаточно прочитать ее заголовок.
надёжнее использовать SizeOfOptionalHeader Код (Text): movzx ecx,[eax].IMAGE_NT_HEADERS.FileHeader.SizeOfOptionalHeader lea eax,[ecx][eax].IMAGE_NT_HEADERS.OptionalHeader.Magic