【发布时间】:2019-02-18 20:57:09
【问题描述】:
我试图利用给定的程序,但我不知道我做错了什么。长话短说,我设法注入代码来覆盖 RIP。这意味着我应该能够重定向代码执行,但问题是,我得到了 SIGSEGV。我是否必须以特殊方式设计注入堆栈才能获得 SIGSEGV?
我的游戏计划是利用函数mainloop 并更改返回地址。函数mainloop 的堆栈具有以下值:
0000| 0x7fffffffdff0 --> 0xa7400ffffe010
0008| 0x7fffffffdff8 --> 0xf423f55758260
0016| 0x7fffffffe000 --> 0x7fffffffe010 --> 0x5555555550b0 (<__libc_csu_init>: push r15)
0024| 0x7fffffffe008 --> 0x5555555550a4 (<main+66>: mov eax,0x0)
所以返回地址存储在0x7fffffffe008,我设法用指向我要执行的代码的地址覆盖了那个值。在这种情况下,地址为0x555555554e6e。
程序的回溯如下:
#6 0x0000555555554fab in mainloop ()
#7 0x00005555555550a4 in main ()
#8 0x00007ffff7e1109b in __libc_start_main (main=0x555555555062 <main>, argc=0x1, argv=0x7fffffffe0f8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffe0e8) at ../csu/libc-start.c:308
#9 0x000055555555486a in _start ()
如您所见,当我退出 mainloop 时,我将返回到 main,而当我退出 main 时,我会转到一堆 libc 函数,以便程序干净地退出(?)。
那么当我运行我的漏洞利用代码时会发生什么?这个:
0000| 0x7ffe1b3d4150 --> 0x424142001b3d4170
0008| 0x7ffe1b3d4158 ("ABABABABABABABABnNUUUU")
0016| 0x7ffe1b3d4160 ("ABABABABnNUUUU")
0024| 0x7ffe1b3d4168 --> 0x555555554e6e ('nNUUUU')
0032| 0x7ffe1b3d4170 --> 0x55a34784000a
0040| 0x7ffe1b3d4178 --> 0x7f7c156c409b (<__libc_start_main+235>: mov edi,eax)
0048| 0x7ffe1b3d4180 --> 0x0
0056| 0x7ffe1b3d4188 --> 0x7ffe1b3d4258 --> 0x7ffe1b3d5474 ("./device")
您看到的是堆栈。我添加了一些字节,以便您获得更多上下文。但我认为我设法为我的漏洞打到了正确的填充尺寸。我已经设法改变了第 24 字节的值。
但我的 PEDA/GDB 似乎并不将该值视为指令指针,这很奇怪。它似乎将其视为 C 字符串(?)。回溯如下所示:
#6 0x000055a347849fab in mainloop ()
#7 0x0000555555554e6e in ?? ()
#8 0x000055a34784000a in ?? ()
#9 0x00007f7c156c409b in __libc_start_main (main=0x55a34784a062 <main>, argc=0x1, argv=0x7ffe1b3d4258, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7ffe1b3d4248) at ../csu/libc-start.c:308
#10 0x000055a34784986a in _start ()
当我退出 mainloop 时,我在 PEDA/GDB 中得到以下信息:
Stopped reason: SIGSEGV
0x0000555555554e6e in ?? ()
如果我在 GDB 中运行命令 i f,我会得到:
Stack level 0, frame at 0x7ffe1b3d4178:
rip = 0x555555554e6e; saved rip = 0x55a34784000a
called by frame at 0x7ffe1b3d4180
Arglist at 0x7ffe1b3d4168, args:
Locals at 0x7ffe1b3d4168, Previous frame's sp is 0x7ffe1b3d4178
Saved registers:
rip at 0x7ffe1b3d4170
在地址0x0000555555554e6e,程序执行以下ASM:
0x0000555555554e6e <+172>: lea rdi,[rip+0x20126b] # 0x5555557560e0 <flag2>
所以我似乎有正确的 RIP,但仅此而已。 伙计们,这是怎么回事?
【问题讨论】:
-
那么,
0x0000555555554e6e是什么? -
lea rdi,[rip+0x20126b]不会因为任何现有的寄存器内容而出错。我认为唯一的解释是0x0000555555554e6e不在可执行页面中。是在.data还是什么的,你编译的目标程序没有-zexecstack? (是的,该 gcc 选项适用于.data和 BSS 以及实际堆栈。) -
@PeterCordes,我很确定代码是可执行的,因为我可以从程序本身运行它。地址
0x0000555555554e6e指向一个名为process的函数中的特定行,我知道我可以执行它。 -
您对
0x0000555555554e6e的反汇编是在实际目标进程发生段错误后提取的吗?除非发生了raise(SIGSEGV)或kill(pid, SIGESGV)的操作,否则我不知道那条指令还会出现什么错误,如果它是这样反汇编的。您可以检查/proc/PID/maps以查找包含该地址的映射的权限。这一切都是从 GDB 内部运行的,因此 ASLR 始终处于禁用状态(程序的重复运行将在同一地址加载。) -
@PeterCordes 嗯,我想你可以做点什么。所以可执行文件是预编译的,我也得到了 C 语言的源代码。当我从 GDB 运行 exec 并反汇编函数时,我总是得到相同的地址,
0x0000555555554e6e。那是我要执行的特定代码行。但是当我从 Pwntools 运行它时,同一行代码的地址发生了变化。所以也许我的策略是正确的。可能是我没有正确的地址来处理通过 Pwntools 执行程序时的特定实例。是否可以注入某种相对指令指针?
标签: c assembly stack-overflow exploit pwntools