我想使用Raspberry PI和Raspbian OS为ARMv6指令集架构编写一个简单的缓冲区溢出示例。我首先看一下堆栈框架的布局。很遗憾,我无法找到回邮地址。请考虑以下示例:
void foo
(int b)
{
int c = 3;
}
int main
(int argc, char **argv)
{
int a = 1;
foo(2);
a = 4;
}
我用它编译了它:
gcc exploit_me.c -g -O0 -o exploit_me
使用gdb调试代码可以获得以下信息:
gdb exploit_me
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-linux-gnueabihf".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/pi/_development/buffer_overflow/exploit_me...done.
(gdb) b 4
Breakpoint 1 at 0x83a0: file exploit_me.c, line 4.
(gdb) run
Starting program: /home/pi/_development/buffer_overflow/exploit_me
Breakpoint 1, foo (b=2) at exploit_me.c:4
4 int c = 3;
(gdb) disas foo
Dump of assembler code for function foo:
0x00008390 <+0>: push {r11} ; (str r11, [sp, #-4]!)
0x00008394 <+4>: add r11, sp, #0
0x00008398 <+8>: sub sp, sp, #20
0x0000839c <+12>: str r0, [r11, #-16]
=> 0x000083a0 <+16>: mov r3, #3
0x000083a4 <+20>: str r3, [r11, #-8]
0x000083a8 <+24>: add sp, r11, #0
0x000083ac <+28>: pop {r11}
0x000083b0 <+32>: bx lr
End of assembler dump.
(gdb) info r
r0 0x2 2
r1 0xbefff804 3204446212
r2 0xbefff80c 3204446220
r3 0x1 1
r4 0x0 0
r5 0x0 0
r6 0x82e4 33508
r7 0x0 0
r8 0x0 0
r9 0x0 0
r10 0xb6fff000 3070226432
r11 0xbefff69c 3204445852
r12 0xb6fc0000 3069968384
sp 0xbefff688 0xbefff688
lr 0x83d8 33752
pc 0x83a0 0x83a0 <foo+16>
cpsr 0x60000010 1610612752
(gdb) disas main
Dump of assembler code for function main:
0x000083b4 <+0>: push {r11, lr}
0x000083b8 <+4>: add r11, sp, #4
0x000083bc <+8>: sub sp, sp, #16
0x000083c0 <+12>: str r0, [r11, #-16]
0x000083c4 <+16>: str r1, [r11, #-20]
0x000083c8 <+20>: mov r3, #1
0x000083cc <+24>: str r3, [r11, #-8]
0x000083d0 <+28>: mov r0, #2
0x000083d4 <+32>: bl 0x8390 <foo>
0x000083d8 <+36>: mov r3, #4
0x000083dc <+40>: str r3, [r11, #-8]
0x000083e0 <+44>: mov r0, r3
0x000083e4 <+48>: sub sp, r11, #4
0x000083e8 <+52>: pop {r11, pc}
End of assembler dump.
(gdb) x/12xw $sp
0xbefff688: 0x00000000 0x00000002 0x00008360 0x00008438
0xbefff698: 0xb6fc1b80 0xbefff6b4 0xbefff804 0x00000001
0xbefff6a8: 0x00000000 0x00000001 0x00000000 0xb6eac81c
根据保存返回地址的链接寄存器设置为地址0x83d8
lr 0x83d8 33752
这确实是main中下一条指令的正确地址:
0x000083d8 <+36>: mov r3, #4
然而,堆栈(请参阅gdb输出的结尾)不包含阻止缓冲区溢出攻击的返回地址。
根据设计,返回地址是仅保存在链接寄存器中而不是被推入堆栈还是我遗漏了什么?
答案 0 :(得分:5)
我对手臂架构并不熟悉,但Power PC也是如此。当你调用一个函数时,你的返回地址存储在lr中。如果再调用一个级别,则将前一个lr推入堆栈。基本上,lr始终包含您所在功能的返回地址。如果您需要在呼叫历史记录中更高一些,则需要查看堆栈。
因此...
void myFunc2( void)
{
myFunc3();
}
void myFunc1( void )
{
myFunc2();
}
如果您在myFunc3中,则lr将包含myFunc2的返回地址。从myFunc2到myFunc1的返回地址位于堆栈的某处。我认为你可以做你正在尝试破坏myFunc1的返回地址,而不是你想要的myFunc2。
对于power pc,您可以通过阅读本文来了解寄存器和堆栈的工作原理 Power PC EABI