Driver: Add proc new/del logs.

This commit is contained in:
Nodir Temirkhodjaev 2017-11-24 13:53:11 +05:00
parent 21cf3a22f4
commit f734a01738
6 changed files with 266 additions and 77 deletions

View File

@ -5,7 +5,9 @@
#define FORT_LOG_ALIGN 4
#define FORT_LOG_FLAG_BLOCKED 0x01000000
#define FORT_LOG_FLAG_STAT 0x02000000
#define FORT_LOG_FLAG_PROC_NEW 0x02000000
#define FORT_LOG_FLAG_PROC_DEL 0x04000000
#define FORT_LOG_FLAG_STAT_TRAF 0x08000000
#define FORT_LOG_FLAG_TYPE_MASK 0xFF000000
#define FORT_LOG_BLOCKED_HEADER_SIZE (3 * sizeof(UINT32))
@ -16,6 +18,16 @@
#define FORT_LOG_BLOCKED_SIZE_MAX FORT_LOG_BLOCKED_SIZE(FORT_LOG_PATH_MAX)
#define FORT_LOG_PROC_NEW_HEADER_SIZE (2 * sizeof(UINT32))
#define FORT_LOG_PROC_NEW_SIZE(path_len) \
((FORT_LOG_PROC_NEW_HEADER_SIZE + (path_len) \
+ (FORT_LOG_ALIGN - 1)) & ~(FORT_LOG_ALIGN - 1))
#define FORT_LOG_PROC_DEL_SIZE (2 * sizeof(UINT32))
#define FORT_LOG_SIZE_MAX FORT_LOG_BLOCKED_SIZE_MAX
#define fort_log_type(p) (*((UINT32 *) (p)) & FORT_LOG_FLAG_TYPE_MASK)
@ -53,11 +65,49 @@ fort_log_blocked_header_read (const char *p, UINT32 *remote_ip, UINT32 *pid,
}
static void
fort_log_blocked_read (const char *p, UINT32 *remote_ip, UINT32 *pid,
UINT32 *path_len, const char **path)
fort_log_proc_new_header_write (char *p, UINT32 pid,
UINT32 path_len)
{
fort_log_blocked_header_read(p, remote_ip, pid, path_len);
UINT32 *up = (UINT32 *) p;
*path = p + FORT_LOG_BLOCKED_HEADER_SIZE;
*up++ = FORT_LOG_FLAG_PROC_NEW | path_len;
*up = pid;
}
static void
fort_log_proc_new_write (char *p, UINT32 pid,
UINT32 path_len, const char *path)
{
fort_log_proc_new_header_write(p, pid, path_len);
if (path_len) {
RtlCopyMemory(p + FORT_LOG_PROC_NEW_HEADER_SIZE, path, path_len);
}
}
static void
fort_log_proc_new_header_read (const char *p, UINT32 *pid,
UINT32 *path_len)
{
UINT32 *up = (UINT32 *) p;
*path_len = (*up++ & ~FORT_LOG_FLAG_TYPE_MASK);
*pid = *up;
}
static void
fort_log_proc_del_write (char *p, UINT32 pid)
{
UINT32 *up = (UINT32 *) p;
*up++ = FORT_LOG_FLAG_PROC_DEL;
*up = pid;
}
static void
fort_log_proc_del_read (const char *p, UINT32 *pid)
{
UINT32 *up = (UINT32 *) p;
*pid = *up;
}

View File

