[转载]用dumper打开运行程序的core dump功能
来源:互联网 发布:交通大学网络教育好吗 编辑:程序博客网 时间:2024/04/28 22:37
用dumper打开运行程序的core dump功能
应用程序在异常发生的时候产生的内存转储文件,即core文件,对于应用程序开发人员调试有随机或者是很难重现的bug的应用程序有重要的意义。无奈,当 前很多的Linux发行版为了防止core文件占用过多的磁盘空间,或者说是污染系统,core dump功能默认都是关闭的,你可以通过ulimit -c查看你正在使用的发行版的情况:
xiaosuo@gentux dumper $ ulimit -c
0
诚然,这些core文件对于普 通用户来说,确实意义不大,默认关闭core dump功能也是无可厚非的。
如果应用程序因为某个不可恢复的bug最终退出,那么我们也 不要奢求它能给我们留下什么bug的蛛丝马迹,除非你打开core dump功能。实际上,有的时候,bug也许并不导致程序的异常退出,而是进入了某个微妙的状态(比如死锁),表现出来的情况就是行为的异常,如果此时应 用程序运行的操作系统上有gdb,或者可以安装gdb,那么你很幸运,你能够进行在线的调试;否则,面对这样一个可能千载难逢的bug重现现场,也许就只 有望洋兴叹的份了!的确,有的时候strace就能帮我们了解一些情况,但是信息仍旧比较有限:只能显示和系统调用有关的信息。也许,你已经懊悔或者是抱 怨为什么不默认打开core dump的功能,但是牢骚除了把气氛变得更糟外,并不能实际解决什么问题,倒不如想想如何补救。
也许我们可 以向正处于异常的进程植入一段打开core dump功能的代码,然后通知它去执行植入的代码,最后我们就可以通过向他发送SIGSEGV信号来产生我们所需要的core文件了。
搜 罗了一些资料,并试验了多次后,终于完成了这个叫做dumper的小程序,它能够打开运行着的进程的core dump功能;如果用户需要,它还可以在等待3s后,向异常程序发送SIGSEGV,令其产生core文件。
dumper.c:
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#ifndef __WALL
#define __WALL 0
#endif
void enable_core_dump(void);
int inject(pid_t pid, const char *shellcode, int size)
{
long ptr;
int i;
struct user_regs_struct data;
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) {
perror("Attach");
return -1;
}
/* wait for the stopping of the target process */
if (waitpid(pid, NULL, __WALL) == -1) {
perror("waitpid");
return -1;
}
if (ptrace(PTRACE_GETREGS, pid, NULL, &data) == -1) {
perror("Getregs");
return -1;
}
/* save the return address, since we use jmp to call the
* function instead of call instruction */
data.esp -= sizeof(long);
if (ptrace(PTRACE_POKETEXT, pid, data.esp, data.eip) == -1) {
perror("Poketext");
return -1;
}
/* transfer the shellcode to the target process */
if (size < 0)
size = strlen(shellcode);
ptr = data.eip = data.esp - size - 1024;
for (i = 0; i < size; i += sizeof(long)) {
if (ptrace(PTRACE_POKETEXT, pid, ptr, *((long*)(shellcode + i))) == -1) {
perror("Poktext");
return -1;
}
ptr += sizeof(long);
}
/* set the instruction counter */
data.eip += 2; /* skip the two instructions: nop */
if (ptrace(PTRACE_SETREGS, pid, NULL, &data) == -1) {
perror("Setregs");
return -1;
}
/* detach the target process and let it run... */
if (ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1) {
perror("Detach");
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
pid_t pid;
if (argc < 2) {
printf("Usage: %s pid [-k]/n", argv[0]);
return -1;
}
pid = atoi(argv[1]);
printf("Start injecting(%d)...", pid);
if (inject(pid, (const char *)enable_core_dump, 0x2c) != 0) {
printf("Failed/n");
return -1;
}
printf("OK/n");
/* sleep for a moment. When waken up, the core dump of the target
* process should be enabled. */
if (argc > 2 && strcmp(argv[2], "-k") == 0) {
sleep(3);
kill(pid, SIGSEGV);
}
return 0;
}
enable_core_dump_i386.S
/*
* call the function: setrlimit(RLIMIT_CORE, {-1, -1});
* after calling that, the process is allowed to save
* the core dump file if exception, such as SIGSEGV, occurs.
*/
/* XXX:
* Something important to do before the exploitation is to put two nops bytes
* before the shellcode. Reason is simple : if ptrace has interrupted a syscall
* being executed, the kernel will subtract two bytes from eip after the
* PTRACE_DETACH to restart the syscall.
*/
.globl enable_core_dump
enable_core_dump:
nop
nop
pusha
push %ebp
mov %esp, %ebp
sub $8, %esp
movl $-1, -8(%ebp)
movl $-1, -4(%ebp)
lea -8(%ebp), %eax
mov %eax, %ecx
xor %ebx, %ebx
mov $4, %bl
xor %eax, %eax
mov $75, %al
int $0x80
leave
popa
ret
nop /* padding byte */
nop
nop
编译方法如下:
xiaosuo@gentux dumper $ gcc dumper.c enable_core_dump_i386.S -o dumper
使 用起来比较简单,只要给出要打开core dump功能的进程号即可,如果还跟有-k参数,它还负责给目标进程发送SIGSEGV令其退出,并产生core dump文件。比如,需要打开进程号是14091的进程的core dump功能:
xiaosuo@gentux dumper $ ./dumper 14091
Start injecting(14091)...OK
如果想立即使其退出并生成core 文件:
xiaosuo@gentux dumper $ ./dumper 14091 -k
Start injecting(14091)...OK
14091 进程将退出,并产生core文件:
段 错误 (core dumped)
xiaosuo@gentux dumper $ ls core.14091
core.14091
代 码上的注释已经比较完备了,这里就不再赘述,如果哪里不明白,可参考文后的参考资料。
注意:以上程序只适用于32bit的x86系统,不过其他平台上的实现亦能由此原 理炮制出来,请有需求者自己。
- [转载]用dumper打开运行程序的core dump功能
- [转载]用dumper打开运行程序的core dump功能
- 使用core dump查看程序运行异常
- Linux系统打开core dump的配置,以及用最短程序抛出core
- Linux系统打开core dump的配置,以及用最短程序抛出core
- (转载)core dump的使用
- 【转载】System Dump与Core Dump的区别
- Linux环境中以daemon方式运行的程序生成core dump
- Linux环境中以daemon方式运行的程序生成core dump
- Linux环境中以daemon方式运行的程序生成core dump
- 我的程序又core dump了
- 学会用core dump调试程序错误
- 学会用core dump调试程序错误
- 学会用core dump调试程序错误
- 学会用core dump调试程序错误
- 学会用core dump调试程序错误
- 学会用core dump调试程序错误
- 学会用core dump调试程序错误
- 内存字节对齐总结
- 使用ifstream和getline读取文件内容[转自c++博客]
- 关于读博士的一些感想
- urlopen?能抓百度的查询网页却抓不了google的?
- 配置Flash Player mms.cfg 不存在的解决办法
- [转载]用dumper打开运行程序的core dump功能
- 单例模式(自己写的,没有技术含量,跟我一样的菜鸟看吧)
- span宽度解决方法
- 用C操作MySQL
- (水水水)zoj 1622 switch
- [转载]ARM MMU工作原理剖析
- Memcached在.NET中的应用(转载)
- 开始写博客
- Linux与Windows共享文件