Skip to content
This repository has been archived by the owner on Jun 7, 2018. It is now read-only.

Extract crash line if symbols present #44

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 36 additions & 10 deletions afl_utils/AflThread.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,22 @@ def run(self):
self.in_queue_lock.release()
self.exit = True

class Crash:
Copy link
Owner

@rc0r rc0r Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, maybe it's more suitable to call this class Sample since not necessarily all of the testing samples result in crashes?

def __init__(self, sample="", exploitability="", description="", hash="", line=""):
self.sample=""
self.exploitability=""
self.description=""
self.hash=""
self.line=""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably wanted to initialize member variables from arguments (even it's not used anywhere in the code atm)?

self.sample=sample
...


class GdbThread(threading.Thread):
def __init__(self, thread_id, gdb_cmd, out_dir, grep_for, out_queue, out_queue_lock):
def __init__(self, thread_id, gdb_cmd, out_dir, out_queue, out_queue_lock):
threading.Thread.__init__(self)
self.id = thread_id
self.gdb_cmd = gdb_cmd
self.out_dir = out_dir
self.out_queue = out_queue
self.out_queue_lock = out_queue_lock
self.grep_for = grep_for

def run(self):
try:
Expand All @@ -99,15 +105,35 @@ def run(self):
script_output = e.output

script_output = script_output.decode(errors='replace').splitlines()


crashes_array=[]
start=0
end=0
i=0
#to split the crashes and put them in an array
for line in script_output:
matching = [line.replace(g, '') for g in self.grep_for if g in line]
matching = " ".join(matching).strip('\' ')
matching = matching.replace(self.out_dir, '')
if len(matching) > 0:
self.out_queue_lock.acquire()
self.out_queue.put(matching)
self.out_queue_lock.release()
if "Crash sample:" in line:
start=i
if "Explanation:" in line:
crashes_array.append("\n".join(script_output[start:i+1]))
i+=1

for crash in crashes_array:
crash_obj=Crash()
for line in crash.split("\n"):
if "Crash sample: '" in line:
crash_obj.sample=line.split("Crash sample: '")[1][:-1]
elif "Exploitability Classification: " in line:
crash_obj.exploitability=line.split("Exploitability Classification: ")[1]
elif "Short description: " in line:
crash_obj.description=line.split("Short description: ")[1]
elif "Hash: " in line:
crash_obj.hash=line.split("Hash: ")[1]
elif " at " in line:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

" at " does not match any output line of my personal gdb+exploitable setup (rendering the entire pr uneffective). Could this be improved to be more generic?

This is supposed to extract source file and line (f.e. main.c:123) from the crashing location, right?

crash_obj.line=line.split(" at ")[1]
self.out_queue_lock.acquire()
self.out_queue.put(crash_obj)
self.out_queue_lock.release()


class AflTminThread(threading.Thread):
Expand Down
32 changes: 13 additions & 19 deletions afl_utils/afl_collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,6 @@ def execute_gdb_script(out_dir, script_filename, num_samples, num_threads):

out_dir = os.path.expanduser(out_dir) + "/"

grep_for = [
"Crash sample: '",
"Exploitability Classification: ",
"Short description: ",
"Hash: ",
]

queue_list = []
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to keep the list of exploitable output parsing keywords. This way they're all listed in one place throughout the code. So whenever the output of exploitable changes, we'll only have to update this list.


thread_list = []
Expand All @@ -256,7 +249,7 @@ def execute_gdb_script(out_dir, script_filename, num_samples, num_threads):
out_queue_lock = threading.Lock()
queue_list.append((out_queue, out_queue_lock))

t = AflThread.GdbThread(n, script_args, out_dir, grep_for, out_queue, out_queue_lock)
t = AflThread.GdbThread(n, script_args, out_dir, out_queue, out_queue_lock)
thread_list.append(t)
print_ok("Executing gdb+exploitable script '%s.%d'..." % (script_filename, n))
t.daemon = True
Expand All @@ -275,36 +268,36 @@ def execute_gdb_script(out_dir, script_filename, num_samples, num_threads):

i = 1
print("*** GDB+EXPLOITABLE SCRIPT OUTPUT ***")
for g in range(0, len(grepped_output)-len(grep_for)+1, len(grep_for)):
if grepped_output[g+3] == "EXPLOITABLE":
for crash in grepped_output:
if crash.exploitability == "EXPLOITABLE":
cex = clr.RED
ccl = clr.BRI
elif grepped_output[g+3] == "PROBABLY_EXPLOITABLE":
elif crash.exploitability == "PROBABLY_EXPLOITABLE":
cex = clr.YEL
ccl = clr.BRI
elif grepped_output[g+3] == "PROBABLY_NOT_EXPLOITABLE":
elif crash.exploitability == "PROBABLY_NOT_EXPLOITABLE":
cex = clr.BRN
ccl = clr.RST
elif grepped_output[g+3] == "NOT_EXPLOITABLE":
elif crash.exploitability == "NOT_EXPLOITABLE":
cex = clr.GRN
ccl = clr.GRA
elif grepped_output[g+3] == "UNKNOWN":
elif crash.exploitability == "UNKNOWN":
cex = clr.BLU
ccl = clr.GRA
else:
cex = clr.GRA
ccl = clr.GRA

if len(grepped_output[g]) < 24:
if len(crash.sample) < 24:
# Assume simplified sample file names,
# so save some output space.
ljust_width = 24
else:
ljust_width = 64
print("%s[%05d]%s %s: %s%s%s %s[%s]%s" % (clr.GRA, i, clr.RST, grepped_output[g].ljust(ljust_width, '.'), cex,
grepped_output[g+3], clr.RST, ccl, grepped_output[g+1], clr.RST))
classification_data.append({'Sample': grepped_output[g], 'Classification': grepped_output[g+3],
'Classification_Description': grepped_output[g+1], 'Hash': grepped_output[g+2],
print("%s[%05d]%s %s: %s%s%s %s[%s]%s %s" % (clr.GRA, i, clr.RST, crash.sample.ljust(ljust_width, '.'), cex,
crash.exploitability, clr.RST, ccl, crash.description, clr.RST, crash.line ))
classification_data.append({'Sample': crash.sample, 'Classification': crash.exploitability ,
'Classification_Description': crash.description, 'Hash': crash.hash,
'User_Comment': ''})
i += 1

Expand All @@ -322,6 +315,7 @@ def execute_gdb_script(out_dir, script_filename, num_samples, num_threads):
return classification_data



def main(argv):
show_info()

Expand Down