Вопрос. Хочу переделать exe файл в dll. Более подробно я описал тут: http://www.cracklab.ru/f/index.php?action=vthread&forum=5&topic=7040 и создал такую же тему рядом: http://www.wasm.ru/forum/viewtopic.php?id=17799 Что могут посоветовать дзенствующие?
Тогда по частям. Хочу для начала изменить точку входа, вставить дополнительный код DllEntryPoint() и табличку экспорта, не важно пока с какими там значениями адресов. Работаем с .EXE. Для начала я просмотрел секцию кода на предмет свободного места. Не много оказалось. До следующей секции 288 байт (0x0120). Код на асме забить можно и секцию экспорта туда тоже поместиться. Секцию экспорта я нашёл в .DLL файле и просто скопировал структуру IMAGE_DIRECTORY_ENTRY_EXPORT (P.S. т.е. я хотел сказать IMAGE_EXPORT_DIRECTORY) прямо в конец секции .text в файле .EXE. Размер её составил 176 байт (0x00B0). Насколько мне помниться есть некоторая свобода в расположении секций и то, что я засунул секцию экспорта в .text - просто немного сейчас усложнит мне жизнь. Пока есть возможность я не хочу менять размера бинарика. Теперь, нужно или не нужно менять NumberOfSections в IMAGE_FILE_HEADER? Вопрос на первый взгляд странный, но в .DLL файле, откуда я взял этот экспорт, найти стандартным путём смещение на таблицу экспорта мне не удалось. Я её поиском нашёл по известным мне именам экспортируемых функций. Так вот... А...аа в IMAGE_DIRECTORY_ENTRY_EXPORT есть запись. Теперь понятно. Тогда такой вопрос. Теперь мне нужно заполнить просто поля: VirtualAddress и Size. Если с последним понятно, то как правильно выбрать VirtualAddress? Просмотреть все записи массива IMAGE_DATA_DIRECTORY, найти самый большой адрес и что-то к нему прибавив записать в качестве VirtualAddress для секции экспорта, так? Как должен образ таблицы экспорта располагаться в памяти после загрузки? Также как в файле - в секции кода - или всё таки в своей собвстенной области какой? Я не слишком замудрил? Потом перейду к написанию DllEntryPoint() и возможно модификации таблицы перемещений. P.S. Чёрт я ошибся, нашёл поиском похоже не IMAGE_EXPORT_DIRECTORY, а что-то непонятное, но смахивающее на неё. Зараза. Должен же где-то быть список функций, адресов и ординалов экспорта. Почему эта структура в файле не так выглядит... ёклмн. Ладно пойдём сначала.
во-первых, я не вижу необходимости конвертить exe в длл, т.к. возникает куда больше проблем, чем другой вариант - тот же ехе, только с собственным загрзчиком-интерпретатором во-вторых, длл грузятся не по статическому адресу, так что в случае с длл тебе придётся ещё и релоки создавать в-третьих, загрузчик, о котором я сказал может как раз и вызывать твою собственную длл (а-ля плагин), которая и будет добавлять функционал твоему ехе пример (коротко): ты создаешь длл, в которой реализуешь весь недостающий тебе функционал ты пишешь компактный загрузчик, который будет грузить созданную тобой длл (не ехе). ты вставялешь код загрузчика в не твой ехе, примерно как вирус т.е. в итоге ты как бы заражаешь файл своим вирусом что должен делать загрузчик: давать возможность исходной программе нормально "инициализоваться", собрать адреса всех нужных функций, запустить длл-расширени и передать ей адреса ф-ций и любую другую инфу, которая может понадобитья. P.S. почитал твои посты по теме. уфф.
Вообще, можно покомбинировать. Сначала я хотел делать по-другому (первое что в голову пришло) - есть 2 программы, которые бы использовали одну dll, но поскольку каждой программе выделяется своё адресное пространство, то ясно, что это ни как не катит, насколько я себе это представляю. Когда пришло осознание, то начал думать о dll-"перехватчиках". Тут ещё нужно понять для чего я это делаю. Mathcad имеет своё рабочее пространство переменных и работает с ними, Maple движок в нём (mkernel.dll, та самая в которую я хочу превратить .exe файл) тоже работает со своим пространством переменных. Mathcad может обращаться к Maple, чтобы посмотреть его переменные, но только очень ограниченно и другого пути посмотреть пространство переменных Maple (mkernel.dll) нет. С другой стороны есть пакет MapleV R4, который свободно общается с mkernel.lib (статически привязан к wmaple.exe - это тот .EXE, который я хочу превратить в dll). Самое простое, что мне пришло на ум - переделать Exe в Dll и подсунуть её Mathcad'у. Что тогда будет? На экране будет 2 окна как бы одного приложения. Первое окно Mathcad'а, который может решать задачи в своём пространстве и заглядывать в пространство символьного движка (новоиспеченного mkernel.dll). Второе окно - MapleV R4 - он понятия не имеет, что работает "приаттаченным" к Mathcad'у. Те функции, что для Mathcad'а являются импортируемыми, для него "родные". В этом случае мы имеем полный контроль над Maple движком, полный поддерживаемый набор функций, полный доступ к пространству переменных... ну и всё это через его собственный родной интерфейс. Это МЕЧТА. Такие дела. Я не понял, что значит создавать "релоки"? Таблица перемещения в WMAPLE.EXE имеется. Я так понимаю мне нужно будет её модифицировать, но не создавать. Максимум мне её нужно будет дополнить, если я напишу "привязанный" дополнительный код (в DllEntryPoint()). Вот здесь я не очень понял. Мне не совсем ясен механизм в том контексте, что я изложил выше. Дело в том, что у меня нет никакого дополнительного функционала. Весь дополнительный функционал уже написан за меня, а что самое главное С УЧЁТОМ ПРОТОКОЛОВ ОБМЕНА между интерфейсом командной строки и движком mkernel.dll. Вся эта функциональность содержится в файле WMAPLE.EXE, ничего лишнего там нет. Мне нужен MDI это IDE для доступа к пространству переменных mkernel.dll в процессе mathcad.exe. Сам я лучше не напишу. Работать это должно так: Запускается Mathcad, он подгружает mkernel.dll (кроме всех прочих), во время инициализации dll'ка создаёт окно IDE от MapleV R4, которое висит на экране. Далее продолжается загрузка mathcad'а, который создаёт уже своё окно - свою IDE. Я могу переключаться между окнами и работать то в одной среде, то в другой, но САМОЕ ГЛАВНОЕ, что я могу результаты работы в MapleV R4 "видеть" в Mathcad. Это очень удобно. Хотя maple движок и запускается в среде mathcad, последний по своей функциональности и в подмётки не годится библиотеке mkernel.dll, ИМЕННО ПОЭТОМУ мне нужен полный доступ через _стандартный_ интерфейс к этой библиотеке. Мне не понятно обращение к public данных экспортируемых dll. Дело в том, что эти несколько (3) структуры содержат сводную инфу о работе maple движка. Понятно, что Mathcad обращается к ним как бы "напрямую". Никаких функций не вызывается - вопрос - как мне узнать, что "не мой exe" обратился к public переменной?
Чтобы разговор был попредметней, могу два файла в архиве показать (zip, ~ 967Кб): http://slil.ru/23581910 Найденные мной смещения и прочую доп инфу запостю попозже. P.S. Здесь 2 файла в архиве: wmaple.exe и mkernel.dll - они выделены из дистрибутивов соотв-щих программ, поэтому запускать или что-то там делать с ними смысла нет . Таблицу экспорта в mkernel.dll смотрите по смещению: 0x00066750, котороче, а остальное dumpbin \exports, если не помните так он разрисует. Ах.. вот, что он рисует: Код (Text): Dump of file mkernel.dll File Type: DLL Section contains the following exports for MKERNEL.dll 0 characteristics 3300C0E1 time date stamp Tue Feb 11 23:56:33 1997 0.00 version 1 ordinal base 13 number of functions 11 number of names ordinal hint RVA name 10 0 0003A710 CleanUpBeforeExit 13 1 00006BC0 DLLAllowGC 2 2 000240E0 DLLParseMaple 12 3 000155F0 DLLProtectFromGC 4 4 00023140 EvaluateDAG 1 5 0003A760 InitializeMaple 6 6 00040880 KernelMemoryStats 11 7 000442E0 RestartMaple 8 8 000690DC allowSSystemFlag 7 9 0006A8D0 r_unit 9 A 0006A8CC r_unit0 Summary 1F000 .data 1000 .idata 2000 .rdata 6000 .reloc 1000 .rsrc 66000 .text Это если набивать лень. Код (Text): 8 8 000690DC allowSSystemFlag 7 9 0006A8D0 r_unit 9 A 0006A8CC r_unit0 Это 2 переменные типа DWORD и один массив, если правильно дезассемблил. Что то я видать напутал с количеством функций выше по постам... это от того, что я уже не первую mkernel.dll разбирал, всё в голове смешалось. Нету ординалов 3 и 5 - пропущены.
Теперь, чтобы сравнить, насколько похожи функции в dll и exe файле, я дам смещения для каждой из функций там и там: Код (Text): mkernel.dll wmaple.exe Names ____________________________________________ 0003A710 000A88B0 CleanUpBeforeExit 00006BC0 000187C0 DLLAllowGC 000240E0 00056C80 DLLParseMaple 000155F0 0002E370 DLLProtectFromGC 00023140 00049670 EvaluateDAG 0003A760 000A7D90 InitializeMaple 00040880 ???????? KernelMemoryStats 000442E0 000CA0A0 RestartMaple 000690DC 001B9298 allowSSystemFlag 0006A8D0 001BA108 r_unit 0006A8CC 001BA104 r_unit0 В оригинале вообще с базой было так: 1003A710 004A88B0 CleanUpBeforeExit 10006BC0 004187C0 DLLAllowGC 100240E0 00456C80 DLLParseMaple 100155F0 0042E370 DLLProtectFromGC 10023140 00449670 EvaluateDAG 1003A760 004A7D90 InitializeMaple 10040880 ???????? KernelMemoryStats 100442E0 004CA0A0 RestartMaple 100690DC 005B9298 allowSSystemFlag 1006A8D0 005BA108 r_unit 1006A8CC 005BA104 r_unit0 KernelMemoryStats я не нашёл. В wmaple.exe даже аналог DllEntryPoint() можно найти по функциональности. Правильно ли я базу вычел для секции данных (r_unit и пр.)? Если кто будет смотреть в код после дизассемблирования, то воочию увидит совпадение на 99%. Потому я и сделал вывод, что замена в принципе возможна.
Итак, вроде бы заработало. После многочисленных телодвижений exe превратился в dll, но пока я не стал интерфейс запускать. Надо сказать, что я не всё подчистить как надо, но Mathcad пока не ругается, решает как полагается. Для этого потребовалось совсем не много: 1) Я создал секцию экспорта, нашёл все функции (кроме одной) и прописал их адреса в секции 2) Одну функцию пришлось прямо в машинных кодах дописывать к секции кода. Благо она небольшая, но 2 релокейшна придётся делеать для неё, т.к. две инструкции обращаются по абсолютным адресам. Хорошо, что эта функция предназначена только для небольшого мониторинга. 3) Также к секции кода дописал заглушку DllMain и поменял точку входа на неё 4) Добавил флаг IMAGE_FILE_DLL ([0x96]: 0x210e) , ну и конечно поменял имя на mkernel.dll Для пущей уверенности дизассемблил заново в IDA - всё тип топ. Релоки в экзешнике были, кроме того, пришлось отдельно проверять работают они или нет - это отдельная история. Самое трудное оказалось правильно таблицу экспорта разрисовать, тут dumbbin помог, каждый раз его просил посмотреть всё ли в порядке. Наконец решил подсунуть это дело Mathcad'у (была маленькая вероятность, что сразу заработает). Заработало. Тестирую. Но это ещё не всё. ВОПРОС. В dll содержится код MDI приложения, там обычный код, начинающийся со start и т.д. Мне нужно, чтобы при инициализации dll этот код получил управление и отобразил (создал) интерфейс, причём потом вернул управление обратно для загрузки остального кода и непосредственно приложения-родителя. Как это делается? Организовать отдельный поток и функцию start() выполнять в нём? Функция эта ведь зациклится наверное, если так, то я не смогу основного приложения загрузить. Как тут быть? Я знаю что это возможно, есть пример, но разбираться долго. Подскажите кто что знает. Спасибо за внимание. P.S. Ещё. Стартап коду какие параметры от системы передаются при запуске приложения? Если я хочу сам выполнить вызов по call, то какие переменные и в каком количестве нужно передовать библиотечной функции start()? Если может кого не затруднит показать простой код создания потока и запуска в нём своей функции. Или пошлите за примером. Только одно условие, желательно всё это в машинных кодах Ну если нету в кодах, то хотя бы на masm'е, чтобы лишнего кода было как можно меньше.
Так. Значит start() код требует всего одного параметра (указателя) да и ещё не пользует его. Это как раз что доктор прописал для функции CreatThread(), но вот беда, Exe не импортирует такой функции. Либо мне менять таблицу импорта ещё и добавлять туда CreateThread(), либо использовать GetProcessAddress(), но это тоже потребует вызова... а-га, последняя функция импортируется. Поэтому, пожалуй, остановимся на получении адреса CreateThread() в явном виде, а потом call'ом его call'ом. Хотя кто знает, может изменить таблицу импорта проще гораздо... не менял инкогда.
Спасиб, делаем. Тут вопросик по релокам возник. Заколустали они уже. Хочу добавить в таблицу перемещаемых элементов 2 записи. Знаю куда и что добавить. Залез в секцию, нашёл нужную страницу, добавил 4 байта смещений. В заголовке поправил размер на 4 байта. В начале файла добавил к истинному размеру секции 4 байта, ну и наконец выровнял размер файла, убрав лишние 4 байта из свободного пространства, которое выравнивает секцию .reloc. Я зря гнал на свой просмотрщик pe-файлов, он нормально воспринимает вложенные секции, дописал к нему часть, которая релоки смотрит. Загружаю в него, вроде всё тип-топ. Добавленные записи вижу, они соотв-ют смещениям в секции кода. Но такая фигня, когда подсовываю этот файл Mathcad'у, то он вылетает с ошибкой. Типа обратилась не потому адресу или вроде того. ВОПРОС. Как прально самому добавлять записи в .reloc? О чём я мог забыть? Я знаю, что есть утилита, которая за меня всё сделает - в PETools плагин. Но она по-моему туповата. Вместо того, чтобы использовать имеющееся свободное место, она "потёрла" секцию .reloc не удалив её и создала вторую секцию с тем же названием! Такой киш-мишь получается, 2 секции с одинаковым названием, внутри одной таблица экспорта, а внутри другой сами релоки - по-моему это не нормально, хотя может и будет работать. Некрасиво, когда 2 секции с одним названием - не по хакерски как-то. Мало того размер файла увеличила. P.S. В секцию релок я сам таблицу экспорта вставил, т.к. больше некуда было. Там места полно под выравнивание. А, не, там ошибка при инициализации приложения пишет. P.S. Такое чувство, что блоки релоков не независимые, а к чему-то привязаны. Когда я вставляю одну запись на место заполнителя (блок, куда мне нужно прописаться имеет один заполнитель для выравнивания), то вижу (в Olly), что поправка произошла при загрузке dll в месте моего приаттаченного кода. Когда же добавляю ещё одну запись, то ошибка инициализации. Не понятно чем лечить.
Ребят, хочу заплатить за работу. Сделаю предоплату (аванс). Мне некогда делать апгрейд своим знаниям, поэтому прошу откликнуться тем, у кого есть силы, время и возможности доделать так как я хочу. Очень я привык к старому и доброму для меня инструменту (Mathcad 11) и его возможностей мне хватает, но небольшую доработку хотел бы сделать. Вот предварительное ТЗ. Оно может несколько измениться из-за характера самой задачи в процессе её решения. Все необходимые материалы и консультацию предоставлю. Есть ПО математической тематики - "Mathcad 11 Enterprise Edition" (дистриб для тестирования предоставлю). Это математический пакет для численных и символьных расчётов средней сложности - не численный калькулятор, но и не монстр типа Matlab'а. У него есть нераскрытый потенциал, а именно библиотека символьных вычислений. Доступ к её функциональности искусственно ограничен самим интерфейсом MC11, но в принципе сама библиотека заменяема исполняемым файлом системы компьютерной алгебры MapleV R4, поскольку является её урезанной и слегка изменённой копией. В бытность свою фирма Mathsoft (ныне её приобрела PTC) купила лицензию на возможность использования части символьного движка, который до 13-й версии MC так и не менялся, сейчас (MC14) стоит движок от MuPAD - другой системы компьютерной алгебры. Так вот, это всё лирические отступления. В MC11 встроен интерфейс к интерпретатору символьного движка (библиотека mkernel.dll - сам движок). Этот интерфейс не использует каких-либо защит или уловок и проверок и можно считать, что обращается к движку напрямую как-бы текстом. Эту библиотеку можно заменить, как я уже сказал, на исполняемый файл от оригинальной системы той же версии, т.е. MapleV R4, плюс использовать все вторичные библиотеки этой системы и её интерфейс, что является предметом предлагаемой работы. Что я уже сделал. Я сопоставил два файла: mkernel.dll и WMAPLE.EXE, чтобы понять можно ли превратить exe в dll. Это оказалось возможным. Оба файла вместе с проектными файлами IDA я могу предоставить. Там можно просто посмотреть на то, что в обоих файлах присутствует практически идентичный код, касаемый доступа к символьному интерпретатору. Поскольку exe-файл не имел экспортируемых функций, я восстановил секцию экспорта со всеми ссылками на функции внутри exe, которые были идентичны экспортируемым функциям dll. Там кроме самых функций экспортируются также 2 переменные. Также я проделал ряд манипуляций, чтобы exe был dll. Подправил точку входа, дописал стандартный код обработчика в точке входа. В общем место там есть, где разбежаться. Созданный таким образом файл прекрасно "фунциклирует" вместо старого. Не совсем правда так как хотелось бы, но вполне достаточно. Делал я это около года назад, был после этого занят, так что кое-чего уже не упомню. Сейчас решил вернуться к идее. Что мне нужно. В exe файле содержится интерфейс. Его нужно так сказать "поднять" в параллельном потоке. Т.е. мне нужно, чтобы при загрузке MC11 также появлялся интерфейс MapleV R4. Они будут работать в одной области "символьной памяти", что мне и нужно. dll MC11 не содержит импортируемых функций работы с потоками, т.е. точнее их создания, но там есть по крайней мере GetProcAddress(). В общем, нужно будет написать код в машинных кодах для создания потока, которому в качестве функции отдать адрес функцию start(). Этот адрес у меня имеется. В машинных - это я конечно загнул, но нужно будет сделать все операции для внедрения такого кода, вплоть до того, чтобы добавить релоки, на чём я собственно и застрял год назад. Возможно я довольно сумбурно излагаю. Могу выложить то, что я сделал и более подробно объяснить чего хочу (все материалы будут доступны посредством моего ftp). Хотелось бы знать сколько могли бы стоит такого рода услуги. Спасибо за внимание.
uni Хм, насколько я помню (занимался встраиванием различных матсистем года 4 назад), maple предоставляла интерфейс[ы] к своему движку (maplec.dll) и почему бы просто не вызвать maple через него? То же самое и с MuPAD'ом — у него также есть приличный СОМ интерфейс, правда, реализованный как exe server. Почему для тебя критично, чтобы символьный движок находился в одном АП с целевой прогой (в данном случае MathCAD)?
"А это правильный вопрос" (с) Действительно, можно использовать открытые интерфейсы к движкам, которые правда появились много позже (в современном их виде). Дело в другом. MC11 очень мало использует символьные вычисления. Там все функции символьного движка, которые доступны, выведены на специальный тулбар. Получается, что вместе возможных 3000 функций я могу лишь использовать какие-то полтора десятка, что просто смешно. Это во-первых. Во-вторых, MC11 преобразует по умолчанию результаты работы maple-интерпретатора в свой вид, т.е. можно сразу (или почти) использовать результаты работы maple-движка. Комбинация интерфейса MC, его численных библиотек и символьной алгебры maple даёт силу, которая превосходит по возможностям современные версии подобных программ. Превосходит в удобстве работы для рядового инженера. Интерфейс MC очень удобен для визуализации, не хватает только командной строки, которую я и хочу приделать хотя бы таким образом. Кроме того, я смогу теперь расширять символьные возможности MC путём написания собственных библиотек (символьных) в родной IDE maple. О чём раньше даже мечтать нельзя было. Плюсы такого гибрида можно показать на примерах, где MC11 бьёт старшие свои версии простотой работы вплоть до MC14. Ещё хочу сказать, что OEM версия dll, которая используется в MC11 использует устаревший интерфейс взаимодействия при помощи набора из нескольких функций. Я не могу их заменить ни на что другое как только на точно такую же библиотеку. Кроме того этот интерфейс стар на столько, что я не смог найти приличной доки по нему. Кстати говоря, современный Matlab до сих пор использует вариант такой же библиотеки, насколько я вижу, может чуть более современной, но по возможностям всё той же. Там экспортируются функции: MapleInitialize, MapleEvaluate, MapleRestart и пр. В принципе пример работы с этой библиотекой можно было бы вытащить из её обёртки для Matlab, но уж это сложнее, предлагаемой мною задачи. Я лишь хочу подсунуть полную версию maple-движка для MC11, далее он будет её использовать как ни в чём не бывало. Никаких других телодвижений делать не нужно, зато сам MC11 станет уже "примочкой" для maple-библиотеки (!), т.к. последняя намного более функциональней, чем сам MC11. Вот так, вкратце. Правда я может чего не знаю, буду внимательным слушателем тогда. При реализации моей задачи библиотека может подойти также и для старших версий MC - 12, 13 и 13.5, т.к. там используется идентичная. Потому что MathCAD знает что делать с принятыми данными результатов символьных преобразований. Если я его попрошу вычислить символьно сложный интеграл, то могу сразу присвоить результат вычисления идентификатору, который будет уже функцией. Т.е. я в одну строчку записываю создание новой функции, через символьное как бы преобразование. При этом MC переведёт свой запрос на язык maple, отдаст на выполнение maple, тот вычислит и вернёт ответ обратно, MC получит ответ, преобразует его в свою форму и создаст функцию на основе этого ответа, которую я могу использовать как родную для MC. Это очень удобно и красиво выглядит. Более всего мне нравится в MC быстрота, с которой работаешь с выражениями (при навыке). Можно по крайней мере показать людям, которые текстовые строки maple слабо разумеют.
Вот пример расчёта, который затруднительно сделать в соверменной версии MC14 из-за закрытия недокументированных возможностей работы с символьным движком. http://slil.ru/24865266 Там самое интересное на первой странице. То, что подсвечено красным и есть использование недокументированных приёмов. MC говорит, что не знает функций det() и кроме того он не ясно понимает что такое Jacobian. Эти функции символьные, первая берётся прямо из символьного движка, а вторая является результатом искусскуного программирования одного забугорного товарища. Вторую можно было тоже использовать из maple, но есть ограничения интерфейса MC - он не позволяет просто напросто записать нужно выражение. Фишка этого документа в том, что он полностью автоматизирован - это означает, что нужно только ввести начальные данные и получится ответ, при этом выполнятся и численные и символьные вычисления. В обычном MC11 такого сделать не всегда возможно. Расчёты имеют более "человеческий" вид. Я не спорю, что тоже самое можно сделать и в maple и в mupad. Но уж так вышло, что начинал я именно с MC и привык к нему, как старым добрым окошкам нортона, потому до сих пор юзаю Far, хотя он глючит с именами и иногда приходится юзать Total Cmd Podarok Edition. P.S. Здесь ещё нужно учитывать, что не требуется установленной версии Maple. Достаточно лишь dll. У меня установлены все известные математические пакеты последних версий, но предпочитаю я пользоваться лишь MC11, иногда MC14. А вообще, смотря какая стоит задача.
Этот этап закрыт. Сам всё сделал. Править релоки - полная фигня по сравнению с остальными появившимися проблемами. Сделал я как хотел, теперь при загрузке MC появляется сначала окно IDE MapleV R4, но увы, после её загрузки, MC затыкается на одном месте зараза. Самое, что смешное, когда я изменю всего один байт (отключу создание потока для IDE Maple в mkernel.dll), то это место MC проходится замечательно и всё грузится и можно работать. Это самое место ошибки (ошибка - "правильная", не связанная с неверным указателем и пр. явно) связано с вызовом CoCreateInstance() из одной подключаемой dll. Заколустался уже Olly заставлять перезапускать процесс и смотреть отличия загрузки. Блин, совсем чуть-чуть осталось. Будем думать.
Объявляю тему закрытой в виду полного завершения проекта. Кому интересно, далее на форум пользователей: [Maplecad VR4/1X] http://forum.exponenta.ru/viewtopic.php?t=5353