Как правильно перехватить аргумент элипсис?
От: пффф  
Дата: 08.06.23 09:37
Оценка:
Привет!

В общем, не помню, как оно правильно называется, ... как в printf.

Есть допустим функция int some_cool_printf(const char* format, ...).
Сорцов нет, версии с va_args нет, я хочу сделать прокладку типа:

int some_cool_printf(const char* format, ...) // my version of some_cool_printf
{
    // do something with args

    auto orgSomeCoolPrint = getOrgSomeCoolPrint();
    return orgSomeCoolPrint(...);
}
// ...




Просто так это не сделать, насколько помню. Тут, по идее, выручил бы не вызов, а переход по адресу some_cool_printf. Ну, и with_log_some_cool_printf должна быть declspec(naked) или как-то так.

Интересует Win32/64, и MSVC, но и про более общие решения было бы интересно узнать.

Вроде бы declspec(naked) нет в x64, не?
Асма вроде точно в x64 нет, да?


А что если тупо goto вкорячить, прокатит?
    goto some_cool_printf;


Или через какие-то setjump'ы извращаться?
Или вручную нагенерить инструкции перехода? Как это правильно сделать? Может, есть что-то подобное готовое?
Re: Как правильно перехватить аргумент элипсис?
От: pva  
Дата: 08.06.23 20:23
Оценка: +1
Здравствуйте, пффф, Вы писали:

П>В общем, не помню, как оно правильно называется, ... как в printf.


П>Есть допустим функция int some_cool_printf(const char* format, ...).

П>Сорцов нет, версии с va_args нет, я хочу сделать прокладку типа:
Не очень понятно чего там у тебя нет, ты бы все-таки почитал про va_args.
newbie
Re: Как правильно перехватить аргумент элипсис?
От: CreatorCray  
Дата: 08.06.23 20:26
Оценка:
Здравствуйте, пффф, Вы писали:

П>Интересует Win32/64, и MSVC, но и про более общие решения было бы интересно узнать.


Тебе ж уже в С++ ответили и с вариадиками и с __VA_ARGS__
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[2]: Как правильно перехватить аргумент элипсис?
От: пффф  
Дата: 09.06.23 08:58
Оценка:
Здравствуйте, pva, Вы писали:

П>>Есть допустим функция int some_cool_printf(const char* format, ...).

П>>Сорцов нет, версии с va_args нет, я хочу сделать прокладку типа:
pva>Не очень понятно чего там у тебя нет, ты бы все-таки почитал про va_args.

Я читал про va_args.
Как оно мне поможет, если я хочу перехватить функцию с элипсисом, и при этом у оригинальной функции нет версии с va_args
Re[2]: Как правильно перехватить аргумент элипсис?
От: пффф  
Дата: 09.06.23 09:02
Оценка:
Здравствуйте, CreatorCray, Вы писали:

П>>Интересует Win32/64, и MSVC, но и про более общие решения было бы интересно узнать.


CC>Тебе ж уже в С++ ответили и с вариадиками и с __VA_ARGS__


Это сработает, только если я имею сорцы. Мне же ещё хочется сделать свою прокладку между чужим собраным кодом и чужой собранной либой
Re[3]: Как правильно перехватить аргумент элипсис?
От: CreatorCray  
Дата: 09.06.23 09:40
Оценка:
Здравствуйте, пффф, Вы писали:

П>Мне же ещё хочется сделать свою прокладку между чужим собраным кодом и чужой собранной либой

либа тут .lib или же .dll?
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[3]: Как правильно перехватить аргумент элипсис?
От: pva  
Дата: 09.06.23 09:45
Оценка:
Здравствуйте, пффф, Вы писали:

П>Я читал про va_args.

П>Как оно мне поможет, если я хочу перехватить функцию с элипсисом, и при этом у оригинальной функции нет версии с va_args
Тогда прийдется похачить, наподобие
#include <windows.h>
#include <stdio.h>

unsigned char BswapData[] =
{
  0x0F, 0xC9, // bswap ecx
  0x89, 0xC8, // mov   eax, ecx
  0xC3        // ret
};

unsigned long (__fastcall *Bswap)(unsigned long) =
  (unsigned long (__fastcall *)(unsigned long)) &BswapData[0];

int main(void)
{
  DWORD dummy;
  VirtualProtect(BswapData, sizeof(BswapData), PAGE_EXECUTE_READWRITE, &dummy);
  printf("0x%lX\n", Bswap(0x10203040));
  return 0;
}


Сделать свой ручной jmp, порешать вопросы со стеком и будет тебе счастье.
newbie
Re[4]: Как правильно перехватить аргумент элипсис?
От: пффф  
Дата: 09.06.23 21:47
Оценка:
Здравствуйте, CreatorCray, Вы писали:

П>>Мне же ещё хочется сделать свою прокладку между чужим собраным кодом и чужой собранной либой

CC>либа тут .lib или же .dll?

dll. Но и про вариант с lib тоже интересно
Re[4]: Как правильно перехватить аргумент элипсис?
От: пффф  
Дата: 09.06.23 21:57
Оценка:
Здравствуйте, pva, Вы писали:

pva>Тогда прийдется похачить, наподобие


Да, спс, как-то так наверно и буду делать


pva>Сделать свой ручной jmp, порешать вопросы со стеком и будет тебе счастье.


А какие вопросы могут быть со стеком? Локальные переменные?
А если, допустим, в перехватчике some_func я просто вызываю log_some_func и потом сразу jump? В примере там вроде без локальных переменных, шаманить со стеком ничего не нужно вроде?
void some_func(a,b,c)
{
    log_some_func(a,b,c);
    // jump here
}
Re[5]: Как правильно перехватить аргумент элипсис?
От: CreatorCray  
Дата: 09.06.23 23:40
Оценка:
Здравствуйте, пффф, Вы писали:

П> dll. Но и про вариант с lib тоже интересно


Тут придётся в асм лезть. С lib ешё геморнее.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[5]: Как правильно перехватить аргумент элипсис?
От: pva  
Дата: 10.06.23 11:05
Оценка:
Здравствуйте, пффф, Вы писали:

pva>>Тогда прийдется похачить, наподобие

П>Да, спс, как-то так наверно и буду делать

pva>>Сделать свой ручной jmp, порешать вопросы со стеком и будет тебе счастье.

П>А какие вопросы могут быть со стеком? Локальные переменные?
П>А если, допустим, в перехватчике some_func я просто вызываю log_some_func и потом сразу jump? В примере там вроде без локальных переменных, шаманить со стеком ничего не нужно вроде?
Если правильно помню то для элипсисов за стек отвечает вызывающая функия. Но твоя прокси-функция не naked и в прологе может изменять состояние стека (например, сохранение регистров). Перед jmp [originalFn] тебе нужно привести стековый указатель в корректный вид. Как скомпилишь свой код — посмотри дизазсм и дальше уже корректируй как нужно.
newbie
Re[5]: Как правильно перехватить аргумент элипсис?
От: nodir.temir https://github.com/tnodir
Дата: 22.06.23 16:09
Оценка: 6 (1)
Здравствуйте, пффф, Вы писали:

П>Здравствуйте, CreatorCray, Вы писали:


П>>>Мне же ещё хочется сделать свою прокладку между чужим собраным кодом и чужой собранной либой

CC>>либа тут .lib или же .dll?

П>dll. Но и про вариант с lib тоже интересно


Если правильно понял, то похожую прокладку я сделал для перенаправления callback-ов в драйвере:
https://github.com/tnodir/fort/tree/master/src/driver/proxycb
Отредактировано 22.06.2023 16:12 nodir.temir . Предыдущая версия . Еще …
Отредактировано 22.06.2023 16:10 nodir.temir . Предыдущая версия .
Re[4]: Как правильно перехватить аргумент элипсис?
От: mike_rs Россия  
Дата: 29.09.23 10:23
Оценка:
Здравствуйте, pva, Вы писали:

pva> VirtualProtect(BswapData, sizeof(BswapData), PAGE_EXECUTE_READWRITE, &dummy);


такое нельзя делать в современных версиях ос, ошибку вернет
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.