Здравствуйте, пффф, Вы писали:
П>Есть ли возможность более или менее легально, без грязных хаков, узнать, откуда вызвали функцию?
Насколько грязным не должен быть хак? https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html
П>Предполагаем, что у нас фон-неймановская архитектура, стек растёт вниз — т.е. обычная винда или линукс на не экзотическом железе.
Куда растёт стек — пофиг.
П>Я краем уха слышал о способах передачи параметров, как стек организован, и тп, и вот что родилось:
П>1) При вызове функций компилятор складывает параметры на стек, затем вызывает функцию, при этом на стек помещается адрес возврата, т.е он у нас ниже последнего параметра
Почти. Только в соглашениях посовременнее стараются максимум передать в регистрах и только если этого недостаточно — класть на стек.
П>2) Все параметры кладутся на стек, расширяясь до int'а, как минимум. Тут не очень понятно, а на x64 как оно происходит, до какого размера расширяется параметр, до 4х байт или до 8им?
И снова тут.
П>3) Если у нас единственный аргумент, то отнимаем 4/8 байт от его адреса, и получаем адрес, где лежит адрес возврата, так?
Не совсем, см. 16-байтное выравнивание стека при вызове.
П>4) Если у нас несколько параметров, и мы в общем случае не знаем порядок их укладки на стек (stdcall/cdecl), то мы берём адреса крайних параметров и выбираем из них меньший, так?
Что такое "меньший"?
П>Тут не понятно, а как быть, если у функции нет параметров? Или функция — какая-нибудь fastcall, которая передаёт первый(ые) параметр(ы) в регистрах? Или, вроде, на x64 никакого fastcall для этого специально указывать не надо, там вроде стандартное соглашение о передаче параметров через регистр. Как быть?
Это решается или через регистр BP/EBP/RBP, или через отладочную информацию.
П>С передачей структур/классов по значению тоже не очень понятно, сколько в итоге они там места на стеке занимать будут.
Здравствуйте, пффф, Вы писали:
П>Есть ли возможность более или менее легально, без грязных хаков, узнать, откуда вызвали функцию?
Я о такой возможности не знаю (легально и без хаков). Но сама потребость в этом подозрительна. Я в такой ситуации задался бы вопросом: а все ли здесь благополучно с дизайном? По моим представлениям любая зависимость (знание) вызываемой сущности от вызывающего кода не совсем естественна. Разве что, для отладочных целей?
Есть ли возможность более или менее легально, без грязных хаков, узнать, откуда вызвали функцию?
Предполагаем, что у нас фон-неймановская архитектура, стек растёт вниз — т.е. обычная винда или линукс на не экзотическом железе.
Я краем уха слышал о способах передачи параметров, как стек организован, и тп, и вот что родилось:
1) При вызове функций компилятор складывает параметры на стек, затем вызывает функцию, при этом на стек помещается адрес возврата, т.е он у нас ниже последнего параметра
2) Все параметры кладутся на стек, расширяясь до int'а, как минимум. Тут не очень понятно, а на x64 как оно происходит, до какого размера расширяется параметр, до 4х байт или до 8им?
3) Если у нас единственный аргумент, то отнимаем 4/8 байт от его адреса, и получаем адрес, где лежит адрес возврата, так?
4) Если у нас несколько параметров, и мы в общем случае не знаем порядок их укладки на стек (stdcall/cdecl), то мы берём адреса крайних параметров и выбираем из них меньший, так?
Тут не понятно, а как быть, если у функции нет параметров? Или функция — какая-нибудь fastcall, которая передаёт первый(ые) параметр(ы) в регистрах? Или, вроде, на x64 никакого fastcall для этого специально указывать не надо, там вроде стандартное соглашение о передаче параметров через регистр. Как быть?
С передачей структур/классов по значению тоже не очень понятно, сколько в итоге они там места на стеке занимать будут.
Здравствуйте, netch80, Вы писали:
П>>Есть ли возможность более или менее легально, без грязных хаков, узнать, откуда вызвали функцию?
N>Насколько грязным не должен быть хак? N>https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html
Я для MSVC?
П>>Предполагаем, что у нас фон-неймановская архитектура, стек растёт вниз — т.е. обычная винда или линукс на не экзотическом железе.
N>Куда растёт стек — пофиг.
Почему?
П>>Я краем уха слышал о способах передачи параметров, как стек организован, и тп, и вот что родилось:
П>>1) При вызове функций компилятор складывает параметры на стек, затем вызывает функцию, при этом на стек помещается адрес возврата, т.е он у нас ниже последнего параметра
N>Почти. Только в соглашениях посовременнее стараются максимум передать в регистрах и только если этого недостаточно — класть на стек.
Ну вот это как раз вроде про x64, не?
Интересуют вызовы функций из DLL, не произвольный плюсовый код
П>>4) Если у нас несколько параметров, и мы в общем случае не знаем порядок их укладки на стек (stdcall/cdecl), то мы берём адреса крайних параметров и выбираем из них меньший, так?
N>Что такое "меньший"?
Ниже на стеке, ближе к началу адресного пространства. Чего непонятного-то?
Здравствуйте, rg45, Вы писали:
П>>Есть ли возможность более или менее легально, без грязных хаков, узнать, откуда вызвали функцию?
R>Я о такой возможности не знаю (легально и без хаков).
Ну хорошо, а как нелегально и с хаками?
R>Но сама потребость в этом подозрительна. Я в такой ситуации задался бы вопросом: а все ли здесь благополучно с дизайном?
Причем тут дизайн? Я перехват химичу, и хочу знать, откуда он вызван
Здравствуйте, пффф, Вы писали:
R>>Я о такой возможности не знаю (легально и без хаков).
П>Ну хорошо, а как нелегально и с хаками?
Ну для этого нужно закладываться на какой-то конкретный прокол вызова (cdecl, stdcall, fastcall, etc.), вдобавок нужно быть уверенным, что функция не заинлайнилась, потом, через анализ содержимого регистров (ESP, EBP, etc), с учетом размера стека, занимаемого параметрами и локальными переменными, можно будет вытащить адрес возврата. Я с этим баловался давненько, сейчас сходу всех деталей и не припомню уже. Самый простой путь — написать функцию-прототип и посмотреть асемблерный код, как она устроена.
Здравствуйте, rg45, Вы писали:
R>>>Я о такой возможности не знаю (легально и без хаков).
П>>Ну хорошо, а как нелегально и с хаками?
R>Ну для этого нужно закладываться на какой-то конкретный прокол вызова (cdecl, stdcall, fastcall, etc.), вдобавок нужно быть уверенным, что функция не заинлайнилась,
Функции в DLL-ках, либо stdcall, изредка может быть cdecl, другого, по идее, не должно быть. С инлайном тоже всё понятно — его не будет
R>потом, через анализ содержимого регистров (ESP, EBP, etc) можно будет вытащить адрес возврата. Я с этим баловался давненько, сейчас сходу всех деталей и не припомню уже.
Ну вот как-то безе регистров уж совсем, хотелось бы. И x86/x64 чтобы, желательно поуниверсальнее
Здравствуйте, пффф, Вы писали:
П>Функции в DLL-ках, либо stdcall, изредка может быть cdecl, другого, по идее, не должно быть. С инлайном тоже всё понятно — его не будет
П>Ну вот как-то безе регистров уж совсем, хотелось бы. И x86/x64 чтобы, желательно поуниверсальнее
Можешь добавить в длл-ку функцию-прототип, пройти по ней с отладчиком и заглянуть в ассемлер, чтобы понять, как она устроена. Потом можно будет ассемблерными вставками вытащить адрес возврата.
Здравствуйте, пффф, Вы писали:
R>>Но сама потребость в этом подозрительна. Я в такой ситуации задался бы вопросом: а все ли здесь благополучно с дизайном?
П>Причем тут дизайн? Я перехват химичу, и хочу знать, откуда он вызван
Перезахват чего?
Если эта функция твоя, и вызывать её тоже будешь ты, то сделай ей первый параметр — имя вызывающей функции.
И чтоб два раза не вставать — ну получишь ты адрес вызова. Это 64-разрядное число. Что ты с ним дальше делать будешь?
Здравствуйте, YuriV, Вы писали:
П>>Причем тут дизайн? Я перехват химичу, и хочу знать, откуда он вызван
YV>Если перехват ВинАПИ, то есть Microsoft Detours.
Спасибо, но вопрос был не о том. Перехват я сделал, да, при помощи Detours
Здравствуйте, пффф, Вы писали:
A>>И чтоб два раза не вставать — ну получишь ты адрес вызова. Это 64-разрядное число. Что ты с ним дальше делать будешь? П>Узнаю, в каком модуле этот адрес, и начну дизасмить модуль с того места
Что если я для перехода куда-то подменил адрес возврата в стеке и сделал ret?
Ты не узнаешь откуда "было вызвано".
Здравствуйте, пффф, Вы писали:
П>Есть ли возможность более или менее легально, без грязных хаков, узнать, откуда вызвали функцию?
Нет. Если надо то передавайте ей явно информацию откуда и в каком контексте была вызвана функция.