【问题标题】:Copying string to stack in gdb将字符串复制到gdb中的堆栈
【发布时间】:2016-10-17 13:26:21
【问题描述】:

为什么

我想使用 gdb 作为拦截 open 系统调用的一种方式,并让应用程序获得与它所要求的不同文件的句柄。类似的东西:

replace-file filea=fileb cat filea
# prints out contents of fileb

我可以拦截open 系统调用,但我必须提供一个新的文件名,它应该是一个存在于下层内存中的字符串。
我想避免为此使用malloc,因为那时我依赖于下级中可用的库,而是将其存储在堆栈中(“在”进程使用的部分之后),因为我只需要下一个代码线,我对它之后被覆盖没有问题。

什么

但是,我很难写入堆栈。
我知道堆栈向下增长,所以我尝试将堆栈指针减少我的字符串的大小,将字符串复制到指针,然后增加堆栈指针。我在将字符串复制到堆栈指针指向的位置时遇到了麻烦。

到目前为止我所拥有的:

# script.gdb
handle all pass    handle al pass
set print thread-events off

set $file_a = "/etc/fstab"
set $file_b = "/etc/passwd"
set $len = $_strlen($file_b)
set $len = $len + 1

catch syscall open
commands
  silent
  # $rax == return value
  # IF x64, $rdi == filename
  set $outside = ! $outside
  if ( $_streq((char *)$rdi, $file_a) )

    printf "rsp: %d\n", $rsp
    set $rsp = $rsp - $len

    printf "rsp: %d\n", $rsp
    call strcpy($rsp, $file_b)
    printf "rsp: %d\n", $rsp
    printf "%d: %s\n", $rsp,$rsp

    set $rsp = $rsp + $len
  end
  continue
end
run

测试用例:

    $ gdb -batch -q -x script.gdb --args python -c "print open('/etc/fstab').read()"
Catchpoint 1 (syscall 'open' [2])
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
rsp: -10392
rsp: -10404
$1 = -10404
rsp: -10404
-10404: /etc/passwd
Traceback (most recent call last):
  File "<string>", line 1, in <module>
IOError: [Errno 38] Function not implemented: '/etc/fstab'
[Inferior 1 (process 25336) exited with code 01]

【问题讨论】:

  • 堆栈对齐是否可能是问题所在? linux 上的 x86-64 需要 16 字节的堆栈对齐。所以像set $old = $rsp、set $rsp = $rsp - $len、set $rsp = (unsigned long long)$rsp &amp; (unsigned long long)~0xf、.....、set $rsp = $old 这样的东西可能会起作用
  • @Andrew 不。虽然对齐很有趣,因为它提到了“strcpy-sse2-unaligned”。我怀疑这里的 strcpy 不好,需要换成别的东西
  • 我目前认为在系统调用中间执行代码是问题所在。我得到的错误看起来类似于github.com/mozilla/rr/issues/605

标签: c pointers gdb


【解决方案1】:

你有你的论据,以错误的方式解决 strcpy。它是:

char *strcpy(char *dest, const char *src);

但你有:

call strcpy($newfile, $rsp)

我假设$newfile 确实是您要使用的新名称$file_b,所以这应该是src,而$rsp 是您要放置新文件名的位置,所以是dest。

您还需要将修改后的 $rsp 值存储到 $rdi 中,以便 open 看到修改后的参数。

【讨论】:

  • 这是一个很好的步骤,但它还没有工作 - 用结果编辑。我想我正在写堆栈的另一部分,因为Function not implemented: '/etc/fstab 显然涉及我的文件名
  • 我查看了 GDB 源代码,但我认为这目前不会起作用。在系统调用捕获中使用call 会破坏 GDB 的内部状态,从而导致系统调用无法正确完成。我认为答案可能是编写一个 python 辅助函数,将字符串一次一个字节地复制到堆栈中,这样就可以避免使用call。
  • 你能把我链接到源吗?听起来很有趣
  • @Nitz 我认为这是一个很好的起点sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=gdb/… 如果你打开'set debug infrun 1' & 'set debug lin-lwp 1' 你可以看到lp-&gt;syscall_state 这是预期的当您使用调用时(在系统调用入口处停止时),缓存系统调用入口和出口之间的状态被破坏。如果您在 gdb 上使用 gdb 并在 lp-&gt;syscall_state 上放置一个观察点,那么应该很容易准确地看到发生了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-25
  • 2019-05-05
  • 1970-01-01
  • 2012-04-17
  • 2021-06-03
  • 1970-01-01
相关资源
最近更新 更多