Вызов функции без импорта

Сегодня посмотрел очередную свежую серию MLP:FiM и понял, что мне нечем себя занять. В связи с этим решил включить трек моей любимой группы (как вы, наверное, догадались - это Ранетки :D) и написать что-нибудь эдакое на ассемблере.
По совету друзей, которые маются всякой фигней, вместо того, чтобы заняться чем-нибудь полезным и написать нормальную статью в блог, выбор пал на написание нескольких макросов, которые позволяют вызывать библиотечные функции без использования таблицы импорта.
Минусы: макросы базозависимые.
Плюсы: макросы потокобезопасные.
Anyway: на базе этих макросов можно достаточно быстро построить новые, удобные вам.

Пример использования получившихся макросов:


Сами макросы:

Надеюсь, кому-нибудь пригодится.
Исходные коды одним архивом: скачать.

Обновлено: 14.11.11

Вызов функции без импорта: 21 комментарий

  1. Спасибо, весьма интересно! Единственное, что значит базозависимые?
    "Минусы: макросы базозависимые."

    1. Значит, что они используют абсолютные смещения (секция данных используется). Вот если бы все макросы только стек и относительные смещения использовали, тогда базозависимыми они бы не были.

  2. А если один из параметров макроса "xinvoke" будет "addr localvar" адресом локальной переменной, то такой макрос должен не сработать. Как быть?

  3. Это само собой, вопрос, непонятно как отличить локальную от глобальной, ведь нужно будет во время генераии push сделать lea reg, push reg.

    1. Что значит "как отличить", если ты сам код пишешь и видишь, где локальные, где глобальные :)
      Я предлагаю в макросы не толкать addr, а перед вызовом макроса делать lea, а в макрос уже регистр передавать.
      Хотя если немного поколупать макросы, возможно, получится и универсально сделать.

  4. Понял ход твоих мыслей. Это обходной путь, так неинтересно. :) А я думаю как можно сделать полную эмуляцию invoke, чтобы и с адресами локальных переменных не было проблем. Неисключена и такая ситуация, что количество параметров которые должны содержать адреса локальных переменных будет больше, чем рабочих регистров. Можно конечно использовать указатели, но это обходной путь.

    1. Кстати, если в invoke ты используешь и регистр eax, и addr что_то, он ругнется. А чтобы эти макросы заставить работать как invoke, надо над ними поработать еще)

    2. Только что сделал полную эмуляцию invoke, даже предупреждение выдает, если попытаться использовать в одном вызове оператор addr и регистр eax. Завтра выложу.

  5. Спасибо за обновление, полезный макрос. Предлагаю использовать предупреждение только в том случае, если регистр eax используется левее, чем addr, т.к. только в таком случае регистр eax будет реинициализироваться. Такую проверку можно сделать сохранением индекса параметров, а перед варнингом сделать проверку IF index_eax LT index_addr.
    Правильно ли я понимаю, различия между адресом глобальной и локальной переменной нету? Будут идеи как отличить адрес глобальной от локальной переменной?

    1. Адрес никак не отличишь. Разве что, существуют какие-то виндовые функции, позволяющие отличить адрес стека от адреса кучи. Локальные переменные всегда в стеке лежат, глобальные - в куче. Может быть, такое и вручную реализуемо, не задумывался. По идее, где-то должны лежать указатели на начальные адреса стека и кучи процесса...

  6. DX, ты бы не мог сделать не базозависимую версию (для крипторов/пакеров/протекторов)? Я пишу криптор.

      1. DX:
        "Значит, что они используют абсолютные смещения (секция данных используется). Вот если бы все макросы только стек и относительные смещения использовали, тогда базозависимыми они бы не были."

        1. Ну так возьми и напиши базонезависимые макросы, what's the problem? Человек, пишущий криптор сам, должен в таком разбираться.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *