Skip to content

Commit

Permalink
merging branches
Browse files Browse the repository at this point in the history
  • Loading branch information
angelkillah committed Feb 19, 2014
1 parent 28748e1 commit ccf1aab
Show file tree
Hide file tree
Showing 18 changed files with 584 additions and 214 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
zer0m0n v0.3
zer0m0n v0.4
============

zer0m0n is a driver for Cuckoo Sandbox, it will perform kernel analysis during the execution of a malware. There are many ways for a malware author to bypass Cuckoo detection, he can detect the hooks, hardcodes the Nt* functions to avoid the hooks, detect the virtual machine... The goal of this driver is to offer the possibility for the user to choose between the classical userland analysis or a kernel analysis, which will be harder to detect or bypass.
Expand All @@ -8,6 +8,13 @@ Actually, it only works for XP 32 bit Windows machines, because of SSDT hooks us
CHANGELOG
=========

v0.4
+ bug fixes
+ more anti VM detection features
+ log new loaded modules through ZwCreateSection() hook
+ shadow ssdt hook
+ handle shutdown attempt through ExitWindowsEx() => abort analysis

v0.3
+ fix minor bugs
+ fix ZwTerminateProcess race condition (notify analyzer.py of process termination)
Expand Down
146 changes: 117 additions & 29 deletions bin/cuckoo.patch

Large diffs are not rendered by default.

Binary file modified bin/cuckoo_files.zip
Binary file not shown.
Binary file modified bin/logs_dispatcher.exe
Binary file not shown.
19 changes: 0 additions & 19 deletions bin/update_cuckoo.sh

This file was deleted.

Binary file modified bin/zer0m0n.sys
Binary file not shown.
2 changes: 2 additions & 0 deletions src/app/logtbl.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ const char *logtbl[] = {
"ZwQueryAttributesFile",
"ZwReadVirtualMemory",
"ZwResumeThread",
"ZwCreateSection",
"ZwUserCallOneParam",
NULL
};
char logtbl_explained[sizeof(logtbl)/sizeof(char *)] = {0};
41 changes: 26 additions & 15 deletions src/app/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Zer0m0n. If not, see <http://www.gnu.org/licenses/>.
//
// along with Zer0m0n. If not, see <http://www.gnu.org/licenses/>.//
//
// File : main.c
// Abstract : Main function for zer0m0n
Expand Down Expand Up @@ -54,7 +53,7 @@ int main(int argc, char **argv)
HANDLE hThreads[NUMBER_OF_THREADS];
int i;
init = 0;

RtlInitUnicodeString = (RTLINITUNICODESTRING)GetProcAddress(LoadLibrary("ntdll.dll"), "RtlInitUnicodeString");
if(RtlInitUnicodeString == NULL)
return -1;
Expand Down Expand Up @@ -105,6 +104,7 @@ int main(int argc, char **argv)
}
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Description : retrieve logs from kernel, parse them and send them to the cuckoo machine host
//
Expand Down Expand Up @@ -134,6 +134,7 @@ VOID parse_logs(PTHREAD_CONTEXT p)
HRESULT hr;

context = *p;
i=0, j=0;

log.funcname = NULL;
log.procname = NULL;
Expand Down Expand Up @@ -265,7 +266,7 @@ VOID parse_logs(PTHREAD_CONTEXT p)
if(log.nb_arguments)
log.arguments = (PARAMETERS*)malloc(log.nb_arguments * sizeof(PARAMETERS));

