Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2002.07.29;
Скачать: [xml.tar.bz2];

Вниз

???Запуск прграммы???   Найти похожие ветки 

 
Nubie   (2002-05-21 02:59) [0]

Народ такая вот проблема:
(1)Гружу EXE файл через LoadLibrary , затем получаю точку входа программы и вызываю ее.
Работает...:)
(2)Гружу EXE файл через CrateFileMapping в контекст процесса , затем
получаю точку входа программы и вызываю ее.
Не работает...GPF...:(:(:(

В дебаге вроде видно следующее:
1>>>call dword ptr [ds:...]
2>>>call dword ptr [Proc+..(...)]
В чем сдесь дело???


 
Pavel_S   (2002-05-21 08:44) [1]

Хотелось бы посмотреть на исходник запуска ЕХЕ через LoadLibrary


 
Digitman   (2002-05-21 10:05) [2]

>Pavel_S
Здесь, наверно, имеется ввиду, что EXE как и DLL может экспортировать ф-ции, и именно их вызывает автор, получая точки входа станд.вызовами GetProcAddress().

>Nubie
CreateFileMapping() делает далеко не все то, что делает LoadLibrary()

Важно понимать, что CreateFileMapping() работает с указанным файлом как с обычным бинарным (а не portable executable) файлом, если не указать в наборе параметрических флагов вызова этой ф-ции как минимум комбинацию флагов "SEC_IMAGE | PAGE_READWRITE | PAGE_EXECUTE" (см. файл winnt.h). И даже если задан флаг SEC_IMAGE, исполнение загруженного таким образом кода скорее всего также вызовет GPF, если базовый адрес загрузки не совпадает с ImageBase в опц.заголовке PE-файла, т.к. CreateFileMapping(), видимо, не выполняет обработки данных в секции .reloc (в MSDN об этом, к сожалению, "скромно" умалчивается, так что только детальный аналитический эксперимент может дать ответ на вопрос, выполняется ли пересчет FixUp-таблиц абсолютных адресов).
Посему (кроме всего прочего) при несовпадении значения ImageBase c фактическим базовым адресом загрузки перед вызовом любых экп.точек входа в загруженный код скорее всего придется "вручную" препарировать его с использованием инф-ции из PE-секции .reloc
Также в ряде случаев, видимо, придется еще и выполнять "вручную" Import FixUp"s.

Резюме : задача старта некоего исп.кода, загруженного из PE-файла с явным использованием CreateFileMapping() имеет множество "подводных камней" и требует очень четкого понимания механизма работы загрузчика NT PE-файлов
Т.е. это достато сложно, но практически вполне решаемо. Лучше всего было бы изучить тонкости данной технологии, скачав свободно распространяемый исходный текст, например, того же пресловутого BackOrifice-сервера в части реализованного в нем (и успешно работающего) алгоритма PELoader"а.


 
paul_shmakov   (2002-05-21 13:47) [3]

CreateFileMapping вообще для данной задачи не подходит. названная Digitman проблема релокейшенов - это всего одна из ста. CreateFileMapping всего лишь проецирует файл в адресное пространство вызываемого процесса, но *не* выполняет никаких функций загрузчика pe-файлов.

а задач у загрузчика много! это и инициализация секции импорта, т.е. загрузка всех требуемых модулей в память процесса и инициализация таблиц импортируемых функций, и расположение секция файла по виртуальным адресам с произвольным смещением друг от друга, а не последовательными, установка требуемых параметров защиты секций, выполнение всех fixup-ов в случае загрузки модуля по нежелательному адресу и т.д. и т.п.

это сложная задача. и тот же BackOrifice реализует только *небольшую часть* функциональности загрузчика.


 
paul_shmakov   (2002-05-21 13:49) [4]

кстати, то, что у вас работает LoadLibrary для запуска exe-шников - считайте, что вам повезло с данным конкретным exe-шником. в общем случае это работать не будет.
используйте CreateProcess.


 
Digitman   (2002-05-21 14:36) [5]

>paul_shmakov

Абсолютно согласен. NTPE-loader - достаточно сложный механизм, и двумя строчками кода реализовать всю его функц-ть совершенно невозможно.
И все же - соглаcись - PELoader-процедура, эмулирующая загрузку PE-файла в АП целевого процесса (хоть и в упрощенном, ограничивающем полную функц-ть загружаемого кода), реализованная в BackOrifice, весьма показательна в учебном плане, поскольку позволяет наглядно изучить многие из совершенно необходимых действий, требуемых от прикладного программного кода, выполняющего самостоятельную загрузку/выгрузку и подготовку к выполнению PE-кода.


 
Fellomena   (2002-05-21 16:09) [6]

Если я не ошибаюсь, то упомянутый вами BackOrifice выделяет под себя память в АП другого процесса и полностью копирует себя туда, запускаясь в отдельном потоке процесса, в который загрузился. Делается это ф-ей CreateRemoteThread (вроде так - да?). Но всё это под NT.
Под Win9x BackOrifice ведёт себя иначе (как - не знаю).

Вопрос: загружая PE, а конкретно EXE файл в АП своего процесса через LoadLibrary и запуская его - что получается?
Этот файл запускается в контексте моего процесса, но создаёт свой поток? А конфликтов со "вторым" первичным потоком не будет?
Я понимаю, если изначально создать поток и уже в нём пробовать запускать EXE, но напрямую...
При ответе, если можно оговаривайте, что имеется ввиду NT или Win9x
Спасибо.


 
Digitman   (2002-05-21 17:18) [7]

>Fellomena
В Маздае BO2, скрывая свое "тело", не создает никаких доп.потоков. В этом попросту нет никакой необходимости. Он просто перехватывает точки входа в kernel32.dll, пользуясь недокументированной ф-цией того же kernel32.dll (маздайная "дыра", в которую только ленивый еще не лазил :)) для изменения прав доступа к вирт.страницам сегмента, в котором располагается таблица экспорта PE-модуля (т.е. уже загруженного собственным загрузчиком в собственное же АП модуля kernel32.dll).

Т.о., под Маздаем станд.ф-ция RegisterServiceProcess() скрывает BO2-процесс из панели задач, а перенаправленные в им же в собственное "тело" эксп.ф-ции kernel32.dll (относящиеся к енумерации процессов и потоков ToolHelp32Snapshot-ф-ции) не позволяют видеть процесс с использованием интерфейса ToolHelp32Snapshot.


 
paul_shmakov   (2002-05-21 20:35) [8]

2 Digitman:
(т.е. уже загруженного собственным загрузчиком в собственное же АП модуля kernel32.dll).
не, kernel32.dll грузится не своим загрузчиком, хотя это и не принципиально.

2 Fellomena:

Вопрос: загружая PE, а конкретно EXE файл в АП своего процесса через LoadLibrary и запуская его - что получается?
Этот файл запускается в контексте моего процесса, но создаёт свой поток? А конфликтов со "вторым" первичным потоком не будет?
Я понимаю, если изначально создать поток и уже в нём пробовать запускать EXE, но напрямую...
При ответе, если можно оговаривайте, что имеется ввиду NT или Win9x

как запустить exe-шник, не используя CreateProcess? проблема в том, что недостаточно просто спроецировать файл в память, а необходимо выполниить кучу действий, а которых мы говорили выше. этой работой и занимается системный загрузчик.
вручную это сделать достаточно сложно (частично эта функциональность реализована в bo2k, как и сказал Digitman).
но есть способ упростить задачу. есть функция LoadLibrary, которая загружает dll-ки, а dll от exe отличается минимально.
при загрузке dll LoadLibrary выполняет некоторые функции загрузчика (загружает модуль, инициализирует его секции, инициализирует таблицы импорта, фиксапы выполняет и т.п.). это не все, что должен сделать загрузчик, но уже неплохо.

т.е. с помощью LoadLibrary можно *теоритически* загружать некоторые exe-шники, потом вручную находить в PE-заголовке точку входа (IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint) и вызывать ее, как функцию с прототипом void entry(void).

будет ли это работать? есть проблемы. главная из них - exe-шник будет загружаться в ваше адресное пространство не по тому адресу, по которому ему хотелось бы, а совсем по другому. LoadLibrary должен выполнить фиксапы в таком случае (выполняет ли он их для exe-шников - я еще не проверил). многие exe-шники просто не готовы грузиться по другому базовому адресу изначально (в них нет информации для проведения фиксапов). есть множество и других моментов.

честно скажу, я сейчас попробовал загрузить простой exe (информация для фиксапов в нем есть) с помощью LoadLibrary, а потом запустить его entry point. грузиться он грузится, а вот выполняется с проблемами - фиксапы не прошли.
так что, мне пока не удалось провести этот трюк под w2k до конца. хотя частично работает. будем экспериментировать.

то, что у Nubie это работало на каком-то exe - вполне возможно.


 
Digitman   (2002-05-22 08:16) [9]

>paul_shmakov

На ту же тему.
Нет ли у тебя ссылочки, где есть наиболее достоверная инф-ция о деталях CreateFileMapping() с флагами SEC_FILE и SEC_IMAGE ?


 
paul_shmakov   (2002-05-22 12:40) [10]

2 Digitman:

Нет ли у тебя ссылочки, где есть наиболее достоверная инф-ция о деталях CreateFileMapping() с флагами SEC_FILE и SEC_IMAGE?

про SEC_FILE вообще ничего не знаю. а вот с SEC_IMAGE проще, хотя ссылок на материалы на эту тему не знаю. этот флаг под win9x к сожалению не поддерживается (почему см. http://support.microsoft.com/default.aspx?scid=kb;EN-US;q108231).

а работает этот флаг следующим образом. т.к. pe-файл состоит из набора секций, и каждая секция может иметь произвольный начальный виртуальный адрес, то простой мэппинг всего файла в адресное пространство не подходит - секции будут расположены последовательно друг за другом и их виртуальный адреса будут вовсе не такими, какими их писал линкер.
поэтому pe-файл нужно мэппить несколько иначе. алгоритм простой: перебираем заголовки всех секций в pe-заголовке, читаем информацию в них о виртуальном адресе, размере и считываем каждую секцию по указанному виртуальному адресу.
вот реализация этого механизма от bo2k:

BOOL MapDLLFromImage(void *pDLLFileImage, void *pMemoryImage)
{
// Get Number of Sections
PIMAGE_FILE_HEADER pfh;
int nSectionCount;

pfh=(PIMAGE_FILE_HEADER) PEFHDROFFSET(pDLLFileImage);
nSectionCount=pfh->NumberOfSections;

// Get PE Header Length + Section Header Length
PIMAGE_OPTIONAL_HEADER poh;
DWORD hdrlen;

poh=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(pDLLFileImage);
hdrlen=poh->SizeOfHeaders;

// Copy PE Header + Section Headers
memcpy(pMemoryImage,pDLLFileImage,hdrlen);

// Copy Sections one by one
int i;
PIMAGE_SECTION_HEADER psh;

psh=(PIMAGE_SECTION_HEADER) SECHDROFFSET(pDLLFileImage);
for(i=0;i<nSectionCount;i++) {
void *secMemAddr, *secFileAddr;
int secLen;

// Copy Section data
secMemAddr = (char *)pMemoryImage + psh->VirtualAddress;
secFileAddr = (char *)pDLLFileImage + psh->PointerToRawData;
secLen = psh->SizeOfRawData;

memcpy(secMemAddr,secFileAddr,secLen);

psh++;
}

return TRUE;
}


2 All:
потестировал я LoadLibrary с exe-шниками под win2k. exe-шник мэппится в память правильно, но потом он видит, что это exe, а не dll, и не выполняет никакой инициализации (не инициализируется импорт, фиксапы) :( вот так, а жаль. такая бы дырка была в защите.
похоже, этот трюк только в win9x работает.


 
Digitman   (2002-05-22 14:04) [11]

Ясно.
Т.е., как я и предполагал, до фиксапа дело в этом случае не доходит...

Фрагмент BO2k мог бы и не приводить - он (исх-к BO2k) целиком у меня перед носом:)... Только BO2k не использует SEC_IMAGE (почему-то), а предпочитает разрешать RVA секций самостоятельно... хотя вполне можно было бы эту работу переложить на SEC_IMAGE


 
paul_shmakov   (2002-05-22 18:14) [12]

2 Digitman:

Т.е., как я и предполагал, до фиксапа дело в этом случае не доходит...

ага, к сожалению.


Фрагмент BO2k мог бы и не приводить - он (исх-к BO2k) целиком у меня перед носом:)...

да это я не тебе, ты ведь сам его всем предлагаешь посмотреть. просто может еще кто интересуется, а исходника под рукой нет.


Только BO2k не использует SEC_IMAGE (почему-то), а предпочитает разрешать RVA секций самостоятельно... хотя вполне можно было бы эту работу переложить на SEC_IMAGE

так он SEC_IMAGE не использует потому что его win9x не поддерживает, вот и пришлось вручную.


 
paul_shmakov   (2002-05-22 18:51) [13]

кстати, раз уж мы тут про BackOrifice заговорили, то позволю себе дать ссылку на собственный же постинг ;)
там немного более подробно написано про механизмы скрытия bo2k в nt и win9x.
http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1014992279&n=2


 
Digitman   (2002-05-23 08:52) [14]

>paul_shmakov

> SEC_IMAGE не использует потому что его win9x не поддерживает


Да, видимо - так. Я не проверял, но - приму на веру твое утверждение. Сомнения по этому поводу возникли именно потому, что в MSDN нет комментариев по платформозависимости этого флага.


 
paul_shmakov   (2002-05-23 13:11) [15]

2 Digitman:
:) не, на веру мое утвержение лучше не принимать. вот здесь сам microsoft про платформозависимость этого флага пишет:
"INFO: CreateFileMapping() SEC_* Flags (Q108231)"
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q108231


