gpt4 book ai didi

shell - gdbserver:执行目标的shell命令

转载 作者:行者123 更新时间:2023-12-02 03:34:29 26 4
gpt4 key购买 nike

例如!ls将执行ls gdb 本身中有命令,但如何在远程端执行此操作?

应该很简单,但我不明白。 Per documentation类似 target remote | lstarget remote | !ls应该可以解决这个问题,但要么它是错误的,要么我不明白一些东西:这样的命令使 gdb 尝试关闭当前 session ,并开始调试 ls二进制。

我还发现了一些monitor cmd提到过,但是 monitor !ls只是触发Unknown monitor command消息。

最佳答案

解决方法是实现执行以下操作的自定义 gdb 命令:

  1. fork 远程进程;
  2. 切换到劣等子;
  3. 用执行用户提供的命令的 shell 替换子进程;
  4. 显示远程命令的输出;
  5. 返回到下级父级。

有几个限制需要考虑:

  • 在 gdb call 命令上无法解析符号:我们需要通过地址调用 libc 函数,这需要预先加载地址;
  • 需要安装 libc 调试信息,否则无法检索符号;
  • 自动加载子进程的远程库符号时可能会遇到巨大的速度减慢的情况:相反,我们可以使用父进程预加载地址,然后禁用自动符号加载;
  • 从 gdb call 命令执行的 Shell 命令输出不会在 gdb 终端中回显:但是,我们可以将其捕获到远程临时文件中,然后读取到内存并打印。

gdb session 示例:

# Given remote terminal running `gdbserver :2345 ./remote_executable`, we connect to that server.
target extended-remote 192.168.1.4:2345

# Load our custom gdb command `rcmd`.
source ./remote-cmd.py

# Run until a point where libc has been loaded on the remote process, e.g. start of main().
b main
r

# Don't need the main() breakpoint anymore.
del 1

# Run the remote command, e.g. `ls`.
rcmd ls

远程cmd.py:

#!/usr/bin/env python3

import gdb
import re
import traceback
import uuid


class RemoteCmd(gdb.Command):
def __init__(self):
self.addresses = {}

self.tmp_file = f'/tmp/{uuid.uuid4().hex}'
gdb.write(f"Using tmp output file: {self.tmp_file}.\n")

gdb.execute("set detach-on-fork off")
gdb.execute("set follow-fork-mode parent")

gdb.execute("set max-value-size unlimited")
gdb.execute("set pagination off")
gdb.execute("set print elements 0")
gdb.execute("set print repeats 0")

super(RemoteCmd, self).__init__("rcmd", gdb.COMMAND_USER)

def preload(self):
for symbol in [
"close",
"execl",
"fork",
"free",
"lseek",
"malloc",
"open",
"read",
]:
self.load(symbol)

def load(self, symbol):
if symbol not in self.addresses:
address_string = gdb.execute(f"info address {symbol}", to_string=True)
match = re.match(
f'Symbol "{symbol}" is at ([0-9a-fx]+) .*', address_string, re.IGNORECASE
)
if match and len(match.groups()) > 0:
self.addresses[symbol] = match.groups()[0]
else:
raise RuntimeError(f'Could not retrieve address for symbol "{symbol}".')

return self.addresses[symbol]

def output(self):
# From `fcntl-linux.h`
O_RDONLY = 0
gdb.execute(
f'set $fd = (int){self.load("open")}("{self.tmp_file}", {O_RDONLY})'
)

# From `stdio.h`
SEEK_SET = 0
SEEK_END = 2
gdb.execute(f'set $len = (int){self.load("lseek")}($fd, 0, {SEEK_END})')
gdb.execute(f'call (int){self.load("lseek")}($fd, 0, {SEEK_SET})')
if int(gdb.convenience_variable("len")) <= 0:
gdb.write("No output was captured.")
return

gdb.execute(f'set $mem = (void*){self.load("malloc")}($len)')
gdb.execute(f'call (int){self.load("read")}($fd, $mem, $len)')
gdb.execute('printf "%s\\n", (char*) $mem')

gdb.execute(f'call (int){self.load("close")}($fd)')
gdb.execute(f'call (int){self.load("free")}($mem)')

def invoke(self, arg, from_tty):
try:
self.preload()

is_auto_solib_add = gdb.parameter("auto-solib-add")
gdb.execute("set auto-solib-add off")

parent_inferior = gdb.selected_inferior()
gdb.execute(f'set $child_pid = (int){self.load("fork")}()')
child_pid = gdb.convenience_variable("child_pid")
child_inferior = list(
filter(lambda x: x.pid == child_pid, gdb.inferiors())
)[0]
gdb.execute(f"inferior {child_inferior.num}")

try:
gdb.execute(
f'call (int){self.load("execl")}("/bin/sh", "sh", "-c", "exec {arg} >{self.tmp_file} 2>&1", (char*)0)'
)
except gdb.error as e:
if (
"The program being debugged exited while in a function called from GDB"
in str(e)
):
pass
else:
raise e
finally:
gdb.execute(f"inferior {parent_inferior.num}")
gdb.execute(f"remove-inferiors {child_inferior.num}")

self.output()
except Exception as e:
gdb.write("".join(traceback.TracebackException.from_exception(e).format()))
raise e
finally:
gdb.execute(f'set auto-solib-add {"on" if is_auto_solib_add else "off"}')


RemoteCmd()

关于shell - gdbserver:执行目标的shell命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26757055/

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