// for the moment, we only have 3 arguments/values maximum to log
// for the moment, we only have 7 arguments/values maximum to log
switch(log.nb_arguments)
{
case 0:
Expand All @@ -290,34 +291,34 @@ VOID parse_logs(PTHREAD_CONTEXT p)
i = log_resolve_index(log.funcname, 0);
loq(log.g_sock,i,log.funcname,log.success,log.ret,log.fmt,log.arguments[0].arg,log.arguments[0].value,log.arguments[1].arg,log.arguments[1].value,log.arguments[2].arg,log.arguments[2].value);
break;

case 4:
retrieve_parameters(log.nb_arguments, msg->message, ptr_msg, size, log.arguments);
i = log_resolve_index(log.funcname, 0);
loq(log.g_sock,i,log.funcname,log.success,log.ret,log.fmt,log.arguments[0].arg,log.arguments[0].value,log.arguments[1].arg,log.arguments[1].value,log.arguments[2].arg,log.arguments[2].value,log.arguments[3].arg,log.arguments[3].value);
break;

case 5:
retrieve_parameters(log.nb_arguments, msg->message, ptr_msg, size, log.arguments);
i = log_resolve_index(log.funcname, 0);
loq(log.g_sock,i,log.funcname,log.success,log.ret,log.fmt,log.arguments[0].arg,log.arguments[0].value,log.arguments[1].arg,log.arguments[1].value,log.arguments[2].arg,log.arguments[2].value,log.arguments[3].arg,log.arguments[3].value,log.arguments[4].arg,log.arguments[4].value);
break;

case 6:
retrieve_parameters(log.nb_arguments, msg->message, ptr_msg, size, log.arguments);
i = log_resolve_index(log.funcname, 0);
loq(log.g_sock,i,log.funcname,log.success,log.ret,log.fmt,log.arguments[0].arg,log.arguments[0].value,log.arguments[1].arg,log.arguments[1].value,log.arguments[2].arg,log.arguments[2].value,log.arguments[3].arg,log.arguments[3].value,log.arguments[4].arg,log.arguments[4].value,log.arguments[5].arg,log.arguments[5].value);
break;

case 7:
retrieve_parameters(log.nb_arguments, msg->message, ptr_msg, size, log.arguments);
i = log_resolve_index(log.funcname, 0);
loq(log.g_sock,i,log.funcname,log.success,log.ret,log.fmt,log.arguments[0].arg,log.arguments[0].value,log.arguments[1].arg,log.arguments[1].value,log.arguments[2].arg,log.arguments[2].value,log.arguments[3].arg,log.arguments[3].value,log.arguments[4].arg,log.arguments[4].value,log.arguments[5].arg,log.arguments[5].value,log.arguments[6].arg,log.arguments[6].value);
break;

default:
break;
}
}

// if the log contains "ZwWriteFile" as function name, notifies cuckoo that a file has to be dumpped
if(!strcmp(log.funcname, "ZwWriteFile") && !log.ret)
Expand All @@ -339,8 +340,17 @@ VOID parse_logs(PTHREAD_CONTEXT p)

// if a driver is loaded, notifies cuckoo to stop the analysis
if(!strcmp(log.funcname, "LOAD_DRIVER"))
{
printf("DRIVER LOADED ! Terminating analysis...\n");
pipe("KSUBVERT");
}

// if a shutdown/reboot is attempted, notifies cuckoo to stop the analysis
if(!strcmp(log.funcname, "ZwUserCallOneParam"))
{
printf("SHUTDOWN ATTEMPT BLOCKED !\n");
pipe("KSUBVERT");
}
// notifies analyzer.py that a process has terminated
if(!strcmp(log.funcname, "ZwTerminateProcess") && !log.ret)
pipe("KTERMINATE:%d", atoi(log.arguments[1].value));
Expand All @@ -360,19 +370,20 @@ VOID parse_logs(PTHREAD_CONTEXT p)
free(log.fmt);
log.fmt = NULL;
}

if(log.arguments)
{
for(j = 0; j < log.nb_arguments; j++)
for(i=0; i<log.nb_arguments; i++)
{
if(log.arguments[j].value != NULL)
free(log.arguments[j].value);
if(log.arguments[j].arg != NULL)
free(log.arguments[j].arg);
free(log.arguments[i].arg);
free(log.arguments[i].value);
}
free(log.arguments);
log.arguments = NULL;
}

