#c #function-pointers
#c #указатели на функции
Вопрос:
Я пытаюсь изучить несколько различных методов вызова функций по адресу.
bool gl_draw_text(uint x, uint y, uint color, uint alpha, char *fmt);
Я вызываю именно эту функцию. В настоящее время я вызываю ее следующим образом. (И это работает нормально.)
static void glDrawText(char* text, int x, int y)
{
DWORD func = 0x10057970;
__asm
{
push text
push 255
push 14
push y
push x
call dword ptr [func]
}
}
Метод, который я хочу использовать, — это этот.
void Hack()
{
bool (draw*)(uint, uint, uint, uint, char*);
draw = 0x10057970;
(draw)(20, 20, 14, 255, "Text");
}
Но я не знаю, как правильно передать адрес функции, чтобы она работала компилировалась. ?
Существует также метод, который использует виртуальную функцию, мне любопытно, как работает и этот метод. (Я также могу использовать MS Detours для подключения, а затем вызвать функцию подобным образом, как этот метод работает за кулисами, если вы знаете.)
Итак, чтобы внести ясность, я просто спрашиваю о различных методах выполнения этой задачи, но перечислил несколько, которые мне интересны после прочтения о них, и т.д.
Комментарии:
1. Это не работает или не компилируется? Как правило, фактический адрес функции изменится при перекомпиляции или даже при повторном запуске той же программы.
2. @Neil, это не волшебство, это реальный адрес реальной функции. @aramadia, это, как я уже сказал, проблема с кастингом.
3. @TheMonster Я хочу сказать, откуда вы знаете, что это адрес функции?
4. Потому что я делаю? Не уверен, почему это важно, вы должны просто поверить мне на слово. Но, если вам действительно нужно знать. Я знаю, что это адрес, потому что я взламываю игру, эта функция является частью другой библиотеки DLL, взламывающей ту же игру, я знаю человека, который написал упомянутую другую библиотеку DLL, они сказали мне смещение, где я мог его найти, я отладил .exe, проверил и, конечно же, там это было.
5. @TheMonster Почему я должен верить вам на слово? И DLL можно довольно легко загрузить по другому адресу, в зависимости от множества вещей.
Ответ №1:
Вы всегда можете привести:
typedef bool (*funcptr)(uint, uint, uint, uint, char*);
funcptr draw = (funcptr)0x10057970;
или в C :
funcptr draw = reinterpret_cast<funcptr>(0x10057970);
Однако это совершенно неопределенное поведение.
Также, в общем случае, ничто не мешает компилятору переместить целевую функцию или даже полностью исключить ее, если он не видит, что она вызывается явно.
Комментарии:
1. Ну, адрес существует в .exe, который я взламываю, я должен был упомянуть об этом. (На самом деле это часть другой библиотеки DLL, она должна быть добавлена в таблицу экспорта в какой-то момент в будущем, но пока я должен получить к ней доступ следующим образом. Или написать свой собственный, а GL текст — это небольшая боль, чтобы сделать самому.) Спасибо, кстати, я попробую это. 🙂
2. Вы непреднамеренно приняли нетрадиционный синтаксис Theonster, используя
(funcptr*)
вместо(*funcptr)
. Я надеюсь, что используемый вами компилятор не настолько нетрадиционен, чтобы принять это!3. Я видел asterisk (звездочка недействительности) и т.д. Но не то, что вы предлагаете, также, как я упоминал, я где-то читал об этом методе, но мне было любопытно, как заставить его работать с адресом. (У меня есть свои причины, и это должно работать нормально, эта функция никуда не денется, поверьте мне, она существует уже несколько дней.)
4. Я действительно не понимаю, почему за это проголосовали, поскольку это на самом деле не решает вопрос и, по общему признанию, вызывает UB .
5. @Neil: Все ваши негативные комментарии просто вдохновили меня тоже проголосовать за это. Что тебя здесь гложет?
Ответ №2:
Этот код компилируется (см. http://ideone.com/celq1 ):
typedef unsigned int uint ;
int main()
{
bool (*draw)(uint, uint, uint, uint, const char*);
draw = reinterpret_cast<bool (*)(uint, uint, uint, uint, const char*)>(0x10057970);
draw(20, 20, 14, 255, "Text");
}
Но, конечно, она не запускается 🙂
PS Я изменил char*
на const char*
, чтобы избавиться от предупреждения компилятора. Похоже, const char*
это то, что вы хотите здесь, но это не существенно для идеи.
Отредактировано, чтобы добавить: На самом деле, даже это компилируется, если вы хотите произвести впечатление на своих друзей:
typedef unsigned int uint ;
int main()
{
reinterpret_cast<bool (*)(uint, uint, uint, uint, const char*)>(0x10057970)
(20, 20, 14, 255, "Text");
}
Комментарии:
1. Спасибо, это было то, что я искал. 🙂 -Компилируется и работает, как ожидалось.