@ -104,15 +104,60 @@ fort_buffer_close (PFORT_BUFFER buf)
fort_buffer_data_del(buf->data_free);
}
static NTSTATUS
fort_buffer_prepare (PFORT_BUFFER buf, UINT32 len, PCHAR *out,
PIRP *irp, NTSTATUS *irp_status, ULONG_PTR *info)
{
/* Check pending buffer */
if (buf->out_len && buf->out_top < buf->out_len) {
const UINT32 out_top = buf->out_top;
UINT32 new_top = out_top + len;
/* Is it time to flush logs? */
if (buf->out_len - new_top < FORT_LOG_SIZE_MAX) {
if (irp != NULL) {
buf->out_len = 0;
*irp = buf->irp;
buf->irp = NULL;
*irp_status = STATUS_SUCCESS;
*info = new_top;
new_top = 0;
} else {
buf->out_len = out_top;
new_top = out_top;
}
}
*out = buf->out + out_top;
buf->out_top = new_top;
} else {
PFORT_BUFFER_DATA data = fort_buffer_data_alloc(buf, len);
const UINT32 buf_top = data ? data->top : FORT_BUFFER_SIZE;
const UINT32 new_top = buf_top + len;
if (new_top > FORT_BUFFER_SIZE) {
return STATUS_BUFFER_TOO_SMALL; /* drop on buffer overflow */
}
*out = data->p + buf_top;
data->top = new_top;
}
return STATUS_SUCCESS;
}
static NTSTATUS
fort_buffer_blocked_write (PFORT_BUFFER buf, UINT32 remote_ip, UINT32 pid,
UINT32 path_len, const PVOID path,
PIRP *irp, NTSTATUS *irp_status, ULONG_PTR *info)
{
UINT32 len;
PCHAR out;
UINT32 len;
KLOCK_QUEUE_HANDLE lock_queue;
NTSTATUS status = STATUS_SUCCESS;
NTSTATUS status;
if (path_len > FORT_LOG_PATH_MAX) {
path_len = 0; /* drop too long path */
@ -122,43 +167,64 @@ fort_buffer_blocked_write (PFORT_BUFFER buf, UINT32 remote_ip, UINT32 pid,
KeAcquireInStackQueuedSpinLock(&buf->lock, &lock_queue);
/* Try to directly write to pending client */
if (buf->out_len) {
const UINT32 out_top = buf->out_top;
UINT32 new_top = out_top + len;
status = fort_buffer_prepare(buf, len, &out,
irp, irp_status, info);
/* Is it time to flush logs? */
if (buf->out_len - new_top < FORT_LOG_BLOCKED_SIZE_MAX) {
buf->out_len = 0;
*irp = buf->irp;
buf->irp = NULL;
*irp_status = STATUS_SUCCESS;
*info = new_top;
new_top = 0;
}
out = buf->out + out_top;
buf->out_top = new_top;
} else {
PFORT_BUFFER_DATA data = fort_buffer_data_alloc(buf, len);
const UINT32 buf_top = data ? data->top : FORT_BUFFER_SIZE;
const UINT32 new_top = buf_top + len;
if (new_top > FORT_BUFFER_SIZE) {
status = STATUS_BUFFER_TOO_SMALL;
goto end; /* drop on buffer overflow */
}
out = data->p + buf_top;
data->top = new_top;
if (NT_SUCCESS(status)) {
fort_log_blocked_write(out, remote_ip, pid, path_len, path);
}
fort_log_blocked_write(out, remote_ip, pid, path_len, path);
KeReleaseInStackQueuedSpinLock(&lock_queue);
return status;
}
static NTSTATUS
fort_buffer_proc_new_write (PFORT_BUFFER buf, UINT32 pid,
UINT32 path_len, const PVOID path,
PIRP *irp, NTSTATUS *irp_status, ULONG_PTR *info)
{
PCHAR out;
UINT32 len;
KLOCK_QUEUE_HANDLE lock_queue;
NTSTATUS status;
if (path_len > FORT_LOG_PATH_MAX) {
path_len = 0; /* drop too long path */
}
len = FORT_LOG_PROC_NEW_SIZE(path_len);
KeAcquireInStackQueuedSpinLock(&buf->lock, &lock_queue);
status = fort_buffer_prepare(buf, len, &out,
irp, irp_status, info);
if (NT_SUCCESS(status)) {
fort_log_proc_new_write(out, pid, path_len, path);
}
KeReleaseInStackQueuedSpinLock(&lock_queue);
return status;
}
static NTSTATUS
fort_buffer_proc_del_write (PFORT_BUFFER buf, UINT32 pid)
{
PCHAR out;
const UINT32 len = FORT_LOG_PROC_DEL_SIZE;
KLOCK_QUEUE_HANDLE lock_queue;
NTSTATUS status;
KeAcquireInStackQueuedSpinLock(&buf->lock, &lock_queue);
status = fort_buffer_prepare(buf, len, &out, NULL, NULL, NULL);
if (NT_SUCCESS(status)) {
fort_log_proc_del_write(out, pid);
}
end:
KeReleaseInStackQueuedSpinLock(&lock_queue);
return status;
@ -181,7 +247,7 @@ fort_buffer_xmove (PFORT_BUFFER buf, PIRP irp, PVOID out, ULONG out_len,
if (!buf_top) {
if (buf->out_len) {
status = STATUS_INSUFFICIENT_RESOURCES;
} else if (out_len < FORT_LOG_BLOCKED_SIZE_MAX) {
} else if (out_len < FORT_LOG_SIZE_MAX) {
status = STATUS_BUFFER_TOO_SMALL;
} else {
buf->irp = irp;

View File

@ -172,10 +172,15 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
FORT_CONF_FLAGS conf_flags;
UINT32 flags;
UINT32 remote_ip;
UINT32 process_id;
UINT32 path_len;
PVOID path;
BOOL ip_included, blocked;
PIRP irp = NULL;
ULONG_PTR info;
NTSTATUS irp_status;
UNUSED(layerData);
UNUSED(flowContext);
@ -198,6 +203,7 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
goto permit;
remote_ip = inFixedValues->incomingValue[remoteIpField].value.uint32;
process_id = (UINT32) inMetaValues->processId;
path_len = inMetaValues->processPath->size - sizeof(WCHAR); // chop terminating zero
path = inMetaValues->processPath->data;
@ -209,44 +215,44 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
if (!blocked) {
if (ip_included && conf_flags.log_stat) {
fort_stat_flow_associate(&g_device->stat, inMetaValues->flowHandle,
g_device->flow4_id, (UINT32) inMetaValues->processId);
NTSTATUS status;
status = fort_stat_flow_associate(&g_device->stat,
inMetaValues->flowHandle, g_device->flow4_id, process_id);
if (NT_SUCCESS(status)) {
fort_buffer_proc_new_write(&g_device->buffer,
process_id, path_len, path,
&irp, &irp_status, &info);
} else if (status != STATUS_OBJECT_NAME_EXISTS) {
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
"FORT: Classify v4: Flow assoc. error: %d\n", status);
}
}
goto permit;
}
if (conf_flags.log_blocked) {
PIRP irp = NULL;
ULONG_PTR info;
NTSTATUS irp_status, status;
status = fort_buffer_blocked_write(
&g_device->buffer, remote_ip,
(UINT32) inMetaValues->processId, path_len, path,
&irp, &irp_status, &info);
if (NT_SUCCESS(status)) {
if (irp != NULL) {
fort_request_complete_info(irp, irp_status, info);
}
} else {
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
"FORT: Classify v4: Log buffer error: %d (path len: %d)\n",
status, path_len);
}
fort_buffer_blocked_write(&g_device->buffer,
remote_ip, process_id, path_len, path,
&irp, &irp_status, &info);
}
block:
classifyOut->actionType = FWP_ACTION_BLOCK;
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
return;
goto end;
permit:
classifyOut->actionType = FWP_ACTION_PERMIT;
if ((filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT)) {
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
}
return;
end:
if (irp != NULL) {
fort_request_complete_info(irp, irp_status, info);
}
}
static void
@ -298,7 +304,11 @@ fort_callout_flow_delete_v4 (UINT16 layerId,
UNUSED(layerId);
UNUSED(calloutId);
fort_stat_flow_delete(&g_device->stat, flowContext);
if (NT_SUCCESS(fort_stat_flow_delete(&g_device->stat, flowContext))) {
const UINT32 process_id = (UINT32) flowContext;
fort_buffer_proc_del_write(&g_device->buffer, process_id);
}
}
static void

View File

@ -46,23 +46,26 @@ fort_stat_proc_inc (PFORT_STAT stat, int proc_index)
proc->refcount++;
}
static void
static NTSTATUS
fort_stat_proc_dec (PFORT_STAT stat, int proc_index)
{
PFORT_STAT_PROC proc = &stat->procs[proc_index];
if (--proc->refcount > 0)
return;
return STATUS_OBJECT_NAME_EXISTS;
if (proc_index == stat->proc_top - 1) {
/* Chop from buffer */
stat->proc_top--;
return;
} else {
/* Add to free chain */
proc->process_id = 0;
proc->refcount = stat->proc_free_index;
stat->proc_free_index = proc_index;
}
proc->process_id = 0;
proc->refcount = stat->proc_free_index;
stat->proc_free_index = proc_index;
return STATUS_SUCCESS;
}
static void
@ -138,29 +141,34 @@ fort_stat_close (PFORT_STAT stat)
}
}
static void
static NTSTATUS
fort_stat_flow_associate (PFORT_STAT stat, UINT64 flow_id,
UINT32 callout_id, UINT32 process_id)
{
KLOCK_QUEUE_HANDLE lock_queue;
UINT64 flow_context;
int proc_index;
NTSTATUS status;
KeAcquireInStackQueuedSpinLock(&stat->lock, &lock_queue);
proc_index = fort_stat_proc_index(stat, process_id);
if (proc_index == -1) {
proc_index = fort_stat_proc_add(stat, process_id);
if (proc_index == -1)
if (proc_index == -1) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto end;
}
}
flow_context = (UINT64) process_id | ((UINT64) proc_index << 32);
fort_stat_proc_inc(stat, proc_index);
if (!NT_SUCCESS(FwpsFlowAssociateContext0(flow_id,
FWPS_LAYER_STREAM_V4, callout_id, flow_context))) {
status = FwpsFlowAssociateContext0(flow_id,
FWPS_LAYER_STREAM_V4, callout_id, flow_context);
if (!NT_SUCCESS(status)) {
fort_stat_proc_dec(stat, proc_index);
}
@ -169,22 +177,27 @@ fort_stat_flow_associate (PFORT_STAT stat, UINT64 flow_id,
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
"FORT: flow +: %d\n", process_id);
return status;
}
static void
static NTSTATUS
fort_stat_flow_delete (PFORT_STAT stat, UINT64 flow_context)
{
KLOCK_QUEUE_HANDLE lock_queue;
NTSTATUS status;
const int proc_index = (int) (flow_context >> 32);
KeAcquireInStackQueuedSpinLock(&stat->lock, &lock_queue);
fort_stat_proc_dec(stat, proc_index);
status = fort_stat_proc_dec(stat, proc_index);
KeReleaseInStackQueuedSpinLock(&lock_queue);
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
"FORT: flow -: %d\n", (UINT32) flow_context);
return status;
}
static void

