-
-
[原创]PWN入门-11-制服_dl_resolve_runtime
-
发表于: 2024-9-12 22:37 8592
-
当程序使用动态链接库中的函数时,由于链接器无法确定动态链接函数的地址信息,所以会将动态链接函数的绑定过程拖到运行期再进行操作,这一过程被称作是动态链接。
动态链接分成启动期链接和调用期链接两种,启动期链接指的是动态链接器LD运行时就将全部的动态链接函数地址解析好,调用期链接指的是动态链接函数首次调用时再进行解析,调用期链接的做法也被称作是延迟绑定。
在启动过程中,lazy变量是会决定是否在启动时对动态链接函数的地址进行解析,该变量的数值是根据.dynamic动态链接节中是否存在BIND_NOW标志进行设置的。
当程序不需要延迟绑定时,elf_machine_runtime_setup函数内部根据lazy变量的提示不会做任何的操作,紧接着会直接通过ELF_DYNAMIC_DO_XXX函数解析全部的动态链接函数。
当程序需要延迟绑定时,elf_machine_runtime_setup函数修改.plt节中首表项内的信息为解析函数的信息,使得首次调用时程序可以根据解析函数完成动态链接函数的解析操作,而ELF_DYNAMIC_DO_XXX函数则不会进行任何操作。
下面展示了调用期链接具体使用的解析函数。
从上面可以看到程序会根据0x404000中的地址信息决定调用的函数是什么,当解析函数完成解析工作后,0x404000中的地址一定会被修改为动态链接函数的所在地址,因此我们可以在0x404000地址上设置监测点,查看解析函数的真身是谁。
当监测点发现地址上的数据发生变动后,就会自动中断下来,通过查看调用栈可以知道_dl_runtime_resolve_fxsave负责解析动态链接函数。
_dl_runtime_resolve_fxsave函数的顺利工作,依赖ELF中动态链接节和重定位节信息,下面会先对这些相关的节进行分析。
.dynamic动态链接节是极为重要的,因为它里面存放着程序进行动态链接的全部所需信息,所以程序只需要一个.dynamic节,就可以检索到所有的相关信息。
.dynamic节可以看作是一张表,表中有各种各样的表项,表项信息通过Elf64_Dyn结构体进行描述。
在/usr/include/elf.h头文件中,可以找到Elf64_Dyn结构体的定义,d_tag成员用于标明表项对应的动态链接属性,d_un成员表示属性对应的具体数值。
d_tag的有非常多的种类,下面只列出了部分,完整的列表和解释可以在/usr/include/elf.h头文件中找到。
当动态链接属性是DT_FLAGS或DT_FLAGS_1时,d_val成员的数值会是DF_xxx或DF_1_xxx的中的某一个。
比如前面提到的BIND_NOW标志就是通过DT_FLAGS和DT_FLAGS_1进行描述的。
通过readelf工具的-d选项可以轻松的将动态链接节中的信息解析出来,这是非常方便且利于人类阅读的信息,它这里做了两大操作,一是找到.dynamic节的位置,而是将.dynamic节中的二进制信息解析成人类可读的信息。
接下来会演示如何手动找到.dynamic节的位置。
第一步查看ELF头信息,获得节头表的位置0x3720、节头表中表项大小0x40以及节头表中表项数量0x24。
找到节头表的位置后,可以非常轻松的将.dynamic节找出来(此处是21号表项),并根据节头表中表项的定义,将.dynamic节头的信息解析出来。
查看.dynamic节中内容,可以发现结果和上方readelf工具的-d选项的解析内容一致。
程序使用的函数和全局变量往往被称作是符号,.symtab节中会存储着全部的符号信息,而.dynsym节则会专门存储与动态链接相关的符号信息,.dynsym节与.symtab节共用同一个结构描述信息。
.dynstr节是专门为st_name成员设立的,作为索引值辅助.dynsym节匹配符号名。
GLibC通过.gnu.hash节加快符号的查找过程,关于.gnu.hash节是如何进行工作的问题,这里暂时不会进行解析。
在ELF文件中,重定位节分成.rela.dyn和.rela.plt两类,它们的区别在于重定位时修正地址的位置不同,其中.rela.dyn修正的信息位于.got节,.rela.plt节修正的信息位于.got.plt节。
至于.got节和.got.plt节,它们的区别在于完成重定位工作后,是否会被GNU_RELRO段设置为只读状态。
重定位节的作用可以从下面结构体的定义中略窥一二,其中r_offset成员指示出了需要修改的重定位信息位置,r_info成员则指示出了重定位类型和符号索引值,这里的索引值用于在.dynsym节内检索符号,r_addend成员显示的将加数指了出来(Elf64_Rel中使用隐式加数),r_addend和r_offset共同指明了待修改的重定位信息位置。
在上面我们介绍了与动态链接相关的各种节信息,但是目前我们只是知道它们会辅助动态链接函数调用的顺利进行,但是还并不知道它们之间是如何协同工作的,下面就会对此进行解析。
首次调用动态链接函数时,PLT中首条指令jmp会带我们前往第二条指令push,push会将符号在.rela.plt中的索引值压入栈内,最后一条jmp指令会带我们前往.plt节中的首表项。
.plt节中的首表项中存储着_dl_runtime_resolve_fxsave函数的地址,该函数进行重定位操作的关键函数。
push指令会将当前link_map信息所在地址压入栈内。
0x403ff0中保存的link_map信息地址和0x403ff8中保存的_dl_runtime_resolve_fxsave函数地址位于.got节,并由LD在启动时修改。
_dl_runtime_resolve_fxsave函数的反汇编如下所示,同时下方也写明了对汇编代码的解释。
从汇编代码中可以看到,函数由序言、获取动态链接函数、结语、调用动态链接函数四大部分组成。
首先看到的是序言部分,它的主要作用是分配栈空间。
在之前的PLT中,两个push指令先后向栈上压入了符号索引值以及link_map信息的地址,它们会提供给_dl_fixup函数使用,不将它们交给调用者寄存器传递,是因为调用者寄存器已经被用于放置动态链接函数的形参了。
这里会先将旧的rsp保存到rbx内,以便_dl_fixup函数获取参数。
动态链接函数最多接收六个参数作为形参,它们通过调用者寄存器进行保存,但由于接下来会使用_dl_fixup函数获取动态链接函数,该函数会使用新的形参,动态链接函数也需要在_dl_fixup函数运行后操作,所以这里会先将调用者寄存器中的参数保存到栈上,等到动态链接函数真被调用时再从栈上放出来。
这里还有一个特殊的寄存器rax,它并不在传递形参的寄存器范围之内,但它也是一个特殊的寄存器,会被用于存储返回值,同时也会被用于存储系统调用号。
保存好动态链接函数的参数后,就会从rbx中取出符号索引值以及link_map信息的地址,交给_dl_fixup函数,最后对_dl_fixup函数进行调用。
当函数返回之后,因为rax在后面会被使用,所以它会将返回值交给r11。
函数结语的作用是恢复栈空间和寄存器空间数据。
恢复好栈空间和寄存器数据后,动态链接函数有了正确被调用的基础,最后就是通过r11中保存的动态链接函数地址进行跳转,实现动态链接函数的调用。
从上面分析的反汇编结果中可以看到,_dl_runtime_resolve_fxsave函数的主要操作就是调用_dl_fixup函数,然后根据_dl_fixup函数的返回值进行跳转,那么接下来就让我们将视线转移到_dl_fixup函数的内部。
进入到_dl_fixup函数后,就会开始修正重定位信息。
函数内部首先出现的就是函数序言,其主要作用在于分配栈空间。
其中rbx、r12、r13、r14、r15位于被调用者寄存器范围内,它们的数值放入栈内,寄存器空间留给其他被调用者使用。
rdi中存储的是link_map的地址,这里会在rbx内再保存一份。
完成设置栈空间的操作后,首先会准备参数,其中r8寄存器中存储着.dynsym的地址,不过它是怎么取到的呢?
程序及动态链接库所需的链接信息由link_map结构体进行管理,在该结构体内存在着一个名为l_info的成员,该成员的作用是动态链接信息(根据.dynamic节获取),我们知道.dynamic节是一张表,每个表项都会占据一段空间,l_info中存储的就是表项的内存地址信息。
l_info成员位于偏移0x40处,大小为0x280,此处偏移0x70是为了寻找SYMTAB表项(.dynsym节)。
检索到SYMTAB表项的地址后,然后根据表项的定义,偏移0x8处就是.dynsym节的地址。
参与比较运算的数值分别是0x20和rdi+0x356地址上存储的数据,这里GLibC中使用了一个特别的用法,就是在变量名后添加:和数字,作用是指定变量占用的比特位,其中rdi+0x356对应着link_map中的l_audit_any_plt到l_find_object_processed成员,0x20就是用于判断l_find_object_processed成员的值是否为1。
test指令和je指令是较为常见的比较运算指令,其中的也逻辑并不复杂,test指令在进行完与运行后,会根据运算结果设置eflags标志位寄存器中的ZF标志位(Zero Flag),je指令会根据ZF标志位决定是否跳转(ZF为1时跳转),下面展示了test指令运行前后的eflags寄存器信息。
这里如果判断l_find_object_processed为1,就代表lt_library不需要处理,反之则进行处理,一般情况下都是不需要进行处理的。
rdx存储着link_map结构体中存储的基地址l_addr成员,之前mov (%rdi),%rdx操作将l_addr赋给rdx。
获得.dynsym节的真实地址后,就会再获取.dynstr节的真实地址,r9经过函数序言内的xor %r9d,%r9d后已经被置零,不管l_find_object_processed将是不是修正值交给了r9,程序使用r9进行加法运行产生的结果始终是正确的。
STRTAB表项位于l_info成员的0x68位置,这里取出STRTAB表项后,会将表项中存放的.dynstr节的地址放入rdi内。
获取完.dynstr节后,会接着按照上面的套路获取.rela.plt节信息。
rsi寄存器中存放的是_dl_runtime_resolve_fxsave函数寄过来的符号索引值,符号索引值值会先后通过lea指令扩张24倍。
l_info偏移0xf8处是JMPREL表项,该表项对应着.rela.plt节,偏移0x8可以获取.rela.plt节的地址,因为.rela.plt节也可以被看作是一张表,每个表项通过Elf64_Rela结构体描述,所以想要使用符号索引值检索重定位符号信息,就相当于索引值乘Elf64_Rela结构体大小。
不难知道Elf64_Rela结构体大小是24,此时就解开了lea指令将符号索引值扩张24倍的原因。
.rela.plt节的基地址加上索引偏移数值后,就可以得到指定重定位信息的地址,该地址位于r13寄存器内。
找到重定位信息中,可以在偏移0x0处找到r_offset成员,偏移0x8处找到r_info成员。
r_info表述的数值分成符号索引值和重定位类型两部分,高位是符号索引值,低位是重定位类型,shr指令右移32位取出符号索引值给rax,随后会利用lea指令将符号索引值乘24倍,24是Elf64_Sym结构体的大小。
r8中存储的是.dynsym节基地址,基地址加符号索引值乘符号表大小,就可以获取动态链接符号的信息了。
接下来cmp指令会将r_info的低位字节与0x7进行比较,定位方式ELF_MACHINE_JMP_SLOT对应的数值就是0x7,jne指令如果发现运行结果不是0(ZF为0),那么就会跳转到偏移0x663的位置,执行退出动作。
得到待重定位的符号信息后,会从符号信息中取出st_other成员(偏移0x5,st_name占4字节,st_info占1字节),然后st_other成员将与0x3进行比较,判断符号是否被导致,如果符号是导出的,那么就需要执行查找操作。
如果符号是未导出的,那么它对我们来讲就是已知的,就会直接跳转到偏移0x624处,不会执行查找操作。
执行符号查找操作时,会先从l_info成员中偏移0x208处取出VERSYM表项,如果发现符号信息为空就会跳转到0x199处,不对符号信息进行处理,反之则会进行处理。
当程序不进行跳转时,就会根据VERSYM表项地址偏移0x8找到.gnu.version节的地址。
然后再偏移6字节(前面lea (%rax,%rax,1),%rcx,先扩大了3倍)得到vd_cnt成员给edx,最后与0x7fff进行与运算,可以发现该数值就是重定位符号的版本信息索引值。
在此之后,会从l_info偏移0x320的位置取出l_versions成员(记录了所有的版本信息),借助刚刚找到的版本信息索引值(乘8是因为当前单位是字节,占8比特),可以将重定位符号对应的版本信息找出来。
最后如果发现版本信息中哈希值是控制,就会直接将清空整个版本信息。
设置完版本信息后,程序会从fs寄存器偏移0x18处取出数值给ecx,fs是为了保存局部线程信息而存在的,其中偏移0x18对应着multiple_threads,显然这里使用判断程序是否是多线程,如果发现multiple_threads为0,就会跳转到0x233的位置,不针对多线程进行设置。反之,则会设置偏移0x1c处的gscope_flag成员,避免不同线程间发生冲突。
确保多线程不会惹来麻烦的前提下,程序会开始通过_dl_lookup_symbol_x函数寻找符号,首先要做的是准备_dl_lookup_symbol_x函数需要的形参。
从汇编代码中可以看出函数接收8个参数,前6个通过寄存器传递,后2个通过栈空间传递,首先第一个参数rdi内存放的是之前通过.dynstr获得的重定位符号名,第二个参数rsi内存放是之前一直使用的link_map基地址,第三个参数rdx存储的是.dynsym节中的动态链接符号信息,第四个参数rcx是刚刚从link_map偏移0x3c8处取出的l_scope_mem成员,第五个参数r8是动态链接符号的版本信息,第六个参数r9存放1,第七个参数rsp+0x0存放的是1(它是前面根据多线程属性设置的数值),第八个参数rsp+0x8存放的是0。
_dl_lookup_symbol_x函数内部具体的操作暂时不从汇编代码的角度进行解析,这里暂时只需要知道它会根据符号名进行检索,返回对应动态链接库的基地址,并修改提供的动态链接符号信息。
找到动态链接的基地址后,首先做的从TLS中取出gscope_flag,判断是否是多线程,如果是多线程就会跳转到0x424处,反之则会继续执行。
由于当前程序是单线程的,所以会继续前往0x292处执行。
当程序在0x292处继续执行时,会先从rbp-0x40处取出.dynsym节中的动态链接符号信息,然后判断它是否为空值,为空值就前往0x496处。
当程序继续正常运行时,会在偏移0x6的位置的st_shndx成员,并于SHN_ABS进行比较,如果相等就跳转到0x536的位置,SHN_ABS代表符号是绝对的。
接下来做的是判断_dl_lookup_symbol_x函数返回的动态链接库基地址(r15存储)是否为空,如果为空也会跳转到0x536的位置。
上面做的判断主要是为了下面的操作,首先会将r15存储的libc.so.6基地址加上.dynsym节中puts符号信息的偏移值(这里偏移值已经被_dl_lookup_symbol_x函数修改),得到puts函数的最终地址,该最终地址会存储在rbp-0x38位置。
在完成取到puts函数真实地址的任务后,程序会对符号信息中的st_info成员跟STT_GNU_IFUNC0xa进行判断,如果相等就跳转到0x648的位置。
接下来要判断的是偏移0x378的l_reloc_result成员,只有当模块提供la_symbind时才会生效,当然这是小概率情况(0x367-0x387的区域会暂时忽略),所以它会先跳转到0x520,到达0x520后,会先将puts函数地址放入rax内,然后再跳回0x391的位置。
此时解析函数进入最后阶段,首先会判断_dl_bind_not的数值,确定PLT是应该更新的,最后将rax中的puts函数地址返回,由于r14中存放的一直是PLT的地址,所以mov %rax,(%r14)操作就相当于修改PLT中的地址为puts函数的地址,使得下次调用时可以之间前往puts函数。
从0x419到0x689之间存在着上面各种判断异常然后跳转的地址,由于这部分是小概率的情况,所以在这里不会进行解析。
回到_dl_runtime_resolve_fxsave首先做的就是将puts函数地址交给r11,然后对之前占用的寄存器数值进行恢复,然后就是调用r11中的地址,实现puts函数的调用。
首先_dl_runtime_resolve_fxsave函数是解析的第一步,它的作用是调用实际进行解析的_dl_fixup函数,并等待_dl_fixup函数返回,由于_dl_fixup函数返回的就是动态链接函数的地址,所以可以直接根据返回值进行调用,实现先解析后调用的操作。
负责解析的_dl_fixup函数依赖.dynamic节,.dynamic节内含有.dynsym节、.dynstr节以及.rela.plt节等动态链接所需的信息,因此只要包含一个.dynamic节就可以了,在link_map结构体中含有l_info成员,这个成员涵括.dynamic节中各个表项的地址。
不管是.dynsym节、.dynstr节还是.rela.plt节中的任意一个,它们都可以看作是一张表,里面可能具有非常多的表项,因此PLT阶段的push xxx会将索引值压入栈内,等待后续使用,该索引值是专门为PLT准备的,所以根据该索引值可用从.rela.plt节中检索到正确的表项,此时可以获取需要重定位的符号,由于.rela.plt节中的r_info高字节(右数4字节),存储着.dynsym节中符号的索引值,因此重定位符号的具体信息也有了,.dynsym节中的st_name成员存储的索引值可以从.dynstr节内检索到符号对应的字符串。
.dynsym节、.dynstr节以及.rela.plt节中的信息已经足够程序知道如何对符号进行重定位,但是符号的所在地还是未知的,只有在正确的动态链接库中找到符号才可以完成动态链接。在.dynamic节还保存着NEEDED和VERSYM信息,NEEDED指明了程序依赖的动态链接库,动态link_map结构体通过l_version成员专门保存这些信息,.gnu.version节提供了抓专门的索引值用于检索正确的动态链接库。
此时进入收尾阶段,首先会准备参数交给_dl_lookup_symbol_x函数用于检索符号所在动态链接库的基地址,并修改动态链接符号信息,然后获取动态链接函数的地址并修改PLT,最后对函数进行调用。



在延迟绑定的过程中,_dl_lookup_symbol_x函数的操作至关重要的,它查找符号的依据是.dynstr中的符号名,如果我们可以控制.dynstr节,那么就可以劫持_dl_runtime_resolve到我们期望的函数内部。
因为.dynstr节始终都是只读的,不能进行篡改,所以我们不得不将主意打到.dynamic节中,当程序是No RelRO属性时,.dynamic节就是可写可读的,如果我们修改.dynamic节中存储的.dynstr节地址,并且在新地址上构造假的.dynstr节,那么我们就可以完成劫持。
虽然.dynamic动态链接节变得不可写了,但是我们还有_dl_fixup函数接收的两个参数link_map l和int reloc_arg可以控制,这两个变量较为特殊,动态链接函数的调用占用了全部的调用者寄存器,使得它们只能通过栈进行保存,这对于我们是十分有利的,因为不再需要通过pop指令向栈上传输数据了。
首先我们要寻找一块空闲的可写可读内存(.bss段的上方是十分合适的,这一点在栈迁移中进行过解释),在这段内存区域中,我们需要向其中填充构造的重定位信息(参考.rela.plt定义)、符号信息(参考.dynsym定义)、字符串信息。
_dl_fixup函数首先会通过reloc_arg检索重定位信息,基地址是.rela.plt的起始地址,因此reloc_arg等价于假重定位信息起始地址减去.rela.plt的起始地址再除以24(单个表项对应的Elf64_Rela的大小),重定位信息中的r_info可用于检索符号信息,符号信息中的st_name可用于检索字符串,参考reloc_arg就可以构造出这些偏移值。
此时_dl_fixup函数会通过“坏的”reloc_arg一步步的逼迫函数需要从我们构造的“坏”数据中检索重定位相关的信息(Elf64_Rela、Elf64_Sym结构体内的其他信息则需要按需填充)。
检索到我们构造的假信息后,_dl_fixup函数会对版本信息进行检查,这个检查是可有可无的,因此这里我们需要泄露link_map的地址,将link_map上记录版本信息的数值设置为空值。
最后我们就可以让_dl_lookup_symbol_x函数根据我们指定的信息检索符号了。
_dl_fixup函数一共只依赖两个参数,而且这两个参数都是我们可以控制的,那么我们把这两个参数全部都伪造了不就可以吗,不一定需要泄露地址啊!
理想是很丰满的,但现实是更残酷的,_dl_fixup函数的内部虽然只用link_map的一小部分,但是借助_dl_lookup_symbol_x函数检索符号时,也会用到link_map中不少的内容,link_map是一个非常庞大的结构体,想要把它完全伪造好并不是一个简单的事情。
上面解析_dl_fixup函数时,我们发现当函数发现符号未导出时,就会采用已知符号地址加上修正值l_addr对符号进行检索,这种方式有一种好处,就是不需要大量使用link_map中的信息,减少了我们伪造的难度。
这时我们只需要构造link_map中的SYMTAB、STRTAB、JMPREL、l_addr几个部分。
由于代码比较简单,这里不会从反汇编的角度进行分析,下面直接给出了源代码。
通过上面的分析我们可以构造出下方所示的exploit。
此处利用的gadget是_libc_csu_init函数提供的,但我当前使用的GLibC版本是2.36,已经超出了2.33,GLibC不会再向ELF文件中插入_libc_csu_init函数。
为了使用_libc_csu_init函数提供的gadget,这里手动编译了GLibC的2.31版本,因为_libc_csu_init函数位于libc_nonshared.a的内部,所以可以利用ar工具解包静态链接库,得到保护_libc_csu_init函数的elf-init.oS文件,当可执行程序编译时将该文件加入链接,就可以得到_libc_csu_init函数了。
如果想要查看GCC在编译过程的详细信息,可以添加--verbose参数进行查看。
运行上电的exploit后,就可以成功获取Shell了。
假如上方exploit中的payload的占位字符不使用\x00进行填充,而是使用普通字符填充,那么当exploit运行时,我们就会可能无法获取Shell,因为这个时候程序就崩溃了。
程序崩溃的原因是,ret指令取出一个异常地址进行返回,进而导致崩溃。
这一问题出现的根源在于,GLibC通过__clone_internal函数创建进行时返回了错误码,这个错误码是内核返回的(syscall指令后出现),是内核出现错误了,还是我们的payload出现错误了呢?
要知道Linux内核是经过千锤百炼的,创建进程更是被大量使用的功能,出错的概率非常小,那么问题在我们这边?
如果仔细观察__clone_internal接收的参数可以知道,它的参数依赖于__spawnix函数接收的参数。
__spawnix函数接收的参数中,有一个非常特别的参数envp,它是程序的环境变量参数,被放置在栈上,因此它是非常容易被我们的payload影响的。
观察envp参数可以确认这一猜想,它里面的数据的确是payload里面用来填充的普通字符,但如果我们用\x00进行填充,那么envp就会被视作是空值,不会产生问题。
0x000000000000001e (FLAGS) BIND_NOW0x000000000000001e (FLAGS) BIND_NOWvoid_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], int reloc_mode, int consider_profiling){ ...... ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc); ......}# define ELF_DYNAMIC_RELOCATE(map, scope, lazy, consider_profile, skip_ifunc) \ do { \ int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy), \ (consider_profile)); \ if (((map) != &GL(dl_rtld_map) || DO_RTLD_BOOTSTRAP)) \ ELF_DYNAMIC_DO_RELR (map); \ ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc); \ ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc); \ } while (0)void_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], int reloc_mode, int consider_profiling){ ...... ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc); ......}# define ELF_DYNAMIC_RELOCATE(map, scope, lazy, consider_profile, skip_ifunc) \ do { \ int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy), \ (consider_profile)); \ if (((map) != &GL(dl_rtld_map) || DO_RTLD_BOOTSTRAP)) \ ELF_DYNAMIC_DO_RELR (map); \ ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc); \ ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc); \ } while (0)0x0000000000401134 <+14>: call 0x401030 <puts@plt>(gdb) x /3i 0x401030 0x401030 <puts@plt>: jmp *0x2fca(%rip) # 0x404000 <puts@got.plt> 0x401036 <puts@plt+6>: push $0x0 0x40103b <puts@plt+11>: jmp 0x4010200x0000000000401134 <+14>: call 0x401030 <puts@plt>(gdb) x /3i 0x401030 0x401030 <puts@plt>: jmp *0x2fca(%rip) # 0x404000 <puts@got.plt> 0x401036 <puts@plt+6>: push $0x0 0x40103b <puts@plt+11>: jmp 0x401020(gdb) bt#0 0x00007ffff7fd7184 in _dl_fixup (l=0x7ffff7ffe2e0, reloc_arg=<optimized out>) at dl-runtime.c:163#1 0x00007ffff7fd9557 in _dl_runtime_resolve_fxsave () at ../sysdeps/x86_64/dl-trampoline.h:98#2 0x0000000000401139 in main () at main.c:5#3 0x00007ffff7dd0e08 in ?? () from /usr/lib/libc.so.6#4 0x00007ffff7dd0ecc in __libc_start_main () from /usr/lib/libc.so.6#5 0x0000000000401065 in _start ()(gdb) bt#0 0x00007ffff7fd7184 in _dl_fixup (l=0x7ffff7ffe2e0, reloc_arg=<optimized out>) at dl-runtime.c:163#1 0x00007ffff7fd9557 in _dl_runtime_resolve_fxsave () at ../sysdeps/x86_64/dl-trampoline.h:98#2 0x0000000000401139 in main () at main.c:5#3 0x00007ffff7dd0e08 in ?? () from /usr/lib/libc.so.6#4 0x00007ffff7dd0ecc in __libc_start_main () from /usr/lib/libc.so.6#5 0x0000000000401065 in _start ()typedef struct{ Elf64_Sxword d_tag; /* Dynamic entry type */ union { Elf64_Xword d_val; /* Integer value */ Elf64_Addr d_ptr; /* Address value */ } d_un;} Elf64_Dyn;typedef struct{ Elf64_Sxword d_tag; /* Dynamic entry type */ union { Elf64_Xword d_val; /* Integer value */ Elf64_Addr d_ptr; /* Address value */ } d_un;} Elf64_Dyn;#define DT_NULL 0#define DT_NEEDED 1......#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)#define DT_EXTRANUM 3#define DT_NULL 0#define DT_NEEDED 1......#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)#define DT_EXTRANUM 3readelf工具解析出来的友好信息:0x000000000000001e (FLAGS) BIND_NOW0x000000006ffffffb (FLAGS_1) Flags: NOW16进制信息:403f18 1e000000 00000000 08000000 00000000 ................403f28 fbffff6f 00000000 01000000 00000000 ...o............elf文件中的定义信息:#define DT_FLAGS 30#define DT_FLAGS_1 0x6ffffffb#define DF_BIND_NOW 0x00000008#define DF_1_NOW 0x00000001readelf工具解析出来的友好信息:0x000000000000001e (FLAGS) BIND_NOW0x000000006ffffffb (FLAGS_1) Flags: NOW16进制信息:403f18 1e000000 00000000 08000000 00000000 ................403f28 fbffff6f 00000000 01000000 00000000 ...o............elf文件中的定义信息:#define DT_FLAGS 30#define DT_FLAGS_1 0x6ffffffb#define DF_BIND_NOW 0x00000008#define DF_1_NOW 0x00000001Dynamic section at offset 0x2df8 contains 24 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] ...... 0x0000000000000000 (NULL) 0x0Dynamic section at offset 0x2df8 contains 24 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] ...... 0x0000000000000000 (NULL) 0x000000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|00000010 02 00 3e 00 01 00 00 00 40 10 40 00 00 00 00 00 |..>.....@.@.....|00000020 40 00 00 00 00 00 00 00 20 37 00 00 00 00 00 00 |@....... 7......|00000030 00 00 00 00 40 00 38 00 0d 00 40 00 24 00 23 00 |....@.8...@.$.#.|00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|00000010 02 00 3e 00 01 00 00 00 40 10 40 00 00 00 00 00 |..>.....@.@.....|00000020 40 00 00 00 00 00 00 00 20 37 00 00 00 00 00 00 |@....... 7......|00000030 00 00 00 00 40 00 38 00 0d 00 40 00 24 00 23 00 |....@.8...@.$.#.|节头表定义:typedef struct{ Elf64_Word sh_name; /* Section name (string tbl index) */ Elf64_Word sh_type; /* Section type */ Elf64_Xword sh_flags; /* Section flags */ Elf64_Addr sh_addr; /* Section virtual addr at execution */ Elf64_Off sh_offset; /* Section file offset */ Elf64_Xword sh_size; /* Section size in bytes */ Elf64_Word sh_link; /* Link to another section */ Elf64_Word sh_info; /* Additional section information */ Elf64_Xword sh_addralign; /* Section alignment */ Elf64_Xword sh_entsize; /* Entry size if section holds table */} Elf64_Shdr;节头表中的21号表项对应的16进制信息:00003c60 eb 00 00 00 06 00 00 00 03 00 00 00 00 00 00 00 |................|00003c70 f8 3d 40 00 00 00 00 00 f8 2d 00 00 00 00 00 00 |.=@......-......|00003c80 d0 01 00 00 00 00 00 00 07 00 00 00 00 00 00 00 |................|00003c90 08 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 |................|16进制信息解析:sh_name: 0x35b3+0xeb,0x35b3是字符串节的起始地址,0xeb是节名的索引值 0000369e 2e 64 79 6e 61 6d 69 63 00 2e 67 6f 74 00 2e 67 |.dynamic..got..gsh_type: #define SHT_DYNAMIC 6sh_flags: #define SHF_WRITE (1 << 0) /* Writable */ #define SHF_ALLOC (1 << 1) 0x3 = b11 -> WAsh_addr:0x3df8,sh_offset:0x2df8,sh_size:0x01d0sh_link:0x7,sh_info:0x0,sh_addralign:0x8,sh_entsize:0x10readelf中的动态链接节头信息(与手工解析结果一致):[21] .dynamic DYNAMIC 0000000000403df8 00002df8 00000000000001d0 0000000000000010 WA 7 0 8节头表定义:typedef struct{ Elf64_Word sh_name; /* Section name (string tbl index) */ Elf64_Word sh_type; /* Section type */ Elf64_Xword sh_flags; /* Section flags */ Elf64_Addr sh_addr; /* Section virtual addr at execution */ Elf64_Off sh_offset; /* Section file offset */ Elf64_Xword sh_size; /* Section size in bytes */ Elf64_Word sh_link; /* Link to another section */ Elf64_Word sh_info; /* Additional section information */ Elf64_Xword sh_addralign; /* Section alignment */ Elf64_Xword sh_entsize; /* Entry size if section holds table */} Elf64_Shdr;节头表中的21号表项对应的16进制信息:00003c60 eb 00 00 00 06 00 00 00 03 00 00 00 00 00 00 00 |................|00003c70 f8 3d 40 00 00 00 00 00 f8 2d 00 00 00 00 00 00 |.=@......-......|00003c80 d0 01 00 00 00 00 00 00 07 00 00 00 00 00 00 00 |................|00003c90 08 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 |................|16进制信息解析:sh_name: 0x35b3+0xeb,0x35b3是字符串节的起始地址,0xeb是节名的索引值 0000369e 2e 64 79 6e 61 6d 69 63 00 2e 67 6f 74 00 2e 67 |.dynamic..got..gsh_type: #define SHT_DYNAMIC 6sh_flags: #define SHF_WRITE (1 << 0) /* Writable */ #define SHF_ALLOC (1 << 1) 0x3 = b11 -> WAsh_addr:0x3df8,sh_offset:0x2df8,sh_size:0x01d0sh_link:0x7,sh_info:0x0,sh_addralign:0x8,sh_entsize:0x10readelf中的动态链接节头信息(与手工解析结果一致):[21] .dynamic DYNAMIC 0000000000403df8 00002df8 00000000000001d0 0000000000000010 WA 7 0 800002df8 01 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00 |................|00002e08 0c 00 00 00 00 00 00 00 00 10 40 00 00 00 00 00 |..........@.....|......00002f58 f0 ff ff 6f 00 00 00 00 ee 04 40 00 00 00 00 00 |...o......@.....|00002f68 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|00002df8 01 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00 |................|00002e08 0c 00 00 00 00 00 00 00 00 10 40 00 00 00 00 00 |..........@.....|......00002f58 f0 ff ff 6f 00 00 00 00 ee 04 40 00 00 00 00 00 |...o......@.....|00002f68 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|typedef struct{ Elf64_Word st_name; /* Symbol name (string tbl index) */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ Elf64_Section st_shndx; /* Section index */ Elf64_Addr st_value; /* Symbol value */ Elf64_Xword st_size; /* Symbol size */} Elf64_Sym;Symbol table '.dynsym' contains 6 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (2) 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...] 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (3) 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMC[...]typedef struct{ Elf64_Word st_name; /* Symbol name (string tbl index) */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ Elf64_Section st_shndx; /* Section index */ Elf64_Addr st_value; /* Symbol value */ Elf64_Xword st_size; /* Symbol size */} Elf64_Sym;Symbol table '.dynsym' contains 6 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (2) 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...] 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (3) 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMC[...][ 7] .dynstr STRTAB 0000000000400470 00000470 000000000000007e 0000000000000000 A 0 0 100000470 00 70 75 74 73 00 5f 5f 6c 69 62 63 5f 73 74 61 |.puts.__libc_sta|......000004e0 72 54 4d 43 6c 6f 6e 65 54 61 62 6c 65 00 00 00 |rTMCloneTable...|[ 7] .dynstr STRTAB 0000000000400470 00000470 000000000000007e 0000000000000000 A 0 0 100000470 00 70 75 74 73 00 5f 5f 6c 69 62 63 5f 73 74 61 |.puts.__libc_sta|......000004e0 72 54 4d 43 6c 6f 6e 65 54 61 62 6c 65 00 00 00 |rTMCloneTable...|[ 5] .gnu.hash GNU_HASH 00000000004003c0 000003c0 000000000000001c 0000000000000000 A 6 0 8000003c0 01 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 |................|000003d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|[ 5] .gnu.hash GNU_HASH 00000000004003c0 000003c0 000000000000001c 0000000000000000 A 6 0 8000003c0 01 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 |................|000003d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|Relocation section '.rela.dyn' at offset 0x530 contains 4 entries: Offset Info Type Sym. Value Sym. Name + Addend000000403fc8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.34 + 0000000403fd0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTM[...] + 0000000403fd8 000400000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0000000403fe0 000500000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCl[...] + 0Relocation section '.rela.plt' at offset 0x590 contains 1 entry: Offset Info Type Sym. Value Sym. Name + Addend000000404000 000300000007 R_X86_64_JUMP_SLOT 0000000000000000 puts@GLIBC_2.2.5 + 0Relocation section '.rela.dyn' at offset 0x530 contains 4 entries: Offset Info Type Sym. Value Sym. Name + Addend000000403fc8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.34 + 0000000403fd0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTM[...] + 0000000403fd8 000400000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0000000403fe0 000500000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCl[...] + 0Relocation section '.rela.plt' at offset 0x590 contains 1 entry: Offset Info Type Sym. Value Sym. Name + Addend000000404000 000300000007 R_X86_64_JUMP_SLOT 0000000000000000 puts@GLIBC_2.2.5 + 0typedef struct{ Elf64_Addr r_offset; /* Address */ Elf64_Xword r_info; /* Relocation type and symbol index */} Elf64_Rel;typedef struct{ Elf64_Addr r_offset; /* Address */ Elf64_Xword r_info; /* Relocation type and symbol index */ Elf64_Sxword r_addend; /* Addend */} Elf64_Rela;typedef struct{ Elf64_Addr r_offset; /* Address */ Elf64_Xword r_info; /* Relocation type and symbol index */} Elf64_Rel;typedef struct{ Elf64_Addr r_offset; /* Address */ Elf64_Xword r_info; /* Relocation type and symbol index */ Elf64_Sxword r_addend; /* Addend */} Elf64_Rela;(gdb) 0x0000000000401030 in puts@plt ()1: x/i $rip=> 0x401030 <puts@plt>: jmp *0x2fca(%rip) # 0x404000 <puts@got.plt>(gdb) x /gx 0x4040000x404000 <puts@got.plt>: 0x0000000000401036(gdb) si0x0000000000401036 in puts@plt ()1: x/i $rip=> 0x401036 <puts@plt+6>: push $0x0(gdb) 0x0000000000401030 in puts@plt ()1: x/i $rip=> 0x401030 <puts@plt>: jmp *0x2fca(%rip) # 0x404000 <puts@got.plt>(gdb) x /gx 0x4040000x404000 <puts@got.plt>: 0x0000000000401036(gdb) si0x0000000000401036 in puts@plt ()1: x/i $rip=> 0x401036 <puts@plt+6>: push $0x0(gdb) x /gx 0x403ff80x403ff8: 0x00007ffff7fd9510(gdb) info symbol 0x00007ffff7fd9510_dl_runtime_resolve_fxsave in section .text of /lib64/ld-linux-x86-64.so.20000000000401020 <puts@plt-0x10>: 401020: ff 35 ca 2f 00 00 push 0x2fca(%rip) # 403ff0 <_GLOBAL_OFFSET_TABLE_+0x8> 401026: ff 25 cc 2f 00 00 jmp *0x2fcc(%rip) # 403ff8 <_GLOBAL_OFFSET_TABLE_+0x10> 40102c: 0f 1f 40 00 nopl 0x0(%rax)(gdb) x /gx 0x403ff80x403ff8: 0x00007ffff7fd9510(gdb) info symbol 0x00007ffff7fd9510_dl_runtime_resolve_fxsave in section .text of /lib64/ld-linux-x86-64.so.20000000000401020 <puts@plt-0x10>: 401020: ff 35 ca 2f 00 00 push 0x2fca(%rip) # 403ff0 <_GLOBAL_OFFSET_TABLE_+0x8> 401026: ff 25 cc 2f 00 00 jmp *0x2fcc(%rip) # 403ff8 <_GLOBAL_OFFSET_TABLE_+0x10> 40102c: 0f 1f 40 00 nopl 0x0(%rax)函数序言:0x00007ffff7fd9510 <+0>: endbr640x00007ffff7fd9514 <+4>: push %rbx保存rbx寄存器数值,腾出rbx寄存器空间0x00007ffff7fd9515 <+5>: mov %rsp,%rbx保存rsp到rbx0x00007ffff7fd9518 <+8>: and $0xfffffffffffffff0,%rsp清零rsp中的低4个比特位,跟0x10对齐0x00007ffff7fd951c <+12>: sub $0x240,%rsp分配栈空间函数序言:0x00007ffff7fd9510 <+0>: endbr640x00007ffff7fd9514 <+4>: push %rbx保存rbx寄存器数值,腾出rbx寄存器空间0x00007ffff7fd9515 <+5>: mov %rsp,%rbx保存rsp到rbx0x00007ffff7fd9518 <+8>: and $0xfffffffffffffff0,%rsp清零rsp中的低4个比特位,跟0x10对齐0x00007ffff7fd951c <+12>: sub $0x240,%rsp分配栈空间0x00007ffff7fd9523 <+19>: mov %rax,(%rsp)0x00007ffff7fd9527 <+23>: mov %rcx,0x8(%rsp)0x00007ffff7fd952c <+28>: mov %rdx,0x10(%rsp)0x00007ffff7fd9531 <+33>: mov %rsi,0x18(%rsp)0x00007ffff7fd9536 <+38>: mov %rdi,0x20(%rsp)0x00007ffff7fd953b <+43>: mov %r8,0x28(%rsp)0x00007ffff7fd9540 <+48>: mov %r9,0x30(%rsp)保存寄存器数值到栈上,腾出寄存器空间0x00007ffff7fd9545 <+53>: fxsave 0x40(%rsp) # mov (LOCAL_STORAGE_AREA + 8)(%BASE), %RSI_LP保存上下文信息0x00007ffff7fd954a <+58>: mov 0x10(%rbx),%rsi0x00007ffff7fd954e <+62>: mov 0x8(%rbx),%rdi准备形参给_dl_fixup0x00007ffff7fd9552 <+66>: call 0x7ffff7fd6ff0 <_dl_fixup>调用_dl_fixup0x00007ffff7fd9557 <+71>: mov %rax,%r11保存返回值到r110x00007ffff7fd9523 <+19>: mov %rax,(%rsp)0x00007ffff7fd9527 <+23>: mov %rcx,0x8(%rsp)0x00007ffff7fd952c <+28>: mov %rdx,0x10(%rsp)0x00007ffff7fd9531 <+33>: mov %rsi,0x18(%rsp)0x00007ffff7fd9536 <+38>: mov %rdi,0x20(%rsp)0x00007ffff7fd953b <+43>: mov %r8,0x28(%rsp)0x00007ffff7fd9540 <+48>: mov %r9,0x30(%rsp)保存寄存器数值到栈上,腾出寄存器空间0x00007ffff7fd9545 <+53>: fxsave 0x40(%rsp) # mov (LOCAL_STORAGE_AREA + 8)(%BASE), %RSI_LP保存上下文信息0x00007ffff7fd954a <+58>: mov 0x10(%rbx),%rsi0x00007ffff7fd954e <+62>: mov 0x8(%rbx),%rdi准备形参给_dl_fixup0x00007ffff7fd9552 <+66>: call 0x7ffff7fd6ff0 <_dl_fixup>调用_dl_fixup0x00007ffff7fd9557 <+71>: mov %rax,%r11保存返回值到r11函数结语:0x00007ffff7fd955a <+74>: fxrstor 0x40(%rsp)恢复上下文信息0x00007ffff7fd955f <+79>: mov 0x30(%rsp),%r90x00007ffff7fd9564 <+84>: mov 0x28(%rsp),%r80x00007ffff7fd9569 <+89>: mov 0x20(%rsp),%rdi0x00007ffff7fd956e <+94>: mov 0x18(%rsp),%rsi0x00007ffff7fd9573 <+99>: mov 0x10(%rsp),%rdx0x00007ffff7fd9578 <+104>: mov 0x8(%rsp),%rcx0x00007ffff7fd957d <+109>: mov (%rsp),%rax0x00007ffff7fd9581 <+113>: mov %rbx,%rsp0x00007ffff7fd9584 <+116>: mov (%rsp),%rbx恢复之前保存的寄存器数值,让后续的使用者使用的数值仍是正确的0x00007ffff7fd9588 <+120>: add $0x18,%rsp函数结语:0x00007ffff7fd955a <+74>: fxrstor 0x40(%rsp)恢复上下文信息0x00007ffff7fd955f <+79>: mov 0x30(%rsp),%r90x00007ffff7fd9564 <+84>: mov 0x28(%rsp),%r80x00007ffff7fd9569 <+89>: mov 0x20(%rsp),%rdi0x00007ffff7fd956e <+94>: mov 0x18(%rsp),%rsi0x00007ffff7fd9573 <+99>: mov 0x10(%rsp),%rdx0x00007ffff7fd9578 <+104>: mov 0x8(%rsp),%rcx0x00007ffff7fd957d <+109>: mov (%rsp),%rax0x00007ffff7fd9581 <+113>: mov %rbx,%rsp0x00007ffff7fd9584 <+116>: mov (%rsp),%rbx恢复之前保存的寄存器数值,让后续的使用者使用的数值仍是正确的0x00007ffff7fd9588 <+120>: add $0x18,%rsp调用动态链接函数:0x00007ffff7fd958c <+124>: jmp *%r11跳转到r11寄存器保存的地址调用动态链接函数:0x00007ffff7fd958c <+124>: jmp *%r11跳转到r11寄存器保存的地址0x00007ffff7fd6ff0 <+0>: endbr640x00007ffff7fd6ff4 <+4>: push %rbp保存调用者栈底指针0x00007ffff7fd6ff5 <+5>: xor %r9d,%r9d0x00007ffff7fd6ff8 <+8>: mov %rsp,%rbp设置当前函数的栈底指针0x00007ffff7fd6ffb <+11>: push %r150x00007ffff7fd6ffd <+13>: push %r140x00007ffff7fd6fff <+15>: push %r130x00007ffff7fd7001 <+17>: push %r120x00007ffff7fd7003 <+19>: push %rbx腾出寄存器空间0x00007ffff7fd7004 <+20>: mov %rdi,%rbx0x00007ffff7fd7007 <+23>: sub $0x18,%rsp分配栈空间0x00007ffff7fd6ff0 <+0>: endbr640x00007ffff7fd6ff4 <+4>: push %rbp保存调用者栈底指针0x00007ffff7fd6ff5 <+5>: xor %r9d,%r9d0x00007ffff7fd6ff8 <+8>: mov %rsp,%rbp设置当前函数的栈底指针0x00007ffff7fd6ffb <+11>: push %r150x00007ffff7fd6ffd <+13>: push %r140x00007ffff7fd6fff <+15>: push %r130x00007ffff7fd7001 <+17>: push %r120x00007ffff7fd7003 <+19>: push %rbx腾出寄存器空间0x00007ffff7fd7004 <+20>: mov %rdi,%rbx0x00007ffff7fd7007 <+23>: sub $0x18,%rsp分配栈空间0x00007ffff7fd700b <+27>: mov 0x70(%rdi),%rax根据形参传递的地址,取出偏移0x70处的数据给rax0x00007ffff7fd700f <+31>: mov (%rdi),%rdx将rdi保存地址上的数值传给rdx0x00007ffff7fd7012 <+34>: mov 0x8(%rax),%r80x00007ffff7fd7016 <+38>: testb $0x20,0x356(%rdi)0x00007ffff7fd701d <+45>: je 0x7ffff7fd7025 <_dl_fixup+53>0x00007ffff7fd700b <+27>: mov 0x70(%rdi),%rax根据形参传递的地址,取出偏移0x70处的数据给rax0x00007ffff7fd700f <+31>: mov (%rdi),%rdx将rdi保存地址上的数值传给rdx0x00007ffff7fd7012 <+34>: mov 0x8(%rax),%r80x00007ffff7fd7016 <+38>: testb $0x20,0x356(%rdi)0x00007ffff7fd701d <+45>: je 0x7ffff7fd7025 <_dl_fixup+53>.dynamic节: ...... 0x0000000000000006 (SYMTAB) 0x4003e0 .......dynsym节:[ 6] .dynsym DYNSYM 00000000004003e0 000003e0 0000000000000090 0000000000000018 A 7 1 8rax:(gdb) info registers rdirdi 0x7ffff7ffe2e0 140737354130144(gdb) x /gx 0x7ffff7ffe2e0+0x700x7ffff7ffe350: 0x0000000000403e88(gdb) x /gx 0x403e880x403e88: 0x0000000000000006r8:(gdb) x /gx 0x403e88+0x80x403e90: 0x00000000004003e0.dynamic节: ...... 0x0000000000000006 (SYMTAB) 0x4003e0 .......dynsym节:[ 6] .dynsym DYNSYM 00000000004003e0 000003e0 0000000000000090 0000000000000018 A 7 1 8rax:(gdb) info registers rdirdi 0x7ffff7ffe2e0 140737354130144(gdb) x /gx 0x7ffff7ffe2e0+0x700x7ffff7ffe350: 0x0000000000403e88(gdb) x /gx 0x403e880x403e88: 0x0000000000000006r8:(gdb) x /gx 0x403e88+0x80x403e90: 0x00000000004003e0unsigned int l_audit_any_plt:1;unsigned int l_removed:1;unsigned int l_contiguous:1;unsigned int l_free_initfini:1;unsigned int l_ld_readonly:1;unsigned int l_find_object_processed:1;unsigned int l_audit_any_plt:1;unsigned int l_removed:1;unsigned int l_contiguous:1;unsigned int l_free_initfini:1;unsigned int l_ld_readonly:1;unsigned int l_find_object_processed:1;运行前:(gdb) info registers eflags eflags 0x10202 [ IF RF ]运行后:(gdb) info registers eflags eflags 0x10246 [ PF ZF IF RF ]运行前:(gdb) info registers eflags eflags 0x10202 [ IF RF ]运行后:(gdb) info registers eflags eflags 0x10246 [ PF ZF IF RF ]0x00007ffff7fd701f <+47>: add %rdx,%r80x00007ffff7fd7022 <+50>: mov %rdx,%r90x00007ffff7fd701f <+47>: add %rdx,%r80x00007ffff7fd7022 <+50>: mov %rdx,%r90x00007ffff7fd7025 <+53>: mov 0x68(%rbx),%rax......0x00007ffff7fd7030 <+64>: mov 0x8(%rax),%rdi....0x00007ffff7fd703f <+79>: add %r9,%rdi0x00007ffff7fd7025 <+53>: mov 0x68(%rbx),%rax......0x00007ffff7fd7030 <+64>: mov 0x8(%rax),%rdi....0x00007ffff7fd703f <+79>: add %r9,%rdi偏移0x68的元素为.dynmaic节中.dynstr节:(gdb) x /gx $rbx0x7ffff7ffe2e0: 0x0000000000000000(gdb) x /gx $rbx+0x680x7ffff7ffe348: 0x0000000000403e78(gdb) x /gx 0x403e78+0x80x403e80: 0x0000000000400470.dynamic节中存储的.dynstr节信息: 0x0000000000000005 (STRTAB) 0x400470.dynstr节信息: [ 7] .dynstr STRTAB 0000000000400470 00000470 000000000000007e 0000000000000000 A 0 0 1偏移0x68的元素为.dynmaic节中.dynstr节:(gdb) x /gx $rbx0x7ffff7ffe2e0: 0x0000000000000000(gdb) x /gx $rbx+0x680x7ffff7ffe348: 0x0000000000403e78(gdb) x /gx 0x403e78+0x80x403e80: 0x0000000000400470.dynamic节中存储的.dynstr节信息: 0x0000000000000005 (STRTAB) 0x400470.dynstr节信息: [ 7] .dynstr STRTAB 0000000000400470 00000470 000000000000007e 0000000000000000 A 0 0 1Elf64_Rela结构体大小:(gdb) p sizeof(Elf64_Rela)$11 = 24Elf64_Rela结构体大小:(gdb) p sizeof(Elf64_Rela)$11 = 240x00007ffff7fd7029 <+57>: mov %esi,%r12d0x00007ffff7fd702c <+60>: lea (%r12,%r12,2),%rcx0x00007ffff7fd7034 <+68>: mov 0xf8(%rbx),%rax0x00007ffff7fd703b <+75>: mov 0x8(%rax),%rax0x00007ffff7fd7042 <+82>: lea (%rax,%rcx,8),%r130x00007ffff7fd7046 <+86>: add %r9,%r130x00007ffff7fd7029 <+57>: mov %esi,%r12d0x00007ffff7fd702c <+60>: lea (%r12,%r12,2),%rcx0x00007ffff7fd7034 <+68>: mov 0xf8(%rbx),%rax0x00007ffff7fd703b <+75>: mov 0x8(%rax),%rax0x00007ffff7fd7042 <+82>: lea (%rax,%rcx,8),%r130x00007ffff7fd7046 <+86>: add %r9,%r130x00007ffff7fd7049 <+89>: mov 0x8(%r13),%rsi0x00007ffff7fd704d <+93>: mov 0x0(%r13),%r140x00007ffff7fd7051 <+97>: mov %rsi,%rax0x00007ffff7fd7054 <+100>: add %rdx,%r140x00007ffff7fd7049 <+89>: mov 0x8(%r13),%rsi0x00007ffff7fd704d <+93>: mov 0x0(%r13),%r140x00007ffff7fd7051 <+97>: mov %rsi,%rax0x00007ffff7fd7054 <+100>: add %rdx,%r14(gdb) p sizeof(Elf64_Sym)$12 = 24(gdb) p sizeof(Elf64_Sym)$12 = 240x00007ffff7fd7057 <+103>: shr $0x20,%rax0x00007ffff7fd705b <+107>: lea (%rax,%rax,1),%rcx0x00007ffff7fd705f <+111>: add %rcx,%rax0x00007ffff7fd7062 <+114>: lea (%r8,%rax,8),%rax0x00007ffff7fd7066 <+118>: mov %rax,-0x40(%rbp)0x00007ffff7fd706a <+122>: cmp $0x7,%esi0x00007ffff7fd706d <+125>: jne 0x7ffff7fd7287 <_dl_fixup+663>r8+24=0x400428下面通过Elf64_Sym结构体对该地址上的数据进行解释:(gdb) p *(Elf64_Sym*)(0x400428)$16 = {st_name = 1, st_info = 18 '\022', st_other = 0 '\000', st_shndx = 0, st_value = 0, st_size = 0}st_name索引值刚好可以和下方0x400471对应(0x400470 + 1)rdi对应.dynstr节:(gdb) x /s $rdi0x400470: ""(gdb) 0x400471: "puts"st_info数值对应二进制格式为:0001 0010#define STB_GLOBAL 1;#define STT_FUNC 2高4个比特位数值为1,对应STB_GLOBAL,低4字节为2,对应STT_FUNC上面分析的结果与readelf工具解析的结果一致:3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (3)0x00007ffff7fd7057 <+103>: shr $0x20,%rax0x00007ffff7fd705b <+107>: lea (%rax,%rax,1),%rcx0x00007ffff7fd705f <+111>: add %rcx,%rax0x00007ffff7fd7062 <+114>: lea (%r8,%rax,8),%rax0x00007ffff7fd7066 <+118>: mov %rax,-0x40(%rbp)0x00007ffff7fd706a <+122>: cmp $0x7,%esi0x00007ffff7fd706d <+125>: jne 0x7ffff7fd7287 <_dl_fixup+663>r8+24=0x400428下面通过Elf64_Sym结构体对该地址上的数据进行解释:(gdb) p *(Elf64_Sym*)(0x400428)$16 = {st_name = 1, st_info = 18 '\022', st_other = 0 '\000', st_shndx = 0, st_value = 0, st_size = 0}st_name索引值刚好可以和下方0x400471对应(0x400470 + 1)rdi对应.dynstr节:(gdb) x /s $rdi0x400470: ""(gdb) 0x400471: "puts"st_info数值对应二进制格式为:0001 0010#define STB_GLOBAL 1;#define STT_FUNC 2高4个比特位数值为1,对应STB_GLOBAL,低4字节为2,对应STT_FUNC上面分析的结果与readelf工具解析的结果一致:3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (3)与0x3进行比较的来源:#define STV_PROTECTED 3#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)0x00007ffff7fd7073 <+131>: testb $0x3,0x5(%rax)0x00007ffff7fd7077 <+135>: jne 0x7ffff7fd7260 <_dl_fixup+624>与0x3进行比较的来源:#define STV_PROTECTED 3#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)0x00007ffff7fd7073 <+131>: testb $0x3,0x5(%rax)0x00007ffff7fd7077 <+135>: jne 0x7ffff7fd7260 <_dl_fixup+624>0x00007ffff7fd707d <+141>: mov 0x208(%rbx),%rdx0x00007ffff7fd7084 <+148>: xor %r8d,%r8d0x00007ffff7fd7087 <+151>: test %rdx,%rdx0x00007ffff7fd708a <+154>: je 0x7ffff7fd70b7 <_dl_fixup+199>0x00007ffff7fd708c <+156>: add %r9,%rcx0x00007ffff7fd708f <+159>: add 0x8(%rdx),%rcx0x00007ffff7fd7093 <+163>: movzwl (%rcx),%edx0x00007ffff7fd7096 <+166>: and $0x7fff,%edx0x00007ffff7fd709c <+172>: lea (%rdx,%rdx,2),%rcx0x00007ffff7fd70a0 <+176>: mov 0x320(%rbx),%rdx0x00007ffff7fd70a7 <+183>: lea (%rdx,%rcx,8),%r80x00007ffff7fd70ab <+187>: mov 0x8(%r8),%r10d0x00007ffff7fd70af <+191>: test %r10d,%r10d0x00007ffff7fd70b2 <+194>: jne 0x7ffff7fd70b7 <_dl_fixup+199>0x00007ffff7fd70b4 <+196>: xor %r8d,%r8d0x00007ffff7fd707d <+141>: mov 0x208(%rbx),%rdx0x00007ffff7fd7084 <+148>: xor %r8d,%r8d0x00007ffff7fd7087 <+151>: test %rdx,%rdx0x00007ffff7fd708a <+154>: je 0x7ffff7fd70b7 <_dl_fixup+199>0x00007ffff7fd708c <+156>: add %r9,%rcx0x00007ffff7fd708f <+159>: add 0x8(%rdx),%rcx0x00007ffff7fd7093 <+163>: movzwl (%rcx),%edx0x00007ffff7fd7096 <+166>: and $0x7fff,%edx0x00007ffff7fd709c <+172>: lea (%rdx,%rdx,2),%rcx0x00007ffff7fd70a0 <+176>: mov 0x320(%rbx),%rdx0x00007ffff7fd70a7 <+183>: lea (%rdx,%rcx,8),%r80x00007ffff7fd70ab <+187>: mov 0x8(%r8),%r10d0x00007ffff7fd70af <+191>: test %r10d,%r10d0x00007ffff7fd70b2 <+194>: jne 0x7ffff7fd70b7 <_dl_fixup+199>0x00007ffff7fd70b4 <+196>: xor %r8d,%r8dVERSYM对应的.gnu.version节结构体定义:typedef struct{ Elf64_Half vd_version; /* Version revision */ Elf64_Half vd_flags; /* Version information */ Elf64_Half vd_ndx; /* Version Index */ Elf64_Half vd_cnt; /* Number of associated aux entries */ Elf64_Word vd_hash; /* Version name hash value */ Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ Elf64_Word vd_next; /* Offset in bytes to next verdef entry */} Elf64_Verdef;VERSYM对应的.gnu.version节结构体定义:typedef struct{ Elf64_Half vd_version; /* Version revision */ Elf64_Half vd_flags; /* Version information */ Elf64_Half vd_ndx; /* Version Index */ Elf64_Half vd_cnt; /* Number of associated aux entries */ Elf64_Word vd_hash; /* Version name hash value */ Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ Elf64_Word vd_next; /* Offset in bytes to next verdef entry */} Elf64_Verdef;获取的版本信息:(gdb) info registers rdxrdx 0x3 3.gnu.version中记录的版本信息:Version symbols section '.gnu.version' contains 6 entries: Addr: 0x00000000004004ee Offset: 0x000004ee Link: 6 (.dynsym) 000: 0 (*local*) 2 (GLIBC_2.34) 1 (*global*) 3 (GLIBC_2.2.5) 004: 1 (*global*) 1 (*global*) 符号对应的版本信息:Relocation section '.rela.plt' at offset 0x590 contains 1 entry: Offset Info Type Sym. Value Sym. Name + Addend000000404000 000300000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0获取的版本信息:(gdb) info registers rdxrdx 0x3 3.gnu.version中记录的版本信息:Version symbols section '.gnu.version' contains 6 entries: Addr: 0x00000000004004ee Offset: 0x000004ee Link: 6 (.dynsym) 000: 0 (*local*) 2 (GLIBC_2.34) 1 (*global*) 3 (GLIBC_2.2.5) 004: 1 (*global*) 1 (*global*) 符号对应的版本信息:Relocation section '.rela.plt' at offset 0x590 contains 1 entry: Offset Info Type Sym. Value Sym. Name + Addend000000404000 000300000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0(gdb) info registers r8r8 0x7ffff7f9c5c8 140737353729480(gdb) p *(struct r_found_version*)0x7ffff7f9c5c8$36 = {name = 0x400492 "GLIBC_2.2.5", hash = 157882997, hidden = 0, filename = 0x400488 "libc.so.6"}(gdb) info registers r8r8 0x7ffff7f9c5c8 140737353729480(gdb) p *(struct r_found_version*)0x7ffff7f9c5c8$36 = {name = 0x400492 "GLIBC_2.2.5", hash = 157882997, hidden = 0, filename = 0x400488 "libc.so.6"}0x00007ffff7fd70b7 <+199>: mov %fs:0x18,%ecx0x00007ffff7fd70bf <+207>: mov $0x1,%edx0x00007ffff7fd70c4 <+212>: test %ecx,%ecx0x00007ffff7fd70c6 <+214>: je 0x7ffff7fd70d9 <_dl_fixup+233>0x00007ffff7fd70c8 <+216>: movl $0x1,%fs:0x1c0x00007ffff7fd70d4 <+228>: mov $0x5,%edx0x00007ffff7fd70b7 <+199>: mov %fs:0x18,%ecx0x00007ffff7fd70bf <+207>: mov $0x1,%edx0x00007ffff7fd70c4 <+212>: test %ecx,%ecx0x00007ffff7fd70c6 <+214>: je 0x7ffff7fd70d9 <_dl_fixup+233>0x00007ffff7fd70c8 <+216>: movl $0x1,%fs:0x1c0x00007ffff7fd70d4 <+228>: mov $0x5,%edxp *(tcbhead_t*)$fs_base$39 = {tcb = 0x7ffff7da8740, dtv = 0x7ffff7da90e0, self = 0x7ffff7da8740, multiple_threads = 0, gscope_flag = 0, sysinfo = 0, stack_guard = 15852976144659649792, pointer_guard = 7034873935951137108, unused_vgetcpu_cache = {0, 0}, feature_1 = 0, __glibc_unused1 = 0, __private_tm = {0x0, 0x0, 0x0, 0x0}, __private_ss = 0x0, ssp_base = 0, __glibc_unused2 = {{{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, { i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, { i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}}, __padding = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}p *(tcbhead_t*)$fs_base$39 = {tcb = 0x7ffff7da8740, dtv = 0x7ffff7da90e0, self = 0x7ffff7da8740, multiple_threads = 0, gscope_flag = 0, sysinfo = 0, stack_guard = 15852976144659649792, pointer_guard = 7034873935951137108, unused_vgetcpu_cache = {0, 0}, feature_1 = 0, __glibc_unused1 = 0, __private_tm = {0x0, 0x0, 0x0, 0x0}, __private_ss = 0x0, ssp_base = 0, __glibc_unused2 = {{{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, { i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, { i = {0, 0, 0, 0}}}, {{i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}, {i = {0, 0, 0, 0}}}}, __padding = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}0x00007ffff7fd70d9 <+233>: mov 0x3c8(%rbx),%rcx0x00007ffff7fd70e0 <+240>: mov (%rax),%eax0x00007ffff7fd70e2 <+242>: push $0x00x00007ffff7fd70e4 <+244>: lea -0x40(%rbp),%rsi0x00007ffff7fd70e8 <+248>: push %rdx0x00007ffff7fd70e9 <+249>: mov $0x1,%r9d0x00007ffff7fd70ef <+255>: mov %rsi,%rdx0x00007ffff7fd70f2 <+258>: mov %rbx,%rsi0x00007ffff7fd70f5 <+261>: add %rax,%rdi0x00007ffff7fd70f8 <+264>: call 0x7ffff7fd0970 <_dl_lookup_symbol_x>0x00007ffff7fd70fd <+269>: mov %rax,%r15(gdb) info registers rdi rsi rdx rcx r8 r9rdi 0x400471 4195441rsi 0x7ffff7ffe2e0 140737354130144rdx 0x7fffffffdb70 140737488345968rcx 0x7ffff7ffe680 140737354131072r8 0x7ffff7f9c5c8 140737353729480r9 0x1 1(gdb) x /gx $rsp0x7fffffffdb60: 0x0000000000000001(gdb) 0x7fffffffdb68: 0x00000000000000000x00007ffff7fd70d9 <+233>: mov 0x3c8(%rbx),%rcx0x00007ffff7fd70e0 <+240>: mov (%rax),%eax0x00007ffff7fd70e2 <+242>: push $0x00x00007ffff7fd70e4 <+244>: lea -0x40(%rbp),%rsi0x00007ffff7fd70e8 <+248>: push %rdx0x00007ffff7fd70e9 <+249>: mov $0x1,%r9d0x00007ffff7fd70ef <+255>: mov %rsi,%rdx0x00007ffff7fd70f2 <+258>: mov %rbx,%rsi0x00007ffff7fd70f5 <+261>: add %rax,%rdi0x00007ffff7fd70f8 <+264>: call 0x7ffff7fd0970 <_dl_lookup_symbol_x>0x00007ffff7fd70fd <+269>: mov %rax,%r15(gdb) info registers rdi rsi rdx rcx r8 r9rdi 0x400471 4195441rsi 0x7ffff7ffe2e0 140737354130144rdx 0x7fffffffdb70 140737488345968rcx 0x7ffff7ffe680 140737354131072r8 0x7ffff7f9c5c8 140737353729480r9 0x1 1(gdb) x /gx $rsp0x7fffffffdb60: 0x0000000000000001(gdb) 0x7fffffffdb68: 0x0000000000000000(gdb) info registers raxrax 0x7ffff7f9c000 140737353728000(gdb) x /gx 0x7ffff7f9c0000x7ffff7f9c000: 0x00007ffff7dab0007ffff7dab000-7ffff7dcf000 r--p 00000000 08:01 7351314 /usr/lib/libc.so.6(gdb) info registers raxrax 0x7ffff7f9c000 140737353728000(gdb) x /gx 0x7ffff7f9c0000x7ffff7f9c000: 0x00007ffff7dab0007ffff7dab000-7ffff7dcf000 r--p 00000000 08:01 7351314 /usr/lib/libc.so.60x00007ffff7fd7100 <+272>: mov %fs:0x18,%eax0x00007ffff7fd7108 <+280>: pop %r80x00007ffff7fd710a <+282>: pop %r90x00007ffff7fd710c <+284>: test %eax,%eax0x00007ffff7fd710e <+286>: jne 0x7ffff7fd7198 <_dl_fixup+424>0x00007ffff7fd7100 <+272>: mov %fs:0x18,%eax0x00007ffff7fd7108 <+280>: pop %r80x00007ffff7fd710a <+282>: pop %r90x00007ffff7fd710c <+284>: test %eax,%eax0x00007ffff7fd710e <+286>: jne 0x7ffff7fd7198 <_dl_fixup+424>0x00007ffff7fd7114 <+292>: mov -0x40(%rbp),%rax0x00007ffff7fd7118 <+296>: test %rax,%rax0x00007ffff7fd711b <+299>: je 0x7ffff7fd71e0 <_dl_fixup+496>0x00007ffff7fd7121 <+305>: cmpw $0xfff1,0x6(%rax)0x00007ffff7fd7126 <+310>: je 0x7ffff7fd7208 <_dl_fixup+536>0x00007ffff7fd712c <+316>: test %r15,%r150x00007ffff7fd712f <+319>: je 0x7ffff7fd7208 <_dl_fixup+536>0x00007ffff7fd7114 <+292>: mov -0x40(%rbp),%rax0x00007ffff7fd7118 <+296>: test %rax,%rax0x00007ffff7fd711b <+299>: je 0x7ffff7fd71e0 <_dl_fixup+496>0x00007ffff7fd7121 <+305>: cmpw $0xfff1,0x6(%rax)0x00007ffff7fd7126 <+310>: je 0x7ffff7fd7208 <_dl_fixup+536>0x00007ffff7fd712c <+316>: test %r15,%r150x00007ffff7fd712f <+319>: je 0x7ffff7fd7208 <_dl_fixup+536>rbp-0x40存储0x7ffff7db1af0,下面通过Elf64_Sym进行解释:(gdb) p *(Elf64_Sym*)0x7ffff7db1af0$3 = {st_name = 27823, st_info = 34 '"', st_other = 0 '\000', st_shndx = 15, st_value = 527328, st_size = 518}0x7ffff7dc2c98是libc.so.6中.dynstr节的地址:(gdb) x /s 0x7ffff7dc2c98+278230x7ffff7dc9947: "puts"#define SHN_ABS 0xfff1rbp-0x40存储0x7ffff7db1af0,下面通过Elf64_Sym进行解释:(gdb) p *(Elf64_Sym*)0x7ffff7db1af0$3 = {st_name = 27823, st_info = 34 '"', st_other = 0 '\000', st_shndx = 15, st_value = 527328, st_size = 518}0x7ffff7dc2c98是libc.so.6中.dynstr节的地址:(gdb) x /s 0x7ffff7dc2c98+278230x7ffff7dc9947: "puts"#define SHN_ABS 0xfff10x00007ffff7fd7135 <+325>: mov (%r15),%rdx0x00007ffff7fd7138 <+328>: add 0x8(%rax),%rdx0x00007ffff7fd713c <+332>: mov %rdx,-0x38(%rbp)0x00007ffff7fd7135 <+325>: mov (%r15),%rdx0x00007ffff7fd7138 <+328>: add 0x8(%rax),%rdx0x00007ffff7fd713c <+332>: mov %rdx,-0x38(%rbp)#define STT_GNU_IFUNC 100x00007ffff7fd7140 <+336>: movzbl 0x4(%rax),%eax0x00007ffff7fd7144 <+340>: and $0xf,%eax0x00007ffff7fd7147 <+343>: cmp $0xa,%al0x00007ffff7fd7149 <+345>: je 0x7ffff7fd7278 <_dl_fixup+648>#define STT_GNU_IFUNC 100x00007ffff7fd7140 <+336>: movzbl 0x4(%rax),%eax0x00007ffff7fd7144 <+340>: and $0xf,%eax0x00007ffff7fd7147 <+343>: cmp $0xa,%al0x00007ffff7fd7149 <+345>: je 0x7ffff7fd7278 <_dl_fixup+648>0x00007ffff7fd714f <+351>: mov 0x378(%rbx),%rax0x00007ffff7fd7156 <+358>: test %rax,%rax0x00007ffff7fd7159 <+361>: je 0x7ffff7fd71f8 <_dl_fixup+520>0x00007ffff7fd715f <+367>: shl $0x5,%r120x00007ffff7fd7163 <+371>: add %rax,%r120x00007ffff7fd7166 <+374>: mov 0x1c(%r12),%eax0x00007ffff7fd716b <+379>: test %eax,%eax0x00007ffff7fd716d <+381>: je 0x7ffff7fd7210 <_dl_fixup+544>0x00007ffff7fd7173 <+387>: mov (%r12),%rax0x00007ffff7fd714f <+351>: mov 0x378(%rbx),%rax0x00007ffff7fd7156 <+358>: test %rax,%rax0x00007ffff7fd7159 <+361>: je 0x7ffff7fd71f8 <_dl_fixup+520>0x00007ffff7fd715f <+367>: shl $0x5,%r120x00007ffff7fd7163 <+371>: add %rax,%r120x00007ffff7fd7166 <+374>: mov 0x1c(%r12),%eax0x00007ffff7fd716b <+379>: test %eax,%eax0x00007ffff7fd716d <+381>: je 0x7ffff7fd7210 <_dl_fixup+544>0x00007ffff7fd7173 <+387>: mov (%r12),%raxp *(struct rtld_global_ro*)0x7ffff7ffca80$19 = {_dl_debug_mask = 0, _dl_platform = 0x7fffffffe439 "x86_64", _dl_platformlen = 6, _dl_pagesize = 4096, ......}0x00007ffff7fd7177 <+391>: mov 0x25953(%rip),%edx # 0x7ffff7ffcad0 <_rtld_global_ro+80>0x00007ffff7fd717d <+397>: test %edx,%edx0x00007ffff7fd717f <+399>: jne 0x7ffff7fd7184 <_dl_fixup+404>0x00007ffff7fd7181 <+401>: mov %rax,(%r14)0x00007ffff7fd7184 <+404>: lea -0x28(%rbp),%rsp0x00007ffff7fd7188 <+408>: pop %rbx0x00007ffff7fd7189 <+409>: pop %r120x00007ffff7fd718b <+411>: pop %r130x00007ffff7fd718d <+413>: pop %r140x00007ffff7fd718f <+415>: pop %r150x00007ffff7fd7191 <+417>: pop %rbp0x00007ffff7fd7192 <+418>: retp *(struct rtld_global_ro*)0x7ffff7ffca80$19 = {_dl_debug_mask = 0, _dl_platform = 0x7fffffffe439 "x86_64", _dl_platformlen = 6, _dl_pagesize = 4096, ......}0x00007ffff7fd7177 <+391>: mov 0x25953(%rip),%edx # 0x7ffff7ffcad0 <_rtld_global_ro+80>0x00007ffff7fd717d <+397>: test %edx,%edx0x00007ffff7fd717f <+399>: jne 0x7ffff7fd7184 <_dl_fixup+404>0x00007ffff7fd7181 <+401>: mov %rax,(%r14)0x00007ffff7fd7184 <+404>: lea -0x28(%rbp),%rsp0x00007ffff7fd7188 <+408>: pop %rbx0x00007ffff7fd7189 <+409>: pop %r120x00007ffff7fd718b <+411>: pop %r130x00007ffff7fd718d <+413>: pop %r140x00007ffff7fd718f <+415>: pop %r150x00007ffff7fd7191 <+417>: pop %rbp0x00007ffff7fd7192 <+418>: ret0x00007ffff7fd7193 <+419>: nopl 0x0(%rax,%rax,1)0x00007ffff7fd7198 <+424>: xor %eax,%eax......0x00007ffff7fd71f8 <+520>: mov -0x38(%rbp),%rax0x00007ffff7fd71fc <+524>: jmp 0x7ffff7fd7177 <_dl_fixup+391>......0x00007ffff7fd72a1 <+689>: call 0x7ffff7fe1970 <__GI___assert_fail>0x00007ffff7fd7193 <+419>: nopl 0x0(%rax,%rax,1)0x00007ffff7fd7198 <+424>: xor %eax,%eax......0x00007ffff7fd71f8 <+520>: mov -0x38(%rbp),%rax0x00007ffff7fd71fc <+524>: jmp 0x7ffff7fd7177 <_dl_fixup+391>......0x00007ffff7fd72a1 <+689>: call 0x7ffff7fe1970 <__GI___assert_fail>0x0000000000000001 (NEEDED) Shared library: [libc.so.6].....0x000000006ffffff0 (VERSYM) 0x4004ee0x0000000000000000 (NULL) 0x00x0000000000000001 (NEEDED) Shared library: [libc.so.6].....0x000000006ffffff0 (VERSYM) 0x4004ee0x0000000000000000 (NULL) 0x0#define LOOKUP_VALUE_ADDRESS(map, set) ((set) || (map) ? (map)->l_addr : 0)#define SYMBOL_ADDRESS(map, ref, map_set) \ ((ref) == NULL ? 0 \ : (__glibc_unlikely ((ref)->st_shndx == SHN_ABS) ? 0 \ : LOOKUP_VALUE_ADDRESS (map, map_set)) + (ref)->st_value)value = DL_FIXUP_MAKE_VALUE (l, SYMBOL_ADDRESS (l, sym, true));赞赏
- [原创]PWN入门-24-MMAP除妖 2869
- PWN入门-23-LargeBin托梦 3142
- [原创]PWN入门-22-FastBin与DoubleFree降妖 4543
- [原创]PWN入门-21-OffByOne遇险 4621
- [原创]Web安全入门-网络资源的访问-隧道 5979