ruby_smb 2.0.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/verify.yml +46 -0
- data/README.md +0 -1
- data/examples/anonymous_auth.rb +3 -3
- data/examples/append_file.rb +10 -8
- data/examples/auth_capture.rb +71 -0
- data/examples/authenticate.rb +9 -5
- data/examples/delete_file.rb +8 -6
- data/examples/dump_secrets_from_sid.rb +207 -0
- data/examples/enum_domain_users.rb +75 -0
- data/examples/enum_registry_key.rb +5 -4
- data/examples/enum_registry_values.rb +5 -4
- data/examples/get_computer_info.rb +42 -0
- data/examples/list_directory.rb +8 -6
- data/examples/negotiate_with_netbios_service.rb +9 -5
- data/examples/net_share_enum_all.rb +6 -4
- data/examples/pipes.rb +11 -12
- data/examples/query_service_status.rb +102 -0
- data/examples/read_file.rb +8 -6
- data/examples/read_registry_key_value.rb +6 -5
- data/examples/rename_file.rb +9 -7
- data/examples/tree_connect.rb +7 -5
- data/examples/write_file.rb +9 -7
- data/lib/ruby_smb/client/authentication.rb +5 -10
- data/lib/ruby_smb/client/echo.rb +2 -4
- data/lib/ruby_smb/client/negotiation.rb +13 -16
- data/lib/ruby_smb/client/tree_connect.rb +2 -4
- data/lib/ruby_smb/client/utils.rb +16 -10
- data/lib/ruby_smb/client/winreg.rb +1 -1
- data/lib/ruby_smb/client.rb +102 -75
- data/lib/ruby_smb/compression/lznt1.rb +164 -0
- data/lib/ruby_smb/compression.rb +7 -0
- data/lib/ruby_smb/dcerpc/bind.rb +28 -20
- data/lib/ruby_smb/dcerpc/bind_ack.rb +29 -28
- data/lib/ruby_smb/dcerpc/client.rb +542 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_bind_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_bind_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_request.rb +57 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_response.rb +76 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_request.rb +46 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_response.rb +168 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_extensions.rb +56 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_request.rb +121 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_response.rb +118 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_unbind_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_unbind_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/drsr.rb +909 -0
- data/lib/ruby_smb/dcerpc/epm/epm_ept_map_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/epm/epm_ept_map_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/epm/epm_twrt.rb +211 -0
- data/lib/ruby_smb/dcerpc/epm.rb +75 -0
- data/lib/ruby_smb/dcerpc/error.rb +20 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +1204 -80
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb +24 -0
- data/lib/ruby_smb/dcerpc/netlogon.rb +102 -0
- data/lib/ruby_smb/dcerpc/p_syntax_id_t.rb +4 -3
- data/lib/ruby_smb/dcerpc/pdu_header.rb +7 -7
- data/lib/ruby_smb/dcerpc/ptypes.rb +1 -0
- data/lib/ruby_smb/dcerpc/request.rb +85 -19
- data/lib/ruby_smb/dcerpc/response.rb +45 -10
- data/lib/ruby_smb/dcerpc/rpc_auth3.rb +28 -0
- data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
- data/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string.rb +118 -0
- data/lib/ruby_smb/dcerpc/samr/rpc_sid.rb +150 -0
- data/lib/ruby_smb/dcerpc/samr/samr_close_handle_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/samr/samr_close_handle_response.rb +24 -0
- data/lib/ruby_smb/dcerpc/samr/samr_connect_request.rb +32 -0
- data/lib/ruby_smb/dcerpc/samr/samr_connect_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response.rb +55 -0
- data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_request.rb +48 -0
- data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_response.rb +38 -0
- data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_response.rb +48 -0
- data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/samr/samr_open_domain_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/samr/samr_open_domain_response.rb +24 -0
- data/lib/ruby_smb/dcerpc/samr/samr_open_user_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/samr/samr_open_user_response.rb +24 -0
- data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/samr.rb +613 -0
- data/lib/ruby_smb/dcerpc/sec_trailer.rb +26 -0
- data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +56 -79
- data/lib/ruby_smb/dcerpc/srvsvc.rb +27 -4
- data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +36 -0
- data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +45 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +27 -0
- data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl.rb +477 -0
- data/lib/ruby_smb/dcerpc/uuid.rb +3 -0
- data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +2 -2
- data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +62 -0
- data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +2 -19
- data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +3 -20
- data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +5 -14
- data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +5 -14
- data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +1 -9
- data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +4 -3
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +6 -7
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +2 -2
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +9 -18
- data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +4 -13
- data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +7 -15
- data/lib/ruby_smb/dcerpc/winreg/regsam.rb +3 -1
- data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +28 -0
- data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/winreg.rb +99 -22
- data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response.rb +88 -0
- data/lib/ruby_smb/dcerpc/wkssvc.rb +65 -0
- data/lib/ruby_smb/dcerpc.rb +45 -11
- data/lib/ruby_smb/dialect.rb +45 -0
- data/lib/ruby_smb/dispatcher/base.rb +1 -1
- data/lib/ruby_smb/dispatcher/socket.rb +2 -2
- data/lib/ruby_smb/error.rb +21 -5
- data/lib/ruby_smb/field/file_time.rb +1 -1
- data/lib/ruby_smb/field/string16.rb +5 -1
- data/lib/ruby_smb/field/stringz16.rb +17 -1
- data/lib/ruby_smb/generic_packet.rb +11 -1
- data/lib/ruby_smb/gss/provider/authenticator.rb +42 -0
- data/lib/ruby_smb/gss/provider/ntlm.rb +303 -0
- data/lib/ruby_smb/gss/provider.rb +35 -0
- data/lib/ruby_smb/gss.rb +56 -63
- data/lib/ruby_smb/nbss/session_header.rb +4 -4
- data/lib/ruby_smb/ntlm.rb +61 -0
- data/lib/ruby_smb/server/server_client/negotiation.rb +156 -0
- data/lib/ruby_smb/server/server_client/session_setup.rb +82 -0
- data/lib/ruby_smb/server/server_client.rb +162 -0
- data/lib/ruby_smb/server.rb +54 -0
- data/lib/ruby_smb/signing.rb +59 -0
- data/lib/ruby_smb/smb1/file.rb +10 -25
- data/lib/ruby_smb/smb1/packet/negotiate_response.rb +11 -11
- data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +1 -1
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +1 -2
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +1 -13
- data/lib/ruby_smb/smb1/pipe.rb +12 -6
- data/lib/ruby_smb/smb1/tree.rb +13 -9
- data/lib/ruby_smb/smb2/file.rb +33 -33
- data/lib/ruby_smb/smb2/negotiate_context.rb +18 -2
- data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +4 -0
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +9 -0
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +0 -1
- data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -2
- data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +1 -1
- data/lib/ruby_smb/smb2/pipe.rb +13 -6
- data/lib/ruby_smb/smb2/tree.rb +21 -11
- data/lib/ruby_smb/smb2.rb +3 -1
- data/lib/ruby_smb/version.rb +1 -1
- data/lib/ruby_smb.rb +5 -3
- data/spec/lib/ruby_smb/client_spec.rb +199 -86
- data/spec/lib/ruby_smb/compression/lznt1_spec.rb +32 -0
- data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +69 -41
- data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +75 -21
- data/spec/lib/ruby_smb/dcerpc/client_spec.rb +714 -0
- data/spec/lib/ruby_smb/dcerpc/drsr_spec.rb +2169 -0
- data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +3977 -239
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request_spec.rb +69 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response_spec.rb +53 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request_spec.rb +69 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response_spec.rb +37 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request_spec.rb +45 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response_spec.rb +37 -0
- data/spec/lib/ruby_smb/dcerpc/p_syntax_id_t_spec.rb +18 -4
- data/spec/lib/ruby_smb/dcerpc/pdu_header_spec.rb +27 -1
- data/spec/lib/ruby_smb/dcerpc/request_spec.rb +76 -11
- data/spec/lib/ruby_smb/dcerpc/response_spec.rb +99 -9
- data/spec/lib/ruby_smb/dcerpc/rpc_auth3_spec.rb +75 -0
- data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +162 -0
- data/spec/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string_spec.rb +340 -0
- data/spec/lib/ruby_smb/dcerpc/samr/rpc_sid_spec.rb +116 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_request_spec.rb +40 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_response_spec.rb +48 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_request_spec.rb +56 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_response_spec.rb +47 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request_spec.rb +63 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response_spec.rb +265 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request_spec.rb +52 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response_spec.rb +36 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_request_spec.rb +56 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_response_spec.rb +48 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request_spec.rb +48 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response_spec.rb +42 -0
- data/spec/lib/ruby_smb/dcerpc/samr_spec.rb +420 -0
- data/spec/lib/ruby_smb/dcerpc/sec_trailer_spec.rb +92 -0
- data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +149 -110
- data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +21 -17
- data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +168 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +39 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +68 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +53 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +152 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +76 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +47 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +508 -0
- data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +15 -23
- data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +73 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +44 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +4 -56
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +4 -56
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +10 -34
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +10 -34
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +2 -26
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +17 -20
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +0 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +20 -44
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +8 -32
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +18 -42
- data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +4 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +45 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
- data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +219 -62
- data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request_spec.rb +43 -0
- data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response_spec.rb +410 -0
- data/spec/lib/ruby_smb/dcerpc/wkssvc_spec.rb +70 -0
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +10 -10
- data/spec/lib/ruby_smb/error_spec.rb +34 -5
- data/spec/lib/ruby_smb/field/string16_spec.rb +22 -0
- data/spec/lib/ruby_smb/field/stringz16_spec.rb +12 -0
- data/spec/lib/ruby_smb/generic_packet_spec.rb +7 -0
- data/spec/lib/ruby_smb/gss/provider/ntlm/account_spec.rb +32 -0
- data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +101 -0
- data/spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb +32 -0
- data/spec/lib/ruby_smb/gss/provider/ntlm_spec.rb +113 -0
- data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
- data/spec/lib/ruby_smb/server/server_client_spec.rb +156 -0
- data/spec/lib/ruby_smb/server_spec.rb +32 -0
- data/spec/lib/ruby_smb/smb1/file_spec.rb +2 -4
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +0 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +0 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +0 -5
- data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +0 -6
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +20 -14
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +22 -0
- data/spec/lib/ruby_smb/smb2/file_spec.rb +61 -9
- data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +20 -14
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +58 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/support/bin_helper.rb +9 -0
- data.tar.gz.sig +0 -0
- metadata +229 -23
- metadata.gz.sig +0 -0
- data/.travis.yml +0 -6
- data/lib/ruby_smb/client/signing.rb +0 -64
- data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +0 -35
- data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +0 -98
data/lib/ruby_smb/client.rb
CHANGED
|
@@ -2,18 +2,19 @@ module RubySMB
|
|
|
2
2
|
# Represents an SMB client capable of talking to SMB1 or SMB2 servers and handling
|
|
3
3
|
# all end-user client functionality.
|
|
4
4
|
class Client
|
|
5
|
+
require 'ruby_smb/ntlm'
|
|
6
|
+
require 'ruby_smb/signing'
|
|
5
7
|
require 'ruby_smb/client/negotiation'
|
|
6
8
|
require 'ruby_smb/client/authentication'
|
|
7
|
-
require 'ruby_smb/client/signing'
|
|
8
9
|
require 'ruby_smb/client/tree_connect'
|
|
9
10
|
require 'ruby_smb/client/echo'
|
|
10
11
|
require 'ruby_smb/client/utils'
|
|
11
12
|
require 'ruby_smb/client/winreg'
|
|
12
13
|
require 'ruby_smb/client/encryption'
|
|
13
14
|
|
|
15
|
+
include RubySMB::Signing
|
|
14
16
|
include RubySMB::Client::Negotiation
|
|
15
17
|
include RubySMB::Client::Authentication
|
|
16
|
-
include RubySMB::Client::Signing
|
|
17
18
|
include RubySMB::Client::TreeConnect
|
|
18
19
|
include RubySMB::Client::Echo
|
|
19
20
|
include RubySMB::Client::Utils
|
|
@@ -160,9 +161,16 @@ module RubySMB
|
|
|
160
161
|
|
|
161
162
|
# The UID set in SMB1
|
|
162
163
|
# @!attribute [rw] user_id
|
|
163
|
-
# @return [
|
|
164
|
+
# @return [Integer]
|
|
164
165
|
attr_accessor :user_id
|
|
165
166
|
|
|
167
|
+
# The Process ID set in SMB1
|
|
168
|
+
# It is randomly generated during the client initialization, but can
|
|
169
|
+
# be modified using the accessor.
|
|
170
|
+
# @!attribute [rw] pid
|
|
171
|
+
# @return [Integer]
|
|
172
|
+
attr_accessor :pid
|
|
173
|
+
|
|
166
174
|
# The maximum size SMB message that the Client accepts (in bytes)
|
|
167
175
|
# The default value is equal to {MAX_BUFFER_SIZE}.
|
|
168
176
|
# @!attribute [rw] max_buffer_size
|
|
@@ -258,16 +266,26 @@ module RubySMB
|
|
|
258
266
|
# @return [Integer] the negotiated SMB version
|
|
259
267
|
attr_accessor :negotiated_smb_version
|
|
260
268
|
|
|
269
|
+
# Whether or not the server supports multi-credit operations. It is
|
|
270
|
+
# reported by the LARGE_MTU capabiliy as part of the negotiation process
|
|
271
|
+
# (SMB 2.x and 3.x).
|
|
272
|
+
# @!attribute [rw] server_supports_multi_credit
|
|
273
|
+
# @return [Boolean] true if the server supports multi-credit operations,
|
|
274
|
+
# false otherwise
|
|
275
|
+
attr_accessor :server_supports_multi_credit
|
|
276
|
+
|
|
261
277
|
# @param dispatcher [RubySMB::Dispatcher::Socket] the packet dispatcher to use
|
|
262
278
|
# @param smb1 [Boolean] whether or not to enable SMB1 support
|
|
263
279
|
# @param smb2 [Boolean] whether or not to enable SMB2 support
|
|
264
280
|
# @param smb3 [Boolean] whether or not to enable SMB3 support
|
|
265
|
-
def initialize(dispatcher, smb1: true, smb2: true, smb3: true, username:, password:, domain: '.',
|
|
281
|
+
def initialize(dispatcher, smb1: true, smb2: true, smb3: true, username:, password:, domain: '.',
|
|
282
|
+
local_workstation: 'WORKSTATION', always_encrypt: true, ntlm_flags: NTLM::DEFAULT_CLIENT_FLAGS)
|
|
266
283
|
raise ArgumentError, 'No Dispatcher provided' unless dispatcher.is_a? RubySMB::Dispatcher::Base
|
|
267
284
|
if smb1 == false && smb2 == false && smb3 == false
|
|
268
285
|
raise ArgumentError, 'You must enable at least one Protocol'
|
|
269
286
|
end
|
|
270
287
|
@dispatcher = dispatcher
|
|
288
|
+
@pid = rand(0xFFFF)
|
|
271
289
|
@domain = domain
|
|
272
290
|
@local_workstation = local_workstation
|
|
273
291
|
@password = password.encode('utf-8') || ''.encode('utf-8')
|
|
@@ -280,27 +298,22 @@ module RubySMB
|
|
|
280
298
|
@smb3 = smb3
|
|
281
299
|
@username = username.encode('utf-8') || ''.encode('utf-8')
|
|
282
300
|
@max_buffer_size = MAX_BUFFER_SIZE
|
|
283
|
-
# These sizes will be
|
|
301
|
+
# These sizes will be modified during negotiation
|
|
284
302
|
@server_max_buffer_size = SERVER_MAX_BUFFER_SIZE
|
|
285
303
|
@server_max_read_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
|
|
286
304
|
@server_max_write_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
|
|
287
305
|
@server_max_transact_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
|
|
306
|
+
@server_supports_multi_credit = false
|
|
288
307
|
|
|
289
308
|
# SMB 3.x options
|
|
290
309
|
@session_encrypt_data = always_encrypt
|
|
291
310
|
|
|
292
|
-
negotiate_version_flag = 0x02000000
|
|
293
|
-
flags = Net::NTLM::Client::DEFAULT_FLAGS |
|
|
294
|
-
Net::NTLM::FLAGS[:TARGET_INFO] |
|
|
295
|
-
negotiate_version_flag ^
|
|
296
|
-
Net::NTLM::FLAGS[:OEM]
|
|
297
|
-
|
|
298
311
|
@ntlm_client = Net::NTLM::Client.new(
|
|
299
312
|
@username,
|
|
300
313
|
@password,
|
|
301
314
|
workstation: @local_workstation,
|
|
302
315
|
domain: @domain,
|
|
303
|
-
flags:
|
|
316
|
+
flags: ntlm_flags
|
|
304
317
|
)
|
|
305
318
|
|
|
306
319
|
@tree_connects = []
|
|
@@ -344,38 +357,35 @@ module RubySMB
|
|
|
344
357
|
# @param packet [RubySMB::GenericPacket] the packet to set the message id for
|
|
345
358
|
# @return [RubySMB::GenericPacket] the modified packet
|
|
346
359
|
def increment_smb_message_id(packet)
|
|
347
|
-
packet.smb2_header.message_id = smb2_message_id
|
|
360
|
+
packet.smb2_header.message_id = self.smb2_message_id
|
|
348
361
|
self.smb2_message_id += 1
|
|
349
362
|
packet
|
|
350
363
|
end
|
|
351
364
|
|
|
352
365
|
# Performs protocol negotiation and session setup. It defaults to using
|
|
353
366
|
# the credentials supplied during initialization, but can take a new set of credentials if needed.
|
|
354
|
-
def login(username: self.username, password: self.password,
|
|
367
|
+
def login(username: self.username, password: self.password,
|
|
368
|
+
domain: self.domain, local_workstation: self.local_workstation,
|
|
369
|
+
ntlm_flags: NTLM::DEFAULT_CLIENT_FLAGS)
|
|
355
370
|
negotiate
|
|
356
|
-
session_setup(username, password, domain,
|
|
357
|
-
local_workstation: local_workstation
|
|
371
|
+
session_setup(username, password, domain,
|
|
372
|
+
local_workstation: local_workstation,
|
|
373
|
+
ntlm_flags: ntlm_flags)
|
|
358
374
|
end
|
|
359
375
|
|
|
360
376
|
def session_setup(user, pass, domain, do_recv=true,
|
|
361
|
-
local_workstation: self.local_workstation)
|
|
377
|
+
local_workstation: self.local_workstation, ntlm_flags: NTLM::DEFAULT_CLIENT_FLAGS)
|
|
362
378
|
@domain = domain
|
|
363
379
|
@local_workstation = local_workstation
|
|
364
380
|
@password = pass.encode('utf-8') || ''.encode('utf-8')
|
|
365
381
|
@username = user.encode('utf-8') || ''.encode('utf-8')
|
|
366
382
|
|
|
367
|
-
negotiate_version_flag = 0x02000000
|
|
368
|
-
flags = Net::NTLM::Client::DEFAULT_FLAGS |
|
|
369
|
-
Net::NTLM::FLAGS[:TARGET_INFO] |
|
|
370
|
-
negotiate_version_flag ^
|
|
371
|
-
Net::NTLM::FLAGS[:OEM]
|
|
372
|
-
|
|
373
383
|
@ntlm_client = Net::NTLM::Client.new(
|
|
374
384
|
@username,
|
|
375
385
|
@password,
|
|
376
386
|
workstation: @local_workstation,
|
|
377
387
|
domain: @domain,
|
|
378
|
-
flags:
|
|
388
|
+
flags: ntlm_flags
|
|
379
389
|
)
|
|
380
390
|
|
|
381
391
|
authenticate
|
|
@@ -394,8 +404,7 @@ module RubySMB
|
|
|
394
404
|
raise RubySMB::Error::InvalidPacket.new(
|
|
395
405
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
|
396
406
|
expected_cmd: RubySMB::SMB2::Packet::LogoffResponse::COMMAND,
|
|
397
|
-
|
|
398
|
-
received_cmd: response.smb2_header.command
|
|
407
|
+
packet: response
|
|
399
408
|
)
|
|
400
409
|
end
|
|
401
410
|
else
|
|
@@ -406,8 +415,7 @@ module RubySMB
|
|
|
406
415
|
raise RubySMB::Error::InvalidPacket.new(
|
|
407
416
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
|
408
417
|
expected_cmd: RubySMB::SMB1::Packet::LogoffResponse::COMMAND,
|
|
409
|
-
|
|
410
|
-
received_cmd: response.smb_header.command
|
|
418
|
+
packet: response
|
|
411
419
|
)
|
|
412
420
|
end
|
|
413
421
|
end
|
|
@@ -416,7 +424,7 @@ module RubySMB
|
|
|
416
424
|
end
|
|
417
425
|
|
|
418
426
|
# Sends a packet and receives the raw response through the Dispatcher.
|
|
419
|
-
# It will also sign the packet if
|
|
427
|
+
# It will also sign the packet if necessary.
|
|
420
428
|
#
|
|
421
429
|
# @param packet [RubySMB::GenericPacket] the request to be sent
|
|
422
430
|
# @param encrypt [Boolean] true if encryption has to be enabled for this transaction
|
|
@@ -427,15 +435,16 @@ module RubySMB
|
|
|
427
435
|
version = packet.packet_smb_version
|
|
428
436
|
case version
|
|
429
437
|
when 'SMB1'
|
|
430
|
-
packet.smb_header.uid = user_id if user_id
|
|
431
|
-
packet =
|
|
438
|
+
packet.smb_header.uid = self.user_id if self.user_id
|
|
439
|
+
packet.smb_header.pid_low = self.pid if self.pid
|
|
440
|
+
packet = smb1_sign(packet) if signing_required && !session_key.empty?
|
|
432
441
|
when 'SMB2'
|
|
433
442
|
packet = increment_smb_message_id(packet)
|
|
434
443
|
packet.smb2_header.session_id = session_id
|
|
435
|
-
unless packet.is_a?(RubySMB::SMB2::Packet::SessionSetupRequest)
|
|
436
|
-
if self.smb2
|
|
444
|
+
unless packet.is_a?(RubySMB::SMB2::Packet::SessionSetupRequest) || session_key.empty?
|
|
445
|
+
if self.smb2 && signing_required
|
|
437
446
|
packet = smb2_sign(packet)
|
|
438
|
-
elsif self.smb3
|
|
447
|
+
elsif self.smb3 && (signing_required || packet.is_a?(RubySMB::SMB2::Packet::TreeConnectRequest))
|
|
439
448
|
packet = smb3_sign(packet)
|
|
440
449
|
end
|
|
441
450
|
end
|
|
@@ -443,35 +452,38 @@ module RubySMB
|
|
|
443
452
|
packet = packet
|
|
444
453
|
end
|
|
445
454
|
|
|
455
|
+
encrypt_data = false
|
|
446
456
|
if can_be_encrypted?(packet) && encryption_supported? && (@session_encrypt_data || encrypt)
|
|
447
|
-
|
|
448
|
-
raw_response = recv_encrypt
|
|
449
|
-
loop do
|
|
450
|
-
break unless is_status_pending?(raw_response)
|
|
451
|
-
sleep 1
|
|
452
|
-
raw_response = recv_encrypt
|
|
453
|
-
end
|
|
454
|
-
else
|
|
455
|
-
dispatcher.send_packet(packet)
|
|
456
|
-
raw_response = dispatcher.recv_packet
|
|
457
|
-
loop do
|
|
458
|
-
break unless is_status_pending?(raw_response)
|
|
459
|
-
sleep 1
|
|
460
|
-
raw_response = dispatcher.recv_packet
|
|
461
|
-
end unless version == 'SMB1'
|
|
457
|
+
encrypt_data = true
|
|
462
458
|
end
|
|
459
|
+
send_packet(packet, encrypt: encrypt_data)
|
|
460
|
+
raw_response = recv_packet(encrypt: encrypt_data)
|
|
461
|
+
smb2_header = nil
|
|
462
|
+
loop do
|
|
463
|
+
smb2_header = RubySMB::SMB2::SMB2Header.read(raw_response)
|
|
464
|
+
break unless is_status_pending?(smb2_header)
|
|
465
|
+
sleep 1
|
|
466
|
+
raw_response = recv_packet(encrypt: encrypt_data)
|
|
467
|
+
rescue IOError
|
|
468
|
+
# We're expecting an SMB2 packet, but the server sent an SMB1 packet
|
|
469
|
+
# instead. This behavior has been observed with older versions of Samba
|
|
470
|
+
# when something goes wrong on the server side. So, we just ignore it
|
|
471
|
+
# and expect the caller to handle this wrong response packet.
|
|
472
|
+
break
|
|
473
|
+
end unless version == 'SMB1'
|
|
463
474
|
|
|
464
475
|
self.sequence_counter += 1 if signing_required && !session_key.empty?
|
|
476
|
+
# update the SMB2 message ID according to the received Credit Charged
|
|
477
|
+
self.smb2_message_id += smb2_header.credit_charge - 1 if smb2_header && self.server_supports_multi_credit
|
|
465
478
|
raw_response
|
|
466
479
|
end
|
|
467
480
|
|
|
468
481
|
# Check if the response is an asynchronous operation with STATUS_PENDING
|
|
469
482
|
# status code.
|
|
470
483
|
#
|
|
471
|
-
# @param
|
|
484
|
+
# @param smb2_header [String] the response packet SMB2 header
|
|
472
485
|
# @return [Boolean] true if it is a status pending operation, false otherwise
|
|
473
|
-
def is_status_pending?(
|
|
474
|
-
smb2_header = RubySMB::SMB2::SMB2Header.read(raw_response)
|
|
486
|
+
def is_status_pending?(smb2_header)
|
|
475
487
|
value = smb2_header.nt_status.value
|
|
476
488
|
status_code = WindowsError::NTStatus.find_by_retval(value).first
|
|
477
489
|
status_code == WindowsError::NTStatus::STATUS_PENDING &&
|
|
@@ -497,37 +509,50 @@ module RubySMB
|
|
|
497
509
|
['0x0300', '0x0302', '0x0311'].include?(@dialect)
|
|
498
510
|
end
|
|
499
511
|
|
|
500
|
-
# Encrypt and send a packet
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
512
|
+
# Encrypt (if required) and send a packet.
|
|
513
|
+
#
|
|
514
|
+
# @param encrypt [Boolean] true if the packet should be encrypted, false
|
|
515
|
+
# otherwise
|
|
516
|
+
def send_packet(packet, encrypt: false)
|
|
517
|
+
if encrypt
|
|
518
|
+
begin
|
|
519
|
+
packet = smb3_encrypt(packet.to_binary_s)
|
|
520
|
+
rescue RubySMB::Error::RubySMBError => e
|
|
521
|
+
raise RubySMB::Error::EncryptionError, "Error while encrypting #{packet.class.name} packet (SMB #{@dialect}): #{e}"
|
|
522
|
+
end
|
|
506
523
|
end
|
|
507
|
-
dispatcher.send_packet(
|
|
524
|
+
dispatcher.send_packet(packet)
|
|
508
525
|
end
|
|
509
526
|
|
|
510
|
-
# Receives the raw response through the Dispatcher and decrypt the packet.
|
|
527
|
+
# Receives the raw response through the Dispatcher and decrypt the packet (if required).
|
|
511
528
|
#
|
|
529
|
+
# @param encrypt [Boolean] true if the packet is encrypted, false otherwise
|
|
512
530
|
# @return [String] the raw unencrypted packet
|
|
513
|
-
def
|
|
531
|
+
def recv_packet(encrypt: false)
|
|
514
532
|
begin
|
|
515
533
|
raw_response = dispatcher.recv_packet
|
|
516
534
|
rescue RubySMB::Error::CommunicationError => e
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
raise RubySMB::Error::InvalidPacket, 'Not a SMB2 TransformHeader packet'
|
|
535
|
+
if encrypt
|
|
536
|
+
raise RubySMB::Error::EncryptionError, "Communication error with the "\
|
|
537
|
+
"remote host: #{e.message}. The server supports encryption but was "\
|
|
538
|
+
"not able to handle the encrypted request."
|
|
539
|
+
else
|
|
540
|
+
raise e
|
|
541
|
+
end
|
|
525
542
|
end
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
543
|
+
if encrypt
|
|
544
|
+
begin
|
|
545
|
+
transform_response = RubySMB::SMB2::Packet::TransformHeader.read(raw_response)
|
|
546
|
+
rescue IOError
|
|
547
|
+
raise RubySMB::Error::InvalidPacket, 'Not a SMB2 TransformHeader packet'
|
|
548
|
+
end
|
|
549
|
+
begin
|
|
550
|
+
raw_response = smb3_decrypt(transform_response)
|
|
551
|
+
rescue RubySMB::Error::RubySMBError => e
|
|
552
|
+
raise RubySMB::Error::EncryptionError, "Error while decrypting #{transform_response.class.name} packet (SMB #@dialect}): #{e}"
|
|
553
|
+
end
|
|
530
554
|
end
|
|
555
|
+
raw_response
|
|
531
556
|
end
|
|
532
557
|
|
|
533
558
|
# Connects to the supplied share
|
|
@@ -551,7 +576,7 @@ module RubySMB
|
|
|
551
576
|
# @param [String] host
|
|
552
577
|
def net_share_enum_all(host)
|
|
553
578
|
tree = tree_connect("\\\\#{host}\\IPC$")
|
|
554
|
-
named_pipe = tree.
|
|
579
|
+
named_pipe = tree.open_pipe(filename: "srvsvc", write: true, read: true)
|
|
555
580
|
named_pipe.net_share_enum_all(host)
|
|
556
581
|
end
|
|
557
582
|
|
|
@@ -568,6 +593,7 @@ module RubySMB
|
|
|
568
593
|
self.smb2_message_id = 0
|
|
569
594
|
self.client_encryption_key = nil
|
|
570
595
|
self.server_encryption_key = nil
|
|
596
|
+
self.server_supports_multi_credit = false
|
|
571
597
|
end
|
|
572
598
|
|
|
573
599
|
# Requests a NetBIOS Session Service using the provided name.
|
|
@@ -605,7 +631,7 @@ module RubySMB
|
|
|
605
631
|
session_request.session_header.session_packet_type = RubySMB::Nbss::SESSION_REQUEST
|
|
606
632
|
session_request.called_name = called_name
|
|
607
633
|
session_request.calling_name = calling_name
|
|
608
|
-
session_request.session_header.
|
|
634
|
+
session_request.session_header.stream_protocol_length =
|
|
609
635
|
session_request.num_bytes - session_request.session_header.num_bytes
|
|
610
636
|
session_request
|
|
611
637
|
end
|
|
@@ -621,5 +647,6 @@ module RubySMB
|
|
|
621
647
|
@preauth_integrity_hash_value + data.to_binary_s
|
|
622
648
|
)
|
|
623
649
|
end
|
|
650
|
+
|
|
624
651
|
end
|
|
625
652
|
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
module RubySMB
|
|
2
|
+
module Compression
|
|
3
|
+
module LZNT1
|
|
4
|
+
def self.compress(buf, chunk_size: 0x1000)
|
|
5
|
+
out = ''
|
|
6
|
+
until buf.empty?
|
|
7
|
+
chunk = buf[0...chunk_size]
|
|
8
|
+
compressed = compress_chunk(chunk)
|
|
9
|
+
# chunk is compressed
|
|
10
|
+
if compressed.length < chunk.length
|
|
11
|
+
out << [0xb000 | (compressed.length - 1)].pack('v')
|
|
12
|
+
out << compressed
|
|
13
|
+
else
|
|
14
|
+
out << [0x3000 | (chunk.length - 1)].pack('v')
|
|
15
|
+
out << chunk
|
|
16
|
+
end
|
|
17
|
+
buf = buf[chunk_size..-1]
|
|
18
|
+
break if buf.nil?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
out
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.compress_chunk(chunk)
|
|
25
|
+
blob = chunk
|
|
26
|
+
out = ''
|
|
27
|
+
pow2 = 0x10
|
|
28
|
+
l_mask3 = 0x1002
|
|
29
|
+
o_shift = 12
|
|
30
|
+
until blob.empty?
|
|
31
|
+
bits = 0
|
|
32
|
+
tmp = ''
|
|
33
|
+
i = -1
|
|
34
|
+
loop do
|
|
35
|
+
i += 1
|
|
36
|
+
bits >>= 1
|
|
37
|
+
while pow2 < (chunk.length - blob.length)
|
|
38
|
+
pow2 <<= 1
|
|
39
|
+
l_mask3 = (l_mask3 >> 1) + 1
|
|
40
|
+
o_shift -= 1
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
max_len = [blob.length, l_mask3].min
|
|
44
|
+
offset, length = find(chunk[0...(chunk.length - blob.length)], blob, max_len)
|
|
45
|
+
|
|
46
|
+
# try to find more compressed pattern
|
|
47
|
+
_offset2, length2 = find(chunk[0...chunk.length - blob.length + 1], blob[1..-1], max_len)
|
|
48
|
+
|
|
49
|
+
length = 0 if length < length2
|
|
50
|
+
|
|
51
|
+
if length > 0
|
|
52
|
+
symbol = ((offset - 1) << o_shift) | (length - 3)
|
|
53
|
+
tmp << [symbol].pack('v')
|
|
54
|
+
# set the highest bit
|
|
55
|
+
bits |= 0x80
|
|
56
|
+
blob = blob[length..-1]
|
|
57
|
+
else
|
|
58
|
+
tmp += blob[0]
|
|
59
|
+
blob = blob[1..-1]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
break if blob.empty? || i == 7
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
out << [bits >> (7 - i)].pack('C')
|
|
66
|
+
out << tmp
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
out
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.decompress(buf, length_check: true)
|
|
73
|
+
out = ''
|
|
74
|
+
until buf.empty?
|
|
75
|
+
header = buf.unpack1('v')
|
|
76
|
+
length = (header & 0xfff) + 1
|
|
77
|
+
raise EncodingError, 'invalid chunk length' if length_check && length > (buf.length - 2)
|
|
78
|
+
|
|
79
|
+
chunk = buf[2...length + 2]
|
|
80
|
+
out << if header & 0x8000 == 0
|
|
81
|
+
chunk
|
|
82
|
+
else
|
|
83
|
+
decompress_chunk(chunk)
|
|
84
|
+
end
|
|
85
|
+
buf = buf[length + 2..-1]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
out
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def self.decompress_chunk(chunk)
|
|
92
|
+
out = ''
|
|
93
|
+
until chunk.empty?
|
|
94
|
+
flags = chunk[0].unpack1('C')
|
|
95
|
+
chunk = chunk[1..-1]
|
|
96
|
+
8.times do |i|
|
|
97
|
+
if (flags >> i & 1) == 0
|
|
98
|
+
out << chunk[0]
|
|
99
|
+
chunk = chunk[1..-1]
|
|
100
|
+
else
|
|
101
|
+
flag = chunk.unpack1('v')
|
|
102
|
+
pos = out.length - 1
|
|
103
|
+
l_mask = 0xfff
|
|
104
|
+
o_shift = 12
|
|
105
|
+
while pos >= 0x10
|
|
106
|
+
l_mask >>= 1
|
|
107
|
+
o_shift -= 1
|
|
108
|
+
pos >>= 1
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
length = (flag & l_mask) + 3
|
|
112
|
+
offset = (flag >> o_shift) + 1
|
|
113
|
+
|
|
114
|
+
if length >= offset
|
|
115
|
+
out_offset = out[-offset..-1]
|
|
116
|
+
tmp = out_offset * (0xfff / out_offset.length + 1)
|
|
117
|
+
out << tmp[0...length]
|
|
118
|
+
else
|
|
119
|
+
out << out[-offset..-offset + length - 1]
|
|
120
|
+
end
|
|
121
|
+
chunk = chunk[2..-1]
|
|
122
|
+
end
|
|
123
|
+
break if chunk.empty?
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
out
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
class << self
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
def find(src, target, max_len)
|
|
134
|
+
result_offset = 0
|
|
135
|
+
result_length = 0
|
|
136
|
+
1.upto(max_len - 1) do |i|
|
|
137
|
+
offset = src.rindex(target[0...i])
|
|
138
|
+
next if offset.nil?
|
|
139
|
+
|
|
140
|
+
tmp_offset = src.length - offset
|
|
141
|
+
tmp_length = i
|
|
142
|
+
if tmp_offset == tmp_length
|
|
143
|
+
src_offset = src[offset..-1]
|
|
144
|
+
tmp = src_offset * (0xfff / src_offset.length + 1)
|
|
145
|
+
i.upto(max_len) do |j|
|
|
146
|
+
offset = tmp.rindex(target[0...j])
|
|
147
|
+
break if offset.nil?
|
|
148
|
+
|
|
149
|
+
tmp_length = j
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
if tmp_length > result_length
|
|
154
|
+
result_offset = tmp_offset
|
|
155
|
+
result_length = tmp_length
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
result_length < 3 ? [0, 0] : [result_offset, result_length]
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
data/lib/ruby_smb/dcerpc/bind.rb
CHANGED
|
@@ -2,51 +2,59 @@ module RubySMB
|
|
|
2
2
|
module Dcerpc
|
|
3
3
|
# The Bind PDU as defined in
|
|
4
4
|
# [The bind PDU](http://pubs.opengroup.org/onlinepubs/9629399/chap12.htm#tagcjh_17_06_04_03)
|
|
5
|
-
class PContElemT <
|
|
5
|
+
class PContElemT < Ndr::NdrStruct
|
|
6
|
+
default_parameter byte_align: 4
|
|
6
7
|
endian :little
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
ndr_uint16 :p_cont_id, label: 'Context ID'
|
|
10
|
+
ndr_uint8 :n_transfer_syn, label: 'Number of transfer syntaxes', initial_value: 1
|
|
11
|
+
ndr_uint8 :reserved
|
|
11
12
|
p_syntax_id_t :abstract_syntax, label: 'Abstract syntax',
|
|
12
13
|
uuid: -> { endpoint::UUID },
|
|
13
14
|
ver_major: -> { endpoint::VER_MAJOR },
|
|
14
15
|
ver_minor: -> { endpoint::VER_MINOR }
|
|
15
|
-
array
|
|
16
|
+
array :transfer_syntaxes, label: 'Transfer syntax', type: :p_syntax_id_t,
|
|
16
17
|
initial_length: -> { n_transfer_syn },
|
|
17
18
|
uuid: -> { Ndr::UUID },
|
|
18
19
|
ver_major: -> { Ndr::VER_MAJOR },
|
|
19
|
-
ver_minor: -> { Ndr::VER_MINOR }
|
|
20
|
+
ver_minor: -> { Ndr::VER_MINOR },
|
|
21
|
+
byte_align: 4
|
|
20
22
|
end
|
|
21
23
|
|
|
22
|
-
class PContListT <
|
|
24
|
+
class PContListT < Ndr::NdrStruct
|
|
25
|
+
default_parameter byte_align: 4
|
|
23
26
|
endian :little
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
array
|
|
28
|
+
ndr_uint8 :n_context_elem, label: 'Number of context elements', initial_value: -> { 1 }
|
|
29
|
+
ndr_uint8 :reserved
|
|
30
|
+
ndr_uint16 :reserved2
|
|
31
|
+
array :p_cont_elem, label: 'Presentation context elements', type: :p_cont_elem_t,
|
|
29
32
|
initial_length: -> {n_context_elem},
|
|
30
|
-
endpoint: -> {endpoint}
|
|
33
|
+
endpoint: -> {endpoint},
|
|
34
|
+
byte_align: 4
|
|
31
35
|
end
|
|
32
36
|
|
|
33
37
|
class Bind < BinData::Record
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
pdu_header :pdu_header, label: 'PDU header'
|
|
38
|
+
PTYPE = PTypes::BIND
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
uint16 :max_recv_frag, label: 'max receive frag size', initial_value: RubySMB::Dcerpc::MAX_RECV_FRAG
|
|
40
|
-
uint32 :assoc_group_id, label: 'ncarnation of client-server assoc group'
|
|
40
|
+
endian :little
|
|
41
41
|
|
|
42
|
+
# PDU Header
|
|
43
|
+
pdu_header :pdu_header, label: 'PDU header'
|
|
44
|
+
ndr_uint16 :max_xmit_frag, label: 'max transmit frag size', initial_value: RubySMB::Dcerpc::MAX_XMIT_FRAG
|
|
45
|
+
ndr_uint16 :max_recv_frag, label: 'max receive frag size', initial_value: RubySMB::Dcerpc::MAX_RECV_FRAG
|
|
46
|
+
ndr_uint32 :assoc_group_id, label: 'incarnation of client-server assoc group'
|
|
42
47
|
p_cont_list_t :p_context_list, label: 'Presentation context list', endpoint: -> { endpoint }
|
|
43
|
-
|
|
48
|
+
|
|
49
|
+
# Auth Verifier
|
|
50
|
+
sec_trailer :sec_trailer, onlyif: -> { pdu_header.auth_length > 0 }
|
|
51
|
+
string :auth_value,
|
|
44
52
|
onlyif: -> { pdu_header.auth_length > 0 },
|
|
45
53
|
read_length: -> { pdu_header.auth_length }
|
|
46
54
|
|
|
47
55
|
def initialize_instance
|
|
48
56
|
super
|
|
49
|
-
pdu_header.ptype =
|
|
57
|
+
pdu_header.ptype = PTYPE
|
|
50
58
|
end
|
|
51
59
|
end
|
|
52
60
|
end
|