memset(msg, 0, sizeof(KERNEL_MESSAGE));
}
free(msg);
cleanMonitoredProcessList();
}
30 changes: 30 additions & 0 deletions src/app/monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,36 @@
#include "monitor.h"
#include "main.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Description :
// Removes all of the monitored list entries (stops monitoring).
// Parameters :
// None
// Return value :
// int : 1 if no error was encountered, otherwise, returns -1.
// Process :
// Walks through the linked list and removes each entry.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
int cleanMonitoredProcessList()
{
PMONITORED_PROCESS_ENTRY currentMember, tempMember;

if(monitored_process_list == NULL)
return 1;

currentMember = monitored_process_list;
tempMember = NULL;
while(currentMember != NULL)
{
tempMember = currentMember;
currentMember = (PMONITORED_PROCESS_ENTRY)(currentMember->flink);
free(tempMember);
}

monitored_process_list = NULL;
return 1;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Description :
// Adds "pid" process in the monitored list and its associated socket id(starts monitoring this process).
Expand Down
10 changes: 10 additions & 0 deletions src/app/monitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ PMONITORED_PROCESS_ENTRY monitored_process_list;
// FUNCTIONS
/////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Description :
// Removes all of the monitored list entries (stops monitoring).
// Parameters :
// None
// Return value :
// int : 1 if no error was encountered, otherwise, returns -1.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
int cleanMonitoredProcessList();

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Description :
// Adds "pid" process in the monitored list and its associated socket id(starts monitoring this process).
Expand Down
26 changes: 13 additions & 13 deletions src/app/parsing.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,19 @@ void retrieve_parameters(int nb_arguments, char *msg, int ptr_msg, int size, PAR

for(i=0; i<nb_arguments; i++)
{
ptr_msg += size+1;
size = getsize(ptr_msg, msg, 0x3E);
tmp[i].arg = malloc(size);
tmp[i].arg[size-1] = 0x0;
memcpy(tmp[i].arg, msg+ptr_msg, size-1);
ptr_msg += size+1;
if( i == nb_arguments-1)
size = getsize(ptr_msg, msg, 0x00);
else
size = getsize(ptr_msg, msg, 0x2C);
tmp[i].value = malloc(size+1);
tmp[i].value[size] = 0x0;
memcpy(tmp[i].value, msg+ptr_msg, size);
ptr_msg += size+1;
size = getsize(ptr_msg, msg, 0x3E);
tmp[i].arg = malloc(size);
tmp[i].arg[size-1] = 0x0;
memcpy(tmp[i].arg, msg+ptr_msg, size-1);
ptr_msg += size+1;
if( i == nb_arguments-1)
size = getsize(ptr_msg, msg, 0x00);
else
size = getsize(ptr_msg, msg, 0x2C);
tmp[i].value = malloc(size+1);
tmp[i].value[size] = 0x0;
memcpy(tmp[i].value, msg+ptr_msg, size);
}
}

Expand Down
15 changes: 7 additions & 8 deletions src/app/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,26 +117,26 @@ static int _pipe_sprintf(char *out, const char *fmt, va_list args)

int pipe(const char *fmt, ...)
{
int len;
int len, ret;
va_list args;
char *buf;

va_start(args, fmt);

len = _pipe_sprintf(NULL, fmt, args);
if(len > 0) {
buf = malloc(len+1);
_pipe_sprintf(buf, fmt, args);
va_end(args);
return CallNamedPipe(g_pipe_name, buf, len, buf, len,
(unsigned long *) &len, NMPWAIT_WAIT_FOREVER);
ret = CallNamedPipe(g_pipe_name, buf, len, buf, len, (unsigned long *) &len, NMPWAIT_WAIT_FOREVER);
free(buf);
return ret;
}
return -1;
}

int pipe2(void *out, int *outlen, const char *fmt, ...)
{
int len;
int len, ret;
char *buf;
va_list args;
va_start(args, fmt);
Expand All @@ -145,10 +145,9 @@ int pipe2(void *out, int *outlen, const char *fmt, ...)
buf = malloc(len+1);
_pipe_sprintf(buf, fmt, args);
va_end(args);

free(buf);
return CallNamedPipe(g_pipe_name, buf, len, out, *outlen,
ret = CallNamedPipe(g_pipe_name, buf, len, out, *outlen,
(DWORD *) outlen, NMPWAIT_WAIT_FOREVER);
free(buf);
}
return -1;
}
8 changes: 7 additions & 1 deletion src/driver/comm.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,10 @@ NTSTATUS parse_pids(PCHAR pids)
first_pid=FALSE;
}
else
addHiddenProcess(pid);
{
if(pid)
addHiddenProcess(pid);
}
}
start = current+1;
}
Expand Down Expand Up @@ -284,6 +287,9 @@ NTSTATUS ioctl_DeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
switch(pIoStackIrp->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_PID:
// for tests only
//pid = *(ULONG*)Irp->AssociatedIrp.SystemBuffer;

// parse the pids received from cuckoo
status = parse_pids(Irp->AssociatedIrp.SystemBuffer);

Expand Down
Loading

0 comments on commit ccf1aab

Please sign in to comment.