mirror of
https://github.com/tnodir/fort
synced 2024-11-15 07:45:22 +00:00
Driver: Add proc new/del logs.
This commit is contained in:
parent
21cf3a22f4
commit
f734a01738
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user