Skip to content

Commit

Permalink
Added wrapper for the Melkor mutator
Browse files Browse the repository at this point in the history
Added a wrapper for the IO Active's Melkor ELF mutator. It requires the following patch:

joxeankoret/Melkor_ELF_Fuzzer@d1fb577

In order to add the 2 new mutators the following SQL commands must be executed:

 * insert into mutation_engines (name, description, command, date) values ('Melkor mutator', 'Melkor is a very intuitive and easy-to-use ELF file format fuzzer to find functional and security bugs in ELF parsers.' , '%NIGHTMARE_PATH%/mutators/melkor_mutator.py %TEMPLATES_PATH%/%FOLDER% 10 %OUTPUT%', current_date);

 * insert into mutation_engines (name, description, command, date) values ('Melkor mutator multiple', 'This is a wrapper using Melkor mutator to create a zip file with multiple fuzzed samples inside. Useful to fuzz Antivirus engines.', '%NIGHTMARE_PATH%/mutators/melkor_mutator_multiple.py %TEMPLATES_PATH%/%FOLDER% 20 %OUTPUT%', current_date);
  • Loading branch information
Joxean committed Nov 10, 2014
1 parent a458d45 commit ee81310
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 0 deletions.
81 changes: 81 additions & 0 deletions mutators/melkor_mutator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Nightmare Fuzzing Project
@author: joxean
"""

import os
import sys

from shutil import rmtree
from tempfile import mkdtemp

#-----------------------------------------------------------------------
class CMelkorMutator:
def __init__(self, input):
self.input = input

def get_diff(self, inbuf, outbuf):
ret = []
b1 = bytearray(inbuf)
b2 = bytearray(outbuf)
for i in range(len(inbuf)):
if b1[i] != b2[i]:
ret.append(str(i))
return ret

def read_directory(self, tmpdir):
base_file = os.path.basename(self.input)
base_dir = os.path.join(tmpdir, "orcs_%s" % base_file)
filename = os.path.join(base_dir, "Report_%s.txt" % base_file)
additional = open(filename, "rb").readlines()

filename = os.path.join(base_dir, "orc_0001")
return open(filename, "rb").read(), additional

def replace(self, output):
tmpdir = mkdtemp()
try:
old_dir = os.getcwd()
os.chdir(tmpdir)
os.system("melkor -a -q -n 1 %s" % self.input)
os.chdir(old_dir)

new_buf, additional = self.read_directory(tmpdir)
diff = self.get_diff(open(self.input, "rb").read(), new_buf)

# And, finally, write the output file
f = open(output, "wb")
f.write(new_buf)
f.close()

# ...and the .diff file too
f = open(output + ".diff", "wb")
f.write("# Original file created by 'Melkor Mutator' was %s\n" % self.input)
f.write("\n".join(diff))
f.write("\n")
for line in additional:
line = line.strip("\r").strip("\n")
f.write("# %s\n" % line)
f.close()
except:
print "Exception: %s" % sys.exc_info()[1]
finally:
rmtree(tmpdir)

#-----------------------------------------------------------------------
def main(input_file, output_file):
replacer = CMelkorMutator(input_file)
replacer.replace(output_file)

#-----------------------------------------------------------------------
def usage():
print "Usage:", sys.argv[0], "<input file> <output file>"

if __name__ == "__main__":
if len(sys.argv) != 3:
usage()
else:
main(sys.argv[1], sys.argv[2])

61 changes: 61 additions & 0 deletions mutators/melkor_mutator_multiple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Nightmare Fuzzing Project
This mutator creates a ZIP file with various mutated files inside.
@author: joxean
"""

import os
import sys
import random
import zipfile
import tempfile

from melkor_mutator import main as melkor_replace

#-----------------------------------------------------------------------
class CMultipleMelkorMutator:
def __init__(self, samples_path, total, output_zip):
self.samples_path = samples_path
self.total = total
self.output_zip = output_zip

def mutate(self):
with zipfile.ZipFile(self.output_zip, "w") as fuzz_zip:
fuzz_zip.comment = "NIGHTMARE"
for i in range(self.total):
name = tempfile.mktemp()
while 1:
template = random.choice(os.listdir(self.samples_path))
template = os.path.join(self.samples_path, template)
if os.path.isfile(template):
break
continue

melkor_replace(template, name)
try:
fuzz_zip.write(name)

# Add also the .diff file if it was created:
if os.path.exists(name + ".diff"):
fuzz_zip.write(name + ".diff")
os.remove(name + ".diff")
os.remove(name)
except:
print "Error:", sys.exc_info()[1]

#-----------------------------------------------------------------------
def main(path, number, output):
mutator = CMultipleMelkorMutator(path, int(number), output)
mutator.mutate()

#-----------------------------------------------------------------------
def usage():
print "Usage:", sys.argv[0], "samples_path #samples output_zip"

if __name__ == "__main__":
if len(sys.argv) != 4:
usage()
else:
main(sys.argv[1], sys.argv[2], sys.argv[3])

0 comments on commit ee81310

Please sign in to comment.