简体   繁体   English

在ARM Cortex-M系列上确定函数的返回地址

[英]Determining return address of function on ARM Cortex-M series

I want to determine the return address of a function in Keil.我想在Keil中确定一个函数的返回地址。 I opened diassembly section at debugging mode in Keil uvision.我在 Keil uvision 的调试模式下打开了反汇编部分。 What is shown is some assembly code like this:显示的是一些像这样的汇编代码:

在此处输入图片说明

My intention is to inject a simple binary code to microcontroller via using buffer overflow at microcontroller.我的目的是通过在微控制器上使用缓冲区溢出向微控制器注入一个简单的二进制代码。 see: Buffer overflow I want to determine the return address of "test" function .请参阅:缓冲区溢出我想确定“测试”函数的返回地址。 Is it a must to know how to read assembly code or are there any trick to find the return address?是否必须知道如何阅读汇编代码或有什么技巧可以找到返回地址?

I am newbie to assembly.我是组装新手。

R14 or in other name LR hold the return address. R14或其他名称LR保存返回地址。 On the left you can see it in the picture.在左侧,您可以在图片中看到它。 It is 0x08000287 .它是0x08000287

When a function is called, R14 will be overwritten with the address following the call ("BL" or "BLX") instruction.调用函数时,R14 将被调用(“BL”或“BLX”)指令之后的地址覆盖。 If that function doesn't call any other functions, R14 will often be left holding the return address for its duration.如果该函数不调用任何其他函数,则 R14通常会在其持续时间内保留返回地址。 Further, if the function tail-calls another function, the tail call may be replaced with a branch ("B" or "BX"), with R14 holding the return address of the original caller.此外,如果函数尾调用另一个函数,尾调用可以用分支(“B”或“BX”)替换,R14 保存原始调用者的返回地址。 If a function makes a non-tail call to another function, it will be necessary to save R14 "somewhere" (typically the stack, but possibly to another previously-used caller-saved register) at some time before that, and retrieve that value from the stack at some later time, but if optimizations are enabled the location where R14 is saved will generally be unpredictable.如果一个函数对另一个函数进行非尾调用,则必须在此之前的某个时间将 R14 保存在“某处”(通常是堆栈,但也可能保存到另一个先前使用的调用者保存的寄存器中),并检索该值稍后从堆栈中删除,但如果启用了优化,则保存 R14 的位置通常是不可预测的。

Some compilers may have a mode that would stack things consistently enough to be usable, but code will be very compiler-dependent.一些编译器可能有一种模式,可以一致地堆叠东西以供使用,但代码将非常依赖于编译器。 The technique most likely to be successful may be to do something like:最有可能成功的技术可能是执行以下操作:

extern int getStackAddress(uint8_t **addr);  // Always returns zero
void myFunction(...whavever...)
{
  uint8_t *returnAddress;
  if (getStackAddress(&returnAddress)) return; // Put this first.
}

where the getStackAddress would be a machine-code function that stores R14 to the address in R0, loads R0 with zero, and then branches to R14.其中getStackAddress将是一个机器代码函数,它将 R14 存储到 R0 中的地址,用零加载 R0,然后分支到 R14。 There are relatively few code sequences that would be likely to follow that, and if a code examines instructions at the address stored in returnAddress and recognizes one of these code sequences, it would know that the return address for myFunction is stored in a spot appropriate for the sequence in question.可能遵循的代码序列相对较少,如果代码检查存储在returnAddress中的地址处的指令并识别这些代码序列之一,它将知道myFunction的返回地址存储在适合于有问题的顺序。 For example, if it sees:例如,如果它看到:

    test r0,r0
    be ...
    pop {r0,pc}

It would know that the caller's address is second on the stack.它会知道调用者的地址在堆栈中排在第二位。 Likewise if it sees:同样,如果它看到:

    cmp r0,#0
    bne somewhere:
somewhere: ; Compute address based on lower byte of bne
    pop {r0,r1,r2,r4,r5,pc}

then it would know that the caller's address is sixth.那么它就会知道调用者的地址是第六个。

There are a few instructons compilers could use to test a register against zero, and some compilers might use be while others use bne , but for the code above compilers would be likely to use the above pattern, and so counting how many bits are set in the pop instruction would reveal the whereabouts of the return address on the stack.编译器可以使用一些指令来针对零测试寄存器,一些编译器可能使用be而其他编译器使用bne ,但是对于上面的代码,编译器可能会使用上面的模式,因此计算设置了多少位pop指令将揭示堆栈中返回地址的下落。 One wouldn't know until runtime whether this test would actually work, but in cases where it claims to identify the return address it should actually be correct.直到运行时人们才会知道这个测试是否真的有效,但在它声称识别返回地址的情况下,它实际上应该是正确的。

You can find all the answers in the Cortex-M documentation您可以在 Cortex-M 文档中找到所有答案

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337h/Chdedegj.html http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337h/Chdedegj.html

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM