我正在寻找一种枚举所有ELF节及其当前二进制文件的地址以及当前进程可能已加载的所有共享对象的好方法。
我知道dl_iterate_phdr()的存在,这使我可以轻松使用ELF 段列表,但是我正在寻找ELF 节,所以这不是我的正确选择。
我不关心可移植性,只要它可在带有ELF的Linux上运行,我就很高兴!
任何提示表示赞赏!
我遇到了错误的符号解析问题.我的主程序用dlopen加载一个带dlopen的共享库和一个符号.程序和库都是用C语言库代码编写的
int a(int b)
{
return b+1;
}
int c(int d)
{
return a(d)+1;
}
Run Code Online (Sandbox Code Playgroud)
为了使它在64位机器上运行,-fPIC在编译时传递给gcc.
该计划是:
#include <dlfcn.h>
#include <stdio.h>
int (*a)(int b);
int (*c)(int d);
int main()
{
void* lib=dlopen("./libtest.so",RTLD_LAZY);
a=dlsym(lib,"a");
c=dlsym(lib,"c");
int d = c(6);
int b = a(5);
printf("b is %d d is %d\n",b,d);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果程序未使用-fPIC编译,则一切运行正常,但在使用-fPIC编译程序时,它会因分段错误而崩溃.调查导致发现崩溃是由于符号a的错误解决.无论是从库还是主程序(后者是通过在主程序中注释掉调用c()的行获得的),都会在调用a时发生崩溃.
调用c()本身时没有问题,可能是因为c()不是由库本身在内部调用,而a()既是库内部使用的函数,也是库的API函数.
编译程序时,一个简单的解决方法是不使用-fPIC.但这并不总是可行的,例如当主程序的代码必须在共享库本身时.另一种解决方法是将指针重命名为其他功能.但我找不到任何真正的解决方案.
用RTLD_NOW替换RTLD_LAZY没有帮助.
我在运行应用程序时收到消息
java: symbol lookup error: /usr/java/jdk1.7.0_09/jre/lib/amd64/libJdbcOdbc.so: undefined symbol: SQLAllocEnv
Run Code Online (Sandbox Code Playgroud)
该应用程序的目的是使用Pentaho水壶jar文件将数据从一个服务器迁移到另一个服务器.我在目标服务器上使用Jdbc-Odbc连接.我最近从Oracles网站安装了java(jre和jdk).当我设置
export LD_DEBUG=all
Run Code Online (Sandbox Code Playgroud)
我看到以下回复
binding file /usr/java/jdk1.7.0_09/jre/lib/amd64/libJdbcOdbc.so [0] to /lib64/libc.so.6 [0]: normal symbol `__cxa_finalize' [GLIBC_2.2.5]
5193:
5193: calling init: /usr/java/jdk1.7.0_09/jre/lib/amd64/libJdbcOdbc.so
5193:
5193: opening file=/usr/java/jdk1.7.0_09/jre/lib/amd64/libJdbcOdbc.so [0]; direct_opencount=1
5193:
5193: symbol=JNI_OnLoad; lookup in file=/usr/java/jdk1.7.0_09/jre/lib/amd64/libJdbcOdbc.so [0]
5193: symbol=JNI_OnLoad; lookup in file=/usr/java/jdk1.7.0_09/jre/lib/amd64/libjava.so [0]
5193: binding file /usr/java/jdk1.7.0_09/jre/lib/amd64/libJdbcOdbc.so [0] to /usr/java/jdk1.7.0_09/jre/lib/amd64/libjava.so [0]: normal symbol `JNI_OnLoad'
5193: symbol=Java_sun_jdbc_odbc_JdbcOdbc_allocEnv; lookup in file=/usr/java/jdk1.7.0_09/jre/lib/amd64/libjava.so [0]
5193: symbol=Java_sun_jdbc_odbc_JdbcOdbc_allocEnv; lookup in file=/usr/java/jdk1.7.0_09/jre/lib/amd64/server/libjvm.so [0]
5193: symbol=Java_sun_jdbc_odbc_JdbcOdbc_allocEnv; lookup in file=/usr/java/jdk1.7.0_09/jre/lib/amd64/libverify.so [0]
5193: symbol=Java_sun_jdbc_odbc_JdbcOdbc_allocEnv; lookup …Run Code Online (Sandbox Code Playgroud) 我需要在已编译的ELF文件中更改几个变量。为了清楚地说明这一点,我将使用一个简单的C结构作为示例。
单个源文件被编译并从MyFile.c链接(@ 0x1000)到MyFile.elf:
typedef struct {
uint32_t SerialNumber; /* Increments for every time it's programmed */
uint32_t PartNumber; /* Always the same */
char ProdDateTime[32]; /* "YYYY-MM-DD HH:MM:SS" date/time when programmed */
uint32_t CalcCrc32; /* Checksum of the above data */
} MyData_T;
const MyData_T MyData = {
/* SerialNumber */ 0x11111111,
/* PartNumber */ 0x12345678,
/* ProdDateTime[32] */ "2013-11-10 12:49:30",
/* CalcCrc32 */ 0xC0CAC01A
};
Run Code Online (Sandbox Code Playgroud)
现在,我需要一个“控制台工具”(无需编译):
我还没有找到可以完成第一个(1)任务的工具(objcopy等?)。似乎这应该是一个相当普遍的情况?我现在已经编写了自己的工具,但是希望使用开源工具或类似工具。
任何建议/想法/评论/批评都非常感激:D谢谢!!
我正在Linux OS上编写C和C++代码,我正在使用GCC.完成我的代码后,我想生成一个ELF文件.我只能生成"a.out"文件而我不需要它.我怎样才能获得ELF文件?ELF文件出现的原因是什么?或者是否可以使用此程序生成此文件?
我有一个使用mmap系统调用的程序:
map_start = mmap(0, fd_stat.st_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0)
Run Code Online (Sandbox Code Playgroud)
和一个标题变量:
header = (Elf32_Ehdr *) map_start;
Run Code Online (Sandbox Code Playgroud)
如何访问符号表并使用标头变量打印其整个内容?
在ELF二进制文件中,如何更改可加载段的对齐方式?在下面的示例中(请参见右上角),我想将0x200000减少为0x40960。
LOAD 0x000000 0x000000400000 0x0000000000400000 0x000704 0x000704 R E **0x200000**
LOAD 0x000e10 0x000000600e10 0x0000000000600e10 0x000230 0x000238 RW **0x200000**
Run Code Online (Sandbox Code Playgroud)
任何编译专家(GCC或clang)都可以为我提供解决方案吗?
好吧,所以在问我的问题之前,我想介绍一些技术细节,我想确保我是正确的:
位置无关可执行文件 - PIE,是一个无论加载到哪个内存地址都能执行的代码,对吗?
ASLR ------地址空间布局随机化,几乎说明为了保持地址静态,我们会以某种方式随机化它们,
我已经在Linux和基于Unix的系统中特别阅读了实现ASLR是可能的,无论我们的代码是否是PIE,如果它是PIE,所有跳转,调用和偏移是相对的,因此我们没有问题如果不是,请编写一些如何无论代码是可执行的还是共享对象,都会被修改并编辑地址....
对......现在这让我提出几个问题
如果ASLR可以在不是PIE的代码中实现并且是可执行的并且不共享/可重定位对象(我知道重定位如何在可重定位的对象中工作!!!!)它是如何完成的?,elf格式应该没有任何部分说明代码部分中的函数是什么,所以内核加载器可以修改它,对吧?ASLR应该是内核功能,因此实际上可以是例如包含例如这些指令的可执行文件
伪代码:
inc_eax:
add eax, 5
ret
main:
mov eax, 5
mov ebx, 6
call ABSOLUTE_ADDRES{inc_eax}
Run Code Online (Sandbox Code Playgroud)
如果内核可执行加载器没有存储在elf文件中的某个可重定位表中并且不是相对的,以便将可执行文件加载到某个随机地址,那么内核可执行加载器如何知道如何更改地址?
假设我错了,为了实现ASLR,你必须有一个PIE可执行文件,所有段都是相对的,如何编译C++ OOP代码并使其工作,例如,如果我有一个类的实例使用指向其结构中的虚拟表的指针,并且该虚拟表应该保存绝对地址,因此我无法为使用运行时虚拟表的C++程序编译纯PIE,并且不能再使用ASLR. ...我怀疑虚拟表是否包含相对地址,并且对于某些虚拟函数的每次调用都会有不同的虚拟表...
我的最后一个也是最不重要的问题是关于ELF和PIE,是否有一些特殊的方法来检测ELF可执行文件是PIE?我对ELF格式很熟悉所以我怀疑它有一种方法但是我可能错了,无论如何如果没有办法,内核加载器如何知道我们的可执行文件是否是PIE,因此它可以在其上使用ASLR
我已经把这一切搞砸了,如果有人能在这里帮助我,我会很感激,感谢提前
如果,当我运行脚本时,我LD_PRELOAD用来指定要预加载的库,我发现只有当脚本有一个shebang行时才会预加载库.例如,给定此脚本:
# Not a shebang
echo Hello
Run Code Online (Sandbox Code Playgroud)
这个命令:
LD_PRELOAD=/path/to/preload_me.so ./script.sh
Run Code Online (Sandbox Code Playgroud)
该脚本在没有加载库的情况下运行,我可以通过其初始化代码的(非)效果进行监视.
另一方面,如果我添加一个shebang线:
#!/bin/sh
echo Hello
Run Code Online (Sandbox Code Playgroud)
... 当我通过相同的命令运行脚本时,库被加载.似乎确切地指定了哪个解释器; 当然我也可以使用/bin/bash或任何其他sh- 我尝试过的家庭外壳.
为什么有区别,有没有办法确保给定的库在给定的shell简单命令之前预加载,而不管命令是什么?
(改编自另一个问题,其作者拒绝用这些术语表达的问题.)
TL; DR为什么共享库中定义的变量似乎驻留在主程序而不是共享库中定义的段中?
我正在尝试了解ELF文件动态链接。我写了一个虚拟的共享库
// varlib.so
int x = 42;
void set_x() {
x = 16;
}
Run Code Online (Sandbox Code Playgroud)
和使用它的程序
// main.out
#include <stdlib.h>
#include <stdio.h>
extern int x;
void set_x();
int f() {
return x;
}
int main(int argc, char** argv) {
set_x();
printf("%d\n", f());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在查看程序集之前,我假设持有的段x将来自varlib.so(可能是该.data段),main.out并将使用其GOT表(以及用于固定GOT表条目的重定位)进行访问x。但是在检查中我发现
main.out该函数f定义为
0000000000400637 <f>:
400637: 55 push rbp
400638: 48 89 e5 mov rbp,rsp
40063b: 8b 05 f7 09 20 …Run Code Online (Sandbox Code Playgroud) elf ×10
c ×5
gcc ×4
linux ×4
compilation ×2
aslr ×1
assembly ×1
bash ×1
c++ ×1
clang ×1
dlopen ×1
executable ×1
file-format ×1
java ×1
jdbc ×1
ld-preload ×1
linker ×1
mmap ×1
objcopy ×1
process ×1
symbol-table ×1