WSLua DissectorTable GUID Support

This commit is contained in:
Jason Tang 2023-11-01 22:01:15 +00:00 committed by Gilbert Ramirez
parent 14a934fb22
commit ec001766f6
7 changed files with 196 additions and 15 deletions

View File

@ -26,6 +26,7 @@
#include "config.h"
#include <guid-utils.h>
#include <stdio.h> /* for sscanf() */
#include <epan/packet.h>
#include <epan/exceptions.h>
@ -1658,6 +1659,28 @@ dissect_dcerpc_guid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *d
return tvb_captured_length(tvb);
}
static void
dcerpc_init_finalize(dissector_handle_t guid_handle, guid_key *key, dcerpc_uuid_value *value)
{
module_t *samr_module;
const char *filter_name = proto_get_protocol_filter_name(value->proto_id);
g_hash_table_insert(dcerpc_uuids, key, value);
/* Register the GUID with the dissector table */
dissector_add_guid( "dcerpc.uuid", key, guid_handle );
/* add this GUID to the global name resolving */
guids_add_uuid(&key->guid, proto_get_protocol_short_name(value->proto));
/* Register the samr.nt_password preference as obsolete */
/* This should be in packet-dcerpc-samr.c */
if (strcmp(filter_name, "samr") == 0) {
samr_module = prefs_register_protocol_obsolete(value->proto_id);
prefs_register_obsolete_preference(samr_module, "nt_password");
}
}
void
dcerpc_init_uuid(int proto, int ett, e_guid_t *uuid, guint16 ver,
dcerpc_sub_dissector *procs, int opnum_hf)
@ -1665,8 +1688,6 @@ dcerpc_init_uuid(int proto, int ett, e_guid_t *uuid, guint16 ver,
guid_key *key = (guid_key *)g_malloc(sizeof (*key));
dcerpc_uuid_value *value = (dcerpc_uuid_value *)g_malloc(sizeof (*value));
header_field_info *hf_info;
module_t *samr_module;
const char *filter_name = proto_get_protocol_filter_name(proto);
dissector_handle_t guid_handle;
key->guid = *uuid;
@ -1679,24 +1700,37 @@ dcerpc_init_uuid(int proto, int ett, e_guid_t *uuid, guint16 ver,
value->procs = procs;
value->opnum_hf = opnum_hf;
g_hash_table_insert(dcerpc_uuids, key, value);
hf_info = proto_registrar_get_nth(opnum_hf);
hf_info->strings = value_string_from_subdissectors(procs);
/* Register the GUID with the dissector table */
guid_handle = create_dissector_handle( dissect_dcerpc_guid, proto);
dissector_add_guid( "dcerpc.uuid", key, guid_handle );
/* add this GUID to the global name resolving */
guids_add_uuid(uuid, proto_get_protocol_short_name(value->proto));
dcerpc_init_finalize(guid_handle, key, value);
}
/* Register the samr.nt_password preference as obsolete */
/* This should be in packet-dcerpc-samr.c */
if (strcmp(filter_name, "samr") == 0) {
samr_module = prefs_register_protocol_obsolete(proto);
prefs_register_obsolete_preference(samr_module, "nt_password");
void
dcerpc_init_from_handle(int proto, e_guid_t *uuid, guint16 ver,
dissector_handle_t guid_handle)
{
guid_key *key = (guid_key *)g_malloc(sizeof (*key));
dcerpc_uuid_value *value = (dcerpc_uuid_value *)g_malloc(sizeof (*value));
key->guid = *uuid;
key->ver = ver;
value->proto = find_protocol_by_id(proto);
value->proto_id = proto;
value->ett = -1;
value->name = proto_get_protocol_short_name(value->proto);
value->opnum_hf = 0;
if (g_hash_table_contains(dcerpc_uuids, key)) {
g_hash_table_remove(dcerpc_uuids, key);
guids_delete_guid(uuid);
}
dcerpc_init_finalize(guid_handle, key, value);
}
/* Function to find the name of a registered protocol

View File

@ -392,6 +392,8 @@ typedef struct _dcerpc_sub_dissector {
WS_DLL_PUBLIC
void dcerpc_init_uuid (int proto, int ett, e_guid_t *uuid, guint16 ver, dcerpc_sub_dissector *procs, int opnum_hf);
WS_DLL_PUBLIC
void dcerpc_init_from_handle(int proto, e_guid_t *uuid, guint16 ver, dissector_handle_t guid_handle);
WS_DLL_PUBLIC
const char *dcerpc_get_proto_name(e_guid_t *uuid, guint16 ver);
WS_DLL_PUBLIC
int dcerpc_get_proto_hf_opnum(e_guid_t *uuid, guint16 ver);

View File

@ -106,6 +106,47 @@ guids_add_guid(const e_guid_t *guid, const gchar *name)
wmem_tree_insert32_array(guid_to_name_tree, &guidkey[0], (gchar *) name);
}
/* remove a guid to name mapping */
void
guids_delete_guid(const e_guid_t *guid)
{
wmem_tree_key_t guidkey[2];
guint32 g[4];
g[0] = guid->data1;
g[1] = guid->data2;
g[1] <<= 16;
g[1] |= guid->data3;
g[2] = guid->data4[0];
g[2] <<= 8;
g[2] |= guid->data4[1];
g[2] <<= 8;
g[2] |= guid->data4[2];
g[2] <<= 8;
g[2] |= guid->data4[3];
g[3] = guid->data4[4];
g[3] <<= 8;
g[3] |= guid->data4[5];
g[3] <<= 8;
g[3] |= guid->data4[6];
g[3] <<= 8;
g[3] |= guid->data4[7];
guidkey[0].key = g;
guidkey[0].length = 4;
guidkey[1].length = 0;
void *data = wmem_tree_lookup32_array(guid_to_name_tree, &guidkey[0]);
if (data != NULL) {
// This will "remove" the entry by setting its data to NULL
wmem_tree_insert32_array(guid_to_name_tree, &guidkey[0], NULL);
}
}
/* retrieve the registered name for this GUID; uses the scope for the fallback case only */
const gchar *

View File

@ -35,6 +35,9 @@ WS_DLL_PUBLIC void guids_init(void);
/* add a GUID */
WS_DLL_PUBLIC void guids_add_guid(const e_guid_t *guid, const gchar *name);
/* remove a guid to name mapping */
WS_DLL_PUBLIC void guids_delete_guid(const e_guid_t *guid);
/* try to get registered name for this GUID */
WS_DLL_PUBLIC const gchar *guids_get_guid_name(const e_guid_t *guid, wmem_allocator_t *scope);

View File

@ -1381,6 +1381,36 @@ void dissector_delete_uint_range(const char *name, range_t *range,
}
}
/* Remove an entry from a guid dissector table. */
void dissector_delete_guid(const char *name, guid_key* guid_val, dissector_handle_t handle)
{
dissector_table_t sub_dissectors;
dtbl_entry_t *dtbl_entry;
sub_dissectors = find_dissector_table(name);
/* sanity check */
ws_assert(sub_dissectors);
/* Find the table entry */
dtbl_entry = (dtbl_entry_t *)g_hash_table_lookup(sub_dissectors->hash_table, guid_val);
if (dtbl_entry == NULL) {
fprintf(stderr, "OOPS: guid not found in dissector table \"%s\"\n", name);
return;
}
/* Make sure the handles match */
if (dtbl_entry->current != handle) {
fprintf(stderr, "OOPS: handle does not match for guid in dissector table \"%s\"\n", name);
return;
}
/* Remove the table entry */
g_hash_table_remove(sub_dissectors->hash_table, guid_val);
}
static gboolean
dissector_delete_all_check (gpointer key _U_, gpointer value, gpointer user_data)
{

View File

@ -383,6 +383,10 @@ WS_DLL_PUBLIC int dissector_try_guid(dissector_table_t sub_dissectors,
WS_DLL_PUBLIC int dissector_try_guid_new(dissector_table_t sub_dissectors,
guid_key* guid_val, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const gboolean add_proto_name, void *data);
/* Delete a GUID from a dissector table. */
WS_DLL_PUBLIC void dissector_delete_guid(const char *name, guid_key* guid_val,
dissector_handle_t handle);
/** Look for a given value in a given guid dissector table and, if found,
* return the current dissector handle for that value.
*

View File

@ -17,11 +17,15 @@
#include "config.h"
#include "epan/guid-utils.h"
#include "epan/proto.h"
#include "wslua.h"
#include <epan/decode_as.h>
#include <epan/exceptions.h>
#include <epan/show_exception.h>
#include <epan/dissectors/packet-dcerpc.h>
#include <string.h>
/* WSLUA_CONTINUE_MODULE Proto */
@ -166,8 +170,8 @@ WSLUA_CONSTRUCTOR DissectorTable_new (lua_State *L) {
#define WSLUA_OPTARG_DissectorTable_new_UINAME 2 /* The name of the table in the user interface.
Defaults to the name given in `tablename`, but can be any string. */
#define WSLUA_OPTARG_DissectorTable_new_TYPE 3 /* One of `ftypes.UINT8`, `ftypes.UINT16`,
`ftypes.UINT24`, `ftypes.UINT32`, or
`ftypes.STRING`.
`ftypes.UINT24`, `ftypes.UINT32`,
`ftypes.STRING`, or `ftypes.GUID`.
Defaults to `ftypes.UINT32`. */
#define WSLUA_OPTARG_DissectorTable_new_BASE 4 /* One of `base.NONE`, `base.DEC`, `base.HEX`,
`base.OCT`, `base.DEC_HEX` or `base.HEX_DEC`.
@ -194,12 +198,16 @@ WSLUA_CONSTRUCTOR DissectorTable_new (lua_State *L) {
case FT_UINT32:
break;
case FT_GUID:
base = BASE_HEX;
break;
default:
/* Calling WSLUA_OPTARG_ERROR raises a Lua error and
returns from this function. */
WSLUA_OPTARG_ERROR(
DissectorTable_new, TYPE,
"must be ftypes.UINT{8,16,24,32}, ftypes.STRING or ftypes.NONE");
"must be ftypes.UINT{8,16,24,32}, ftypes.STRING, ftypes.GUID or ftypes.NONE");
break;
}
@ -397,6 +405,21 @@ WSLUA_METHOD DissectorTable_add (lua_State *L) {
gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN));
dissector_add_string(dt->name, pattern,handle);
g_free (pattern);
} else if (type == FT_GUID) {
/* Handle GUID type (assuming it is represented as a string in Lua) */
const gchar* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN);
fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL);
const e_guid_t* guid = fvalue_get_guid(fval);
guid_key gk = {*guid, 0};
/* The dcerpc.uuid table requires its own initializer */
if(strcmp(DCERPC_TABLE_NAME, dt->name) == 0) {
e_guid_t uuid;
memcpy(&uuid, guid, sizeof(e_guid_t));
dcerpc_init_from_handle(dissector_handle_get_protocol_index(handle), &uuid, 0, handle);
} else {
dissector_add_guid(dt->name, &gk, handle);
guids_add_uuid(guid, dissector_handle_get_protocol_short_name(handle));
}
} else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
if (lua_isnumber(L, WSLUA_ARG_DissectorTable_add_PATTERN)) {
int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_add_PATTERN);
@ -459,6 +482,21 @@ WSLUA_METHOD DissectorTable_set (lua_State *L) {
const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN);
dissector_delete_all(dt->name, handle);
dissector_add_string(dt->name, pattern,handle);
} else if (type == FT_GUID) {
/* Handle GUID type (assuming it is represented as a string in Lua) */
const gchar* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN);
fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL);
const e_guid_t* guid = fvalue_get_guid(fval);
guid_key gk = {*guid, 0};
/* The dcerpc.uuid table requires its own initializer */
if(strcmp(DCERPC_TABLE_NAME, dt->name) == 0) {
e_guid_t uuid;
memcpy(&uuid, guid, sizeof(e_guid_t));
dcerpc_init_from_handle(dissector_handle_get_protocol_index(handle), &uuid, 0, handle);
} else {
dissector_add_guid(dt->name, &gk, handle);
guids_add_uuid(guid, dissector_handle_get_protocol_short_name(handle));
}
} else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
if (lua_isnumber(L, WSLUA_ARG_DissectorTable_set_PATTERN)) {
int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_set_PATTERN);
@ -515,6 +553,14 @@ WSLUA_METHOD DissectorTable_remove (lua_State *L) {
gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN));
dissector_delete_string(dt->name, pattern,handle);
g_free (pattern);
} else if (type == FT_GUID) {
// Handle GUID type (assuming it is represented as a string in Lua)
const gchar* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN);
fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL);
const e_guid_t* guid = fvalue_get_guid(fval);
guid_key gk = {*guid, 0};
guids_delete_guid(guid);
dissector_delete_guid(dt->name, &gk, handle);
} else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
if (lua_isnumber(L, WSLUA_ARG_DissectorTable_remove_PATTERN)) {
int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_remove_PATTERN);
@ -596,6 +642,16 @@ WSLUA_METHOD DissectorTable_try (lua_State *L) {
if (len > 0) {
handled = TRUE;
}
} else if ( type == FT_GUID ) {
const gchar* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_try_PATTERN);
fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL);
const e_guid_t* guid = fvalue_get_guid(fval);
guid_key gk = {*guid, 0};
len = dissector_try_guid(dt->table, &gk,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree);
if (len > 0) {
handled = TRUE;
}
} else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_try_PATTERN);
@ -639,6 +695,12 @@ WSLUA_METHOD DissectorTable_get_dissector (lua_State *L) {
if (type == FT_STRING) {
const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_dissector_PATTERN);
handle = dissector_get_string_handle(dt->table,pattern);
} else if ( type == FT_GUID ) {
const gchar* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_dissector_PATTERN);
fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL);
const e_guid_t* guid = fvalue_get_guid(fval);
guid_key gk = {*guid, 0};
handle = dissector_get_guid_handle(dt->table,&gk);
} else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_get_dissector_PATTERN);
handle = dissector_get_uint_handle(dt->table,port);
@ -703,6 +765,11 @@ WSLUA_METAMETHOD DissectorTable__tostring(lua_State* L) {
g_string_append_printf(s,"%s Integer(%i):\n",dt->name,base);
break;
}
case FT_GUID:
{
g_string_append_printf(s,"%s GUID:\n",dt->name);
break;
}
case FT_NONE:
{
g_string_append_printf(s,"%s only for Decode As:\n",dt->name);