Я использую frida-trace, чтобы прикрепить обработчик к определенной функции в моем консольном приложении на C++. вот код целевого приложения на C++:
string Add(int a, int b) {
ostringstream oss;
oss << a << " + " << b << " = " << (a + b);
return oss.str();
}
Это функция «добавить» из базового приложения-калькулятора, которая принимает два целых числа и возвращает сумму в строковом формате (например, 1 + 1 = 2).
Я могу найти функцию и создать «обработчик» с Фридой, используя эту команду;
frida-trace -s "Add" SimpleCalculator.exe
Обратите внимание, что я буду вызывать метод Add с параметрами 1 и 1 на протяжении всех тестов. Например, я могу определить, когда вызывается функция;
onEnter(log, args, state) {
log('Add method was called...')
},
Теперь я хочу прочитать, какие аргументы были переданы функции. Я попытался использовать массив «args» для чтения аргументов, но этот массив, похоже, содержит адреса памяти, а не фактические значения. Это понятно, но я не мог понять, как получить реальные значения по этим адресам. Если я зарегистрирую адреса;
onEnter(log, args, state) {
log(args[0]);
log(args[1]);
},
Выход:
0xf65aeff6e0
0x1
Использование значений из массива args для создания NativePointer, похоже, не влияет на значение (чего я и ожидал);
onEnter(log, args, state) {
var a = new NativePointer(args[0]);
log(a);
},
Это просто печатает тот же адрес для 1-го аргумента, что и простая команда log(args[0]) (выходной результат: 0xf65aeff6e0). Затем я попробовал readInt(), но это печатает 539697201, что не является правильным значением аргумента (он должен печатать 1). Я также пробовал toInt32() и комбинировать их разными способами, но безуспешно. Я тоже пробовал Memory.readInt(a), но оно дает то же случайное значение (539697201). log(args[0].toInt32());, с другой стороны, дает другое случайное значение 1756755344. Может ли кто-нибудь помочь мне понять, как прочитать аргументы, переданные функции?
Вот пример приложения, включая исполняемые файлы (/x64/Release): https://github.com/Emrebener/FridaUseCase1





Декомпилируя исполняемый файл из вашего репозитория, я получаю следующее определение функции для Add:
Add(std::string *result, long double a, long double b)
Похоже, компилятор не использует возвращаемое значение, вместо этого первый аргумент используется как параметр out. Таким образом, случайные значения, которые вы получаете в качестве первого аргумента, представляют собой выделенную память для возвращаемой строки.
Если вы хотите прочитать два параметра, вам нужно использовать arg[1] и arg[2]:
onEnter(log, args, state) {
log(args[1].toInt32());
log(args[2].toInt32());
},
Усвоенный урок: при использовании Frida для программы, у которой есть исходный код, всегда проверяйте функцию с помощью декомпилятора, такого как Ghidra/IDA, чтобы убедиться, что компилятор не изменил код неожиданным образом.
Кстати, массив args начинается с нуля, поэтому первый аргумент равен args[0].
@EmreBener Конечно, первый аргумент — args[0], но, как я указал в своем ответе в вашем случае, первый аргумент, который вы определили в исходном коде, можно найти в args[1], поскольку компилятор добавил дополнительный параметр.
Спасибо! Я изменил тип возвращаемого значения функции на
intи просто вернул результат таким образом. Затем я смог использоватьtoInt32()для получения значений параметров.