如何调试运行时库插入的进程?

问题描述 投票:0回答:2

[我正在研究在Ubuntu 18.04中使用C进行库插入的过程,并且我正在测试包装strlen的两个简单代码:“ mystrlen.c”,“ mystrlenTest.c”。

这是我编写的代码:mystrlen.c

#ifdef RUNTIME
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>

/* strlen wrapper function */
size_t strlen(const char *str) {
    size_t (*strlenp)(const char *) = NULL;
    printf("%s\n", *str);

    strlenp = dlsym(RTLD_NEXT, "strlen");   // Get address of libc strlen
    printf("length: %ld\n", strlenp(str));

    return strlenp(str);
}
#endif

和mystrlenTest.c:

#include <stdio.h>
#include <string.h>

int main(void) {
    char testString[] = "Hello World!";
    printf("length of the testString: %ld\n", strlen(testString));

    return 0;
}

我试图在运行时使用以下命令进行注入:

$ gcc -DRUNTIME -shared -fpic -g -o mystrlen.so mystrlen.c -ldl
$ gcc -g -o mystrlenTest mystrlenTest.c
$ LD_PRELOAD=./mystrlen.so ./mystrlenTest

这就是我得到的全部:Segmentation fault (core dumped)因此,我尝试使用dmesg命令找出发生了什么,结果如下所示:

[842291.658267] mystrlenTest[51446]: segfault at 48 ip 00007f7b918e35a1 sp 00007ffdd7158c88 error 4 in libc-2.27.so[7f7b91755000+1e7000]
[842291.658272] Code: 2e 0f 1f 84 00 00 00 00 00 31 c0 c5 f8 77 c3 66 2e 0f 1f 84 00 00 00 00 00 89 f9 48 89 fa c5 f9 ef c0 83 e1 3f 83 f9 20 77 1f <c5> fd 74 0f c5 fd d7 c1 85 c0 0f 85 df 00 00 00 48 83 c7 20 83 e1

我想问的是,如何使用gdb进行调试?还是有其他调试方法?我知道如何使用gdb调试单个程序,但是调试运行时库插入的进程遇到了困难。如果我可以找到00007f7b918e35a1中的内容,那将是很大的帮助。

c debugging gdb shared-libraries library-interposition
2个回答
0
投票

给出此代码:

size_t strlen(const char *str) {
    size_t (*strlenp)(const char *) = NULL;
    printf("%s\n", *str);

    strlenp = dlsym(RTLD_NEXT, "strlen");   // Get address of libc strlen
    printf("length: %ld\n", strlenp(str));

    return strlenp(str);
}

如果printf()在内部使用strlen(),则将获得无限递归,并且几乎可以肯定会发生分段违规。

注意,在GLIBC中,libc.so在Linux上使用,printf() is implemented通过printf()


0
投票

调用gdb时,您可以传递要设置的环境变量,例如:

vfprintf(), which does indeed make use of strlen()

现在您可以像往常一样在gdb中使用get backtrace。

在您的特定情况下,可能的问题是vfprintf()本身调用了Andrew Henle指出的strlen(),从而导致了无限递归。

[插入时,您需要注意从插入函数中调用的内容,并始终问自己,从插入函数内部进行的任何调用是否都可能导致对同一插入函数或任何其他插入函数的回调,并且需要这样做处理此类情况的步骤。例如,许多标准函数可能会通过gdb --args env LD_PRELOAD=./mystrlen.so ./mystrlenTest 系列函数在内部分配内存,如果您插入printf和朋友,可能会导致意外问题。

© www.soinside.com 2019 - 2024. All rights reserved.