From a9634ab5a0b8d25e67a32e1cff8d0da8e3e2481c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 20 Jun 2016 08:00:20 +0200 Subject: [PATCH] packet-kerberos: add dissection of PAC_DEVICE_INFO Change-Id: I81a3d76e445fa59580f0e95e451092dc526f017d Signed-off-by: Stefan Metzmacher Reviewed-on: https://code.wireshark.org/review/37268 Petri-Dish: Alexis La Goutte Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- .../asn1/kerberos/packet-kerberos-template.c | 38 +++- epan/dissectors/packet-dcerpc-netlogon.c | 190 ++++++++++++++++-- epan/dissectors/packet-dcerpc-netlogon.h | 6 + epan/dissectors/packet-kerberos.c | 48 ++++- 4 files changed, 258 insertions(+), 24 deletions(-) diff --git a/epan/dissectors/asn1/kerberos/packet-kerberos-template.c b/epan/dissectors/asn1/kerberos/packet-kerberos-template.c index f52f9f4cb5..4e41f801b5 100644 --- a/epan/dissectors/asn1/kerberos/packet-kerberos-template.c +++ b/epan/dissectors/asn1/kerberos/packet-kerberos-template.c @@ -213,6 +213,7 @@ static gint ett_krb_pac_logon_info = -1; static gint ett_krb_pac_credential_info = -1; static gint ett_krb_pac_s4u_delegation_info = -1; static gint ett_krb_pac_upn_dns_info = -1; +static gint ett_krb_pac_device_info = -1; static gint ett_krb_pac_server_checksum = -1; static gint ett_krb_pac_privsvr_checksum = -1; static gint ett_krb_pac_client_info_type = -1; @@ -2287,6 +2288,12 @@ dissect_krb5_PAC_UPN_DNS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset static int dissect_krb5_PAC_CLIENT_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_) { + int length = tvb_captured_length_remaining(tvb, offset); + + if (length == 0) { + return offset; + } + proto_tree_add_item(parent_tree, hf_krb_pac_client_claims_info, tvb, offset, -1, ENC_NA); return offset; @@ -2295,7 +2302,29 @@ dissect_krb5_PAC_CLIENT_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int static int dissect_krb5_PAC_DEVICE_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_) { - proto_tree_add_item(parent_tree, hf_krb_pac_device_info, tvb, offset, -1, ENC_NA); + proto_item *item; + proto_tree *tree; + guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */ + static dcerpc_info di; /* fake dcerpc_info struct */ + static dcerpc_call_value call_data; + + item = proto_tree_add_item(parent_tree, hf_krb_pac_device_info, tvb, offset, -1, ENC_NA); + tree = proto_item_add_subtree(item, ett_krb_pac_device_info); + + /* skip the first 16 bytes, they are some magic created by the idl + * compiler the first 4 bytes might be flags? + */ + offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx); + + /* the PAC_DEVICE_INFO blob */ + /* fake whatever state the dcerpc runtime support needs */ + di.conformant_run=0; + /* we need di->call_data->flags.NDR64 == 0 */ + di.call_data=&call_data; + init_ndr_pointer_list(&di); + offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep, + netlogon_dissect_PAC_DEVICE_INFO, NDR_POINTER_UNIQUE, + "PAC_DEVICE_INFO:", -1); return offset; } @@ -2303,6 +2332,12 @@ dissect_krb5_PAC_DEVICE_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, static int dissect_krb5_PAC_DEVICE_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_) { + int length = tvb_captured_length_remaining(tvb, offset); + + if (length == 0) { + return offset; + } + proto_tree_add_item(parent_tree, hf_krb_pac_device_claims_info, tvb, offset, -1, ENC_NA); return offset; @@ -2949,6 +2984,7 @@ void proto_register_kerberos(void) { &ett_krb_pac_credential_info, &ett_krb_pac_s4u_delegation_info, &ett_krb_pac_upn_dns_info, + &ett_krb_pac_device_info, &ett_krb_pac_server_checksum, &ett_krb_pac_privsvr_checksum, &ett_krb_pac_client_info_type, diff --git a/epan/dissectors/packet-dcerpc-netlogon.c b/epan/dissectors/packet-dcerpc-netlogon.c index 0393821b2a..6370566fe5 100644 --- a/epan/dissectors/packet-dcerpc-netlogon.c +++ b/epan/dissectors/packet-dcerpc-netlogon.c @@ -263,6 +263,9 @@ static int hf_netlogon_logon_srv = -1; /* static int hf_netlogon_principal = -1; */ static int hf_netlogon_logon_dom = -1; static int hf_netlogon_resourcegroupcount = -1; +static int hf_netlogon_accountdomaingroupcount = -1; +static int hf_netlogon_domaingroupcount = -1; +static int hf_netlogon_membership_domains_count = -1; static int hf_netlogon_downlevel_domain_name = -1; static int hf_netlogon_dns_domain_name = -1; static int hf_netlogon_ad_client_dns_name = -1; @@ -433,6 +436,8 @@ static gint ett_trust_attribs = -1; static gint ett_get_dcname_request_flags = -1; static gint ett_dc_flags = -1; static gint ett_wstr_LOGON_IDENTITY_INFO_string = -1; +static gint ett_domain_group_memberships = -1; +static gint ett_domains_group_memberships = -1; static expert_field ei_netlogon_auth_nthash = EI_INIT; static expert_field ei_netlogon_session_key = EI_INIT; @@ -1587,6 +1592,104 @@ netlogon_dissect_USER_FLAGS(tvbuff_t *tvb, int offset, return offset; } +static int +netlogon_dissect_GROUP_MEMBERSHIPS(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, + dcerpc_info *di, guint8 *drep, + int hf_count, const char *array_name) +{ + guint32 rgc; + + offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, + hf_count, &rgc); + + offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep, + netlogon_dissect_GROUP_MEMBERSHIP_ARRAY, NDR_POINTER_UNIQUE, + array_name, -1); + + return offset; +} + +static int +netlogon_dissect_DOMAIN_GROUP_MEMBERSHIPS(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *parent_tree, + dcerpc_info *di, guint8 *drep, + int hf_count, const char *name) +{ + proto_item *item=NULL; + proto_tree *tree=NULL; + int old_offset=offset; + + if(parent_tree){ + tree = proto_tree_add_subtree(parent_tree, tvb, offset, 0, + ett_domain_group_memberships, + &item, name); + } + + offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, di, drep); + + offset = netlogon_dissect_GROUP_MEMBERSHIPS(tvb, offset, + pinfo, tree, + di, drep, + hf_count, + "GroupIDs"); + + proto_item_set_len(item, offset-old_offset); + return offset; +} + +static int +netlogon_dissect_DOMAIN_GROUP_MEMBERSHIPS_WRAPPER(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, + dcerpc_info *di, guint8 *drep) +{ + return netlogon_dissect_DOMAIN_GROUP_MEMBERSHIPS(tvb, offset, + pinfo, tree, + di, drep, + hf_netlogon_domaingroupcount, + "DomainGroupIDs"); +} + +static int +netlogon_dissect_DOMAIN_GROUP_MEMBERSHIP_ARRAY(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, + dcerpc_info *di, guint8 *drep) +{ + offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, di, drep, + netlogon_dissect_DOMAIN_GROUP_MEMBERSHIPS_WRAPPER); + + return offset; +} + +static int +netlogon_dissect_DOMAINS_GROUP_MEMBERSHIPS(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *parent_tree, + dcerpc_info *di, guint8 *drep, + int hf_count, const char *name) +{ + proto_item *item=NULL; + proto_tree *tree=NULL; + int old_offset=offset; + guint32 rgc; + + if(parent_tree){ + tree = proto_tree_add_subtree(parent_tree, tvb, offset, 0, + ett_domains_group_memberships, + &item, name); + } + + offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, + hf_count, &rgc); + + offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep, + netlogon_dissect_DOMAIN_GROUP_MEMBERSHIP_ARRAY, + NDR_POINTER_UNIQUE, + name, -1); + + proto_item_set_len(item, offset-old_offset); + return offset; +} + /* * IDL typedef struct { * IDL uint64 LogonTime; @@ -1671,12 +1774,10 @@ netlogon_dissect_VALIDATION_SAM_INFO(tvbuff_t *tvb, int offset, offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_netlogon_group_rid, NULL); - offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, - hf_netlogon_num_rids, NULL); - - offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep, - netlogon_dissect_GROUP_MEMBERSHIP_ARRAY, NDR_POINTER_UNIQUE, - "GROUP_MEMBERSHIP_ARRAY", -1); + offset = netlogon_dissect_GROUP_MEMBERSHIPS(tvb, offset, + pinfo, tree, di, drep, + hf_netlogon_num_rids, + "GroupIDs"); offset = netlogon_dissect_USER_FLAGS(tvb, offset, pinfo, tree, di, drep); @@ -1904,6 +2005,7 @@ netlogon_dissect_VALIDATION_SAM_INFO4(tvbuff_t *tvb, int offset, hf_netlogon_dummy_string10, 0); return offset; } + /* * IDL typedef struct { * IDL uint64 LogonTime; @@ -1944,7 +2046,6 @@ netlogon_dissect_PAC_LOGON_INFO(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) { - guint32 rgc; offset = netlogon_dissect_VALIDATION_SAM_INFO(tvb,offset,pinfo,tree,di, drep); #if 0 int i; @@ -2038,15 +2139,10 @@ netlogon_dissect_PAC_LOGON_INFO(tvbuff_t *tvb, int offset, dissect_ndr_nt_SID_AND_ATTRIBUTES_ARRAY, NDR_POINTER_UNIQUE, "SID_AND_ATTRIBUTES_ARRAY:", -1); - - offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, di, drep); - - offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, - hf_netlogon_resourcegroupcount, &rgc); - - offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep, - netlogon_dissect_GROUP_MEMBERSHIP_ARRAY, NDR_POINTER_UNIQUE, - "ResourceGroupIDs", -1); + offset = netlogon_dissect_DOMAIN_GROUP_MEMBERSHIPS(tvb, offset, + pinfo, tree, di, drep, + hf_netlogon_resourcegroupcount, + "ResourceGroupIDs"); return offset; } @@ -2091,6 +2187,52 @@ netlogon_dissect_PAC_S4U_DELEGATION_INFO(tvbuff_t *tvb, int offset, return offset; } +/* + * IDL typedef struct { + * IDL long UserId; + * IDL long PrimaryGroupId; + * IDL SID AccountDomainId; + * IDL long AccountGroupCount; + * IDL [size_is(AccountGroupCount)] PGROUP_MEMBERSHIP AccountGroupIds; + * IDL ULONG SidCount; + * IDL [size_is(SidCount)] PKERB_SID_AND_ATTRIBUTES ExtraSids; + * IDL ULONG DomainGroupCount; + * IDL [size_is(DomainGroupCount)] PDOMAIN_GROUP_MEMBERSHIP DomainGroup; + * IDL } PAC_DEVICE_INFO; + */ +int +netlogon_dissect_PAC_DEVICE_INFO(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, + dcerpc_info *di, guint8 *drep) +{ + offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, + hf_netlogon_user_rid, NULL); + + offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, + hf_netlogon_group_rid, NULL); + + offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, di, drep); + + offset = netlogon_dissect_GROUP_MEMBERSHIPS(tvb, offset, + pinfo, tree, di, drep, + hf_netlogon_accountdomaingroupcount, + "AccountDomainGroupIds"); + + offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, + hf_netlogon_num_sid, NULL); + + offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep, + dissect_ndr_nt_SID_AND_ATTRIBUTES_ARRAY, NDR_POINTER_UNIQUE, + "ExtraSids:SID_AND_ATTRIBUTES_ARRAY:", -1); + + offset = netlogon_dissect_DOMAINS_GROUP_MEMBERSHIPS(tvb, offset, + pinfo, tree, di, drep, + hf_netlogon_membership_domains_count, + "ExtraDomain Membership Array"); + + return offset; +} + #if 0 static int netlogon_dissect_PAC(tvbuff_t *tvb, int offset, @@ -8513,6 +8655,18 @@ proto_register_dcerpc_netlogon(void) { "ResourceGroup count", "netlogon.resourcegroupcount", FT_UINT32, BASE_DEC, NULL, 0, "Number of Resource Groups", HFILL }}, + { &hf_netlogon_accountdomaingroupcount, + { "AccountDomainGroup count", "netlogon.accountdomaingroupcount", FT_UINT32, BASE_DEC, + NULL, 0, "Number of Account Domain Groups", HFILL }}, + + { &hf_netlogon_domaingroupcount, + { "DomainGroup count", "netlogon.domaingroupcount", FT_UINT32, BASE_DEC, + NULL, 0, "Number of Domain Groups", HFILL }}, + + { &hf_netlogon_membership_domains_count, + { "Membership Domains count", "netlogon.membershipsdomainscount", FT_UINT32, BASE_DEC, + NULL, 0, "Number of ExtraDomain Membership Arrays", HFILL }}, + { &hf_netlogon_computer_name, { "Computer Name", "netlogon.computer_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, @@ -9522,7 +9676,9 @@ proto_register_dcerpc_netlogon(void) &ett_user_flags, &ett_nt_counted_longs_as_string, &ett_user_account_control, - &ett_wstr_LOGON_IDENTITY_INFO_string + &ett_wstr_LOGON_IDENTITY_INFO_string, + &ett_domain_group_memberships, + &ett_domains_group_memberships, }; static ei_register_info ei[] = { { &ei_netlogon_auth_nthash, { diff --git a/epan/dissectors/packet-dcerpc-netlogon.h b/epan/dissectors/packet-dcerpc-netlogon.h index 6be89bec9b..f552fad5df 100644 --- a/epan/dissectors/packet-dcerpc-netlogon.h +++ b/epan/dissectors/packet-dcerpc-netlogon.h @@ -79,4 +79,10 @@ netlogon_dissect_PAC_S4U_DELEGATION_INFO(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep); +/* needed to decrypt PAC_DEVICE_INFO in kerberos */ +int +netlogon_dissect_PAC_DEVICE_INFO(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, + dcerpc_info *di, guint8 *drep); + #endif /* packet-dcerpc-netlogon.h */ diff --git a/epan/dissectors/packet-kerberos.c b/epan/dissectors/packet-kerberos.c index 51c9ba42ea..94e209bfc7 100644 --- a/epan/dissectors/packet-kerberos.c +++ b/epan/dissectors/packet-kerberos.c @@ -434,6 +434,7 @@ static gint ett_krb_pac_logon_info = -1; static gint ett_krb_pac_credential_info = -1; static gint ett_krb_pac_s4u_delegation_info = -1; static gint ett_krb_pac_upn_dns_info = -1; +static gint ett_krb_pac_device_info = -1; static gint ett_krb_pac_server_checksum = -1; static gint ett_krb_pac_privsvr_checksum = -1; static gint ett_krb_pac_client_info_type = -1; @@ -518,7 +519,7 @@ static gint ett_kerberos_PA_FX_FAST_REPLY = -1; static gint ett_kerberos_KrbFastArmoredRep = -1; /*--- End of included file: packet-kerberos-ett.c ---*/ -#line 225 "./asn1/kerberos/packet-kerberos-template.c" +#line 226 "./asn1/kerberos/packet-kerberos-template.c" static expert_field ei_kerberos_decrypted_keytype = EI_INIT; static expert_field ei_kerberos_address = EI_INIT; @@ -639,7 +640,7 @@ typedef enum _KERBEROS_PADATA_TYPE_enum { } KERBEROS_PADATA_TYPE_enum; /*--- End of included file: packet-kerberos-val.h ---*/ -#line 237 "./asn1/kerberos/packet-kerberos-template.c" +#line 238 "./asn1/kerberos/packet-kerberos-template.c" static void call_kerberos_callbacks(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int tag, kerberos_callbacks *cb) @@ -2693,6 +2694,12 @@ dissect_krb5_PAC_UPN_DNS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset static int dissect_krb5_PAC_CLIENT_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_) { + int length = tvb_captured_length_remaining(tvb, offset); + + if (length == 0) { + return offset; + } + proto_tree_add_item(parent_tree, hf_krb_pac_client_claims_info, tvb, offset, -1, ENC_NA); return offset; @@ -2701,7 +2708,29 @@ dissect_krb5_PAC_CLIENT_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int static int dissect_krb5_PAC_DEVICE_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_) { - proto_tree_add_item(parent_tree, hf_krb_pac_device_info, tvb, offset, -1, ENC_NA); + proto_item *item; + proto_tree *tree; + guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */ + static dcerpc_info di; /* fake dcerpc_info struct */ + static dcerpc_call_value call_data; + + item = proto_tree_add_item(parent_tree, hf_krb_pac_device_info, tvb, offset, -1, ENC_NA); + tree = proto_item_add_subtree(item, ett_krb_pac_device_info); + + /* skip the first 16 bytes, they are some magic created by the idl + * compiler the first 4 bytes might be flags? + */ + offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx); + + /* the PAC_DEVICE_INFO blob */ + /* fake whatever state the dcerpc runtime support needs */ + di.conformant_run=0; + /* we need di->call_data->flags.NDR64 == 0 */ + di.call_data=&call_data; + init_ndr_pointer_list(&di); + offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep, + netlogon_dissect_PAC_DEVICE_INFO, NDR_POINTER_UNIQUE, + "PAC_DEVICE_INFO:", -1); return offset; } @@ -2709,6 +2738,12 @@ dissect_krb5_PAC_DEVICE_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, static int dissect_krb5_PAC_DEVICE_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_) { + int length = tvb_captured_length_remaining(tvb, offset); + + if (length == 0) { + return offset; + } + proto_tree_add_item(parent_tree, hf_krb_pac_device_claims_info, tvb, offset, -1, ENC_NA); return offset; @@ -5403,7 +5438,7 @@ dissect_kerberos_EncryptedChallenge(gboolean implicit_tag _U_, tvbuff_t *tvb _U_ /*--- End of included file: packet-kerberos-fn.c ---*/ -#line 2469 "./asn1/kerberos/packet-kerberos-template.c" +#line 2504 "./asn1/kerberos/packet-kerberos-template.c" #ifdef HAVE_KERBEROS static const ber_sequence_t PA_ENC_TS_ENC_sequence[] = { @@ -6706,7 +6741,7 @@ void proto_register_kerberos(void) { NULL, HFILL }}, /*--- End of included file: packet-kerberos-hfarr.c ---*/ -#line 2939 "./asn1/kerberos/packet-kerberos-template.c" +#line 2974 "./asn1/kerberos/packet-kerberos-template.c" }; /* List of subtrees */ @@ -6720,6 +6755,7 @@ void proto_register_kerberos(void) { &ett_krb_pac_credential_info, &ett_krb_pac_s4u_delegation_info, &ett_krb_pac_upn_dns_info, + &ett_krb_pac_device_info, &ett_krb_pac_server_checksum, &ett_krb_pac_privsvr_checksum, &ett_krb_pac_client_info_type, @@ -6804,7 +6840,7 @@ void proto_register_kerberos(void) { &ett_kerberos_KrbFastArmoredRep, /*--- End of included file: packet-kerberos-ettarr.c ---*/ -#line 2961 "./asn1/kerberos/packet-kerberos-template.c" +#line 2997 "./asn1/kerberos/packet-kerberos-template.c" }; static ei_register_info ei[] = {