View File

@ -53,6 +53,21 @@ quint32 FortCommon::logBlockedSize(quint32 pathLen)
return FORT_LOG_BLOCKED_SIZE(pathLen);
}
quint32 FortCommon::logProcNewHeaderSize()
{
return FORT_LOG_PROC_NEW_HEADER_SIZE;
}
quint32 FortCommon::logProcNewSize(quint32 pathLen)
{
return FORT_LOG_PROC_NEW_SIZE(pathLen);
}
quint32 FortCommon::logProcDelSize()
{
return FORT_LOG_PROC_DEL_SIZE;
}
quint32 FortCommon::logType(const char *input)
{
return fort_log_type(input);
@ -72,6 +87,28 @@ void FortCommon::logBlockedHeaderRead(const char *input,
fort_log_blocked_header_read(input, remoteIp, pid, pathLen);
}
void FortCommon::logProcNewHeaderWrite(char *output,
quint32 pid, quint32 pathLen)
{
fort_log_proc_new_header_write(output, pid, pathLen);
}
void FortCommon::logProcNewHeaderRead(const char *input,
quint32 *pid, quint32 *pathLen)
{
fort_log_proc_new_header_read(input, pid, pathLen);
}
void FortCommon::logProcDelWrite(char *output, quint32 pid)
{
fort_log_proc_del_write(output, pid);
}
void FortCommon::logProcDelRead(const char *input, quint32 *pid)
{
fort_log_proc_del_read(input, pid);
}
void FortCommon::confAppPermsMaskInit(void *drvConf)
{
fort_conf_app_perms_mask_init((PFORT_CONF) drvConf);

View File

@ -22,6 +22,11 @@ public:
static quint32 logBlockedHeaderSize();
static quint32 logBlockedSize(quint32 pathLen);
static quint32 logProcNewHeaderSize();
static quint32 logProcNewSize(quint32 pathLen);
static quint32 logProcDelSize();
static quint32 logType(const char *input);
static void logBlockedHeaderWrite(char *output,
@ -31,6 +36,14 @@ public:
quint32 *remoteIp, quint32 *pid,
quint32 *pathLen);
static void logProcNewHeaderWrite(char *output,
quint32 pid, quint32 pathLen);
static void logProcNewHeaderRead(const char *input,
quint32 *pid, quint32 *pathLen);
static void logProcDelWrite(char *output, quint32 pid);
static void logProcDelRead(const char *input, quint32 *pid);
static void confAppPermsMaskInit(void *drvConf);
static bool confIpInRange(const void *drvConf, quint32 ip,
bool included = false);