gpt4 book ai didi

c - 无法在漏洞利用期间注入(inject)有效的指令指针

转载 作者:太空宇宙 更新时间:2023-11-04 03:12:46 26 4
gpt4 key购买 nike

我正在尝试利用给定的程序,但我不知道自己做错了什么。长话短说,我设法注入(inject)代码来覆盖 RIP。这意味着我应该能够重定向代码执行,但问题是,我得到了 SIGSEGV。我是否必须以特殊方式设计注入(inject)堆栈才能避免获得 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,但仅此而已。伙计们,这是怎么回事?

最佳答案

当您从 GDB 中启动程序时,GDB(默认情况下)会禁用 ASLR。在 PIE 可执行文件中,静态代码/数据地址是随机的。仅当您知道正确的绝对地址时,注入(inject)返回地址才有效。

但显然您有时会在 GDB 之外启动您的程序,其中的地址每次都不相同。这显然会导致段错误,并且您的问题没有显示实际 0x0000555555554e6e 在发生段错误的实际过程中的反汇编,这与您声称/假设的相反。

(GCC 在默认情况下制作 PIE 可执行文件是 Linux 上的新事物;如果您正在学习旧教程,它可能会假设可执行文件本身是位置相关的,并且只有库 + 堆栈会被 ASLRed。32-bit absolute addresses no longer allowed in x86-64 Linux? )

参见 Disable randomization of memory addresses以系统范围或每个进程的方式禁用 ASLR,或构建非 PIE 可执行文件。

关于c - 无法在漏洞利用期间注入(inject)有效的指令指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54755241/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com