Skip to content
This repository was archived by the owner on Apr 22, 2020. It is now read-only.

Libcrack #1

Open
wants to merge 7 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
24 changes: 24 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
NAME = codebro
IMGNAME = $(NAME)
ACTIONS = help clean mrproper build run shell

help:
echo "Usage: make $(ACTIONS)"

clean:
docker ps -q -a -f name=$(NAME) | xargs docker rm -f

mrproper:
docker images -q -a $(IMGNAME) | xargs docker rmi -f

build:
docker build -t $(IMGNAME) .

run:
docker run -d --name=$(NAME) -p 127.0.0.1:8000:8000 $(IMGNAME)

shell:
docker exec -i -t $(NAME) /bin/bash

.PHONY: $(ACTIONS)
.SILENT: help
68 changes: 34 additions & 34 deletions codebro/analyzer/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ def clang_parse_file(request, project, file):

def add_function_declaration(project, file, data):
funcname, filename, line, rtype, args = data
function,created = Function.objects.get_or_create(name = funcname,
file = file,
project = project)
function.line = line
function, created = Function.objects.get_or_create(name=funcname,
file=file,
project=project)
function.line = line
function.rtype = rtype
function.save()

Expand All @@ -35,7 +35,7 @@ def add_function_declaration(project, file, data):
arg.function = function
arg.save()

