GDB如何从Coredump文件恢复动态库信息

GDB如何从Coredump文件恢复动态库信息,第1张

查看 error log:

我们拿到了崩溃位置0xee36f1,如何找到与之相对的代码位置呢?

找台测试机,获取对应版本的安装包:

解压:

然后用 GDB 打开 mysqld:

在 0xee36f1 位置打一个断点:

我们可以看到,gdb 将崩溃位置的文件名和行号都打印出来,

剩下的事情,就可以交给开发工程师,按照这个崩溃堆栈来进行问题排查。

赠送章节

红框内的这串信息是什么?我们来解开看一下,

这段信息分为两段,"+0x71" 是一个偏移量,前面是一串文字,我们将文字解析出来:

可以看到前面这串文字是一个函数签名的编码,用 c++filt 还原编码以后,可以看到完整的函数签名。

红框内的这串信息的意思就是崩溃位置是 一个函数起始位置 + 偏移量。

我们大概可以猜到,这个 MySQL 的缺陷是在为 binlog 产生新的文件名时发生的。

小贴士:

函数起始位置 + 偏移量 是一种内存位置的表示方法,但该位置不一定是这个函数内的代码。

以本例来说,0xee36f1 这个位置,程序找到了就近的函数 generate_new_name 的起始位置,计算出有 0x71 这么多偏移,就表示成了 generate_new_name+0x71 这种形式。

但 0xee36f1 这个位置的代码,大概率是,但,不一定是 generate_new_name 这个函数内部的一段代码。

直接修改可执行文件中的代码和变量好像也没有什么比较好的工具,今天leviathan问我用“set write on”相关的问题,我才发现GDB就是可以很方便完成这个工作的工具,下面我向大家介绍一下使用方法。

另,在GDB文档中介绍这个方法也能修改CORE文件的内容,但即使我读了这块的代码,还是对修改CORE文件毫无思路也没成功过,所以本文就不介绍对CORE文件的修改了。

在一般情况下GDB是以只读方式打开可执行文件的,如果需要改变可执行文件,需要在读入文件以前,用GDB启动参数“--write”或者命令“set write on”用可读写方式打开可执行文件。如果文件已经打开了可执行文件,就需要使用exec-file重新以读写方式打开可执行文件,注意如果你还没打开可执行文件,就一定要使用file命令读入,因为exec-file不会重新读入符号信息。

还有要注意的是,因为修改只能修改section的内容,所以能修改的变量只能是非0的全局变量,内容是O的变量会被放入bss。

下面举例修改变量内容:

cat 1.c

#include <stdio.h>

int a = 1

int

main(int argc,char *argv[],char *envp[])

{

printf ("%d\n", a)

return 0

}

gcc -g 1.c

./a.out

1#注意这个输出

gdb

GNU gdb 6.8-debian

Copyright (C) 2008 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law. Type "show copying"

and "show warranty" for details.

This GDB was configured as "x86_64-linux-gnu".

(gdb) set write on#打开功能

(gdb) file ./a.out #打开文件

Reading symbols from /home/teawater/gdb/a.out...done.

(gdb) p a = 100#修改变量的文件中的值

$1 = 100

./a.out

100#注意修改后的输出

下面举例修改代码内容:

cat 1.c

#include <stdio.h>

void

cool (void)

{

printf ("Call function cool.\n")

}

int

main(int argc,char *argv[],char *envp[])

{

cool ()

return 0

}

gcc -g 1.c

./a.out

Call function cool.#注意现在有输出

gdb --write ./a.out #使用--write直接打开可写功能

GNU gdb 6.8-debian

Copyright (C) 2008 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law. Type "show copying"

and "show warranty" for details.

This GDB was configured as "x86_64-linux-gnu"...

(gdb) disas cool

Dump of assembler code for function cool:

0x000000000040050c <cool+0>:push %rbp#注意改之前这条指令

0x000000000040050d <cool+1>:mov%rsp,%rbp

0x0000000000400510 <cool+4>:mov$0x40062c,%edi

0x0000000000400515 <cool+9>:callq 0x4003f8 <puts@plt>

0x000000000040051a <cool+14>:leaveq

0x000000000040051b <cool+15>:retq

End of assembler dump.

(gdb) set *(unsigned char *)(0x000000000040050c) = 0xc3#修改指令

(gdb) disas cool

Dump of assembler code for function cool:

0x000000000040050c <cool+0>:retq #改之后这指令发生了变化

0x000000000040050d <cool+1>:mov%rsp,%rbp

0x0000000000400510 <cool+4>:mov$0x40062c,%edi

0x0000000000400515 <cool+9>:callq 0x4003f8 <puts@plt>

0x000000000040051a <cool+14>:leaveq

0x000000000040051b <cool+15>:retq

End of assembler dump.

./a.out#现在没有输出了 因为cool函数直接返回了

最近看到有个CTF题感觉挺有意思,就是从一个bin中找到一个secret key,然后用来签名session cookies用来怼一个使用go的Web服务器。通常这种类型题的flag都比较直接。可以直接用strings怼这个bin就可以了,然而这次的这个题目中的bin不同,因为有太多杂碎(noise)要过滤了。于是在此我就来展示一下如何用一些基本的Linux命令配合gdb从进程中dump出内存中的信息。

先file一下,

发现是64位的Linux可执行文件。

然后strings一下,

发现字符串太多,还是先不看,再研究深一点吧。

然后先运行一下程序,

然后再另一个终端找到这个进程的PID

然后cat一下它的内存(太长不看TLDR)

似乎太多了有点可怕,但是不用害怕。

然后启动gdb,将改进程attach到gdb上。

然后就是gdb命令

解释一下语法:

然后就是用strings命令找出刚才dump出的文件的字符串,我喜欢最少10个长度的字符串(-n 10)来过滤掉一些无用的信息(noise)。

结果如下:

可以看到好像有个hash值,为了不泄露CTF题的答案,我已经把hash值改了。

总结

好了,你已经找到运行的进程的PID,dump出了那个进程的内存内容,然后用gdb,strings命令找出了有用的数据。

以上翻译自:

https://colin.guru/index.php?title=Dumping_Ram_From_Running_Linux_Processes

Let’s get your hands dirty

Down to business

于是我也想试一下啊,然而我想找一个执行命令之后不退出的进程还蛮难的,最终我想到了apache,然而必须要有客户端与apache建立TCP长连接,如果是那种5xx的错误,比如这个,

就会发现TCP连接建立之后马上又断开了。

于是只能弄一个TCP长连接吧。返回200的那种应该可以。

结果发现还是不行。

于是通过htop漫无目的地找吧,于是还是找apache的主进程吧。

通过htop发信apache的主进程的PID为6900,

于是

(注意:要以root的身份启动,否则可能没有权限。)

然后gdb就开始调试6900进程了,一顿输出啊,几秒之后到达gdb的命令行。

然后dump出heap中的内容。

然后在/root目录找到了那两个dump出来的文件,

从任意一个dump中找出10个字符以上的字符串吧。

————————————————

原文链接: https://blog.csdn.net/caiqiiqi/article/details/72807952


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/sjk/9255070.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-26
下一篇 2023-04-26

发表评论

登录后才能评论

评论列表(0条)

保存