Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Размер класса

79K
01 апреля 2012 года
netstat
8 / / 05.03.2012
Есть приложение и библиотека.

В библиотеке есть метод которому передается указатель на объект класса. Далее она( библиотека ) вызывает метод данного объекта, при дизассемблирование было обнаружено что сдвиг на 12:
 
Код:
// Примерный код в библиотеке
int cl; // Указатель на класс
//...
(*(int (**)())(*(_DWORD *)cl + 12))(); // Вызов данного метода

При попытке воссоздать данный класс я получаю Segmentation fault.

Возникает вопрос - как узнать какой у меня выходит сдвиг? ( указатель на метод - указатель на класс? Но как реализовать? )
Возможно ли просто выделить память, засунуть туда обычную функцию с этим сдвигом и передать указатель на начало участка данной памяти?
67K
01 апреля 2012 года
NoXCode
64 / / 11.03.2012
Может быть вот-так: (*(int (**)())(*(_DWORD *)(cl + 12)))();
79K
01 апреля 2012 года
netstat
8 / / 05.03.2012
Нет, я правильно написал. Да и какая разница? Это то что выполняется в библиотеке. Вопрос стоит в другом.
67K
01 апреля 2012 года
NoXCode
64 / / 11.03.2012
Я думаю что нет:
1. Согласно заданному приоритету выполнения операций, сначала указатель cl
смещается на 12 позиций вперед, а потому уже происходит неявное преобразование
указателя в указатель типа _DWORD* и т.д.

2. Сделать можно это следующим образом: сначала приобразовать объект класса pobj в
указатель типа void* или DWORD* при помощи static_cast:
void* cl = static_cast<void*>(pobj);
Далее сместить указатель cl на определенное количество позиций от начала (в данном
случае 12) cl = cl +12, получить в результате адрес метода класса, который потом преобразовать
в указатель на функцию и передать его в виде аргумента другой функции, внутри которой выполнить
вызов callback-функции по заданому адресу cl <=> требуемый метод класса.
260
01 апреля 2012 года
Ramon
1.1K / / 16.08.2003
Ваши "примерные коды", никому не интересны ибо по сути бесполезны, приводите реальные ассемблерные листинги, объявления ф-ций названия библиотек и тд и тп и тогда, возможно, получите ответ.
79K
01 апреля 2012 года
netstat
8 / / 05.03.2012
1. Код генерировал IDA, не я. Могу кинуть asm код
2. Метод вызывается из библиотеки, сам метод в приложении. Исходный код библиотеки закрыт.

Вот набросал всё в одно приложение, результат - Segmentation fault:

Код:
class IClass
{
public:
    virtual void TestFunct() = 0;
};

class CClass : public IClass
{
public:
        void TestFunct()
        {
            printf( "WORK!\n" );
        }

};

static CClass _class;

int main(int argc, char **argv)
{
    int cl = (int)&_class;
   
    if ( !cl )
        return -1;
       
    (*(void (**)())(*(int*)cl + 12))();
}
на деле в библиотеке функция которой я передаю ссылку на функцию, которая в свою очередь отдаёт указатель на класс:

 
Код:
void *funct()
{
    return (void *)&_class;
}

Входящий параметр функции библиотеки ( по мнению IDA ) - int (*a1)()
79K
01 апреля 2012 года
netstat
8 / / 05.03.2012
 
Код:
mov    0xc(%eax),%eax
call   *%eax
67K
01 апреля 2012 года
NoXCode
64 / / 11.03.2012
Так делать нельзя, напр. в int &class нельзя преобразововать, только DWORD,
и при том, при неявном приведении получить реальный адрес метода класса
из табл. виртуальных функций невозможно. Кстати сам метод может быть
невиртуальным вообще. Как я писал выше реальный адрес можно получить
только при использовании static_cast<void*)(pobj). А runtime- ошибка
Segmentation Fault - это означает, что потерян указатель на страницу
(сегмент) памяти, в который загружен метод. Надо попробовать
void *funct()
{
static CClass* pclass = new CClass();
return static_cast<void *>(pclass);
}
79K
01 апреля 2012 года
netstat
8 / / 05.03.2012
Да говорю не я преобразовывал, а IDA. int не Int - неважно. Это всё в библиотеке. Если использовать static_cast - ошибка та же. Опишу всё заново дабы разложить по полочкам.

Есть функция, так сказать инициализация библиотеки. В неё передается указатель на нашу функцию. Там функция выполняется и результат сохраняется во внутренней переменной библиотеки:
 
Код:
call   *%eax
mov    %eax,0xAAAAAA    ;AAAAAA для наглядности
Далее в библиотеки есть функция в которой используется эта переменная:

 
Код:
mov    0xAAAAAA,%edx  ; Вот эта переменная
test   %edx,%edx      ; Если она объявлена
mov    (%edx),%eax
mov    0xc(%eax),%eax ; Сдвигаем
call   *%eax          ; И вызываем
Вот я и реализовал:

Код:
class IClass
{
public:
    virtual void TestFunct() = 0;
};

class CClass : public IClass
{
public:
        void TestFunct()
        {
            printf( "WORK!\n" );
        }

};

static CClass _class;

static void *getClass()
{
    return (void *)&_class;
}

int main(int argc, char **argv)
{
    //dlsym..
    //...
    // Передаю getClass как void*
}
260
01 апреля 2012 года
Ramon
1.1K / / 16.08.2003
Цитата: netstat
1. Код генерировал IDA, не я. Могу кинуть asm код
2. Метод вызывается из библиотеки, сам метод в приложении. Исходный код библиотеки закрыт.

Вот набросал всё в одно приложение, результат - Segmentation fault:

Код:
class IClass
{
public:
    virtual void TestFunct() = 0;
};

class CClass : public IClass
{
public:
        void TestFunct()
        {
            printf( "WORK!\n" );
        }

};

static CClass _class;

int main(int argc, char **argv)
{
    int cl = (int)&_class;
   
    if ( !cl )
        return -1;
       
    (*(void (**)())(*(int*)cl + 12))();
}
на деле в библиотеке функция которой я передаю ссылку на функцию, которая в свою очередь отдаёт указатель на класс:

 
Код:
void *funct()
{
    return (void *)&_class;
}

Входящий параметр функции библиотеки ( по мнению IDA ) - int (*a1)()



Мой хрустальный шар подсказывает отсутствие в таблице виртуальных ф-ций еще 3х ф-ций членов перед вашим.

79K
01 апреля 2012 года
netstat
8 / / 05.03.2012
Ramon
Если не секрет - с чего Вы взяли, возможно реально я пропустил что-то
260
01 апреля 2012 года
Ramon
1.1K / / 16.08.2003
Цитата: netstat
Ramon
Если не секрет - с чего Вы взяли, возможно реально я пропустил что-то


Вы хотели ответ - вы его получили. Лекции по C++ и его внутренним механизмам оплачиваются отдельно =^_^=

79K
01 апреля 2012 года
netstat
8 / / 05.03.2012
Спасибо, добавил вообще левый метод в класс и всё заработало!)))
443
01 апреля 2012 года
REmindER
292 / / 23.03.2003
Таблица_виртуальных_методов

Первое поле физической структуры объекта - адрес vtable, если есть.

cl - адрес объекта
*(int *) cl - чтение адреса vtable (первого поля по адресу объекта)
*(int *) cl + 12 - смещение в vtable, то есть адрес 4-й виртуальной функции
79K
01 апреля 2012 года
netstat
8 / / 05.03.2012
Спасибо)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог