我想看看 XZ 后门的最小示例。
据我了解:
所以像这样(还不起作用!)
main.c(充当 sshd)
#include <stdio.h>
void critical_function() {
printf("critical_function uncompromised.\n");
}
int main() {
critical_function();
return 0;
}
后门.c
#include <stdio.h>
void compromised_critical_function() {
printf("critical_function COMPROMISED.\n");
}
void *resolve_critical_function() {
return compromised_critical_function;
}
__attribute__((visibility("default")))
void critical_function() __attribute__((ifunc("resolve_critical_function")));
gcc-13 -o prog main.c
gcc-13 -shared -fPIC -o libbackdoor.so backdoor.c
LD_PRELOAD=./libbackdoor.so ./prog
这个打印
critical_function uncompromised.
但我希望它打印 critical_function COMPROMISED.
我认为这不适用于静态组合到二进制文件中的符号。这些符号在二进制文件的文本部分中定义并静态解析:
nm prog | grep critical_function
T critical_function
要使动态链接编辑器 (ld.so) 在运行时进行符号查找,您需要保留符号未定义(
U
命名法中的 nm
)。您可以通过将 critical_function
提取到其自己的翻译单元中并将其编译为链接到您的二进制文件的共享库来完成此操作:
main.c
:void critical_function();
int main(void) {
critical_function();
}
func.c
:#include <stdio.h>
void critical_function() {
printf("critical_function uncompromised.\n");
}
backdoor.c
:#include <stdio.h>
void compromised_critical_function() {
printf("critical_function COMPROMISED.\n");
}
void *resolve_critical_function() {
return compromised_critical_function;
}
__attribute__((visibility("default")))
void critical_function() __attribute__((ifunc("resolve_critical_function")));
通过(
Makefile
)编译:
CFLAGS += -fPIC
all: prog libbackdoor.so
prog: main.o libfunc.so
$(CC) -o $@ $+ -ldl
lib%.so: %.o
$(CC) -shared -o $@ $+
并通过以下方式执行:
LD_PRELOAD=./libbackdoor.so LD_LIBRARY_PATH=$PWD ./prog
critical_function COMPROMISED.
为了完整起见,这里不需要使用 IFUNC 机制来实现这一点; IFUNC 对于在运行时动态计算函数地址很有用,但我们可以无条件覆盖它:
backdoor.c
(替代)#include <stdio.h>
void critical_function() {
printf("critical_function COMPROMISED.\n");
}