在Linux中,使用C/C++代码,使用gdb,如何添加gdb断点来扫描传入的字符串以便打破特定的字符串?
我无法访问特定库的代码,但是我想在该库将特定字符串发送到标准输出时立即中断,这样我就可以回到堆栈并调查我调用库的代码部分.当然我不想等到缓冲区刷新发生.可以这样做吗?也许是例行公事libstdc++?
Ant*_*ony 24
这个问题可能是一个很好的起点:我怎样才能在gdb中的"打印到终端上的东西"中加上断点?
因此,无论什么时候写入stdout,你都可以至少破解.该方法基本上涉及在write系统调用上设置一个断点,其条件是第一个参数是1(即STDOUT).在注释中,还提示如何检查write调用的字符串参数.
我想出了以下内容并使用gdb 7.0.1-debian进行了测试.它看起来效果很好.$esp + 8包含指向传递给字符串的内存位置的指针write,因此首先将其转换为积分,然后转换为指针char.$esp + 4包含要写入的文件描述符(1表示STDOUT).
$ gdb break write if 1 == *(int*)($esp + 4) && strcmp((char*)*(int*)($esp + 8), "your string") == 0
Run Code Online (Sandbox Code Playgroud)
如果你的过程是在X86-64模式下运行,则该参数是通过暂存寄存器传递%rdi和%rsi
$ gdb break write if 1 == $rdi && strcmp((char*)($rsi), "your string") == 0
Run Code Online (Sandbox Code Playgroud)
请注意,由于我们在堆栈上使用临时寄存器而不是变量,因此会删除一级间接.
以上功能strcmp可以在上面的代码段中使用:
编辑:我很喜欢这个问题并找到它的后续答案.我决定写一篇关于它的博客文章.
catch+strstr条件
这种方法很酷的一点是它不依赖于使用的 glibc write:它跟踪实际的系统调用。
此外,它对printf()缓冲更具弹性,因为它甚至可以捕获跨多个printf()调用打印的字符串。
x86_64 版本:
define stdout
catch syscall write
commands
printf "rsi = %s\n", $rsi
bt
end
condition $bpnum $rdi == 1 && strstr((char *)$rsi, "$arg0") != NULL
end
stdout qwer
Run Code Online (Sandbox Code Playgroud)
测试程序:
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
write(STDOUT_FILENO, "asdf1", 5);
write(STDOUT_FILENO, "qwer1", 5);
write(STDOUT_FILENO, "zxcv1", 5);
write(STDOUT_FILENO, "qwer2", 5);
printf("as");
printf("df");
printf("qw");
printf("er");
printf("zx");
printf("cv");
fflush(stdout);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
结果:休息时间:
qwer1qwer2fflush. 前一个printf实际上没有打印任何东西,它们被缓冲了!该writesyacall只是发生在fflush。笔记:
$bpnum感谢 Tromey:https ://sourceware.org/bugzilla/show_bug.cgi ? id = 18727rdi:x86_64中包含Linux系统调用编号的寄存器,1用于writersi: 系统调用的第一个参数,因为write它指向缓冲区strstr: 标准 C 函数调用,搜索子匹配项,如果未找到则返回 NULL在 Ubuntu 17.10、gdb 8.0.1 中测试。
斯特拉斯
如果您感觉互动,另一种选择:
setarch "$(uname -m)" -R strace -i ./stdout.out |& grep '\] write'
Run Code Online (Sandbox Code Playgroud)
示例输出:
[00007ffff7b00870] write(1, "a\nb\n", 4a
Run Code Online (Sandbox Code Playgroud)
现在复制该地址并将其粘贴到:
setarch "$(uname -m)" -R strace -i ./stdout.out |& grep -E '\] write\(1, "a'
Run Code Online (Sandbox Code Playgroud)
这种方法的优点是可以使用常用的 UNIX 工具来操作strace输出,并且不需要很深的 GDB-fu。
解释:
-i 使 strace 输出 RIPsetarch -R使用personality系统调用为进程禁用 ASLR :How to debug with strace -i when everytime address is different GDB 默认已经这样做了,所以不需要再做一次。| 归档时间: |
|
| 查看次数: |
1609 次 |
| 最近记录: |