Link 带有 c 程序的 ELF 二进制文件
Link an ELF binary with a c program
如果只能访问独立的 ELF 程序,我希望能够从我自己的程序中调用程序中的函数。
假设下面的代码是 main.c
#include <stdio.h>
extern int mystery(int a,int b);
int main() {
int a = 0;
int b = 1;
printf("mystery(a,b) = %d\n",mystery(a,b));
return 0;
}
函数 mystery
存在于某个 elf 文件 not_my_program
中。
我想做的是
gcc main.c not_my_program
然而,这给了我一个未定义的引用错误 mystery
。我一直在寻找方法
在论坛上发现无法将此 elf 文件转换为共享对象文件。我还研究过使用
将 main.c
编译成可重定位的目标文件
gcc -c main.c
然后使用 ld
到 link 小精灵 main.o
但我不知道该怎么做。 elf 是 32 位的,但我省略了 -m32
标志。如果 ld
的标志不同,请告诉我。非常感谢任何帮助。
编辑:
readelf -h not_my_program
的输出
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x10e0
Start of program headers: 52 (bytes into file)
Start of section headers: 15116 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 11
Size of section headers: 40 (bytes)
Number of section headers: 30
Section header string table index: 29
Given only access to a standalone ELF program I want to be able to call a function within the program from my own program
听起来你有一个 XY problem。
虽然你想要的在技术上是可行的,但这样做的难度大约是你目前尝试过的难度的 1000 倍。如果您不准备花一两个月的时间来完成这项工作,您应该寻找其他解决方案。
实际上你必须编写一个自定义的 ELF 加载器来将 not_my_program
加载到内存中并对其进行初始化,然后在其中调用 mystery
而不是 main
。
另请注意,mystery
可能依赖于全局数据,并且该数据可能在 main
中初始化,因此无法保证 mystery
在 main
.
之前调用时完全可以工作
P.S。从调试器调用 mystery
就足够了吗?这可以在 30 秒内完成。
这种 hacky 方法适用于一个非常简单的案例。
[ aquila ~ ] $ cat 1.c
int func (int a) { return a * (a-1) ; }
int main(int argc) { return func (argc) ; }
[ aquila ~ ] $ cc 1.c
[ aquila ~ ] $ ./a.out ; echo $?
0
[ aquila ~ ] $ readelf -s a.out | grep func
43: 0000000000400487 19 FUNC GLOBAL DEFAULT 11 func
[ aquila ~ ] $ cat 2.c
#include <stdlib.h>
static __attribute__((constructor)) void main() {
int (*func)() = (int (*)())0x0000000000400487;
exit(func(3));
}
[ aquila ~ ] $ cc -fPIC -shared 2.c -o a.so
[ aquila ~ ] $ LD_PRELOAD=./a.so ./a.out ; echo $?
6
将2.c中的调用者做成带出口的构造函数,不调用主程序的main()
,试图限制调用者以外的代码执行, func()
本身。 return 值为 6 而不是 0 表明调用有效并且主程序的 main()
没有被调用。
如果只能访问独立的 ELF 程序,我希望能够从我自己的程序中调用程序中的函数。
假设下面的代码是 main.c
#include <stdio.h>
extern int mystery(int a,int b);
int main() {
int a = 0;
int b = 1;
printf("mystery(a,b) = %d\n",mystery(a,b));
return 0;
}
函数 mystery
存在于某个 elf 文件 not_my_program
中。
我想做的是
gcc main.c not_my_program
然而,这给了我一个未定义的引用错误 mystery
。我一直在寻找方法
在论坛上发现无法将此 elf 文件转换为共享对象文件。我还研究过使用
main.c
编译成可重定位的目标文件
gcc -c main.c
然后使用 ld
到 link 小精灵 main.o
但我不知道该怎么做。 elf 是 32 位的,但我省略了 -m32
标志。如果 ld
的标志不同,请告诉我。非常感谢任何帮助。
编辑:
readelf -h not_my_program
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x10e0
Start of program headers: 52 (bytes into file)
Start of section headers: 15116 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 11
Size of section headers: 40 (bytes)
Number of section headers: 30
Section header string table index: 29
Given only access to a standalone ELF program I want to be able to call a function within the program from my own program
听起来你有一个 XY problem。
虽然你想要的在技术上是可行的,但这样做的难度大约是你目前尝试过的难度的 1000 倍。如果您不准备花一两个月的时间来完成这项工作,您应该寻找其他解决方案。
实际上你必须编写一个自定义的 ELF 加载器来将 not_my_program
加载到内存中并对其进行初始化,然后在其中调用 mystery
而不是 main
。
另请注意,mystery
可能依赖于全局数据,并且该数据可能在 main
中初始化,因此无法保证 mystery
在 main
.
P.S。从调试器调用 mystery
就足够了吗?这可以在 30 秒内完成。
这种 hacky 方法适用于一个非常简单的案例。
[ aquila ~ ] $ cat 1.c
int func (int a) { return a * (a-1) ; }
int main(int argc) { return func (argc) ; }
[ aquila ~ ] $ cc 1.c
[ aquila ~ ] $ ./a.out ; echo $?
0
[ aquila ~ ] $ readelf -s a.out | grep func
43: 0000000000400487 19 FUNC GLOBAL DEFAULT 11 func
[ aquila ~ ] $ cat 2.c
#include <stdlib.h>
static __attribute__((constructor)) void main() {
int (*func)() = (int (*)())0x0000000000400487;
exit(func(3));
}
[ aquila ~ ] $ cc -fPIC -shared 2.c -o a.so
[ aquila ~ ] $ LD_PRELOAD=./a.so ./a.out ; echo $?
6
将2.c中的调用者做成带出口的构造函数,不调用主程序的main()
,试图限制调用者以外的代码执行, func()
本身。 return 值为 6 而不是 0 表明调用有效并且主程序的 main()
没有被调用。