Assembly 在ARMv7的有效负载中调用函数

Assembly 在ARMv7的有效负载中调用函数,assembly,arm,shellcode,cortex-m3,thumb,Assembly,Arm,Shellcode,Cortex M3,Thumb,我想为我的ARMv7平台编写一个简单的负载。首先,我尝试了一个通过UART发送字符的简单循环: void payload() { while(1) { USART3->DR = 0x68; } } 08000358 <payload>: 8000358: b480 push {r7} 800035a: af00 add r7, sp, #0 800035c: 4b01 ldr r3, [pc

我想为我的ARMv7平台编写一个简单的负载。首先,我尝试了一个通过UART发送字符的简单循环:

void payload()
{
  while(1)
  {
    USART3->DR = 0x68;
  }
}

08000358 <payload>:
 8000358:   b480        push    {r7}
 800035a:   af00        add r7, sp, #0
 800035c:   4b01        ldr r3, [pc, #4]    ; (8000364 <payload+0xc>)
 800035e:   2268        movs    r2, #104    ; 0x68
 8000360:   809a        strh    r2, [r3, #4]
 8000362:   e7fb        b.n 800035c <payload+0x4>
 8000364:   40004800    andmi   r4, r0, r0, lsl #16
这非常有效,字符是通过UART发送的。现在,我想在我的有效负载中调用一个函数:

void payload()
{
  while(1)
    {
      USART3->DR = 0x68;
    asm volatile(
      "bl 0x08000348\n"
    );
  }
}

08000358 <payload>:
 8000358:   b480        push    {r7}
 800035a:   af00        add r7, sp, #0
 800035c:   4b02        ldr r3, [pc, #8]    ; (8000368 <payload+0x10>)
 800035e:   2268        movs    r2, #104    ; 0x68
 8000360:   809a        strh    r2, [r3, #4]
 8000362:   f7ff fff1   bl  8000348 <function>
 8000366:   e7f9        b.n 800035c <payload+0x4>
 8000368:   40004800    andmi   r4, r0, r0, lsl #16
这个角色现在只发送了3次,然后我得到了一个崩溃(处理器的错误处理程序)。我检查了函数的内存区域和缓冲区,两者看起来都一样:

0x8000358 <payload>:    0xaf00b480  0x22684b02  0xf7ff809a  0xe7f9fff1
0x8000368 <payload+16>: 0x40004800  0xb082b580  0xf001af00  0x2102f863

0x20004000 <_heap+3144>:    0xaf00b480  0x22684b02  0xf7ff809a  0xe7f9fff1
0x20004010 <_heap+3160>:    0x40004800  0x00000000  0x00000000  0x00000000
0x8000358:0xaf00b480 0x22684b02 0xf7ff809a 0xe7f9fff1
0x8000368:0x40004800 0xb082b580 0xf001af00 0x2102f863
0x20004000:0xaf00b480 0x22684b02 0xf7ff809a 0xe7f9fff1
0x20004010:0x40004800 0x00000000 0x00000000 0x00000000
goto*(void*)((uint32)缓冲区1)

奇怪的是,使用不必要的内联程序集的人可能会在这里使用一些

当我编译这个时,我得到:

  38:   2201        movs    r2, #1
  3a:   4313        orrs    r3, r2
  3c:   469f        mov pc, r3
  3e:   46c0        nop 
这应该马上失败

从arm文档中:

添加(寄存器)和MOV(寄存器)分支,但不互通

你能做的就是使用一些真正的asm

.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>
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
一旦fifo不再填充字符,就不能这样处理uart数据寄存器

您也不能复制此代码并以这种方式运行它

 8000362:   f7ff fff1   bl  8000348 <function>
我想您没有将function()复制到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
使用我的编译器提供:

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
是的,你不需要或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}
作为你了解我所说内容的起点,如果你永远看到0123456701234567,那么我怀疑你使用的是模拟器,而不是硬件

编辑:

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;
}
编辑2

该程序已经在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
36:4b06 ldr r3,[pc,#24];(50 )
38:469f mov pc,r3
3a:46c0 nop;(mov r8,r8)
3c:22444b02分包r4、r4、#2048;0x800
40:4802605a stmdami r2,{r1,r3,r4,r6,sp,lr}
44:e7f94780 ldrb r4,[r9,r0,lsl#15]!
48:40004800和MI r4、r0、r0、lsl#16
4c:00000000安第克r0,r0,r0
50:20004000和CS 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
goto*(void*)(0x2000001);
36:4b06 ldr r3,[pc,#24];(50 )
38:469f mov pc,r3
3a:46c0 nop;(mov r8,r8)
3c:22444b02分包r4、r4、#2048;0x800
40:4802605a stmdami r2,{r1,r3,r4,r6,sp,lr}
44:e7f94780 ldrb r4,[r9,r0,lsl#15]!
48:40004800和MI r4、r0、r0、lsl#16
4c:00000000安第克r0,r0,r0
50:20004001和CS r4、r0、r1
与此答案顶部的错误相同:

添加(寄存器)和MOV(寄存器)分支,但不互通


在arm文档中搜索该行和/或该术语

这是什么编译器这看起来很旧不符合当前的abi,这不是一件坏事…这是一个微控制器armv7-m而不是armv7?冲击uart数据寄存器不是你如何发送字符出uart,除非这是一个qemu模拟。你的有效负载代码看起来没有优化,所以我没有优化我的。优化时,它不使用帧指针。尝试让gcc在没有作为未优化默认值的情况下构建,将看到这是否有效。您的ram是否在0x200004000或以上?是否正在包装?谢谢,不,这不是家庭作业-只想从编写漏洞开始。我还有一些问题。假设我的函数()始终为0x8000348。我的有效负载应该位于SRAM中,有效负载的地址应该是0x20004000。现在,我将其复制到SRAM:ldr r3,=0x40004800 mov r2,#68 str r2,[r3,#4]ldr r0,=0x08000349 blx r0 b 0x20004000(主),我分支到地址0x20004001。它应该可以工作,因为我用blx 0x08000349调用函数,返回后用b 0x20004000跳回代码的开头(ldr r3)。但同样,不确定您为什么会将其称为一个漏洞,仍然感觉像是有人问的另一个问题。您为什么要分支到0x20004001?您使用什么指令来实现这一点,该指令是否支持交互,arms文档对使用该指令进行交互或不进行交互有何说明?
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;
}
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}
void payload()
{
  uint32_t ra; 
  for(ra=0x30;;ra++)
  {
    ra&=0x37;
    USART3->DR = ra;
  }
}
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;
}
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