Providing extra information from signatures
Waffles-2 opened this issue · comments
Hi,
I have some working signatures and cannot seem to make it so when the signature is clicked, on the web page, that the extra bit of information is expanded below and displayed. I am assuming self.data.append is the way to do this, if anyone could help me out that would get great, cheers.
Below is my code I am trying to do it with:
from lib.cuckoo.common.abstracts import Signature
class rundll32(Signature):
name = "rundll32 loaded"
description = "Rundll32.exe has been executed"
severity = 1
categories = ["DLLs"]
authors = ["Daniel Perrie"]
minimum = "1.2"
evented = True
def __init__(self, *args, **kwargs):
Signature.__init__(self, *args, **kwargs)
self.dll = False
filter_apinames = set(["CreateProcessInternalW"])
def on_call(self, call, process):
if call["api"] == "CreateProcessInternalW":
funcName = self.get_argument(call, "ApplicationName")
if r"C:\Users\admin\AppData\Local\Temp\Cerber3.exe" in funcName:
processName = self.get_argument(call, "Process")
commandLineParameter = self.get_argument(call, "CommandLine")
self.data.append({"Process" : "%s executed rundll32.exe with the command line: %s" % (processName, commandLineParameter)})
self.dll = True
return self.dll
you need return True
if mached, and return False if not, so then cuckoo will know if it must be showed or not
but you already have one much better https://github.com/spender-sandbox/community-modified/blob/master/modules/signatures/cerber_apis.py
I have a return True
in there I just forgot to include it (I have amended it), so the problem is that the signature is being returned as True or false like it should be but it is not including the appended information, like other signatures.
And yeah I know that is a better one, I was just using Cerber as a placeholder for other exes such as rundll32.
you verified what is matched in ifs? you can add logging to see if it was True or False
Where you have the return self.dll is incorrect -- It'll stop processing your signature immediately after the first call to CreateProcessInternalW. Here's what happens regarding returns from on_call:
If you return True from the function, it will mark the signature as matched and stop calling the signature for future APIs. It will also not call the on_complete() function of the signature
If you return False from the function, it will stop calling the signature for future APIs and likewise will not call the on_complete() function of the signature.
What you need to do is return None or simply don't add any return, this will make the signature get called for every CreateProcessInternalW function. So if you want it to only add one entry below the signature for the first instance where it sees the cerber3.exe execution (and you should probably be doing case-insensitive matching there) then return True from the same indentation level as the self.data.append()
-Brad
@doomedraven The code above is correctly returning True or False that is not the problem, hopefully this gif will better illustrate my issue: https://gyazo.com/444c2627c21b3344b1167657b1cf8fbd
@spender-sandbox Thank you that explains it well, I shall try returning None. The cerber3.exe is just a placeholder for testing and will be changed to rundll32.exe, I'll add some matching there though thanks!
@spender-sandbox Hi Brad, sorry for the bother again. I'm struggling to make the changes that you have suggested and to make the signature so that it shows the entries below the signature as currently it doesn't show anything (https://gyazo.com/444c2627c21b3344b1167657b1cf8fbd)
EDIT:
Semi-working code the process in self.data.append isn't working.
from lib.cuckoo.common.abstracts import Signature
class rundll32(Signature):
name = "RunDll32"
description = "RUNDLL32.exe has been executed"
severity = 3
categories = ["anti-av"]
authors = ["Optiv"]
minimum = "1.2"
evented = True
def __init__(self, *args, **kwargs):
Signature.__init__(self, *args, **kwargs)
self.processName = None
self.commandLineParameter = None
filter_apinames = set(["CreateProcessInternalW"])
def on_call(self, call, process):
if call["api"] == "CreateProcessInternalW":
funcName = self.get_argument(call, "ApplicationName")
if r"C:\Users\admin\AppData\Local\Temp\Cerber3.exe" in funcName:
self.processName = self.get_argument(call, "Process")
self.commandLineParameter = self.get_argument(call, "CommandLine")
self.data.append({"Process" : "%s executed rundll32.exe with the command line: %s" % (self.processName, self.commandLineParameter)})
return True
You're returning True at the wrong indentation. Put it under the if.
-Brad
I have moved it under the other if statement, but it still only returns one result even though it should return multiple responses
def on_call(self, call, process):
if call["api"] == "CreateProcessInternalW":
funcName = self.get_argument(call, "ApplicationName")
if r"C:\Users\admin\AppData\Local\Temp\Cerber3.exe" in funcName:
self.processName = self.get_argument(call, "Process")
self.commandLineParameter = self.get_argument(call, "CommandLine")
self.data.append({"Process" : "%s executed rundll32.exe with the command line: %s" % (self.processName, self.commandLineParameter)})
return True
try to not return nothing as Brad told, and add def on_complate(self)
and do return there
So would it be like this? Because this does return as True but does not provide the information appended? Do I have to append the information in def on_complete(self)
?
def on_call(self, call, process):
if call["api"] == "CreateProcessInternalW":
funcName = self.get_argument(call, "ApplicationName")
if r"C:\Users\admin\AppData\Local\Temp\Cerber3.exe" in funcName:
#self.processName = self.get_argument(call, "Process")
self.commandLineParameter = self.get_argument(call, "CommandLine")
self.data.append({"Process" : " " + process["process_name"] + " executed rundll32.exe with the command line: %s" % (self.commandLineParameter)})
return None
def on_complete(self):
return True
yes, but i would suggest add some check to on_complate as is it will return True all the time even when is not cerber3
When I add a check it never returns true and always returns false, do you have an example of a check I could implement?
from lib.cuckoo.common.abstracts import Signature
class rundll32(Signature):
name = "RunDll32"
description = "RUNDLL32.exe has been executed"
severity = 3
categories = ["anti-av"]
authors = ["Optiv"]
minimum = "1.2"
evented = True
def __init__(self, *args, **kwargs):
Signature.__init__(self, *args, **kwargs)
self.processName = None
self.commandLineParameter = None
self.matched = False
filter_apinames = set(["CreateProcessInternalW"])
def on_call(self, call, process):
if call["api"] == "CreateProcessInternalW":
funcName = self.get_argument(call, "ApplicationName")
if r"C:\Users\admin\AppData\Local\Temp\Cerber3.exe" in funcName:
self.processName = self.get_argument(call, "Process")
self.commandLineParameter = self.get_argument(call, "CommandLine")
self.data.append({"Process" : "%s executed rundll32.exe with the command line: %s" % (self.processName, self.commandLineParameter)})
self.matched = True
def on_complete(self):
return self.matched
Brad, unfortunately that signature will always return as False, regardless of whether the on_call def sets self.matched to true, this is my final working signature (not sure if the return None
lines are necessary):
from lib.cuckoo.common.abstracts import Signature
class rundll32(Signature):
name = "RunDll32"
description = "RUNDLL32.exe has been executed"
severity = 1
categories = ["Dll execution"]
authors = ["Daniel Perrie"]
minimum = "1.2"
evented = True
def __init__(self, *args, **kwargs):
Signature.__init__(self, *args, **kwargs)
self.processName = None
self.commandLineParameter = None
filter_apinames = set(["CreateProcessInternalW"])
def on_call(self, call, process):
if call["api"] == "CreateProcessInternalW":
funcName = self.get_argument(call, "ApplicationName")
if r"C:\Windows\system32\rundll32.exe" in funcName:
self.processName = self.get_argument(call, "Process")
self.commandLineParameter = self.get_argument(call, "CommandLine")
self.data.append({"Process" : " " + process["process_name"] + " executed rundll32.exe with the command line: %s" % (self.commandLineParameter)})
return None
return None
def on_complete(self):
if len(self.data) > 0:
return True
else:
return False