【问题标题】:Is there a way to edit argv during runtime using gdb?有没有办法在运行时使用 gdb 编辑 argv?
【发布时间】:2022-01-16 10:11:35
【问题描述】:

有没有办法在运行时使用 gdb 编辑 argv?

我想获取 c 程序的 pid 并将其作为参数 (argv) 传递。

例如:

gdb cProgram
(gdb) b *0x000000000040085b
(gdb) r anyway
(gdb) info inferior
  >Num  Description          Executable
  >* 1    process 2597503    /path/to/file

(gdb) #A command to pass 2597503 as argument (argv)
(gdb) c

谢谢:)

【问题讨论】:

  • 您是否特别想让进程将其 pid 的字符串值作为其第一个参数?如果是这样,您可以直接使用run $$(在使用 shell 运行目标程序的系统上)。

标签: c gdb reverse-engineering


【解决方案1】:

是的,这似乎是可能的,但是,我不知道这样做的含义,其他人需要插话。如果argv 字符串是字符串文字,那么修改它们就是undefined behavior。此外,如果您写入超过原始字符串的长度,则可能也会调用 UB。尽管如此,我还是找到了this answer,它详细说明了如何修改int,并将其调整为字符串。考虑以下程序:

#include <stdio.h>

int main(int argc, char* argv[])
{
  for (int i=1; i<argc; i++)
  {
    printf("%s\n", argv[i]);
  }

  return 0;
}

编译

gcc -Wall -Wextra -g -O0 -std=c99 test.c

然后用 gdb 运行:

gdb a.out
// gdb's intro
(gdb) break main
Breakpoint 1 at ...
(gdb) run arg1 arg2 arg3  // pass it 3 arguments
// breakpoint hit at main
(gdb) print argv[1]
$1 = <address> "arg1"
(gdb) set {char*}(&(argv[1])) = "new4"  // change the value of argv[1]
(gdb) print argv[1]
$2 = <differentAddress> "new4"
(gdb) delete 1 // deletes the break point
(gdb) continue
Continuing.
new4
arg2
arg3
[... exited normally]
(gdb)

所以你有它。这是否真的安全是另一回事,但这改变了argv[1] 对我的价值。我至少会确保原始字符串的长度与您要替换的字符串相同或更长。

【讨论】:

  • argv 指向的字符串是 not 字符串文字。在程序被调用之前,它们被内核注入到应用程序的地址空间中(从内存顶部开始向下工作)。对于环境变量也是如此。内核通过调用start(argc,argv,envp) 启动C 包装器。大多数 C 包装器会通过 envpmainmain(argc,argv,envp),即使规范说不。 argv 中的指针和它们指向的字符串都是modifiable
  • @CraigEstey 非常感谢您提供的信息,如果您不自己编写,我会将其作为答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-09
  • 2016-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-25
相关资源
最近更新 更多