如何更改 esp 中的值?

逆向工程 拆卸 调试 二元分析 数据库
2021-07-09 23:36:06
   0x08048785 <+344>:   movl   $0x0,0xc(%esp)
   0x0804878d <+352>:   movl   $0x804896c,0x8(%esp)
   0x08048795 <+360>:   movl   $0x8048973,0x4(%esp)
   0x0804879d <+368>:   movl   $0x8048973,(%esp)
=> 0x080487a4 <+375>:   call   0x8048470 <execlp@plt>

我想知道是否可以更改传递给函数 execlp() 的参数以执行 shell?如果有可能,我该如何更改这些值,例如 0x8(%esp)?

非常感谢。

1个回答

我想知道是否可以更改传递给函数 execlp() 的参数以执行 shell?

是的,这是可能的。位于调用之前写入堆栈的内存地址处的字符串execlp可以被修补,以便/bin/sh改为执行。如果在当前内存引用之间没有足够的空间用于执行程序的路径名和/或其参数,则必须对写入堆栈的内存地址进行修补,以反映它们引用的新字符串的长度.

在调用之前写入堆栈的内存地址execlp是指向.rodata二进制文件部分中字符串的指针,其中第一个参数(0x8048973在上面的反汇编代码片段中)所指向的字符串是要执行的程序的路径名(我们可以认为execlp是“执行加载路径”)。如果更改此字符串,execlp将加载位于新路径名的程序。

作为参考,这里是手册页中的原型execlp及其描述

int execlp(const char *file, const char *arg, ... /* (char *) NULL */);

const char *argexecl()、execlp() 和 execle() 函数中和后续省略号可以被认为是arg0, arg1, ..., argn它们一起描述了一个或多个指向空终止字符串的指针的列表,这些字符串表示可用于执行的程序的参数列表。按照惯例,第一个参数应该指向与正在执行的文件关联的文件名。参数列表必须以空指针结尾,并且由于这些是可变参数函数,因此必须强制转换此指针(char *) NULL

这是如何execlp工作的一个很好的解释我不明白 execlp() 在 Linux 中是如何工作的

另请注意,由于 ISA 是 x86 并且编译器是 GCC,因此函数的参数以函数原型中相应参数的相反顺序写入堆栈。这意味着写入堆栈的最后一个参数对应于函数原型中的第一个参数。对于execlp,在调用之前写入堆栈的最后一个参数execlp将是指向要加载的程序的路径名的指针。

如果有可能,我该如何更改这些值,例如 0x8(%esp)?

可以使用十六进制编辑器(如)或使用radare2来完成部分中的修补字符串以及.rodata部分中的修补指令和内存地址.textxxdhexedit

资源

要使用 GDB 修补二进制文件,请参阅以下内容:

使用 GDB 修改可执行文件

使用 gdb 修改二进制

使用 GDB 调试:修补

ELF二进制修改:

在 ELF 二进制文件/程序中修复/打孔 - Black Hat

如何向现有的二进制可执行文件添加功能?

精灵外壳