Код здесь:
#include <stdio.h>
#define NUM 0x11a
int data = NUM;
int main(int argc, char * argv[])
{
struct{
unsigned long memoryAddress;
char array[50];
} locals;
locals.memoryAddress= 2;
scanf("%lx", &locals.memoryAddress);
scanf("%49s", locals.array);
printf(locals.array);
data += 5;
printf("\n%d\n", data);
if(data != NUM + 0x5){
printf("Print me!\n");
}
return 0;
}
Я должен получить "Print me!"
. Это атака строки формата, и я использую %n
и gdb.
Итак, как я могу получить адрес памяти данных, чтобы перезаписать его?
NUM
data
и добавления 5 кdata
вы ожидаете, чтоdata
будет отличаться отNUM+5
. - person Roberto Caboni   schedule 29.04.2020data
. Либо вы это уже знаете, либо нет. Если ваша программа была скомпилирована с помощью-fno-pie -no-pie
, вы можете проверить ее с помощьюobjdump
илиgdb
(если вы компилируете с символами) перед запуском программы. - person Marco Bonelli   schedule 29.04.2020%n
позволяет записывать количество символов, записанных на данный момент, в переменную. Если переменной нет или если вы используете точное смещение (например,%5$n
), вы можете выбрать произвольный адрес для записи из стека (в этом случае OP хочет записать вdata
). Поскольку у вас есть контроль над строкой формата, вы можете упаковать произвольный адрес в саму строку формата, а затем найти соответствующее смещение, чтобы%n
использовал этот адрес и писал то, что вы хотите, где хотите (комбинируя его с%NNNc
, чтобы записатьNNN
символов перед строкой).%n
попал). - person Marco Bonelli   schedule 29.04.2020locals.memoryAddress= 2;
есть какое-то особое назначение. Я спрашиваю, потому что сразу за ним следуетscanf("%lx", &locals.memoryAddress);
, которое перезапишет предыдущее значение2
, хранящееся вlocals.memoryAddress
. - person ryyker   schedule 29.04.2020fprintf
. Ни один аргумент не преобразуется, но используется один. - person RobertS supports Monica Cellio   schedule 29.04.2020that is not
определенная стандартом. :) - person ryyker   schedule 29.04.2020%n
без аргумента при вызовеprintf()
? - person RobertS supports Monica Cellio   schedule 29.04.2020printf()
glibc предполагает, что параметры передаются в стеке, поэтому использование%n
берет адрес из стека. Это безопасное предположение, и поведение на 100% детерминировано, поскольку вы можете посмотреть на скомпилированный код библиотеки. Функция вызывается правильно, и с точки зрения компилятора неопределенного поведения нет. Неопределенное поведение может произойти во время выполнения, но, как я уже сказал, вряд ли оно неопределенное. - person Marco Bonelli   schedule 29.04.2020%n
в опубликованном коде? - person Ôrel   schedule 29.04.2020scanf("%49s", locals.array);
- person Marco Bonelli   schedule 29.04.2020