if settings.DEBUG :
if settings.DEBUG:
print "%s %s is declared in %s:%d" % (function.name,
function.args,
function.file.relative_name,
Expand All @@ -46,13 +46,13 @@ def add_function_declaration(project, file, data):

def add_function_call(project, file, data):
(caller, infos) = data
caller, created = Function.objects.get_or_create(name = caller,
file = file,
project = project)
caller, created = Function.objects.get_or_create(name=caller,
file=file,
project=project)

callee, created = Function.objects.get_or_create(name = infos["name"],
file = file,
project = project)
callee, created = Function.objects.get_or_create(name=infos["name"],
file=file,
project=project)

xref = Xref()
xref.project = project
Expand All @@ -62,54 +62,55 @@ def add_function_call(project, file, data):

xref.save()

if settings.DEBUG :
if settings.DEBUG:
print "%s calls %s at %s:%d" % (xref.calling_function.name,
xref.called_function.name,
xref.calling_function.file.relative_name,
xref.called_function_line)

return


@transaction.commit_manually
def generate_file_xref(request, project, file, cparser=None):
local_instance = False

if file.is_parsed:
return False

if cparser is None :
if cparser is None:
cparser = ClangParser(project)
local_instance = True
try:

try:
for out in cparser.get_xref_calls(file.name):
if len(out) == 5: # FUNC_DECL
add_function_declaration(project, file, out)

elif len(out) == 2: # CALL_EXPR
add_function_call(project, file, out)

file.is_parsed = True
file.save()
except Exception, e:

except Exception as e:
if settings.DEBUG:
print "An exception occured", e
transaction.rollback()
return False

else:
transaction.commit()

if local_instance:
save_diagnostics(cparser, project)

return True



@transaction.commit_manually
def save_diagnostics(cparser, project):
try:
try:
for cat, fil, lin, error_msg in cparser.diags:
dbg = Debug()
dbg.category = cat
Expand All @@ -118,11 +119,11 @@ def save_diagnostics(cparser, project):
dbg.message = error_msg
dbg.project = project
dbg.save()
except:
except:
transaction.rollback()
else:
transaction.commit()

return


Expand All @@ -131,20 +132,19 @@ def generate_project_xref(request, project):
generate call xrefs in the project (i.e. on all files), and store them in database
"""
cparser = ClangParser(project)

for file in project.file_set.all():
generate_file_xref(request, project, file, cparser)
save_diagnostics(cparser, project)

save_diagnostics(cparser, project)

project.is_parsed = True
project.save()
if project.xref_set.count() :

if project.xref_set.count():
messages.success(request, "Successfully xref-ed")
return True
else :

else:
messages.error(request, "No xref have been established")
return False

105 changes: 52 additions & 53 deletions codebro/analyzer/clangparse.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import unipath
import clang
import clang

from os import access, R_OK, walk, path

Expand All @@ -10,138 +10,137 @@
from modules.format_string import FormatStringModule



class ClangParser:
"""

"""

def __init__(self, project, clang_args=[]):
"""

"""
clang.cindex.Config.set_library_file("/usr/lib/llvm-3.4/lib/libclang-3.4.so.1")
clang.cindex.Config.set_library_file(
"/usr/lib/llvm-3.4/lib/libclang-3.4.so.1")

self.project = project
self.root_dir = unipath.Path(self.project.code_path)
self.index = Index.create()
self.parser = None

self.clang_args = settings.CLANG_PARSE_OPTIONS
self.clang_args+= self.include_sub_dirs()
self.clang_args+= clang_args
self.clang_args += self.include_sub_dirs()
self.clang_args += clang_args

self.diags = []
self.modules = {}
self.register_modules( [FormatStringModule,] )

self.register_modules([FormatStringModule, ])

def register_modules(self, modules):
"""

"""
for module in modules :
for module in modules:
m = module(self)

# check for existing module id
already_exists = False
for mod in self.modules.values() :
if m.uid == mod.uid :
print("Module Id %d already declared for module '%s', cannot add" % (mod.uid, mod.name))
for mod in self.modules.values():
if m.uid == mod.uid:
print(
"Module Id %d already declared for module '%s', cannot add" %
(mod.uid, mod.name))
already_exists = True
break

if not already_exists:
m.register()

if settings.DEBUG :
print("Using module '%s' on project '%s'" % (m.name, m.module.project.name))


if settings.DEBUG:
print(
"Using module '%s' on project '%s'" %
(m.name, m.module.project.name))

def include_sub_dirs(self):
"""
append subdirs to clang include options
"""
subdirs = [ "-I"+ p.absolute() for p in self.root_dir.walk(filter=unipath.DIRS_NO_LINKS)]
subdirs = ["-I" + p.absolute()
for p in self.root_dir.walk(filter=unipath.DIRS_NO_LINKS)]
return subdirs


def enumerate_files(root_dir, extensions):
"""

"""
for root, dirs, files in walk(root_dir, topdown=True, followlinks=False):
for f in files :
for root, dirs, files in walk(
root_dir, topdown=True, followlinks=False):
for f in files:
fpath = path.join(root, f)
if not access(fpath, R_OK):
continue
for ext in extensions :

for ext in extensions:
if fpath.endswith(ext):
yield(fpath)


def inspect(self, node, caller):
"""

"""

if node.kind == CursorKind.FUNCTION_DECL :
if node.kind == CursorKind.FUNCTION_DECL:
caller = node.spelling

if node.location.file and not node.location.file.name.endswith(".h") :

if node.location.file and not node.location.file.name.endswith(
".h"):
return_type = node.type.get_result()
args = []

for c in node.get_children():
if c.kind == CursorKind.PARM_DECL:
args.append( (c.type.kind.spelling, c.displayname) )
args.append((c.type.kind.spelling, c.displayname))

func = [node.spelling,
node.location.file.name,
node.location.line,
return_type.kind.spelling,
args ]
args]

yield(func)


elif node.kind == CursorKind.CALL_EXPR:
infos = {}
infos['name'] = node.displayname
infos['line'] = node.location.line

for module in self.modules[CursorKind.CALL_EXPR] :
for module in self.modules[CursorKind.CALL_EXPR]:
module.run(node)

yield( (caller, infos) )


yield((caller, infos))

for n in node.get_children():
for i in self.inspect(n, caller) :
for i in self.inspect(n, caller):
yield i


def get_xref_calls(self, filename):
"""

"""

self.parser = self.index.parse(filename, args=self.clang_args)

if self.parser:
if len(self.parser.diagnostics) :
if len(self.parser.diagnostics):
for d in self.parser.diagnostics:
cat, loc, msg = d.category_number, d.location, d.spelling
if loc is None :
if loc is None:
file, line = "Unknown", 0
elif loc.file is None :
elif loc.file is None:
file, line = "Unknown", loc.line
else :
else:
file, line = loc.file.name, loc.line

self.diags.append((cat, file, line, msg))

for node in self.inspect(self.parser.cursor, "<OutOfScope>"):
yield node

Loading