|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Май 23, 2003 20:02:35 Вроде эта тема уже обсуждалось, только найти я ее не смог. В секции импорта на каждую библиотеку есть таблица, в которой находятся указатели на названия функций. После загрузки программы в память на их месте оказываются адреса функций. Как сделать такой экзешник, чтобы при загрузке автоматически настраивались адреса вызовов? Или такое можно сделать только если библиотеки по фиксированным адресам загружать? |
|
|
Дата: Май 23, 2003 21:24:08 Я не совсем тебя понял. Привязать exe к конкретной оси - bind -u filename (утилита из MS VS). Как думаешь - стоит положить? НО - эта утилита патчит IAT. Смысл же тебе понятен. Компилер генерит call xxx -> xxx: jmp [pAPIfunc] -> IAT. Для того, чтобы избавится от jmp надо указать компилеру dllspec. Но call останется все равно! А если ты хочешь call сразу_функцию_не_залезая_в_IAT, то тогда только ручками, на ассемблере. Узнаешь GetProcAddress адреса функций для твоей Windows и вперед! Ручами патчить каждый call. И молись богу, чтобы твой exe не попал на другую ОС и вдвойне молись богу, чтобы (если это dll) ее никто никуда от Preferred load address не унес. Иначе.... |
|
|
Дата: Май 23, 2003 22:35:10 volodya: Вы хотите сказать, что такая последовательность приведет к проблемам: 1. hDLL = GetModuleHandle ("USER32.DLL"); 2. pfn1 = GetProcAddress (hDLL, "SomeWin32API"); 3. My EXE was relocated due to something... 4. hDLL = GetModuleHandle ("USER32.DLL"); 5. pfn2 = GetProcAddress (hDLL, "SomeWin32API"); Теперь адрес pfn1 не будет равен адресу pfn2? |
|
|
Дата: Май 23, 2003 22:57:34 Конечно, не равен. Я, конечно, возможно, выражаюсь излишне самоуверенно, надо бы проверить. Но не должен быть он равен и все тут! Я же говорил о другом. Похоже, Black_mirror хочет сразу звать call SomeWin32API; не залезая в IAT. А это значит, что функция дожна звать СРАЗУ АДРЕС SomeWin32API В ПАМЯТИ - т.е. call 77E6574 (от фонаря взял число, но смысл понятен). Такое можно закодировать, насколько я знаю, только прямо в HIEW, поправив адрес операнда call. Компилятор, по идее, такое пропустить не должен. И тут возникает вопросос. Что произойдет, если по требуемому адресу ничего не будет? Очевидно, GPF. А по поводу relocation я, кажись, погорячился. Здесь важно понимать суть. Смещения всех переменных в памяти, ессно, изменятся. Я себе слабо представляю как можно перерелокейтить exe ВО ВРЕМЯ ВЫПОЛНЕНИЯ, думаю, так просто нельзя, но то, что адреса изменяться - очевидно. Имеет смысл почитать статьи Питрека - он это подробно описывает, а также слить PEBrowseProfessional - он показывает секцию релоков. Описание секции - PE Spec. |
|
|
Дата: Май 24, 2003 00:51:59 Вот, выкопал интересную статейку: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tools /tools/rebase.asp Похоже, только DLLs могут быть 'relocated due to collision...'. Поскольку системные DLLs загружены первыми - они никогда не будут relocated. Таким образом, адреса АPI должны остаться на месте. |
|
|
Дата: Май 24, 2003 17:06:38 Функция написана, только у метода есть два недостатка: 1) страница в памяти отличается от страницы на диске -> если страница кода будет удалена из памяти, то после ее загрузки из exe-файла настройку нужно выполнять заново. Для dll все понятно, если адрез загрузки отличается от базового, то после настройки релоков, винда если не хватает памяти скидыват ее в своп. А вот что может помешать винде считать страницу кода из экзешника, и заново настроить релоки? Может хук можно повесить на pagefault? 2) вполне может быть что элемент в секции reloc ссылается вовсе не на команду call, а байт 0E8h это mod/r , SIB или часть адреса(хотя последнее вряд ли). Может вообще не смысла заменять косвенные вызовы на прямые? format PE GUI entry start include 'include\kernel.inc' include 'include\macro\stdcall.inc' macro pusharg [arg] { reverse push arg } macro directcall proc,[arg] { common if ~ arg eq pusharg arg end if db 0e8h ; код команды call dd proc ; смемещение где будет находится реальный адрес вызова } section '.data' data readable writeable time rd 32 section '.code' code readable executable directcallinit: call $+5 ;ищем imagebase pop ebx and ebx,0ffff0000h add ebx,10000h .l1: sub ebx,10000h cmp word [ebx],'MZ' jnz .l0 .l0: movzx edi,word [ebx+3ch] add edi,ebx cmp dword [edi],'PE' jnz .l1 mov eax,[edi+80h] add eax,ebx push ebx ;imagebase [esp+12] push eax ;import start [esp+8] add eax,[edi+84h] push eax ;import end [esp+4] mov eax,[edi+0a4h] push eax ;reloc size [esp] mov esi,[edi+0a0h] add esi,ebx ;esi - relocbase .l2: cmp dword [esp],0 ;пока не обработаем всю секцию reloc jle .l5 mov ebx,[esi] ;смещение страницы add ebx,[esp+12] ;ebx - адрес страницы mov edi,[esi+4] ;длина релоков для данной страницы add esi,8 sub edi,8 sub dword [esp],8 .l4: cmp edi,0 ;пока не обработаем все релоки для данной страницы jle .l2 mov eax,[esi] ;смещение релока от начала страницы add esi,2 sub edi,2 sub dword [esp],2 and eax,0fffh add eax,ebx ;адрес потенциальной комманды call cmp byte [eax-1],0E8h ;если это не call то идем дальше jnz .l4 mov edx,[eax] ;смещение адреса вызова cmp edx,[esp+4] ;проверяем попадает ли он в секцию импорта jae .l4 cmp edx,[esp+8] jb .l4 mov edx,[edx] ;берем из таблицы адрес вызова sub edx,eax sub edx,4 push edx mov edx,esp invoke WriteProcessMemory,-1,eax,edx,4,edx;правим call pop eax jmp .l4 .l5: add esp,16 ret start: call directcallinit mov [time],time directcall GetSystemTime,[time] directcall SetSystemTime,time directcall ExitProcess,0 section '.idata' import readable writeable include 'include\macro\import.inc' library kernel,'KERNEL32.DLL' kernel: import ExitProcess,'ExitProcess',\ GetSystemTime,'GetSystemTime',\ SetSystemTime,'SetSystemTime',\ WriteProcessMemory,'WriteProcessMemory' section '.reloc' fixups data readable discardable |
|
|
Дата: Май 24, 2003 21:00:16 to AsmGuru62 Вероятно, я неправильно понял вопрос. Естественно и абсолютно понятно, что базовый адрес загрузки dll может быть и будет изменен при необходимости, что же касательно системных dll - то здесь уже все интересно и ситуация разительным образом отличается от таковой в 9x. Для 9x копии dll (kernel, user, gdi) были ОБЩИМИ, в NT - они ЧАСТНЫЕ. А это, знаете ли... А может, расскажете, почему у kernel32.dll и всех остальных есть секция .reloc? to BlackMirror Ой, бля... Кто ж это будет все читать? Ну ладно, потом разберусь. По поводу релоков лучше не гадать, а сразу проверить по докам. И все. По идее, reloc должен показывать на секцию операнда, какой смысл патчить E8? если страница кода будет удалена из памяти, то после ее загрузки из exe-файла настройку нужно выполнять заново Чего? Это что-то новое! У меня такое ощущение, что у меня поехала крыша. Никому даром не нужна такая ОСь, которая будет производить fixup релоков при сбросе в своп! Файл настраивается только один раз - при загрузке! Откуда такая информация? |
|
|
Дата: Май 25, 2003 14:13:29 E8 я и не патчу а проверяю, чтоб чего-нибудь лишнего не по пропатчить. Хотя такая вероятность все равно остается. В программе вместо call [pAPIfunc] записано: db 0E8h patchhere dd pAPIfunc после загрузки процедура directcallinit вместо pAPIfunc записывает APIfunc-patchhere-4 (используя данные из секции reloc), то есть получается call APIfunc. если страница кода будет удалена из памяти, то после ее загрузки из exe-файла настройку нужно выполнять заново Я не совсем точно выразился. Я имел ввиду следующее: Так как страницы секции кода только для чтения, то их можно не сбрасывать в своп, а просто удалить. А когда они потребуется то заново загрузить из exe-файла, и настроить релоки. В секции reloc, для каждой страницы, где нужно что либо настраивать, присутствует следующая структура: pageoffset (относительно imagebase): dword structsize (включая длину массива): dword relocoffset (относительно pagebase): array of word (в старших четырех битах тип, нужно будет потом их учесть, а то программа уж слишком глючной получилась, но работает!) (pagebase=imagebase+pageoffset) Очень похоже что так было сделано для возможности подгрузки страниц из exe-файла. Хотя может быть такое возможно только в других системах. А если релоки настраиваются только при загрузке, то задача почти решена, осталось только разобраться: что нужно патчить, а что нет. |
|
|
Дата: Май 25, 2003 18:06:25 [ Black_mirror: Так как страницы секции кода только для чтения, то их можно не сбрасывать в своп, а просто удалить. ] Только в том случае, если на этой странице нет адресов подвергнутых релоку. В противном случае, в свопе выделяется место куда будет сброшена эта страница. [ Black_mirror: А когда они потребуется то заново загрузить из exe-файла, и настроить релоки. ] Опять же, только в том случае, если на этой странице нет адресов подвергнутых релоку. В противном случае, эта страница подгружается из свопа. [ Black_mirror: А если релоки настраиваются только при загрузке,... ] Если речь о системе, то именно так и происходит. [ Black_mirror: ...то задача почти решена, осталось только разобраться: что нужно патчить, а что нет. ] И еще неплохо было бы разобраться, а зачем это вообще нужно - делать релок екзешнику вручную? Екзешник всегда грузится первым. Там куда он грузится всегда есть место. Зачем релок? Для длл система сама все сделает что нужно. Зачем делать это вручную? |
|
|
Дата: Май 25, 2003 23:36:26 Спасибо что разъяснили когда страницы сбрасываются в своп, а когда из экзешника подгружаются. Релоки вручную я настраивать и не хочу. Мне нужно чтоб в программе вместо call [pAPIfunc] было написано call APIfunc. А для поиска где нужно пропатчить я использую секцию reloc. Плюс данного метода проявляется в td: при отладке он пишет имя модуля и вызываемой функции, а не call [0043D3F4] например. Есть еще небольшой плюсик - таблица адресов импотрируемых функций не засоряет кэш. |
|
|
Дата: Май 26, 2003 13:21:04 [ Black_mirror: Плюс данного метода проявляется в td: при отладке он пишет имя модуля и вызываемой функции, а не call [0043D3F4] например. ] А не проще ли использовать более продвинутый дебагер? |
|
|
Дата: Май 26, 2003 15:21:44 TD мне кажется удобнее остальных. К тому же у него есть одна полезная возможность, отсутствующая у дебаггеров с графическим интерфейсом: можно отлаживать программу на участке PrimarySurface.Lock()/Unlock(). Вот если научусь пользоваться софтайсом может на него перейду. |
|
|
Дата: Май 26, 2003 20:42:47 [ Black_mirror: Вот если научусь пользоваться софтайсом может на него перейду. ] Могу только посоветовать сделать это как можно быстрее, т.к. при использовании этого замечательного инструмента появляется возможность отлаживать что угодно, где угодно и как угодно ;-) |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.070 |