Assembly 如何在gdb中调用程序集?

Assembly 如何在gdb中调用程序集?,assembly,gdb,Assembly,Gdb,在gdb中,我可以使用call来运行函数,但是如果我想运行一些额外的程序集呢?在GCC 5(1)之前,我不知道如何运行任意机器代码,除非您将机器代码输入内存,然后运行它 如果要运行内存中已经存在的代码,只需将指令指针设置为开始,即结束时的断点,然后转到。然后,在断点之后,将指令指针更改回其原始值 但我实际上看不到这个用例。这并不意味着没有,只是通过运行代码可以完成的任何事情,也可以通过直接修改寄存器、标志、内存等来实现 例如,命令: info registers 将转储寄存器的当前值,同时:

在gdb中,我可以使用
call
来运行函数,但是如果我想运行一些额外的程序集呢?

在GCC 5(1)之前,我不知道如何运行任意机器代码,除非您将机器代码输入内存,然后运行它

如果要运行内存中已经存在的代码,只需将指令指针设置为开始,即结束时的断点,然后转到。然后,在断点之后,将指令指针更改回其原始值

但我实际上看不到这个用例。这并不意味着没有,只是通过运行代码可以完成的任何事情,也可以通过直接修改寄存器、标志、内存等来实现

例如,命令:

info registers
将转储寄存器的当前值,同时:

set $eax = 42
eax
寄存器更改为
42

您还可以通过以下方式更改内存:

set *((char*)0xb7ffeca0) = 4
这会将单个字节写入内存位置
0xb7ffeca0
,您还可以使用相同的方法存储更广泛的数据类型



(1) GCC 5允许您使用
编译代码
命令编译和执行任意代码,如文档所示。

编译代码
命令

在7.9左右引入,它允许代码编译和注入,文档:

main.c

#include <stdio.h>

int main(void) {
    int i = 0;
    printf("%d\n", i);
    return 0;
}
然后在GDB中:

(gdb) start
Temporary breakpoint 1 at 0x113d: file main.c, line 4.
Starting program: /home/ciro/test/main.out 

Temporary breakpoint 1, main () at main.c:4
4           int i = 0;
(gdb) next
5           printf("%d\n", i);
(gdb) compile code int j = 1; i = j; asm("nop");
(gdb) continue
Continuing.
1
[Inferior 1 (process 30256) exited normally]
程序输出:

1
为了在GDB 7.9.1、GCC 5.1中实现这一点,我必须使用以下工具运行GDB:

LD_LIBRARY_PATH="$(dirname "$(gcc -print-libgcc-file-name)"):$LD_LIBRARY_PATH" gdb main.out
因此,
libcc1.so
将可见:这是一个最新的GCC组件,它向
cc1
编译器公开了一个C API,但在Ubuntu 19.04上不再需要它了。然而,C++在最小值:

上仍然是必需的。 main.cpp

#include <iostream>

int main() {
    int i = 0;
    std::cout << i << std::endl;
}
有几个构造没有像我预期的那样工作:

  • 返回

  • 包括:

    compile code printf('asdf\n')
    
    在Ubuntu 19.04中

    在上面的main.c上,没有包含的
    printf
    有效,因为我们已经在源代码中包含了它,但是如果我在没有包含的空
    main()
    上尝试它,它会失败:

    gdb command line:1:1: warning: incompatible implicit declaration of built-in function ‘printf’
    gdb command line:1:1: note: include ‘<stdio.h>’ or provide a declaration of ‘printf’
    gdb command line:1:8: warning: character constant too long for its type
    gdb command line:1:8: warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast [-Wint-conversion]
    gdb command line:1:8: note: expected ‘const char *’ but argument is of type ‘int’
    gdb command line:1:1: warning: format not a string literal and no format arguments [-Wformat-security]
    
    gdb命令行:1:1:警告:内置函数“printf”的隐式声明不兼容
    gdb命令行:1:1:注意:包括“”或提供“printf”声明
    gdb命令行:1:8:警告:字符常量对于其类型太长
    gdb命令行:1:8:警告:传递'printf'的参数1将从整数生成指针,而不使用强制转换[-Wint conversion]
    gdb命令行:1:8:注意:应为“const char*”,但参数的类型为“int”
    gdb命令行:1:1:警告:格式不是字符串文字,也没有格式参数[-Wformat security]
    
  • C++中UPUTU 19.04:

    compile code std::cout << "Hello world\n";
    

    编译代码std::cout如果无法直接运行
    mov
    etc,如何修改寄存器?@gdb:例如,您可以使用
    设置$eax=42
    。请参阅更新。您是否也可以演示如何使用
    set
    更改内存?内存中存在执行特定汇编指令的情况。它可能是一个多媒体命令,其结果可能不容易计算。或者一些通常的命令,这些命令比手工编辑寄存器/内存更容易执行,很可能会出错。制作一个pythonapi命令来实现这一点会很有趣。找到一些空闲的可执行内存,在那里编译、编写命令,将ESP改为它,将最后一个命令设置为跳回。很可能很难:-)这似乎不适用于
    asm volatile(“mov$abc,%eax”)
    ,当语言为C时。在
    compile
    命令返回后,
    $rax
    仍有其原始值。当源语言为asm时,GDB 7.10不支持
    compile
    命令,因此即使在调试用asm编写的函数时,该命令也不起作用。@PeterCordes谢谢,我没有尝试过<代码>编译
    确实非常有限。但也有潜力。是的,对于C/C++来说,它看起来非常方便,但不仅仅是为了试验指令对不同输入的作用。我想你可以用一个C变量作为输出操作数,但是你需要一条指令来使用它。在这一点上,只需将指令放在文件中,组装/链接它,然后单步执行,可能会更容易。谢谢你指出这一点,尽管这不是这个问题的好答案。您的
    std::cout
    示例可以用
    -raw
    参数重写为
    compile code-raw#include^Mvoid\u gdb\u expr()-(C++的Hello World与<代码>失败,CUT”不是“STD”< /C>的成员,空<代码>主< /代码>失败,代码< >警告:当我尝试时,找不到编译模块“/tMP/gdBOBjdxrnb/Out1.o”。的符号“yZST4cOUT”。
    
    gdb command line:1:1: warning: incompatible implicit declaration of built-in function ‘printf’
    gdb command line:1:1: note: include ‘<stdio.h>’ or provide a declaration of ‘printf’
    gdb command line:1:8: warning: character constant too long for its type
    gdb command line:1:8: warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast [-Wint-conversion]
    gdb command line:1:8: note: expected ‘const char *’ but argument is of type ‘int’
    gdb command line:1:1: warning: format not a string literal and no format arguments [-Wformat-security]
    
    compile code std::cout << "Hello world\n";
    
    *** WARNING *** there are active plugins, do not report this as a bug unless you can reproduce it without enabling any plugins.
    Event                            | Plugins
    PLUGIN_PRE_GENERICIZE            | libcp1plugin
    PLUGIN_GGC_MARKING               | libcp1plugin
    PLUGIN_PRAGMAS                   | libcp1plugin
    gdb command line:1:6: internal compiler error: in plugin_build_decl, at libcc1/libcp1plugin.cc:1059
    Please submit a full bug report,
    with preprocessed source if appropriate.
    See <file:///usr/share/doc/gcc-8/README.Bugs> for instructions.
    Compilation failed.