goto * (void *) ((uint32_t) buffer | 1);
странно для тех, кто использует ненужную встроенную сборку, мог бы использовать некоторые здесь.
Когда я компилирую это, я получаю:
38: 2201 movs r2, #1
3a: 4313 orrs r3, r2
3c: 469f mov pc, r3
3e: 46c0 nop
и это должно сразу произойти,
Из документации на руку:
ADD (регистр) и MOV (регистр) ветвь без взаимодействия.
Что вы можете сделать, это использовать какой-нибудь настоящий асм
.thumb
.thumb_func
.globl HOP
HOP:
orr r0,#1
bx r0
void HOP ( uint32_t *);
void function()
{
asm volatile(
"nop\n"
"nop\n"
);
}
int main()
{
uint32_t buffer[5];
buffer[0] = 0xaf00b480;
buffer[1] = 0x22684b02;
buffer[2] = 0xf7ff809a;
buffer[3] = 0xe7f9fff1;
buffer[4] = 0x40004800;
// memcpy(0x20004000,&buffer,5*sizeof(uint32));
// goto *(void *)((uint32_t) buffer | 1);
HOP(buffer);
return 0;
}
38: 0018 movs r0, r3
3a: f7ff fffe bl 0 <HOP>
Теперь, если вам не нужна ссылка на ветвь, а вместо этого ветвь, и поскольку вы свободны и свободны с встроенной сборкой, это больше похоже на ваш стиль и не должно иметь проблемы с перемещением, которую генерировал по крайней мере мой компилятор. Кстати, нам нужно посмотреть, что сгенерировал ваш компилятор, чтобы понять, почему вы не сразу потерпели крах.
void function()
{
asm volatile(
"nop\n"
"nop\n"
);
}
int main()
{
uint32_t buffer[5];
buffer[0] = 0xaf00b480;
buffer[1] = 0x22684b02;
buffer[2] = 0xf7ff809a;
buffer[3] = 0xe7f9fff1;
buffer[4] = 0x40004800;
asm (
"add r3,r7,#4\n"
"mov pc,r3\n"
);
return 0;
}
36: 1d3b adds r3, r7, #4
38: 469f mov pc, r3
bx можно использовать, чтобы чувствовать себя лучше
int main()
{
uint32_t buffer[5];
buffer[0] = 0xaf00b480;
buffer[1] = 0x22684b02;
buffer[2] = 0xf7ff809a;
buffer[3] = 0xe7f9fff1;
buffer[4] = 0x40004800;
asm (
"add r3,r7,#5\n"
"bx r3\n"
);
return 0;
}
36: 1d7b adds r3, r7, #5
38: 4718 bx r3
Вы не можете обрабатывать регистр данных Uart таким образом, как только fifo не заполняет больше символов.
вы не можете скопировать этот код и запустить его таким же образом.
8000362: f7ff fff1 bl 8000348 <function>
подходит для встроенной вспышки, пока 8000348 остается там, где есть эта функция, но bl относится к ПК, так что если вы захотите скопировать это в sram (я знал ответ на свой вопрос, позволю вам понять насколько я знаю, это микроконтроллер, так что вы хотели спросить о armv7-m, а не armv7).
20004000: b480 push {r7}
20004002: af00 add r7, sp, #0
20004004: 4b02 ldr r3, [pc, #8] ; 20004010
20004006: 2268 movs r2, #104 ; 0x68
20004008: 809a strh r2, [r3, #4]
2000400A: f7ff fff1 bl 20003FF0
2000400E: e7f9 b.n 20004004
20004010: 40004800
И я полагаю, вы не скопировали функцию () в 0x20003FF0? Какие данные у вас есть по этому адресу при запуске этой программы? Как это выглядит в разобранном виде?
Таким образом, вы "получаете это" по большей части на языке ассемблера, но пропустили несколько вещей.
Теперь вы можете просто написать код, который вы хотели:
.thumb
top:
ldr r3,=0x40004800
mov r2,#68
str r2,[r3,#4]
ldr r0,=function
blx r0
b top
нет необходимости связывать
00000000 <top>:
0: 4b02 ldr r3, [pc, #8] ; (c <top+0xc>)
2: 2244 movs r2, #68 ; 0x44
4: 605a str r2, [r3, #4]
6: 4802 ldr r0, [pc, #8] ; (10 <top+0x10>)
8: 4780 blx r0
a: e7f9 b.n 0 <top>
c: 40004800 andmi r4, r0, r0, lsl #16
10: 00000000 andeq r0, r0, r0
и используя ваш стиль
void function()
{
asm volatile(
"nop\n"
"nop\n"
);
}
int main()
{
uint32_t buffer[10];
buffer[0]=0x22444b02;
buffer[1]=0x4802605a;
buffer[2]=0xe7f94780;
buffer[3]=0x40004800;
buffer[4]=((uint32_t)function)|1;
asm (
"add r3,r7,#5\n"
"bx r3\n"
);
return 0;
}
дает, с моим компилятором:
08000000 <function>:
8000000: b580 push {r7, lr}
8000002: af00 add r7, sp, #0
...
8000016: af00 add r7, sp, #0
8000018: 003b movs r3, r7
800001a: 4a0c ldr r2, [pc, #48] ; (800004c <main+0x3a>)
800001c: 601a str r2, [r3, #0]
...
800003a: 1d7b adds r3, r7, #5
800003c: 4718 bx r3
...
800004c: 22444b02
8000050: 4802605a
8000054: e7f94780
8000058: 40004800
800005c: 08000001
все еще немного хакерский, как ваш код, но теперь вы можете переместить этот код, начиная с 4-байтового выровненного адреса, и у него не будет проблемы с невозможностью вызова
функция функция.
Да, я обманул ссылку для этого примера, у меня нет начальной загрузки. И человек, который действительно беспокоит меня, по умолчанию использует фрейм стека, что за пустая трата времени. Интересно, смогу ли я построить свой набор инструментов без этого? В противном случае это хакерское решение работает лучше:
08000000 <function>:
8000000: 46c0 nop ; (mov r8, r8)
8000002: 46c0 nop ; (mov r8, r8)
8000004: 46c0 nop ; (mov r8, r8)
8000006: 4770 bx lr
08000008 <main>:
8000008: b08a sub sp, #40 ; 0x28
800000a: 466b mov r3, sp
800000c: 4a0a ldr r2, [pc, #40] ; (8000038 <main+0x30>)
800000e: 601a str r2, [r3, #0]
8000010: 466b mov r3, sp
8000012: 4a0a ldr r2, [pc, #40] ; (800003c <main+0x34>)
8000014: 605a str r2, [r3, #4]
тогда можно использовать
void function()
{
asm volatile(
"nop\n"
"nop\n"
);
}
int main()
{
uint32_t buffer[10];
buffer[0]=0x22444b02;
buffer[1]=0x4802605a;
buffer[2]=0xe7f94780;
buffer[3]=0x40004800;
buffer[4]=((uint32_t)function);
asm (
"mov r3,sp\n"
"orr r3,r3,#1\n"
/* "add r3,#1\n" */
"bx r3\n"
);
return 0;
}
Да, да, вам не нужно указывать 1, чтобы функционировать цепочка инструментов, должна была уже позаботиться об этом.
08000008 <main>:
8000008: b08a sub sp, #40 ; 0x28
800000a: 4b09 ldr r3, [pc, #36] ; (8000030 <main+0x28>)
800000c: 9300 str r3, [sp, #0]
800000e: 4b09 ldr r3, [pc, #36] ; (8000034 <main+0x2c>)
8000010: 9301 str r3, [sp, #4]
8000012: 4b09 ldr r3, [pc, #36] ; (8000038 <main+0x30>)
8000014: 9302 str r3, [sp, #8]
8000016: 4b09 ldr r3, [pc, #36] ; (800003c <main+0x34>)
8000018: 9303 str r3, [sp, #12]
800001a: 4b09 ldr r3, [pc, #36] ; (8000040 <main+0x38>)
800001c: 9304 str r3, [sp, #16]
800001e: 466b mov r3, sp
8000020: f043 0301 orr.w r3, r3, #1
8000024: 4718 bx r3
8000026: 2300 movs r3, #0
8000028: 4618 mov r0, r3
800002a: b00a add sp, #40 ; 0x28
800002c: 4770 bx lr
800002e: bf00 nop
8000030: 22444b02 subcs r4, r4, #2048 ; 0x800
8000034: 4802605a stmdami r2, {r1, r3, r4, r6, sp, lr}
8000038: e7f94780 ldrb r4, [r9, r0, lsl #15]!
800003c: 40004800 andmi r4, r0, r0, lsl #16
8000040: 08000001 stmdaeq r0, {r0}
Теперь есть встроенная магия asm, которую вы можете сделать, чтобы загрузить адрес буфера в r3, и вам не нужно полагаться на разборку кода, чтобы понять это. Обратите внимание, потому что вы, кажется, используете armv7-m, несмотря на то, что называете его armv7. Вы можете использовать команду thumb2 orr r3, r3, # 1, которая мысленно верна, вы хотите, чтобы бит там не добавлялся. Но если это armv6-m, как cortex-m0, или вы хотите переносимости, просто сделайте сложение таким же уродливым, как add r3, # 1, потому что это не инструкция thumb2 и она переносима.
Так что, если у вас есть несколько персонажей, я подозреваю, что ваш goto работал каким-то образом, опять похоже, что вы используете qemu, возможно? А может, вот как? Но не пытаясь запустить копию кода в sram, вы вернулись назад, чтобы найти функцию (), но нашли там данные, и это либо привело вас к сбоям, либо, поскольку это произошло непосредственно перед скопированным кодом, оно несколько раз проходило через скопированный код и все, что было там, в конце концов сошло с рельсов. Или, может быть, из-за того, что вы не использовали права uart, вы переполнили буфер, что по крайней мере на одном из этих брендов может привести к прекращению работы uart, пока вы не сбросите флаг переполнения буфера. Предполагая, что вы полагаетесь на вывод UART, чтобы увидеть успех или неудачу. (вы могли увидеть этот сбой при запуске этой программы без вызова функции, из-за чего я считаю, что это симуляция, а не реальное оборудование, или реальное оборудование, вы просто видите часть значений, которые вы вставляете в UART).
Попробуйте вместо этого
void payload()
{
uint32_t ra;
for(ra=0x30;;ra++)
{
ra&=0x37;
USART3->DR = ra;
}
}
в качестве отправной точки, чтобы увидеть, о чем я говорю, если вы видите 0123456701234567 навсегда, тогда я подозреваю, что вы используете симулятор, а не аппаратное обеспечение ....
EDIT:
У orr 1 была проблема с goto, и вы можете просто сделать это:
void function()
{
asm volatile(
"nop\n"
"nop\n"
);
}
int main()
{
uint32_t buffer[10];
buffer[0]=0x22444b02;
buffer[1]=0x4802605a;
buffer[2]=0xe7f94780;
buffer[3]=0x40004800;
buffer[4]=((uint32_t)function);
goto *(void *)((uint32_t) buffer);
return 0;
}
EDIT2
Программа уже находится в SRAM, вы просто копируете ее из SRAM в SRAM ... Если копия является «эксплойтом», тогда все в порядке, но на микроконтроллере вы не копируете это поверх некоторого другого кода, большинство из время, когда весь код заканчивается флэш-памятью, поэтому одно местоположение sram так же хорошо, как и другое.
В любом случае, этот термин здесь не проблема.
В вашем комментарии ниже
В основном я разветвляюсь по адресу 0x20004001.
Нет, это та же ошибка, если вы хотите изменить адрес с одним, вам нужно использовать правильную инструкцию.
void function()
{
asm volatile(
"nop\n"
"nop\n"
);
}
int main()
{
uint32_t buffer[10];
buffer[0]=0x22444b02;
buffer[1]=0x4802605a;
buffer[2]=0xe7f94780;
buffer[3]=0x40004800;
buffer[4]=((uint32_t)function);
//memcpy...
//goto *(void *)((uint32_t) buffer);
goto *(void *)(0x20004000);
return 0;
}
с компилятором на моем компьютере выдает
36: 4b06 ldr r3, [pc, #24] ; (50 <main+0x3e>)
38: 469f mov pc, r3
3a: 46c0 nop ; (mov r8, r8)
3c: 22444b02 subcs r4, r4, #2048 ; 0x800
40: 4802605a stmdami r2, {r1, r3, r4, r6, sp, lr}
44: e7f94780 ldrb r4, [r9, r0, lsl #15]!
48: 40004800 andmi r4, r0, r0, lsl #16
4c: 00000000 andeq r0, r0, r0
50: 20004000 andcs r4, r0, r0
При подключении все равно будет работать.
Но если вы сделаете это
goto *(void *)(0x20004001);
36: 4b06 ldr r3, [pc, #24] ; (50 <main+0x3e>)
38: 469f mov pc, r3
3a: 46c0 nop ; (mov r8, r8)
3c: 22444b02 subcs r4, r4, #2048 ; 0x800
40: 4802605a stmdami r2, {r1, r3, r4, r6, sp, lr}
44: e7f94780 ldrb r4, [r9, r0, lsl #15]!
48: 40004800 andmi r4, r0, r0, lsl #16
4c: 00000000 andeq r0, r0, r0
50: 20004001 andcs r4, r0, r1
Та же ошибка, что и в верхней части этого ответа:
ADD (регистр) и MOV (регистр) ветвь без взаимодействия.
Поиск этой строки и / или этого термина в документации по оружию.