无法在漏洞利用期间注入有效的指令指针
Unable to inject valid instruction pointer during exploit
我正在尝试利用给定的程序,但我不知道自己做错了什么。长话短说,我设法注入代码来覆盖 RIP。这意味着我应该能够重定向代码执行,但问题是,我得到了 SIGSEGV。我是否必须以特殊方式设计注入堆栈才能不获取 SIGSEGV?
我的游戏计划是利用函数 mainloop
并更改 return 地址。函数 mainloop
的堆栈具有以下值:
0000| 0x7fffffffdff0 --> 0xa7400ffffe010
0008| 0x7fffffffdff8 --> 0xf423f55758260
0016| 0x7fffffffe000 --> 0x7fffffffe010 --> 0x5555555550b0 (<__libc_csu_init>: push r15)
0024| 0x7fffffffe008 --> 0x5555555550a4 (<main+66>: mov eax,0x0)
所以 return 地址存储在 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
时,我将 return 编辑到 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 可执行文件中,静态 code/data 地址是随机的。注入 return 地址只有在您知道正确的绝对地址时才有效。
但显然您有时会在 GDB 之外启动您的程序,其中的地址每次都不相同。这显然会导致段错误,并且您的问题没有显示在发生段错误的实际过程中与实际 0x0000555555554e6e
的反汇编,这与您声称/假设的相反。
(GCC 在默认情况下制作 PIE 可执行文件是 Linux 上最近的事情;如果您正在学习旧教程,它可能假设可执行文件本身是位置相关的,只有库 + 堆栈会成为 ASLRed。32-bit absolute addresses no longer allowed in x86-64 Linux?)
有关禁用 ASLR 或构建非 PIE 可执行文件的系统范围或每个进程的方法,请参阅 Disable randomization of memory addresses。
我正在尝试利用给定的程序,但我不知道自己做错了什么。长话短说,我设法注入代码来覆盖 RIP。这意味着我应该能够重定向代码执行,但问题是,我得到了 SIGSEGV。我是否必须以特殊方式设计注入堆栈才能不获取 SIGSEGV?
我的游戏计划是利用函数 mainloop
并更改 return 地址。函数 mainloop
的堆栈具有以下值:
0000| 0x7fffffffdff0 --> 0xa7400ffffe010
0008| 0x7fffffffdff8 --> 0xf423f55758260
0016| 0x7fffffffe000 --> 0x7fffffffe010 --> 0x5555555550b0 (<__libc_csu_init>: push r15)
0024| 0x7fffffffe008 --> 0x5555555550a4 (<main+66>: mov eax,0x0)
所以 return 地址存储在 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
时,我将 return 编辑到 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 可执行文件中,静态 code/data 地址是随机的。注入 return 地址只有在您知道正确的绝对地址时才有效。
但显然您有时会在 GDB 之外启动您的程序,其中的地址每次都不相同。这显然会导致段错误,并且您的问题没有显示在发生段错误的实际过程中与实际 0x0000555555554e6e
的反汇编,这与您声称/假设的相反。
(GCC 在默认情况下制作 PIE 可执行文件是 Linux 上最近的事情;如果您正在学习旧教程,它可能假设可执行文件本身是位置相关的,只有库 + 堆栈会成为 ASLRed。32-bit absolute addresses no longer allowed in x86-64 Linux?)
有关禁用 ASLR 或构建非 PIE 可执行文件的系统范围或每个进程的方法,请参阅 Disable randomization of memory addresses。