我需要在 Linux 下运行专有的 C++ 应用程序,并且需要了解它是否包含广告功能之外的任何功能。
有没有办法列出应用程序进行的所有 API 调用(假设它不使用 Linux 系统调用而仅使用标准 stdc++ 函数)?
一个相似的问题大约十年前就被问到了,答案根本令我不满意。我需要一些完全自动化的东西。
答案1
TL;DR:您可以使用 .hook 跨越共享对象边界的常规函数调用bpftrace
。然而,特别是对于我们所认为的 C++ 标准库,这只是实际 C++“标准库”功能的一小部分。但是,即使你可以跟踪所有这些函数调用,这不会给您任何保证。
没有通用的方法可以知道哪些函数被调用:最终,您无法知道标准库的哪一部分被静态链接到程序中;根据设计,其中大部分甚至是内联的!在 C++ 中,大量标准功能位于 C++ 模板中,因此是程序编译单元的一部分,而不是 libstdc++。更糟糕的是,即使只使用绝对来自共享库的功能,“函数调用”也根本不是什么“特殊”的东西;它只是一个函数。它只是设置您需要传递参数并跳转到地址的寄存器。对于共享对象,该地址是通常在启动时使用标准动态链接器解决,但绝对不能保证这是唯一发生的事情。特别是如果程序在运行时加载库(例如,任何执行插件的库,或脚本语言,或......),它并不像仅列出要导入的函数表那么简单。
您可以跟踪您的用户层程序并为 C++ 标准库中的每个函数插入一个钩子,并记录下来。bpftrace
可能是这里选择的工具。安装 bpftrace,并查看其示例工具,通常位于 /usr/share/bpftrace/tools 中,尤其是bashreadline.bt
:
#!/usr/bin/bpftrace
/*
* bashreadline Print entered bash commands from all running shells.
* For Linux, uses bpftrace and eBPF.
*
* This works by tracing the readline() function using a uretprobe (uprobes).
*
* USAGE: bashreadline.bt
*
* This is a bpftrace version of the bcc tool of the same name.
*
* Copyright 2018 Netflix, Inc.
* Licensed under the Apache License, Version 2.0 (the "License")
*
* 06-Sep-2018 Brendan Gregg Created this.
*/
BEGIN
{
printf("Tracing bash commands... Hit Ctrl-C to end.\n");
printf("%-9s %-6s %s\n", "TIME", "PID", "COMMAND");
}
uretprobe:/bin/bash:readline
{
time("%H:%M:%S ");
printf("%-6d %s\n", pid, str(retval));
}
编写一个小的 awk、Python、PERL 或 PL1 程序,为uretprobe:executable name:function name
(objdump -T /lib64/libstdc++.so
或您认为该程序可能使用的任何库;您可以计算那一出通过strace
,寻找open
电话)。这一切都非常适合脚本化!
我需要在 Linux 下运行专有的 C++ 应用程序,并且需要了解它是否包含广告功能之外的任何功能。
是的,这不会给你任何保证。最好的情况是,您可以看到哪些地址被调用。程序是否准备了一个ROP蹦床来让外部库在正确的情况下为所欲为,是无法做到的。通常,您只能观察程序在正常运行期间的行为。但除非你读过全部在其反汇编的过程中,您无法判断它在 13 号周五运行时、或者 UID=1234 时、或者 CPUID 以 7 结尾时,是否会做一些不同的事情,或者……并且:任何外部库中存在您不需要的任何不需要的功能如果想要程序调用,程序员可以只包含在程序本身中(通过复制功能,或仅通过静态链接)。
这就是为什么操作系统和 UNIXoid 特别是跨操作系统/用户域边界分割特权:无法保证任何给定程序的行为,但 Linux 可以保证(以令人满意的确定性)不允许的程序访问文件无法访问它;而允许访问是程序本身不可能实现的。