有没有办法使用特定的 C 函数/符号作为 nm 的输出

Posted

技术标签:

【中文标题】有没有办法使用特定的 C 函数/符号作为 nm 的输出【英文标题】:Is there a way to use a particular C function/symbol as output by nm 【发布时间】:2021-06-07 08:37:16 【问题描述】:

我正在尝试分析已编译的文件以用于网络安全学习,并希望使用特定功能。

这是nm --defined-only ./compiled_file的输出:

0000000000200d98 d _DYNAMIC
0000000000200f88 d _GLOBAL_OFFSET_TABLE_
0000000000000ba0 R _IO_stdin_used
0000000000000d64 r __FRAME_END__
0000000000000bfc r __GNU_EH_FRAME_HDR
0000000000201010 D __TMC_END__
0000000000201010 B __bss_start
0000000000201000 D __data_start
00000000000007d0 t __do_global_dtors_aux
0000000000200d90 t __do_global_dtors_aux_fini_array_entry
0000000000201008 D __dso_handle
0000000000200d88 t __frame_dummy_init_array_entry
0000000000200d90 t __init_array_end
0000000000200d88 t __init_array_start
0000000000000b90 T __libc_csu_fini
0000000000000b20 T __libc_csu_init
0000000000201010 D _edata
0000000000201018 B _end
0000000000000b94 T _fini
0000000000000660 T _init
0000000000000710 T _start
0000000000201010 b completed.7696
0000000000201000 W data_start
0000000000000740 t deregister_tm_clones
0000000000000810 t frame_dummy
0000000000000a92 T main
000000000000081a T function_I_would_like_to_use                 \\ << this one
0000000000000780 t register_tm_clones

我主要使用 Python(我对 C/C++ 知之甚少,只是基础知识),所以,自然地,我一直试图在 Python 中使用 ctypes 库来处理这个文件,用文件,但据我所知,上面的函数名称都没有出现在对象或其属性的 dir() 中。

我从类似这样的东西开始:https://book.pythontips.com/en/latest/python_c_extension.html#ctypes,然后在dir()/__dict__ 的兔子洞里越走越深,试图找到我认可的东西,但没有运气。

如您所见,我正在尝试在没有任何机器代码知识的情况下对这个 ELF 进行逆向工程,但希望我能在此过程中学到一些东西哈哈!出于练习的目的,我也宁愿在没有外部(第三方)库的情况下执行此操作。

file ./compiled_file 的输出是:

./compiled_file: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=cf62f3afa6f99f98a863d44932d2e
0f9f8594e71, not stripped

所以,我的主要问题是,如上所述,有没有办法在 Python 或其他方式中调用 nmobjdump 等列出的“已定义”函数之一?我读到 BuildID[sha1] 可用于调试。出于我的目的,我是否需要这个?

我希望这个问题不要太宽泛。本质上,我主要是在寻找“是”或“否”,也许在正确的方向上稍微点头,至于​​我是否可以使用上面的信息调用该函数!

编辑:

感谢第一个非常快速的回答和评论,我一直在用 C 语言处理 dlopen/dlsym。脚本如下(改编自 here):

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

int main(int argc, char** argv) 
    void *handle;
    void (*func_in_question)(const char*);
    handle = dlopen("./compiled_file", RTLD_LAZY);
    if (!handle) 
        /* fail to load the library */
        fprintf(stderr, "Error: %s\n", dlerror());
        return EXIT_FAILURE;
    
    *(void**)(&func_in_question) = dlsym(handle, "function_I_would_like_to_use");
    if (!func_in_question) 
        /* no such symbol */
        fprintf(stderr, "Error: %s\n", dlerror());
        dlclose(handle);
        return EXIT_FAILURE;
    
    func_in_question(argv[1]);
    dlclose(handle);
    return EXIT_SUCCESS;

似乎按预期工作,除了它返回:

Error: ./compiled_file: undefined symbol: function_I_would_like_to_use

(其实也是同样的错误,导致我问这个问题¯\_(ツ)_/¯)

然而,原来的问题已经得到解答。

【问题讨论】:

您有一个共享对象并想从中调用一个函数。在 C 语言中,您将使用 dlopen。相当于python的可能是这样的:docs.python.org/3/library/ctypes.html 在 Python 和 C 中(使用dlopen())符号返回为未定义。有什么理由会发生这种情况吗?我将编辑问题以包含 C 脚本。 符号是T,所以它应该在那里并且可以访问。不知道出了什么问题。您的 C 代码看起来不可编译(func_print_name?),但这可能只是一个错字。 您好,谢谢,是的,最小化时的拼写错误,现在更正,实际代码编译/编译得很好。奇怪,你认为值得提出另一个更具体的问题吗? 不确定是否有人能够在不访问该文件的情况下提出任何有用的建议。可能到目前为止,这个问题还没有足够的信息来回答。如果有任何可疑之处,我会取出所有模糊相关的工具(strace、ldd、objdump...)并尝试收集更多信息。 【参考方案1】:

是的,这是可能的。毕竟,在共享库中导出符号的目的是能够使用它们。在 C 中,您可以通过将库链接到应用程序(对于 python 来说不是真正的选项)或运行时加载库并找到所需的符号(在 linux 上:dlopen,dlsym)来做到这一点。手册页示例显示了如何在 C 中执行此操作。

【讨论】:

谢谢,这很有帮助,我一直在用 c 语言处理 dlopen(),但遇到了与 Python 相同的问题。请参阅对原始问题的评论。

以上是关于有没有办法使用特定的 C 函数/符号作为 nm 的输出的主要内容,如果未能解决你的问题,请参考以下文章

如何获取目标文件中类成员的符号?

从 nm 命令中隐藏可执行符号

nm命令

nm命令中符号类型详解

Linux的nm查看动态和静态库中的符号

Linux的nm命令查看动态库和静态库中的符号