核心逻辑:拓展elf文件空间,写入shellcode。

silvio elf文件感染方法

直接从linux二进制分析里面抄算法

.text感染算法

  • 增加ELF文件头中的ehdr->e_shoff(节表偏移)的PAGE_SIZE(页长度)
  • 定位text段的phdr 修改入口点ehdr->e_entry = phdr[TEXT].p_vaddr + phdr[TEXT].p_filesz 增加phdr[TEXT].p_filesz(文件长度)的长度为寄生代码的长度 增加phdr[TEXT].p_memsz(内存长度)的长度为寄生代码的长度
  • 对每个phdr(程序头),对应段若在寄生代码之后,则根据页长度增加对应的偏移
  • 找到text段的最后一个shdr(节头),把shdr[x].sh_size增加为寄生代码的长度
  • 对每个位于寄生代码插入位置之后shdr,根据页长度增加对应的偏移
  • 将真正的寄生代码插入到text段的file_base + phdr[TEXT].p_filesz(text段的尾部)

实现拆解

书中,感染算法是走C语言代码实现的(而且网上抄的代码跑不起来,也不好读。。。。所以还是得自己写一遍),由于当时没有好的elf文件patch工具,但是现在我们有了lief,为理解silvio的文件感染思路,打算使用lief来实现一遍。我们把silvio 感染分为两步,拓展 ,植入

如下代码实现了拓展,那植入就看各自所需了。

import lief

obj = lief.parse("./elf1")
segments = obj.segments
sections = obj.sections
header = obj.header
text_sec = obj.get_section(".text")
# print segment which .text belong to .
text_segment = ""
load_flag = False
# extend segments
for segment in segments:
if segment.type == lief.ELF.SEGMENT_TYPES.LOAD:
if segment.has(".text") :
text_segment = segment
segment.physical_size = segment.physical_size + 0x800
segment.virtual_size += 0x800
load_flag = True
continue
# if load_flag == True :
# segment.physical_size += 0x800

# extent sections
sec_flag = False
for sec in sections:
if sec.name == ".fini" :
sec.size += 0x800
#sec.virtual_address += 0x1000
sec_flag = True
continue
# if sec_flag == True :
# sec.size += 0x800

# modify entryp_point

#header.entrypoint = obj.entrypoint + 0x1000
print(type(obj.entrypoint))
obj.write("update_segment_section")

其他各种文件感染方法

data段感染

按照之前的逻辑,先拓展segment,section,再写入shellcode

假设shellcode长度为SIZEdai。

  1. 增加data section的offset
  2. 增加data所在segment的memsize 和filesize。
  3. 延后bss section的位置 —-》 拓展结束
  4. 调整data权限, 赋予执行权限。
  5. data 空余部分写入shellcode 。
  6. 修改ep。

将PT_NOTE 转化PT_LOAD

这个很简单,PT_NOTE 是临近PT_LOAD的最后一个segment,且不会被加载到内存。

‘参考链接’

自由组合load或自由使用间隙

分类: ELF

pareto

未来什么方向不管,先做自己喜欢做的事情。

0 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注