+ Reply to Thread
Results 1 to 3 of 3

Thread: Определение конца функции.

  1. #1

    Default Определение конца функции.

    Добрый день!

    Появилась следующая задача:
    Есть, например, инструкция CALL 0x400100.
    Я хочу узнать по какому смещению/адресу находится конец вызываемой функции, собственно, начало известно - 0x400100. Как найти конец функции?
    Проблема заключается в том, что ,на сколько я понимаю, надо найти инструкцию RET и тогда я смогу получить конец функции, но этих RET ведь может быть не один, верно ведь? Что делать в таком случаи, как найти нужный, самый последний RET?

  2. #2
    root's Avatar

    Default Re: Определение конца функции.

    Если выходов (RET'ов) больше одного, то им предшествует какая-либо команда ветвления Jxx (например, JNZ). Таким образом, чтобы найти все выходы, нужно проанализировать, как минимум, предшествующие команды Jxx... Если все найденные Jxx указывают на адреса перед RET, то этот RET последний. Но могут быть исключения. Например, если между Jxx и RET находится JMP, который указывает на адрес находящийся за RET, то этот RET не последний.
    Last edited by root; 20-07-2013 at 13:42.
    Успех – это путь от провала до провала без потери энтузиазма. (В. Черчиль)

    Не бойся идти медленно, бойся остановиться. (Китайская пословица)

    When you lose fun and start doing things only for the payback, you're dead. (c) TCLH (Phrack 65, Intro)

  3. 3 пользователя(ей) сказали cпасибо:
    Dark Koder (23-11-2013) coldfire (20-07-2013) ximera (21-07-2013)
  4. #3
    ARCHANGEL's Avatar

    Default Re: Определение конца функции.

    Есть только один способ решить эту задачу правильно. Предположим, что наш код не модифицирует сам себя во время выполнения (для подавляющего большинства программ - это правда). Тогда поиск конца функции заключается в построении графа потока управления и нахождения максимально удалённой инструкции в этом графе. Построение графа в этом случае не так уж и сложно выполнить. Для начала нужно обзавестить дизассемблерным движком. Из нашего первого условия следует, что нам предстоит дизассемблировать неперекрывающиеся команды. Т.е. говоря простым языком, мы не встретим джампов внутрь каких-то инструкции, например. Для такого дизасма справедливо то, что дизассемблировав первую инструкцию, мы имеем её размер, и вторая инструкция начнётся с места адрес_первой_инструкции + размер_первой_инструкции и т.д. И так мы дизасмим себе код, пока не встретится инструкция изменеия потока управления, а это всякие джампы (условные и безусловные), инструкции call, генерацию исключений, трюки push + retn мы пока не рассматриваем, они слишком редкие. Если джамп безусловный, то текущий блок заканчивается. Если условный, то текущий продолжается, и создаётся новый, который начинается с места, на которое управление переходит при выполнении перехода. Инструкция retn завершает текущий блок. Так мы дизасмим до того, пока все блоки не закончатся либо jmp на конце, либо retn. Потом для каждого блока берём адрес его последней инструкции, прибавляем к каждому такому адрес размер этой самой последней инструкции и получаем окончания блоков. Самое большое значение - это конец фнкции. От этого значение вычитаем адрес начала функции, и ура - мы получили размер.
    Добрым быть просто - достаточно обратить свой гнев на негодяев...

  5. 2 пользователя(ей) сказали cпасибо:
    coldfire (24-07-2013) ximera (27-07-2013)
+ Reply to Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
All times are GMT. The time now is 01:32
vBulletin® Copyright ©2000 - 2018
www.reverse4you.org