Размер класса
В библиотеке есть метод которому передается указатель на объект класса. Далее она( библиотека ) вызывает метод данного объекта, при дизассемблирование было обнаружено что сдвиг на 12:
Код:
// Примерный код в библиотеке
int cl; // Указатель на класс
//...
(*(int (**)())(*(_DWORD *)cl + 12))(); // Вызов данного метода
int cl; // Указатель на класс
//...
(*(int (**)())(*(_DWORD *)cl + 12))(); // Вызов данного метода
При попытке воссоздать данный класс я получаю Segmentation fault.
Возникает вопрос - как узнать какой у меня выходит сдвиг? ( указатель на метод - указатель на класс? Но как реализовать? )
Возможно ли просто выделить память, засунуть туда обычную функцию с этим сдвигом и передать указатель на начало участка данной памяти?
Может быть вот-так: (*(int (**)())(*(_DWORD *)(cl + 12)))();
Нет, я правильно написал. Да и какая разница? Это то что выполняется в библиотеке. Вопрос стоит в другом.
1. Согласно заданному приоритету выполнения операций, сначала указатель cl
смещается на 12 позиций вперед, а потому уже происходит неявное преобразование
указателя в указатель типа _DWORD* и т.д.
2. Сделать можно это следующим образом: сначала приобразовать объект класса pobj в
указатель типа void* или DWORD* при помощи static_cast:
void* cl = static_cast<void*>(pobj);
Далее сместить указатель cl на определенное количество позиций от начала (в данном
случае 12) cl = cl +12, получить в результате адрес метода класса, который потом преобразовать
в указатель на функцию и передать его в виде аргумента другой функции, внутри которой выполнить
вызов callback-функции по заданому адресу cl <=> требуемый метод класса.
Ваши "примерные коды", никому не интересны ибо по сути бесполезны, приводите реальные ассемблерные листинги, объявления ф-ций названия библиотек и тд и тп и тогда, возможно, получите ответ.
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))();
}
{
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;
}
{
return (void *)&_class;
}
Входящий параметр функции библиотеки ( по мнению IDA ) - int (*a1)()
Код:
mov 0xc(%eax),%eax
call *%eax
call *%eax
и при том, при неявном приведении получить реальный адрес метода класса
из табл. виртуальных функций невозможно. Кстати сам метод может быть
невиртуальным вообще. Как я писал выше реальный адрес можно получить
только при использовании static_cast<void*)(pobj). А runtime- ошибка
Segmentation Fault - это означает, что потерян указатель на страницу
(сегмент) памяти, в который загружен метод. Надо попробовать
void *funct()
{
static CClass* pclass = new CClass();
return static_cast<void *>(pclass);
}
Есть функция, так сказать инициализация библиотеки. В неё передается указатель на нашу функцию. Там функция выполняется и результат сохраняется во внутренней переменной библиотеки:
Код:
call *%eax
mov %eax,0xAAAAAA ;AAAAAA для наглядности
mov %eax,0xAAAAAA ;AAAAAA для наглядности
Код:
mov 0xAAAAAA,%edx ; Вот эта переменная
test %edx,%edx ; Если она объявлена
mov (%edx),%eax
mov 0xc(%eax),%eax ; Сдвигаем
call *%eax ; И вызываем
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*
}
{
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*
}
Цитата: netstat
1. Код генерировал IDA, не я. Могу кинуть asm код
2. Метод вызывается из библиотеки, сам метод в приложении. Исходный код библиотеки закрыт.
Вот набросал всё в одно приложение, результат - Segmentation fault:
на деле в библиотеке функция которой я передаю ссылку на функцию, которая в свою очередь отдаёт указатель на класс:
Входящий параметр функции библиотеки ( по мнению IDA ) - int (*a1)()
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))();
}
{
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;
}
{
return (void *)&_class;
}
Входящий параметр функции библиотеки ( по мнению IDA ) - int (*a1)()
Мой хрустальный шар подсказывает отсутствие в таблице виртуальных ф-ций еще 3х ф-ций членов перед вашим.
Если не секрет - с чего Вы взяли, возможно реально я пропустил что-то
Цитата: netstat
Ramon
Если не секрет - с чего Вы взяли, возможно реально я пропустил что-то
Если не секрет - с чего Вы взяли, возможно реально я пропустил что-то
Вы хотели ответ - вы его получили. Лекции по C++ и его внутренним механизмам оплачиваются отдельно =^_^=
Спасибо, добавил вообще левый метод в класс и всё заработало!)))
Таблица_виртуальных_методов
Первое поле физической структуры объекта - адрес vtable, если есть.
cl - адрес объекта
*(int *) cl - чтение адреса vtable (первого поля по адресу объекта)
*(int *) cl + 12 - смещение в vtable, то есть адрес 4-й виртуальной функции
Первое поле физической структуры объекта - адрес vtable, если есть.
cl - адрес объекта
*(int *) cl - чтение адреса vtable (первого поля по адресу объекта)
*(int *) cl + 12 - смещение в vtable, то есть адрес 4-й виртуальной функции
Спасибо)