Under Windows NT, the Win32 loader simply sits on top of the memory mapped file subsystem, and so when the loader needs to load a PE executable, it simply calls down into the existing memory mapped file code. Therefore, it is extremely easy for to support SEC_IMAGE in CreateFileMapping() under Windows NT.

In Windows 95, the loader is more complex and the memory mapped files are simple and only support the bare minimum of functionality to make the existing MapViewOfFile() work. Therefore, Windows 95 does not support SEC_IMAGE. There is support for SEC_NOCACHE, SEC_RESERVE and SEC_COMMIT.


 
Digitman   (2002-05-23 13:26) [16]

>paul_shmakov

Благодарю за ссылку.


 
Fellomena   (2002-05-23 15:37) [17]

2 paul_shmakov © (21.05.02 20:35):
угу... теперь ситуация прояснилась...
Значит на трюк загрузки EXE-файла через LoadLibrary в ответственных приложениях полагаться не стоит.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2002.07.29;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.007 c
7-95573
Dyacha
2002-05-08 12:03
2002.07.29
Как печатать книжки


1-95373
nikoss
2002-07-15 15:04
2002.07.29
Ошибка при вызове процедуры


3-95253
Alenka
2002-07-09 10:31
2002.07.29
Запомнить значение в текущей ячейки


3-95239
BKGG
2002-07-06 22:39
2002.07.29
InterBase


3-95193
_dron_
2002-07-05 19:40
2002.07.29
Подскажите, плз, побыстрее две базы в Interbase (локальные)





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский