평소 생각만 하고 언젠가 한번쯤 코딩해봐야지 했던 도구였는데 우연히 보게 되었다.
이 스크립트는 주로 타켓 공격에 많이 이용되는 PDF나 DOC 등 문서 파일의 취약점을 이용하여 악성코드를 감염시킬 때, 만약 문서파일 내부에 악성 PE파일이 있을 경우 뽑아주는 스크립트 이다.
물론 파일 내부에 삽입하지 않고 외부에서 다운로드 받아 실행하는 쉘코드가 들어가 있는 경우도 있지만 경험 상 PE파일이 삽입된 경우가 많았다.
이 스크립트에 사용된 라이브러리도 앞으로 꽤나 유용하게 쓰일거 같다 🙂
#!/usr/bin/python
# [ pyexedump.py ]
#
# By Neil Archibald
#
import sys
import yara # http://code.google.com/p/yara-project/
import pefile # http://code.google.com/p/pefile/
import md5
import mmap
class exedump:
__srch = """
rule exe_drop
{
strings:
$a = "This program cannot be run in DOS mode"
condition:
all of them
}
"""
MZSIZE = 78
def __init__(self, search_file):
self.__offset = None
self.__pe = None
self.__pe_size = None
self.__map = None
self.__rules = yara.compile(source=exedump.__srch)
self.__search_file = search_file
self.__matches = self.__rules.match(self.__search_file)
# end __init__
def __set_pe_size(self):
largest = 0
for section in self.__pe.sections:
addr = section.PointerToRawData + section.SizeOfRawData
if(addr > largest):
largest = addr
# end if
# end for
self.__pe_size = largest
def has_pe(self):
return (self.__matches and len(self.__matches) != 0)
def find_pe(self):
if not self.has_pe():
return None
self.__offset = self.__matches[0].strings[0][0] - exedump.MZSIZE # offset in file to start of MZ header
return self.__offset
def parse_pe(self):
if self.__offset == None and self.find_pe() == None:
return None
fp = open(self.__search_file,'r+b')
self.__map = mmap.mmap(fp.fileno(),0)
fp.close()
self.__pe = pefile.PE(data=self.__map[self.__offset:])
self.__set_pe_size()
self.__map = self.__map[self.__offset:self.__offset + self.__pe_size] #truncate extra bits
return self.__pe_size
def write_pe(self, filename=None):
if not self.__map:
return None
if not filename:
filename = self.gen_filename()
fp = open(filename, "wb+")
fp.write(self.__map)
fp.close()
return filename
def gen_filename(self):
m = md5.new()
m.update(self.__map)
filename = m.hexdigest() + ".exe"
return filename
def get_filesize(self):
if self.__pe_size == None:
self.__pe_size = self.__set_pe_size()
return self.__pe_size
# end exedump
def main(argv):
if(len(argv) != 2):
print "usage: %s \n" % argv[0]
sys.exit(1)
# end if
ed = exedump(argv[1])
if not ed.has_pe():
print "[!] error: no embedded executable file detected"
sys.exit(1)
# end if
print "[+] Searching for embedded EXE file in: %s" % argv[1]
offset = ed.find_pe()
print "[+] Found file embedded EXE at offset: 0x%x" % offset
file_size = ed.parse_pe()
print "[+] Size of PE file: 0x%x bytes." % file_size
exefilename = ed.gen_filename()
print "[+] Writing out exe file to: %s." % exefilename
ed.write_pe(exefilename)
# end main
if __name__ == "__main__":
main(sys.argv)
# end if
출처 : http://blogs.cisco.com/security/extracting-exe-drop-malware/