├── .github ├── FUNDING.yml ├── banner.png └── workflows │ ├── unit_tests.yaml │ └── update_go_pkg_version.yaml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── crypto ├── cmac │ ├── cmac.go │ └── cmac_test.go ├── dcc │ ├── dcc.go │ └── dcc_test.go ├── dcc2 │ ├── dcc2.go │ └── dcc2_test.go ├── gppp │ ├── gppp.go │ └── gppp_test.go ├── lm │ ├── lm.go │ └── lm_test.go ├── md4 │ ├── md4.go │ └── md4_test.go ├── nt │ ├── nt.go │ └── nt_test.go ├── ntlmv1 │ ├── ntlmv1.go │ └── ntlmv1_test.go ├── ntlmv2 │ ├── ntlmv2.go │ └── ntlmv2_test.go ├── pkcs7 │ ├── RFC-5652.pdf │ ├── pkcs7.go │ └── pkcs7_test.go ├── rc4 │ ├── RFC-6229.pdf │ ├── rc4.go │ └── rc4_test.go └── uuid │ ├── uuid.go │ ├── uuid_interface.go │ ├── uuid_interface_test.go │ ├── uuid_test.go │ ├── uuid_v1 │ ├── RFC-4122.pdf │ ├── uuid_v1.go │ └── uuid_v1_test.go │ ├── uuid_v2 │ ├── uuid_v2.go │ └── uuid_v2_test.go │ └── uuid_v8 │ ├── uuid_v8.go │ └── uuid_v8_test.go ├── go.mod ├── go.sum ├── logger ├── logger.go └── logger_test.go ├── network ├── dns │ ├── dns.go │ └── dns_test.go ├── ip │ ├── ipv4.go │ ├── ipv4_test.go │ ├── ipv6.go │ ├── ipv6_test.go │ ├── range.go │ ├── range_test.go │ ├── tcp_port.go │ └── tcp_port_test.go ├── kerberos │ ├── kerberos.go │ └── kerberos_test.go ├── ldap │ ├── certificates.go │ ├── domain_controllers.go │ ├── ldap.go │ ├── ldap_attributes │ │ ├── RelativeIDs.go │ │ ├── UserAccountControl.go │ │ ├── UserAccountControl_test.go │ │ ├── domain_functionnality_level.go │ │ ├── eku.go │ │ ├── enrollement_flags.go │ │ ├── msPKI-Certificate-Name-Flag.go │ │ ├── msPKI-Enrollment-Flag.go │ │ ├── pwdProperties.go │ │ └── sAMAccountType.go │ ├── modify.go │ ├── naming_contexts.go │ ├── objects.go │ ├── objects │ │ ├── LdapSessionInterface.go │ │ ├── computer.go │ │ ├── domain.go │ │ └── user.go │ ├── oid.go │ ├── query.go │ ├── rid.go │ ├── schema │ │ ├── ADSchemaAttributes.go │ │ ├── ADSchemaAttributes_test.go │ │ └── PropertySets.go │ ├── session.go │ ├── sid.go │ ├── utils.go │ └── utils_test.go ├── llmnr │ ├── client.go │ ├── custom_handlers.go │ ├── domain_name.go │ ├── domain_name_test.go │ ├── handler.go │ ├── llmnr.go │ ├── llmnr_test.go │ ├── message.go │ ├── message_test.go │ ├── question.go │ ├── question_test.go │ ├── response_writer.go │ ├── ressource_record.go │ ├── ressource_record_test.go │ ├── server.go │ └── server_test.go ├── netbios │ ├── docs │ │ ├── RFC-1001.pdf │ │ └── RFC-1002.pdf │ ├── nbf │ │ ├── nbf.go │ │ └── nbf_test.go │ ├── nbt │ │ ├── nbt.go │ │ └── nbt_test.go │ ├── nbtns │ │ ├── challenge.go │ │ ├── handlers.go │ │ ├── name.go │ │ ├── nbtns.go │ │ ├── nbtns_test.go │ │ ├── packet.go │ │ ├── redirect.go │ │ ├── server.go │ │ ├── tcp_server.go │ │ └── udp_server.go │ ├── netbios.go │ ├── session.go │ └── session_test.go └── smb │ ├── smb_v10 │ ├── capabilities │ │ ├── capabilities.go │ │ └── capabilities_test.go │ ├── client │ │ ├── client_functions.go │ │ ├── client_structures.go │ │ ├── client_test.go │ │ ├── infos.go │ │ ├── negotiate.go │ │ ├── session.go │ │ └── tree.go │ ├── dialects │ │ ├── dialects.go │ │ └── dialects_test.go │ ├── docs │ │ ├── [MS-CIFS]-250113.pdf │ │ └── [MS-SMB].pdf │ ├── errors │ │ ├── errors.go │ │ └── errors_test.go │ ├── informationlevels │ │ ├── SMB_FIND_FILE_BOTH_DIRECTORY_INFO.go │ │ ├── SMB_FIND_FILE_DIRECTORY_INFO.go │ │ ├── SMB_FIND_FILE_FULL_DIRECTORY_INFO.go │ │ ├── SMB_FIND_FILE_NAMES_INFO.go │ │ ├── SMB_INFO_ALLOCATION.go │ │ ├── SMB_INFO_IS_NAME_VALID.go │ │ ├── SMB_INFO_QUERY_ALL_EAS.go │ │ ├── SMB_INFO_QUERY_EAS_FROM_LIST.go │ │ ├── SMB_INFO_QUERY_EA_SIZE.go │ │ ├── SMB_INFO_SET_EAS.go │ │ ├── SMB_INFO_STANDARD.go │ │ ├── SMB_INFO_VOLUME.go │ │ ├── SMB_QUERY_FILE_ALL_INFO.go │ │ ├── SMB_QUERY_FILE_ALT_NAME_INFO.go │ │ ├── SMB_QUERY_FILE_BASIC_INFO.go │ │ ├── SMB_QUERY_FILE_COMRESSION_INFO.go │ │ ├── SMB_QUERY_FILE_EA_INFO.go │ │ ├── SMB_QUERY_FILE_NAME_INFO.go │ │ ├── SMB_QUERY_FILE_STANDARD_INFO.go │ │ ├── SMB_QUERY_FILE_STREAM_INFO.go │ │ ├── SMB_QUERY_FS_ATTRIBUTE_INFO.go │ │ ├── SMB_QUERY_FS_DEVICE_INFO.go │ │ ├── SMB_QUERY_FS_SIZE_INFO.go │ │ ├── SMB_QUERY_FS_VOLUME_INFO.go │ │ ├── SMB_SET_FILE_ALLOCATION_INFO.go │ │ ├── SMB_SET_FILE_BASIC_INFO.go │ │ ├── SMB_SET_FILE_DISPOSITION_INFO.go │ │ ├── SMB_SET_FILE_END_OF_FILE_INFO.go │ │ └── informationlevels_test.go │ ├── message │ │ ├── commands │ │ │ ├── 0.command_casting.go │ │ │ ├── CheckDirectoryRequest.go │ │ │ ├── CheckDirectoryResponse.go │ │ │ ├── ClosePrintFileRequest.go │ │ │ ├── ClosePrintFileResponse.go │ │ │ ├── CloseRequest.go │ │ │ ├── CloseResponse.go │ │ │ ├── CreateDirectoryRequest.go │ │ │ ├── CreateDirectoryResponse.go │ │ │ ├── CreateNewRequest.go │ │ │ ├── CreateNewResponse.go │ │ │ ├── CreateRequest.go │ │ │ ├── CreateResponse.go │ │ │ ├── CreateTemporaryRequest.go │ │ │ ├── CreateTemporaryResponse.go │ │ │ ├── DeleteDirectoryRequest.go │ │ │ ├── DeleteDirectoryResponse.go │ │ │ ├── DeleteRequest.go │ │ │ ├── DeleteResponse.go │ │ │ ├── EchoRequest.go │ │ │ ├── EchoResponse.go │ │ │ ├── FindClose2Request.go │ │ │ ├── FindClose2Response.go │ │ │ ├── FindCloseRequest.go │ │ │ ├── FindCloseResponse.go │ │ │ ├── FindRequest.go │ │ │ ├── FindResponse.go │ │ │ ├── FindUniqueRequest.go │ │ │ ├── FindUniqueResponse.go │ │ │ ├── FlushRequest.go │ │ │ ├── FlushResponse.go │ │ │ ├── IoctlRequest.go │ │ │ ├── IoctlResponse.go │ │ │ ├── LockAndReadRequest.go │ │ │ ├── LockAndReadResponse.go │ │ │ ├── LockByteRangeRequest.go │ │ │ ├── LockByteRangeResponse.go │ │ │ ├── LockingAndxRequest.go │ │ │ ├── LockingAndxResponse.go │ │ │ ├── LogoffAndxRequest.go │ │ │ ├── LogoffAndxResponse.go │ │ │ ├── NegotiateRequest.go │ │ │ ├── NegotiateResponse.go │ │ │ ├── NtCancelRequest.go │ │ │ ├── NtCreateAndxRequest.go │ │ │ ├── NtCreateAndxResponse.go │ │ │ ├── NtRenameRequest.go │ │ │ ├── NtRenameResponse.go │ │ │ ├── NtTransactRequest.go │ │ │ ├── NtTransactResponse.go │ │ │ ├── NtTransactSecondaryRequest.go │ │ │ ├── NtTransactSecondaryResponse.go │ │ │ ├── OpenAndxRequest.go │ │ │ ├── OpenAndxResponse.go │ │ │ ├── OpenPrintFileRequest.go │ │ │ ├── OpenPrintFileResponse.go │ │ │ ├── OpenRequest.go │ │ │ ├── OpenResponse.go │ │ │ ├── ProcessExitRequest.go │ │ │ ├── ProcessExitResponse.go │ │ │ ├── QueryInformation2Request.go │ │ │ ├── QueryInformation2Response.go │ │ │ ├── QueryInformationDiskRequest.go │ │ │ ├── QueryInformationDiskResponse.go │ │ │ ├── QueryInformationRequest.go │ │ │ ├── QueryInformationResponse.go │ │ │ ├── ReadAndxRequest.go │ │ │ ├── ReadAndxResponse.go │ │ │ ├── ReadMpxRequest.go │ │ │ ├── ReadMpxResponse.go │ │ │ ├── ReadRawRequest.go │ │ │ ├── ReadRawResponse.go │ │ │ ├── ReadRequest.go │ │ │ ├── ReadResponse.go │ │ │ ├── RenameRequest.go │ │ │ ├── RenameResponse.go │ │ │ ├── SearchRequest.go │ │ │ ├── SearchResponse.go │ │ │ ├── SeekRequest.go │ │ │ ├── SeekResponse.go │ │ │ ├── SessionSetupAndxRequest.go │ │ │ ├── SessionSetupAndxResponse.go │ │ │ ├── SetInformation2Request.go │ │ │ ├── SetInformation2Response.go │ │ │ ├── SetInformationRequest.go │ │ │ ├── SetInformationResponse.go │ │ │ ├── Transaction2Request.go │ │ │ ├── Transaction2Response.go │ │ │ ├── Transaction2SecondaryRequest.go │ │ │ ├── Transaction2SecondaryResponse.go │ │ │ ├── TransactionRequest.go │ │ │ ├── TransactionResponse.go │ │ │ ├── TransactionSecondaryRequest.go │ │ │ ├── TransactionSecondaryResponse.go │ │ │ ├── TreeConnectAndxRequest.go │ │ │ ├── TreeConnectAndxResponse.go │ │ │ ├── TreeConnectRequest.go │ │ │ ├── TreeConnectResponse.go │ │ │ ├── TreeDisconnectRequest.go │ │ │ ├── TreeDisconnectResponse.go │ │ │ ├── UnlockByteRangeRequest.go │ │ │ ├── UnlockByteRangeResponse.go │ │ │ ├── WriteAndCloseRequest.go │ │ │ ├── WriteAndCloseResponse.go │ │ │ ├── WriteAndUnlockRequest.go │ │ │ ├── WriteAndUnlockResponse.go │ │ │ ├── WriteAndxRequest.go │ │ │ ├── WriteAndxResponse.go │ │ │ ├── WriteMpxRequest.go │ │ │ ├── WriteMpxResponse.go │ │ │ ├── WritePrintFileRequest.go │ │ │ ├── WritePrintFileResponse.go │ │ │ ├── WriteRawFinal.go │ │ │ ├── WriteRawInterim.go │ │ │ ├── WriteRawRequest.go │ │ │ ├── WriteRequest.go │ │ │ ├── WriteResponse.go │ │ │ ├── andx │ │ │ │ ├── andx.go │ │ │ │ └── andx_test.go │ │ │ ├── codes │ │ │ │ ├── codes.go │ │ │ │ └── codes_test.go │ │ │ ├── command_interface │ │ │ │ ├── command_interface.go │ │ │ │ └── command_interface_test.go │ │ │ ├── commands_test.go │ │ │ └── utils │ │ │ │ ├── utils.go │ │ │ │ └── utils_test.go │ │ ├── data │ │ │ ├── data.go │ │ │ └── data_test.go │ │ ├── header │ │ │ ├── flags │ │ │ │ ├── flags.go │ │ │ │ └── flags_test.go │ │ │ ├── flags2 │ │ │ │ ├── flags2.go │ │ │ │ └── flags2_test.go │ │ │ ├── header.go │ │ │ ├── header_functions.go │ │ │ └── header_test.go │ │ ├── message.go │ │ ├── message_test.go │ │ ├── parameters │ │ │ ├── parameters.go │ │ │ └── parameters_test.go │ │ └── securityfeatures │ │ │ ├── SecurityFeatures.go │ │ │ ├── SecurityFeaturesConnectionlessTransport.go │ │ │ ├── SecurityFeaturesConnectionlessTransport_test.go │ │ │ ├── SecurityFeaturesReserved.go │ │ │ ├── SecurityFeaturesReserved_test.go │ │ │ ├── SecurityFeaturesSecuritySignature.go │ │ │ └── SecurityFeaturesSecuritySignature_test.go │ ├── securitymode │ │ ├── securitymode.go │ │ └── securitymode_test.go │ ├── spnego │ │ ├── auth.go │ │ ├── negotiate.go │ │ ├── ntlm │ │ │ ├── negotiate.go │ │ │ ├── ntlm.go │ │ │ └── version │ │ │ │ ├── version.go │ │ │ │ └── version_test.go │ │ ├── spnego.go │ │ └── spnego_test.go │ ├── subcommands │ │ ├── nt_transact_subcommands.go │ │ ├── nt_transact_subcommands_test.go │ │ ├── transaction2_subcommands.go │ │ ├── transaction2_subcommands_test.go │ │ ├── transaction_subcommands.go │ │ └── transaction_subcommands_test.go │ ├── transport │ │ ├── transport.go │ │ └── transport_test.go │ └── types │ │ ├── LOCKING_ANDX_RANGE32.go │ │ ├── LOCKING_ANDX_RANGE32_test.go │ │ ├── LOCKING_ANDX_RANGE64.go │ │ ├── LOCKING_ANDX_RANGE64_test.go │ │ ├── OEM_STRING.go │ │ ├── OEM_STRING_test.go │ │ ├── SMB_DATE.go │ │ ├── SMB_DATE_test.go │ │ ├── SMB_DIRECTORY_INFORMATION.go │ │ ├── SMB_DIRECTORY_INFORMATION_test.go │ │ ├── SMB_EXT_FILE_ATTR.go │ │ ├── SMB_FEA_LIST.go │ │ ├── SMB_FILE_ATTRIBUTES.go │ │ ├── SMB_FILE_ATTRIBUTES_test.go │ │ ├── SMB_NMPIPE_STATUS.go │ │ ├── SMB_NMPIPE_STATUS_test.go │ │ ├── SMB_RESUME_KEY.go │ │ ├── SMB_RESUME_KEY_test.go │ │ ├── SMB_STRING.go │ │ ├── SMB_STRING_test.go │ │ ├── SMB_TIME.go │ │ ├── ms_dtyp_passthrough.go │ │ └── ms_dtyp_passthrough_functions.go │ ├── smb_v20 │ └── docs │ │ └── [MS-SMB2].pdf │ ├── smb_v21 │ └── docs │ │ └── [MS-SMB2].pdf │ ├── smb_v30 │ └── docs │ │ └── [MS-SMB2].pdf │ ├── smb_v302 │ └── docs │ │ └── [MS-SMB2].pdf │ ├── smb_v311 │ └── docs │ │ └── [MS-SMB2].pdf │ ├── versions.go │ └── versions_test.go ├── utils ├── encoding │ └── utf16 │ │ ├── utf16le.go │ │ └── utf16le_test.go ├── strings.go └── strings_test.go └── windows ├── credentials ├── credentials.go └── credentials_test.go ├── guid ├── Guid.go └── guid_test.go ├── keycredential ├── DNWithBinary.go ├── DNWithBinary_test.go ├── KeyCredential.go ├── crypto │ ├── PrivateKeyEncryptionType.go │ ├── RSAKeyMaterial.go │ ├── RSAKeyMaterial_test.go │ ├── SecretEncryptionType.go │ ├── SecretEncryptionType_test.go │ └── X509Certificate2.go ├── key │ ├── CustomKeyInformation.go │ ├── CustomKeyInformationFlags.go │ ├── CustomKeyInformationVolumeType.go │ ├── KeyCredentialEntryType.go │ ├── KeyCredentialVersion.go │ ├── KeyCredentialVersion_test.go │ ├── KeySource.go │ ├── KeyStrength.go │ ├── KeyUsage.go │ └── KeyUsage_test.go └── utils │ ├── DateTime.go │ ├── DateTime_test.go │ ├── utils.go │ └── utils_test.go ├── ms_dtyp └── common │ ├── data_structures │ ├── EVENT_DESCRIPTOR.go │ ├── EVENT_HEADER.go │ ├── FILETIME.go │ ├── FILETIME_test.go │ ├── GUID.go │ ├── GUID_test.go │ ├── LARGE_INTEGER.go │ ├── LCID.go │ ├── LUID.go │ ├── MULTI_SZ.go │ ├── OBJECT_TYPE_LIST.go │ ├── RPC_UNICODE_STRING.go │ ├── SERVER_INFO_100.go │ ├── SERVER_INFO_101.go │ ├── SYSTEMTIME.go │ ├── UINT128.go │ └── ULARGE_INTEGER.go │ └── data_types │ ├── ADCONNECTION_HANDLE.go │ ├── BOOL.go │ ├── BOOLEAN.go │ ├── BSTR.go │ ├── BYTE.go │ ├── CHAR.go │ ├── DOUBLE.go │ ├── DWORD.go │ ├── DWORD32.go │ ├── DWORD64.go │ ├── DWORDLONG.go │ ├── DWORD_PTR.go │ ├── ERROR_STATUS_T.go │ ├── FLOAT.go │ ├── HANDLE.go │ ├── HCALL.go │ ├── HRESULT.go │ ├── INT.go │ ├── INT16.go │ ├── INT32.go │ ├── INT64.go │ ├── INT8.go │ ├── LDAP_UDP_HANDLE.go │ ├── LMCSTR.go │ ├── LMSTR.go │ ├── LONG.go │ ├── LONG32.go │ ├── LONG64.go │ ├── LONGLONG.go │ ├── LONG_PTR.go │ ├── LPCSTR.go │ ├── LPCVOID.go │ ├── LPCWSTR.go │ ├── LPSTR.go │ ├── LPWSTR.go │ ├── NET_API_STATUS.go │ ├── NTSTATUS.go │ ├── PCONTEXT_HANDLE.go │ ├── QWORD.go │ ├── RPC_BINDING_HANDLE.go │ ├── SHORT.go │ ├── SIZE_T.go │ ├── STRING.go │ ├── UCHAR.go │ ├── UINT.go │ ├── UINT16.go │ ├── UINT32.go │ ├── UINT64.go │ ├── UINT8.go │ ├── ULONG.go │ ├── ULONG32.go │ ├── ULONG64.go │ ├── ULONGLONG.go │ ├── ULONG_PTR.go │ ├── UNC.go │ ├── UNICODE.go │ ├── USHORT.go │ ├── VOID.go │ ├── WCHAR.go │ ├── WORD.go │ └── data_types_test.go └── nt_status ├── nt_status.go └── nt_status_test.go /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: TheManticoreProject 4 | -------------------------------------------------------------------------------- /.github/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/.github/banner.png -------------------------------------------------------------------------------- /.github/workflows/unit_tests.yaml: -------------------------------------------------------------------------------- 1 | name: Run Unit Tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' # Run tests on every branch for every commit 7 | 8 | jobs: 9 | test: 10 | name: Run Unit Tests 11 | runs-on: ${{ matrix.os == 'windows' && 'windows-latest' || 'ubuntu-latest' }} 12 | 13 | strategy: 14 | matrix: 15 | os: [linux, windows] 16 | arch: [amd64, arm64, 386] 17 | exclude: 18 | - os: windows 19 | arch: arm64 20 | 21 | env: 22 | GO111MODULE: 'on' 23 | CGO_ENABLED: '0' 24 | 25 | steps: 26 | - name: Checkout Repository 27 | uses: actions/checkout@v3 28 | 29 | - name: Set up QEMU for ARM64 emulation 30 | if: matrix.arch == 'arm64' && matrix.os != 'windows' 31 | uses: docker/setup-qemu-action@v2 32 | with: 33 | platforms: arm64 34 | 35 | - name: Set up Go 36 | uses: actions/setup-go@v4 37 | with: 38 | go-version: '1.22.1' 39 | 40 | - name: Run Unit Tests 41 | env: 42 | GOOS: ${{ matrix.os }} 43 | GOARCH: ${{ matrix.arch }} 44 | run: | 45 | echo "$GOOS, $GOARCH" 46 | go test -count=1 ./... 47 | -------------------------------------------------------------------------------- /.github/workflows/update_go_pkg_version.yaml: -------------------------------------------------------------------------------- 1 | name: Update Go Pkg Version 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' # Trigger only when a new version tag is pushed 7 | workflow_dispatch: # Allows manual trigger of the workflow 8 | 9 | jobs: 10 | update_go_pkg_version: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout code 15 | uses: actions/checkout@v3 16 | 17 | - name: Extract version from tag 18 | id: extract_version 19 | run: | 20 | TAG=${GITHUB_REF#refs/tags/} 21 | echo "VERSION=${TAG}" >> $GITHUB_ENV 22 | 23 | - name: Update go pkg cache 24 | run: | 25 | export GITHUB_REPOSITORY_LOWER=$(echo ${GITHUB_REPOSITORY} | tr '[:upper:]' '[:lower:]') 26 | curl -v "https://sum.golang.org/lookup/${GITHUB_REPOSITORY_LOWER}@${{ env.VERSION }}" 27 | env: 28 | VERSION: ${{ env.VERSION }} 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # If you prefer the allow list template instead of the deny list, see community template: 2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, built with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Dependency directories (remove the comment below to include it) 18 | # vendor/ 19 | 20 | # Go workspace file 21 | go.work 22 | go.work.sum 23 | 24 | # env file 25 | .env 26 | 27 | # Builds dir 28 | ./bin/ 29 | ./main.go -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all build test clean deps 2 | 3 | GOCMD=go 4 | GOTEST=$(GOCMD) test 5 | 6 | test: 7 | @ $(GOTEST) -count=1 ./... 8 | 9 | clean: 10 | @ $(GOCMD) clean 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](./.github/banner.png) 2 | 3 |

4 | Build 5 | GitHub release (latest by date) 6 | Go Report Card 7 |
8 |

9 | 10 | --- 11 | 12 | ## Features 13 | 14 | - [x] **Cross-Platform Support**: Works on Windows, Linux, and macOS. 15 | - [x] **Multiple Authentication Protocols**: Supports NTLM, Kerberos (soon), and LDAP authentication. 16 | - [x] **Cryptography**: [cmac](crypto/cmac/), [dcc](crypto/dcc/), [dcc2](crypto/dcc2/), [gppp](crypto/gppp/), [lm](crypto/lm/), [md4](crypto/md4/), [nt](crypto/nt/), [ntlmv1](crypto/ntlmv1/), [ntlmv2](crypto/ntlmv2/), [pkcs7](crypto/pkcs7/), [rc4](crypto/rc4/), [uuid](crypto/uuid/) 17 | - [x] **Network Protocol Implementations**: Includes SMB, LDAP, and other common Windows protocols. 18 | - [x] **Extensible Architecture**: Easily add new modules and functionality. 19 | 20 | ## Installation 21 | 22 | Download the latest release for your platform from the [Releases](https://github.com/TheManticoreProject/Manticore/releases) page. 23 | 24 | --- 25 | 26 | ## Contributing 27 | 28 | Pull requests are welcome. Feel free to open an issue if you want to add other features. 29 | -------------------------------------------------------------------------------- /crypto/cmac/cmac_test.go: -------------------------------------------------------------------------------- 1 | package cmac 2 | 3 | import ( 4 | "bytes" 5 | "crypto/aes" 6 | "encoding/hex" 7 | 8 | "testing" 9 | ) 10 | 11 | func TestCMAC(t *testing.T) { 12 | k, err := hex.DecodeString("2b7e151628aed2a6abf7158809cf4f3c") 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | 17 | k1, err := hex.DecodeString("fbeed618357133667c85e08f7236a8de") 18 | if err != nil { 19 | t.Fatal(err) 20 | } 21 | 22 | k2, err := hex.DecodeString("f7ddac306ae266ccf90bc11ee46d513b") 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | 27 | msg2, err := hex.DecodeString("6bc1bee22e409f96e93d7e117393172a") 28 | if err != nil { 29 | t.Fatal(err) 30 | } 31 | 32 | msg3, err := hex.DecodeString("ae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411") 33 | if err != nil { 34 | t.Fatal(err) 35 | } 36 | 37 | msg4, err := hex.DecodeString("e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710") 38 | if err != nil { 39 | t.Fatal(err) 40 | } 41 | 42 | sum1, err := hex.DecodeString("bb1d6929e95937287fa37d129b756746") 43 | if err != nil { 44 | t.Fatal(err) 45 | } 46 | 47 | sum2, err := hex.DecodeString("070a16b46b4d4144f79bdd9dd04a287c") 48 | if err != nil { 49 | t.Fatal(err) 50 | } 51 | 52 | sum3, err := hex.DecodeString("dfa66747de9ae63030ca32611497c827") 53 | if err != nil { 54 | t.Fatal(err) 55 | } 56 | 57 | sum4, err := hex.DecodeString("51f0bebf7e3b9d92fc49741779363cfe") 58 | if err != nil { 59 | t.Fatal(err) 60 | } 61 | 62 | ciph, err := aes.NewCipher(k) 63 | if err != nil { 64 | t.Fatal(err) 65 | } 66 | 67 | h := New(ciph).(*cmac) 68 | 69 | if !bytes.Equal(h.k1, k1) { 70 | t.Error("fail") 71 | } 72 | 73 | if !bytes.Equal(h.k2, k2) { 74 | t.Error("fail") 75 | } 76 | 77 | if !bytes.Equal(h.Sum(nil), sum1) { 78 | t.Error("fail") 79 | } 80 | 81 | h.Write(msg2) 82 | 83 | if !bytes.Equal(h.Sum(nil), sum2) { 84 | t.Error("fail") 85 | } 86 | 87 | h.Write(msg3) 88 | 89 | if !bytes.Equal(h.Sum(nil), sum3) { 90 | t.Error("fail") 91 | } 92 | 93 | h.Write(msg4) 94 | 95 | if !bytes.Equal(h.Sum(nil), sum4) { 96 | t.Error("fail") 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /crypto/gppp/gppp_test.go: -------------------------------------------------------------------------------- 1 | package gppp_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/TheManticoreProject/Manticore/crypto/gppp" 7 | ) 8 | 9 | func Test_GPPPDecrypt(t *testing.T) { 10 | tests := []struct { 11 | encrypted string 12 | expected string 13 | }{ 14 | {"bdajdgpjZqolVYI3h2O2mp+JpxDuZd0xoi2M86z7JuI=", "Podalirius"}, 15 | } 16 | 17 | for _, test := range tests { 18 | result, err := gppp.GPPPDecryptBase64(test.encrypted) 19 | if err != nil { 20 | t.Errorf("GPPPDecrypt(%q) failed: %v", test.encrypted, err) 21 | } 22 | 23 | if result != test.expected { 24 | t.Errorf("GPPPDecrypt(%q) = %q; expected %q", test.encrypted, result, test.expected) 25 | } 26 | } 27 | } 28 | 29 | func Test_GPPPEncrypt(t *testing.T) { 30 | tests := []struct { 31 | plaintext string 32 | expected string 33 | }{ 34 | {"Podalirius", "bdajdgpjZqolVYI3h2O2mp+JpxDuZd0xoi2M86z7JuI="}, 35 | } 36 | 37 | for _, test := range tests { 38 | result, err := gppp.GPPPEncrypt(test.plaintext) 39 | if err != nil { 40 | t.Errorf("GPPPDecrypt(%q) failed: %v", test.plaintext, err) 41 | } 42 | 43 | if result != test.expected { 44 | t.Errorf("GPPPDecrypt(%q) = %q; expected %q", test.plaintext, result, test.expected) 45 | } 46 | } 47 | } 48 | 49 | func Test_GPPPInvolution(t *testing.T) { 50 | tests := []struct { 51 | plaintext string 52 | }{ 53 | {"Podalirius"}, 54 | {"password123"}, 55 | {"SuperSecretPassword!"}, 56 | {"Complex@P4ssw0rd#2023"}, 57 | {""}, 58 | {"This is a longer password with spaces and special chars !@#$%^&*()"}, 59 | {"ÜberPasswörd"}, // Test with non-ASCII characters 60 | } 61 | 62 | for _, test := range tests { 63 | encrypted, err := gppp.GPPPEncrypt(test.plaintext) 64 | if err != nil { 65 | t.Errorf("GPPPEncrypt(%q) failed: %v", test.plaintext, err) 66 | } 67 | 68 | decrypted, err := gppp.GPPPDecryptBase64(encrypted) 69 | if err != nil { 70 | t.Errorf("GPPPDecryptBase64(%q) failed: %v", encrypted, err) 71 | } 72 | 73 | if decrypted != test.plaintext { 74 | t.Errorf("GPPPDecryptBase64(GPPPEncrypt(%q)) = %q; expected %q", test.plaintext, decrypted, test.plaintext) 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /crypto/lm/lm_test.go: -------------------------------------------------------------------------------- 1 | package lm 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLMHash(t *testing.T) { 8 | tests := []struct { 9 | password string 10 | expected string 11 | }{ 12 | {"cG9kYWxpcml1cwo", "350d1cb93bed51ccafe82d1cdb09b5de"}, 13 | {"", "aad3b435b51404eeaad3b435b51404ee"}, 14 | {"0123456", "5645f13f500882b2aad3b435b51404ee"}, 15 | {"0123456789abcdef", "5645f13f500882b21ac3884b83324540"}, 16 | {"0123456789abcde", "5645f13f500882b21ac3884b83324540"}, 17 | {"0123456789abcd", "5645f13f500882b21ac3884b83324540"}, 18 | } 19 | 20 | for _, test := range tests { 21 | t.Run(test.password, func(t *testing.T) { 22 | result := LMHashToHex(test.password) 23 | if result != test.expected { 24 | t.Errorf("LMHashToHex(%q) = %q; expected %q", test.password, result, test.expected) 25 | } 26 | }) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crypto/md4/md4_test.go: -------------------------------------------------------------------------------- 1 | package md4 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMD4(t *testing.T) { 8 | tests := []struct { 9 | source string 10 | hash string 11 | }{ 12 | {"", "31d6cfe0d16ae931b73c59d7e0c089c0"}, 13 | {"abc", "a448017aaf21d8525fc10ae87aa6729d"}, 14 | {"message digest", "d9130a8164549fe818874806e1c7014b"}, 15 | {"abcdefghijklmnopqrstuvwxyz", "d79e1c308aa5bbcdeea8ed63df412da9"}, 16 | {"Podalirius", "13c5197a7245b1cb75829e38e72002ad"}, 17 | {"TheManticoreProject", "9802c1ca09c41e32abd53fdd764f793b"}, 18 | {"00000000000000000000000000000000", "04054272316bf2b21e8039902c980ab7"}, 19 | {"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras risus ante, mollis sed ultricies eget, bibendum at leo. Ut gravida tristique convallis. Vivamus eu pulvinar leo, eu pharetra enim. Nullam in eros mattis, finibus nibh id, eleifend lacus. Sed ac scelerisque nulla. Aenean ut risus id massa maximus suscipit vitae in nisl. Morbi sagittis turpis eu ullamcorper dapibus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec et faucibus risus. Quisque non lobortis purus, id dapibus elit. Donec non ex porttitor, vestibulum eros ut, vulputate ante. Cras rutrum mauris sit amet feugiat iaculis.", "f59ab2ecb4e3ee399b9e37778fe1fb3b"}, 20 | } 21 | 22 | for _, test := range tests { 23 | t.Run(test.source, func(t *testing.T) { 24 | md4 := New() 25 | md4.Write([]byte(test.source)) 26 | result := md4.HexSum() 27 | 28 | if result != test.hash { 29 | t.Errorf("MD4(\"%s\") = %v; want %v", test.source, result, test.hash) 30 | } 31 | }) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /crypto/nt/nt.go: -------------------------------------------------------------------------------- 1 | package nt 2 | 3 | import ( 4 | "encoding/hex" 5 | "strings" 6 | 7 | "github.com/TheManticoreProject/Manticore/crypto/md4" 8 | "github.com/TheManticoreProject/Manticore/utils/encoding/utf16" 9 | ) 10 | 11 | // NTHash computes the NT hash of a password string 12 | // The NT hash is MD4(UTF16-LE(password)) 13 | func NTHash(password string) [16]byte { 14 | // Convert to UTF16 little endian bytes 15 | utf16lePassword := utf16.EncodeUTF16LE(password) 16 | 17 | // Calculate MD4 hash 18 | hash := md4.New() 19 | hash.Write(utf16lePassword) 20 | result := hash.Sum() 21 | 22 | return result 23 | } 24 | 25 | // NTHash computes the NT hash of a password string 26 | // The NT hash is MD4(UTF16-LE(password)) 27 | func NTHashHex(password string) string { 28 | ntHash := NTHash(password) 29 | return strings.ToLower(hex.EncodeToString(ntHash[:])) 30 | } 31 | -------------------------------------------------------------------------------- /crypto/nt/nt_test.go: -------------------------------------------------------------------------------- 1 | package nt 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestNTHash(t *testing.T) { 8 | tests := []struct { 9 | password string 10 | expected string 11 | }{ 12 | {"cG9kYWxpcml1cwo", "625d671c4b67f53df60c694e690bf5ac"}, 13 | {"00000000000000000000000000000000", "312b863247fa4d3fbba0969e4acb7682"}, 14 | {"", "31d6cfe0d16ae931b73c59d7e0c089c0"}, 15 | } 16 | 17 | for _, test := range tests { 18 | result := NTHashHex(test.password) 19 | if result != test.expected { 20 | t.Errorf("NTHash(%q) = %q; expected %q", test.password, result, test.expected) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /crypto/ntlmv2/ntlmv2_test.go: -------------------------------------------------------------------------------- 1 | package ntlmv2_test 2 | 3 | // import ( 4 | // "testing" 5 | 6 | // "github.com/TheManticoreProject/Manticore/crypto/ntlmv2" 7 | // ) 8 | 9 | // func TestNTLMv2HashToHashcatString(t *testing.T) { 10 | // testCases := []struct { 11 | // testName string 12 | // domain string 13 | // username string 14 | // password string 15 | // serverChallenge [8]byte 16 | // clientChallenge [8]byte 17 | // expectedHash string 18 | // }{ 19 | // { 20 | // testName: "Domain username and password to NTLMv2 hashcat string", 21 | // domain: "LAB", 22 | // username: "Podalirius", 23 | // password: "Admin123!", 24 | // serverChallenge: [8]byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, 25 | // clientChallenge: [8]byte{0x14, 0x78, 0x18, 0x65, 0x59, 0x40, 0x07, 0x4B, 0xBB, 0x99, 0xDA, 0x22, 0x21, 0x04, 0xF1, 0x82}, 26 | // expectedHash: "Podalirius::LAB:1122334455667788:147818655940074BBB99DA222104F182:0101000000000000EDC8BDBFD3AADB014B40D4784E921B03000000000200080034004B003200490001001E00570049004E002D00360050004C0059004E003500350045004400420032000400140034004B00320049002E004C004F00430041004C0003003400570049004E002D00360050004C0059004E003500350045004400420032002E0034004B00320049002E004C004F00430041004C000500140034004B00320049002E004C004F00430041004C000800300030000000000000000100000000200000512F465482D41399998EA0D3D7E64F2D0C26B6CF64F7E9CDDA71B01B0574A47F0A001000000000000000000000000000000000000900280048005400540050002F00770069006E002D00360070006C0079006E003500350065006400620032000000000000000000", // Replace with the actual expected hash 27 | // }, 28 | // } 29 | 30 | // for _, tc := range testCases { 31 | // tc := tc // capture range variable 32 | // t.Run(tc.testName, func(t *testing.T) { 33 | // t.Parallel() 34 | // ntlm, err := ntlmv2.NewNTLMv2(tc.domain, tc.username, tc.password, tc.serverChallenge, tc.clientChallenge) 35 | // if err != nil { 36 | // t.Fatalf("Expected no error, got %v", err) 37 | // } 38 | 39 | // hashcatString, err := ntlm.ToHashcatString() 40 | // if err != nil { 41 | // t.Fatalf("Expected no error, got %v", err) 42 | // } 43 | 44 | // if hashcatString != tc.expectedHash { 45 | // t.Errorf("For domain %s, username %s: expected hash %s, got %s", tc.domain, tc.username, tc.expectedHash, hashcatString) 46 | // } 47 | // }) 48 | // } 49 | // } 50 | -------------------------------------------------------------------------------- /crypto/pkcs7/RFC-5652.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/crypto/pkcs7/RFC-5652.pdf -------------------------------------------------------------------------------- /crypto/rc4/RFC-6229.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/crypto/rc4/RFC-6229.pdf -------------------------------------------------------------------------------- /crypto/uuid/uuid_interface.go: -------------------------------------------------------------------------------- 1 | package uuid 2 | 3 | // UUIDInterface is an interface that defines the methods for a UUID 4 | type UUIDInterface interface { 5 | // Marshal converts a UUID structure into a 16-byte array 6 | Marshal() ([]byte, error) 7 | // Unmarshal converts a 16-byte array into a UUID structure 8 | Unmarshal(data []byte) (int, error) 9 | // FromString parses a UUID string in the format "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 10 | FromString(s string) error 11 | // String returns the string representation of the UUID 12 | String() string 13 | } 14 | -------------------------------------------------------------------------------- /crypto/uuid/uuid_interface_test.go: -------------------------------------------------------------------------------- 1 | package uuid_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/TheManticoreProject/Manticore/crypto/uuid" 7 | "github.com/TheManticoreProject/Manticore/crypto/uuid/uuid_v1" 8 | "github.com/TheManticoreProject/Manticore/crypto/uuid/uuid_v2" 9 | ) 10 | 11 | func TestUUIDInterfaceCompatibility(t *testing.T) { 12 | // Test that UUIDv1 implements UUIDInterface 13 | var v1 uuid_v1.UUIDv1 14 | var _ uuid.UUIDInterface = &v1 15 | 16 | // Test that UUIDv1 implements UUIDInterface 17 | var v2 uuid_v2.UUIDv2 18 | var _ uuid.UUIDInterface = &v2 19 | 20 | // // Test that UUIDv1 implements UUIDInterface 21 | // var v3 uuid_v3.UUIDv3 22 | // var _ uuid.UUIDInterface = &v3 23 | 24 | // // Test that UUIDv1 implements UUIDInterface 25 | // var v4 uuid_v4.UUIDv4 26 | // var _ uuid.UUIDInterface = &v4 27 | 28 | // // Test that UUIDv1 implements UUIDInterface 29 | // var v5 uuid_v5.UUIDv5 30 | // var _ uuid.UUIDInterface = &v5 31 | 32 | // // Test that UUIDv1 implements UUIDInterface 33 | // var v6 uuid_v6.UUIDv6 34 | // var _ uuid.UUIDInterface = &v6 35 | 36 | // // Test that UUIDv1 implements UUIDInterface 37 | // var v7 uuid_v7.UUIDv7 38 | // var _ uuid.UUIDInterface = &v7 39 | 40 | // // Test that UUIDv1 implements UUIDInterface 41 | // var v8 uuid_v8.UUIDv8 42 | // var _ uuid.UUIDInterface = &v8 43 | 44 | } 45 | -------------------------------------------------------------------------------- /crypto/uuid/uuid_v1/RFC-4122.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/crypto/uuid/uuid_v1/RFC-4122.pdf -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/TheManticoreProject/Manticore 2 | 3 | go 1.24.0 4 | 5 | require ( 6 | github.com/TheManticoreProject/goopts v1.2.1 7 | github.com/go-ldap/ldap/v3 v3.4.11 8 | github.com/jcmturner/gokrb5/v8 v8.4.4 9 | golang.org/x/crypto v0.37.0 10 | ) 11 | 12 | require ( 13 | github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect 14 | github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect 15 | github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect 16 | github.com/google/uuid v1.6.0 // indirect 17 | github.com/hashicorp/go-uuid v1.0.3 // indirect 18 | github.com/jcmturner/aescts/v2 v2.0.0 // indirect 19 | github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect 20 | github.com/jcmturner/gofork v1.7.6 // indirect 21 | github.com/jcmturner/goidentity/v6 v6.0.1 // indirect 22 | github.com/jcmturner/rpc/v2 v2.0.3 // indirect 23 | golang.org/x/net v0.39.0 // indirect 24 | ) 25 | -------------------------------------------------------------------------------- /logger/logger_test.go: -------------------------------------------------------------------------------- 1 | package logger_test 2 | -------------------------------------------------------------------------------- /network/dns/dns.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "context" 5 | "net" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | // DNSLookup performs a DNS lookup of a hostname (FQDN or hostname) to a specified DNS server. 11 | // 12 | // Parameters: 13 | // - hostname: A string representing the hostname or FQDN to be resolved. 14 | // - dnsServer: A string representing the DNS server to use for the lookup. 15 | // 16 | // Returns: 17 | // - A slice of strings containing the IP addresses of the DNS server. 18 | func DNSLookup(hostname string, dnsServer string) []string { 19 | if !strings.Contains(dnsServer, ":") { 20 | dnsServer = dnsServer + ":53" 21 | } 22 | 23 | r := &net.Resolver{ 24 | PreferGo: true, 25 | Dial: func(ctx context.Context, network, address string) (net.Conn, error) { 26 | d := net.Dialer{ 27 | Timeout: time.Millisecond * time.Duration(10000), 28 | } 29 | return d.DialContext(ctx, network, dnsServer) 30 | }, 31 | } 32 | ip, _ := r.LookupHost(context.Background(), hostname) 33 | 34 | return ip 35 | } 36 | -------------------------------------------------------------------------------- /network/dns/dns_test.go: -------------------------------------------------------------------------------- 1 | package dns_test 2 | -------------------------------------------------------------------------------- /network/ip/ipv6_test.go: -------------------------------------------------------------------------------- 1 | package ip_test 2 | -------------------------------------------------------------------------------- /network/ip/range.go: -------------------------------------------------------------------------------- 1 | package ip 2 | 3 | import "fmt" 4 | 5 | type IPv4Range struct { 6 | Start *IPv4 7 | End *IPv4 8 | } 9 | 10 | // Contains checks if the given IPv4 address is within the range. 11 | // 12 | // Parameters: 13 | // 14 | // ip: The IPv4 address to check. 15 | // 16 | // Returns: 17 | // 18 | // bool: True if the IPv4 address is within the range, false otherwise. 19 | func (r *IPv4Range) Contains(ip *IPv4) bool { 20 | return ip.IsInRange(r.Start, r.End) 21 | } 22 | 23 | // String returns the string representation of the IPv4 range. 24 | // 25 | // Returns: 26 | // 27 | // string: The string representation of the IPv4 range. 28 | func (r *IPv4Range) String() string { 29 | return fmt.Sprintf("%s - %s", r.Start.String(), r.End.String()) 30 | } 31 | 32 | // IPv6Range represents a range of IPv6 addresses. 33 | type IPv6Range struct { 34 | Start *IPv6 35 | End *IPv6 36 | } 37 | 38 | // Contains checks if the given IPv6 address is within the range. 39 | // 40 | // Parameters: 41 | // 42 | // ip: The IPv6 address to check. 43 | // 44 | // Returns: 45 | // 46 | // bool: True if the IPv6 address is within the range, false otherwise. 47 | func (r *IPv6Range) Contains(ip *IPv6) bool { 48 | return ip.IsInRange(r.Start, r.End) 49 | } 50 | 51 | // String returns the string representation of the IPv6 range. 52 | // 53 | // Returns: 54 | // 55 | // string: The string representation of the IPv6 range. 56 | func (r *IPv6Range) String() string { 57 | return fmt.Sprintf("%s - %s", r.Start.String(), r.End.String()) 58 | } 59 | -------------------------------------------------------------------------------- /network/ip/range_test.go: -------------------------------------------------------------------------------- 1 | package ip_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/TheManticoreProject/Manticore/network/ip" 7 | ) 8 | 9 | func TestIPv4RangeContains(t *testing.T) { 10 | start := ip.NewIPv4(192, 168, 1, 0, 24) 11 | end := ip.NewIPv4(192, 168, 1, 255, 24) 12 | ipRange := &ip.IPv4Range{Start: start, End: end} 13 | 14 | tests := []struct { 15 | ip *ip.IPv4 16 | expected bool 17 | }{ 18 | {ip.NewIPv4(192, 168, 1, 1, 24), true}, 19 | {ip.NewIPv4(192, 168, 1, 255, 24), true}, 20 | {ip.NewIPv4(192, 168, 2, 0, 24), false}, 21 | {ip.NewIPv4(192, 168, 0, 255, 24), false}, 22 | } 23 | 24 | for _, test := range tests { 25 | result := ipRange.Contains(test.ip) 26 | if result != test.expected { 27 | t.Errorf("IPv4Range.Contains(%s) = %v; expected %v", test.ip.String(), result, test.expected) 28 | } 29 | } 30 | } 31 | 32 | func TestIPv6RangeContains(t *testing.T) { 33 | start := ip.NewIPv6(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0) 34 | end := ip.NewIPv6(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0xffff) 35 | ipRange := &ip.IPv6Range{Start: start, End: end} 36 | 37 | tests := []struct { 38 | ip *ip.IPv6 39 | expected bool 40 | }{ 41 | {ip.NewIPv6(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), true}, 42 | {ip.NewIPv6(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0xffff), true}, 43 | {ip.NewIPv6(0x2001, 0xdb8, 0, 0, 0, 0, 1, 0), false}, 44 | {ip.NewIPv6(0x2001, 0xdb7, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff), false}, 45 | } 46 | 47 | for _, test := range tests { 48 | result := ipRange.Contains(test.ip) 49 | if result != test.expected { 50 | t.Errorf("IPv6Range.Contains(%s) = %v; expected %v", test.ip.String(), result, test.expected) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /network/ip/tcp_port.go: -------------------------------------------------------------------------------- 1 | package ip 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | type TCPPortRange struct { 11 | Start uint16 12 | End uint16 13 | } 14 | 15 | // String returns the string representation of the TCP port range. 16 | // 17 | // Returns: 18 | // 19 | // string: The string representation of the TCP port range. 20 | func (t *TCPPortRange) String() string { 21 | return fmt.Sprintf("%d-%d", t.Start, t.End) 22 | } 23 | 24 | // NewTCPPortRange creates a new TCP port range instance. 25 | // 26 | // Parameters: 27 | // 28 | // start: The start port number. 29 | // end: The end port number. 30 | // 31 | // Returns: 32 | // 33 | // *TCPPortRange: A new TCP port range instance. 34 | func NewTCPPortRange(start, end uint16) *TCPPortRange { 35 | return &TCPPortRange{Start: start, End: end} 36 | } 37 | 38 | // NewTCPPortRangeFromString creates a new TCP port range instance from a string. 39 | // 40 | // Parameters: 41 | // 42 | // s: The string representation of the TCP port range. 43 | // 44 | // Returns: 45 | // 46 | // *TCPPortRange: A new TCP port range instance. 47 | func NewTCPPortRangeFromString(s string) (*TCPPortRange, error) { 48 | var err error 49 | 50 | if !regexp.MustCompile(`^\s*(?:[0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])\s*-\s*(?:[0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])\s*$`).MatchString(s) { 51 | return nil, fmt.Errorf("invalid port range format") 52 | } 53 | 54 | parts := strings.Split(s, "-") 55 | 56 | if len(parts) == 2 { 57 | start := uint64(0) 58 | if len(parts[0]) > 0 { 59 | start, err = strconv.ParseUint(parts[0], 10, 16) 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | if start > 65535 { 65 | return nil, fmt.Errorf("port range start must be between 0 and 65535") 66 | } 67 | } 68 | 69 | end := uint64(65535) 70 | if len(parts[1]) > 0 { 71 | end, err = strconv.ParseUint(parts[1], 10, 16) 72 | if err != nil { 73 | return nil, err 74 | } 75 | 76 | if end > 65535 { 77 | return nil, fmt.Errorf("port range end must be between 0 and 65535") 78 | } 79 | } 80 | 81 | return NewTCPPortRange(uint16(start), uint16(end)), nil 82 | } 83 | 84 | return nil, fmt.Errorf("invalid port range format") 85 | } 86 | -------------------------------------------------------------------------------- /network/ip/tcp_port_test.go: -------------------------------------------------------------------------------- 1 | package ip_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/TheManticoreProject/Manticore/network/ip" 7 | ) 8 | 9 | func TestNewTCPPortRange(t *testing.T) { 10 | tests := []struct { 11 | start, end uint16 12 | expected *ip.TCPPortRange 13 | }{ 14 | {80, 8080, &ip.TCPPortRange{Start: 80, End: 8080}}, 15 | {0, 65535, &ip.TCPPortRange{Start: 0, End: 65535}}, 16 | {1024, 2048, &ip.TCPPortRange{Start: 1024, End: 2048}}, 17 | } 18 | 19 | for _, tt := range tests { 20 | result := ip.NewTCPPortRange(tt.start, tt.end) 21 | if result.Start != tt.expected.Start || result.End != tt.expected.End { 22 | t.Errorf("NewTCPPortRange(%d, %d) = %v; expected %v", tt.start, tt.end, result, tt.expected) 23 | } 24 | } 25 | } 26 | 27 | func TestNewTCPPortRangeFromString(t *testing.T) { 28 | tests := []struct { 29 | s string 30 | expected *ip.TCPPortRange 31 | hasError bool 32 | }{ 33 | {"80-8080", &ip.TCPPortRange{Start: 80, End: 8080}, false}, 34 | {"0-65535", &ip.TCPPortRange{Start: 0, End: 65535}, false}, 35 | {"1024-2048", &ip.TCPPortRange{Start: 1024, End: 2048}, false}, 36 | {"invalid", nil, true}, 37 | {"80-70000", nil, true}, 38 | } 39 | 40 | for _, tt := range tests { 41 | result, err := ip.NewTCPPortRangeFromString(tt.s) 42 | if (err != nil) != tt.hasError { 43 | t.Errorf("NewTCPPortRangeFromString(%s) error = %v; expected error = %v", tt.s, err, tt.hasError) 44 | } 45 | if err == nil && (result.Start != tt.expected.Start || result.End != tt.expected.End) { 46 | t.Errorf("NewTCPPortRangeFromString(%s) = %v; expected %v", tt.s, result, tt.expected) 47 | } 48 | } 49 | } 50 | 51 | func TestTCPPortRangeString(t *testing.T) { 52 | tests := []struct { 53 | portRange *ip.TCPPortRange 54 | expected string 55 | }{ 56 | {&ip.TCPPortRange{Start: 80, End: 8080}, "80-8080"}, 57 | {&ip.TCPPortRange{Start: 0, End: 65535}, "0-65535"}, 58 | {&ip.TCPPortRange{Start: 1024, End: 2048}, "1024-2048"}, 59 | } 60 | 61 | for _, tt := range tests { 62 | result := tt.portRange.String() 63 | if result != tt.expected { 64 | t.Errorf("TCPPortRange.String() = %v; expected %v", result, tt.expected) 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /network/kerberos/kerberos_test.go: -------------------------------------------------------------------------------- 1 | package kerberos 2 | -------------------------------------------------------------------------------- /network/ldap/ldap.go: -------------------------------------------------------------------------------- 1 | package ldap 2 | 3 | import ( 4 | "fmt" 5 | 6 | goldapv3 "github.com/go-ldap/ldap/v3" 7 | ) 8 | 9 | type Entry = goldapv3.Entry 10 | 11 | type Control = goldapv3.Control 12 | 13 | const ( 14 | ScopeBaseObject = goldapv3.ScopeBaseObject 15 | ScopeSingleLevel = goldapv3.ScopeSingleLevel 16 | ScopeChildren = goldapv3.ScopeChildren 17 | ScopeWholeSubtree = goldapv3.ScopeWholeSubtree 18 | ) 19 | 20 | // GetRootDSE retrieves the Root DSE (Directory Service Entry) from the LDAP server. 21 | // The Root DSE provides information about the LDAP server, including its capabilities, 22 | // naming contexts, and supported controls. 23 | // 24 | // This function performs a base object search with a filter of "(objectClass=*)" 25 | // to retrieve all attributes of the Root DSE. 26 | // 27 | // Returns: 28 | // - A pointer to an ldap.Entry object representing the Root DSE. 29 | // - If an error occurs during the search, the function logs a warning and returns nil. 30 | // 31 | // Example usage: 32 | // 33 | // rootDSE := ldapSession.GetRootDSE() 34 | // if rootDSE != nil { 35 | // fmt.Println("Root DSE retrieved successfully") 36 | // } else { 37 | // fmt.Println("Failed to retrieve Root DSE") 38 | // } 39 | func (ldapSession *Session) GetRootDSE() (*Entry, error) { 40 | // Specify LDAP search parameters 41 | // https://pkg.go.dev/gopkg.in/ldap.v3#NewSearchRequest 42 | searchRequest := goldapv3.NewSearchRequest( 43 | // Base DN blank 44 | "", 45 | // Scope Base 46 | goldapv3.ScopeBaseObject, 47 | // DerefAliases 48 | goldapv3.NeverDerefAliases, 49 | // SizeLimit 50 | 1, 51 | // TimeLimit 52 | 0, 53 | // TypesOnly 54 | false, 55 | // Search filter 56 | "(objectClass=*)", 57 | // Attributes to retrieve 58 | []string{"*"}, 59 | // Controls 60 | nil, 61 | ) 62 | 63 | // Perform LDAP search 64 | searchResult, err := ldapSession.connection.Search(searchRequest) 65 | if err != nil { 66 | return nil, fmt.Errorf("error searching LDAP: %w", err) 67 | } 68 | 69 | return searchResult.Entries[0], nil 70 | } 71 | -------------------------------------------------------------------------------- /network/ldap/ldap_attributes/domain_functionnality_level.go: -------------------------------------------------------------------------------- 1 | package ldap_attributes 2 | 3 | // Domain Functionality Level 4 | // Src: https://eightwone.com/references/ad-functional-levels/ 5 | 6 | import "fmt" 7 | 8 | type DomainFunctionalityLevel uint8 9 | 10 | const ( 11 | DOMAIN_FUNCTIONALITY_LEVEL_2000 DomainFunctionalityLevel = 0 12 | DOMAIN_FUNCTIONALITY_LEVEL_2003_INTERIM DomainFunctionalityLevel = 1 13 | DOMAIN_FUNCTIONALITY_LEVEL_2003 DomainFunctionalityLevel = 2 14 | DOMAIN_FUNCTIONALITY_LEVEL_2008 DomainFunctionalityLevel = 3 15 | DOMAIN_FUNCTIONALITY_LEVEL_2008_R2 DomainFunctionalityLevel = 4 16 | DOMAIN_FUNCTIONALITY_LEVEL_2012 DomainFunctionalityLevel = 5 17 | DOMAIN_FUNCTIONALITY_LEVEL_2012_R2 DomainFunctionalityLevel = 6 18 | DOMAIN_FUNCTIONALITY_LEVEL_2016 DomainFunctionalityLevel = 7 19 | DOMAIN_FUNCTIONALITY_LEVEL_2025 DomainFunctionalityLevel = 10 20 | ) 21 | 22 | var DomainFunctionalityLevelToWindowsVersion = map[DomainFunctionalityLevel]string{ 23 | DOMAIN_FUNCTIONALITY_LEVEL_2000: "Windows 2000", 24 | DOMAIN_FUNCTIONALITY_LEVEL_2003_INTERIM: "Windows Server 2003 Interim", 25 | DOMAIN_FUNCTIONALITY_LEVEL_2003: "Windows Server 2003", 26 | DOMAIN_FUNCTIONALITY_LEVEL_2008: "Windows Server 2008", 27 | DOMAIN_FUNCTIONALITY_LEVEL_2008_R2: "Windows Server 2008 R2", 28 | DOMAIN_FUNCTIONALITY_LEVEL_2012: "Windows Server 2012", 29 | DOMAIN_FUNCTIONALITY_LEVEL_2012_R2: "Windows Server 2012 R2", 30 | DOMAIN_FUNCTIONALITY_LEVEL_2016: "Windows Server 2016", 31 | DOMAIN_FUNCTIONALITY_LEVEL_2025: "Windows Server 2025", 32 | } 33 | 34 | // String returns the string representation of the domain functionality level 35 | func (v DomainFunctionalityLevel) String() string { 36 | if name, exists := DomainFunctionalityLevelToWindowsVersion[v]; exists { 37 | return fmt.Sprintf("Domain Functionality Level: %s", name) 38 | } else { 39 | return fmt.Sprintf("Domain Functionality Level: ? (%d)", v) 40 | } 41 | } 42 | 43 | // IsSupported returns true if the domain functionality level is supported by the current version of Windows 44 | func (v DomainFunctionalityLevel) IsSupported() bool { 45 | return v == DOMAIN_FUNCTIONALITY_LEVEL_2000 || v == DOMAIN_FUNCTIONALITY_LEVEL_2003 || v == DOMAIN_FUNCTIONALITY_LEVEL_2008 || v == DOMAIN_FUNCTIONALITY_LEVEL_2008_R2 || v == DOMAIN_FUNCTIONALITY_LEVEL_2012 || v == DOMAIN_FUNCTIONALITY_LEVEL_2012_R2 || v == DOMAIN_FUNCTIONALITY_LEVEL_2016 || v == DOMAIN_FUNCTIONALITY_LEVEL_2025 46 | } 47 | -------------------------------------------------------------------------------- /network/ldap/ldap_attributes/eku.go: -------------------------------------------------------------------------------- 1 | package ldap_attributes 2 | 3 | // We need to check if they are real 4 | const ( 5 | // Microsoft EKU OIDs 6 | EKU_CLIENT_AUTHENTICATION = "1.3.6.1.5.5.7.3.2" 7 | EKU_SERVER_AUTHENTICATION = "1.3.6.1.5.5.7.3.1" 8 | EKU_CODE_SIGNING = "1.3.6.1.5.5.7.3.3" 9 | EKU_EMAIL_PROTECTION = "1.3.6.1.5.5.7.3.4" 10 | EKU_TIME_STAMPING = "1.3.6.1.5.5.7.3.8" 11 | EKU_OCSP_SIGNING = "1.3.6.1.5.5.7.3.9" 12 | EKU_IPSEC_END_SYSTEM = "1.3.6.1.5.5.7.3.5" 13 | EKU_IPSEC_TUNNEL = "1.3.6.1.5.5.7.3.6" 14 | EKU_IPSEC_USER = "1.3.6.1.5.5.7.3.7" 15 | EKU_ANY = "2.5.29.37.0" 16 | EKU_CERTIFICATE_REQUEST_AGENT = "1.3.6.1.4.1.311.20.2.1" 17 | EKU_SMART_CARD_LOGON = "1.3.6.1.4.1.311.20.2.2" 18 | EKU_DS_EMAIL_REPLICATION = "1.3.6.1.4.1.311.21.19" 19 | EKU_KDC_AUTHENTICATION = "1.3.6.1.5.2.3.5" 20 | EKU_FILE_RECOVERY = "1.3.6.1.4.1.311.10.3.4" 21 | EKU_QUALIFIED_SUBORDINATION = "1.3.6.1.4.1.311.10.3.10" 22 | EKU_KEY_RECOVERY_AGENT = "1.3.6.1.4.1.311.21.6" 23 | EKU_CA_EXCHANGE = "1.3.6.1.4.1.311.21.5" 24 | EKU_LIFETIME_SIGNING = "1.3.6.1.4.1.311.10.3.13" 25 | EKU_DOCUMENT_SIGNING = "1.3.6.1.4.1.311.10.3.12" 26 | EKU_KEY_PACK_LICENSES = "1.3.6.1.4.1.311.10.6.2" 27 | EKU_KEY_PACK_SILENT_USER = "1.3.6.1.4.1.311.10.6.1" 28 | ) 29 | -------------------------------------------------------------------------------- /network/ldap/ldap_attributes/enrollement_flags.go: -------------------------------------------------------------------------------- 1 | package ldap_attributes 2 | 3 | // General Enrollment Flags 4 | // Src: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-crtd/6cc7eb79-3e84-477a-b398-b0ff2b68a6c0 5 | const ( 6 | // Reserved. All protocols MUST ignore this flag. 7 | ENROLLMENT_FLAG_ADD_EMAIL = 0x00000002 8 | // Reserved. All protocols MUST ignore this flag. 9 | ENROLLMENT_FLAG_PUBLISH_TO_DS = 0x00000008 10 | // Reserved. All protocols MUST ignore this flag. 11 | ENROLLMENT_FLAG_EXPORTABLE_KEY = 0x00000010 12 | // This flag is the same as CT_FLAG_AUTO_ENROLLMENT. Indicates that auto-enrollment is enabled for this certificate template. 13 | ENROLLMENT_FLAG_AUTO_ENROLLMENT = 0x00000020 14 | // This flag indicates that this certificate template is for an end entity that represents a machine. 15 | ENROLLMENT_FLAG_MACHINE_TYPE = 0x00000040 16 | // This flag indicates a certificate request for a CA certificate. 17 | ENROLLMENT_FLAG_IS_CA = 0x00000080 18 | // This flag indicates that a certificate based on this section needs to include a template name certificate extension. 19 | ENROLLMENT_FLAG_ADD_TEMPLATE_NAME = 0x00000200 20 | // This flag indicates a certificate request for cross-certifying a certificate. Processing rules are specified in [MS-WCCE]. 21 | ENROLLMENT_FLAG_IS_CROSS_CA = 0x00000800 22 | // This flag indicates that the record of a certificate request for a certificate that is issued need not be persisted by the CA. 23 | ENROLLMENT_FLAG_DONOTPERSISTINDB = 0x00001000 24 | // This flag indicates that the template SHOULD not be modified in any way; it is not used by the client or server in the Windows Client Certificate Enrollment Protocol. 25 | ENROLLMENT_FLAG_IS_DEFAULT = 0x00010000 26 | // This flag indicates that the template MAY be modified if required; it is not used by the client or server in the Windows Client Certificate Enrollment Protocol. 27 | ENROLLMENT_FLAG_IS_MODIFIED = 0x00020000 28 | ) 29 | -------------------------------------------------------------------------------- /network/ldap/ldap_attributes/msPKI-Certificate-Name-Flag.go: -------------------------------------------------------------------------------- 1 | package ldap_attributes 2 | 3 | // msPKI-Certificate-Name-Flag Attribute 4 | // Src: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-crtd/1192823c-d839-4bc3-9b6b-fa8c53507ae1 5 | const ( 6 | MSPKI_CERTIFICATE_NAME_FLAG_ENROLLEE_SUPPLIES_SUBJECT = 0x00000001 7 | MSPKI_CERTIFICATE_NAME_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME = 0x00010000 8 | MSPKI_CERTIFICATE_NAME_FLAG_SUBJECT_ALT_REQUIRE_DOMAIN_DNS = 0x00400000 9 | MSPKI_CERTIFICATE_NAME_FLAG_SUBJECT_ALT_REQUIRE_SPN = 0x00800000 10 | MSPKI_CERTIFICATE_NAME_FLAG_SUBJECT_ALT_REQUIRE_DIRECTORY_GUID = 0x01000000 11 | MSPKI_CERTIFICATE_NAME_FLAG_SUBJECT_ALT_REQUIRE_UPN = 0x02000000 12 | MSPKI_CERTIFICATE_NAME_FLAG_SUBJECT_ALT_REQUIRE_EMAIL = 0x04000000 13 | MSPKI_CERTIFICATE_NAME_FLAG_SUBJECT_ALT_REQUIRE_DNS = 0x08000000 14 | MSPKI_CERTIFICATE_NAME_FLAG_SUBJECT_REQUIRE_DNS_AS_CN = 0x10000000 15 | MSPKI_CERTIFICATE_NAME_FLAG_SUBJECT_REQUIRE_EMAIL = 0x20000000 16 | MSPKI_CERTIFICATE_NAME_FLAG_SUBJECT_REQUIRE_COMMON_NAME = 0x40000000 17 | MSPKI_CERTIFICATE_NAME_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH = 0x80000000 18 | MSPKI_CERTIFICATE_NAME_FLAG_OLD_CERT_SUPPLIES_SUBJECT_AND_ALT_NAME = 0x00000008 19 | ) 20 | -------------------------------------------------------------------------------- /network/ldap/ldap_attributes/sAMAccountType.go: -------------------------------------------------------------------------------- 1 | package ldap_attributes 2 | 3 | type SAMAccountType uint32 4 | 5 | // sAMAccountType Values 6 | // Src: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/e742be45-665d-4576-b872-0bc99d1e1fbe 7 | const ( 8 | // Represents a domain object. 9 | SAM_DOMAIN_OBJECT = 0x00000000 10 | // Represents a group object. 11 | SAM_GROUP_OBJECT = 0x10000000 12 | // Represents a group object that is not used for authorization context generation. 13 | SAM_NON_SECURITY_GROUP_OBJECT = 0x10000001 14 | // Represents an alias object. 15 | SAM_ALIAS_OBJECT = 0x20000000 16 | // Represents an alias object that is not used for authorization context generation. 17 | SAM_NON_SECURITY_ALIAS_OBJECT = 0x20000001 18 | // Represents a user object. 19 | SAM_USER_OBJECT = 0x30000000 20 | // Represents a computer object. 21 | SAM_MACHINE_ACCOUNT = 0x30000001 22 | // Represents a user object that is used for domain trusts. 23 | SAM_TRUST_ACCOUNT = 0x30000002 24 | // Represents an application-defined group. 25 | SAM_APP_BASIC_GROUP = 0x40000000 26 | // Represents an application-defined group whose members are determined by the results of a query. 27 | SAM_APP_QUERY_GROUP = 0x40000001 28 | ) 29 | 30 | var SAMAccountTypeMap = map[SAMAccountType]string{ 31 | SAM_DOMAIN_OBJECT: "DOMAIN_OBJECT", 32 | SAM_GROUP_OBJECT: "GROUP_OBJECT", 33 | SAM_NON_SECURITY_GROUP_OBJECT: "NON_SECURITY_GROUP_OBJECT", 34 | SAM_ALIAS_OBJECT: "ALIAS_OBJECT", 35 | SAM_NON_SECURITY_ALIAS_OBJECT: "NON_SECURITY_ALIAS_OBJECT", 36 | SAM_USER_OBJECT: "USER_OBJECT", 37 | SAM_MACHINE_ACCOUNT: "MACHINE_ACCOUNT", 38 | SAM_TRUST_ACCOUNT: "TRUST_ACCOUNT", 39 | SAM_APP_BASIC_GROUP: "APP_BASIC_GROUP", 40 | SAM_APP_QUERY_GROUP: "APP_QUERY_GROUP", 41 | } 42 | 43 | func (sam SAMAccountType) String() string { 44 | if _, ok := SAMAccountTypeMap[sam]; ok { 45 | return SAMAccountTypeMap[sam] 46 | } 47 | return "UNKNOWN" 48 | } 49 | -------------------------------------------------------------------------------- /network/ldap/objects/LdapSessionInterface.go: -------------------------------------------------------------------------------- 1 | package objects 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/windows/credentials" 5 | "github.com/go-ldap/ldap/v3" 6 | ) 7 | 8 | type LdapSessionInterface interface { 9 | InitSession(string, int, *credentials.Credentials, bool, bool) error 10 | 11 | Connect() (bool, error) 12 | 13 | ReConnect() (bool, error) 14 | 15 | Close() 16 | 17 | // Query functions 18 | Query(searchBase string, query string, attributes []string, scope int) ([]*ldap.Entry, error) 19 | 20 | QueryWholeSubtree(searchBase string, query string, attributes []string) ([]*ldap.Entry, error) 21 | 22 | QueryBaseObject(searchBase string, query string, attributes []string) ([]*ldap.Entry, error) 23 | 24 | QuerySingleLevel(searchBase string, query string, attributes []string) ([]*ldap.Entry, error) 25 | 26 | QueryChildren(searchBase string, query string, attributes []string) ([]*ldap.Entry, error) 27 | 28 | // Domain functions 29 | GetDomain(distinguishedName string) (*Domain, error) 30 | } 31 | -------------------------------------------------------------------------------- /network/ldap/objects/computer.go: -------------------------------------------------------------------------------- 1 | package objects 2 | 3 | import "fmt" 4 | 5 | type Computer struct { 6 | // LdapSession is the LDAP session object 7 | LdapSession LdapSessionInterface 8 | // DistinguishedName is the distinguished name of the computer 9 | DistinguishedName string 10 | // DNSHostname is the DNS hostname of the computer 11 | DNSHostname []string 12 | } 13 | 14 | // GetAllComputers retrieves all computer objects from the LDAP directory. 15 | // 16 | // This function performs an LDAP search to find all objects with the objectClass "computer" 17 | // within the domain's distinguished name. It retrieves the distinguished name and DNS hostname 18 | // attributes for each computer object and constructs a map of Computer objects. 19 | // 20 | // Returns: 21 | // - A map where the keys are the distinguished names of the computer objects and the values are 22 | // pointers to Computer objects representing the retrieved computer objects. 23 | // 24 | // Example usage: 25 | // 26 | // domain := &Domain{LdapSession: ldapSession, DistinguishedName: "DC=example,DC=com"} 27 | // computers := domain.GetAllComputers() 28 | // for dn, computer := range computers { 29 | // fmt.Printf("Computer DN: %s, DNS Hostname: %v\n", dn, computer.DNSHostname) 30 | // } 31 | func (domain *Domain) GetAllComputers() (map[string]*Computer, error) { 32 | attributes := []string{"distinguishedName", "dnsHostname"} 33 | 34 | query := "(objectClass=computer)" 35 | 36 | ldapResults, err := domain.LdapSession.QueryWholeSubtree(domain.DistinguishedName, query, attributes) 37 | if err != nil { 38 | return nil, fmt.Errorf("error querying LDAP: %w", err) 39 | } 40 | 41 | computersMap := make(map[string]*Computer) 42 | 43 | if len(ldapResults) != 0 { 44 | for _, entry := range ldapResults { 45 | computer := &Computer{ 46 | DistinguishedName: entry.GetAttributeValue("distinguishedName"), 47 | DNSHostname: entry.GetEqualFoldAttributeValues("dnsHostname"), 48 | } 49 | 50 | computersMap[entry.GetAttributeValue("distinguishedName")] = computer 51 | } 52 | } 53 | 54 | return computersMap, nil 55 | } 56 | -------------------------------------------------------------------------------- /network/ldap/objects/user.go: -------------------------------------------------------------------------------- 1 | package objects 2 | 3 | type User struct { 4 | // LdapSession is the LDAP session object 5 | LdapSession LdapSessionInterface 6 | // DistinguishedName is the distinguished name of the user 7 | DistinguishedName string 8 | // sAMAccountName is the sAMAccountName of the user 9 | SamAccountName string 10 | } 11 | -------------------------------------------------------------------------------- /network/ldap/schema/ADSchemaAttributes_test.go: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_SchemaAttributeDisplayNameToGUID_In_GUIDToSchemaAttributeDisplayName(t *testing.T) { 8 | for schemaAttributeDisplayName, schemaAttributeGUID := range SchemaAttributeDisplayNameToGUID { 9 | if _, exists := GUIDToSchemaAttributeDisplayName[schemaAttributeGUID]; !exists { 10 | t.Errorf("Key %s from SchemaAttributeDisplayNameToGUID not found in GUIDToSchemaAttributeDisplayName", schemaAttributeDisplayName) 11 | } 12 | } 13 | } 14 | 15 | func Test_GUIDToSchemaAttributeDisplayName_In_SchemaAttributeDisplayNameToGUID(t *testing.T) { 16 | for schemaAttributeGUID, schemaAttributeDisplayName := range GUIDToSchemaAttributeDisplayName { 17 | if _, exists := SchemaAttributeDisplayNameToGUID[schemaAttributeDisplayName]; !exists { 18 | t.Errorf("Key %s from GUIDToSchemaAttributeDisplayName not found in SchemaAttributeDisplayNameToGUID", schemaAttributeGUID) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /network/ldap/utils_test.go: -------------------------------------------------------------------------------- 1 | package ldap_test 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/TheManticoreProject/Manticore/network/ldap" 8 | ) 9 | 10 | func TestConvertSecondsToLDAPDuration(t *testing.T) { 11 | tests := []struct { 12 | name string 13 | input int64 14 | expected string 15 | }{ 16 | {"One day", 86400, "864000000000"}, 17 | {"One hour", 3600, "36000000000"}, 18 | {"One minute", 60, "600000000"}, 19 | {"One second", 1, "10000000"}, 20 | {"Zero", 0, "0"}, 21 | {"Negative value", -1, "-10000000"}, 22 | } 23 | 24 | for _, tt := range tests { 25 | t.Run(tt.name, func(t *testing.T) { 26 | result := ldap.ConvertSecondsToLDAPDuration(tt.input) 27 | if result != tt.expected { 28 | t.Errorf("ConvertSecondsToLDAPDuration(%d) = %s; want %s", tt.input, result, tt.expected) 29 | } 30 | }) 31 | } 32 | } 33 | 34 | func TestConvertUnixTimeStampToLDAPTimeStamp(t *testing.T) { 35 | tests := []struct { 36 | name string 37 | input time.Time 38 | expected int64 39 | }{ 40 | {"Epoch", time.Unix(0, 0), ldap.UnixTimestampStart}, 41 | {"One second after epoch", time.Unix(1, 0), ldap.UnixTimestampStart + 10000000}, 42 | {"One day after epoch", time.Unix(86400, 0), 116445600000000000}, 43 | {"Current time", time.Now(), ldap.ConvertUnixTimeStampToLDAPTimeStamp(time.Now())}, 44 | } 45 | 46 | for _, tt := range tests { 47 | t.Run(tt.name, func(t *testing.T) { 48 | result := ldap.ConvertUnixTimeStampToLDAPTimeStamp(tt.input) 49 | if result != tt.expected { 50 | t.Errorf("ConvertUnixTimeStampToLDAPTimeStamp(%v) = %d; want %d", tt.input, result, tt.expected) 51 | } 52 | }) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /network/llmnr/domain_name_test.go: -------------------------------------------------------------------------------- 1 | package llmnr 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | ) 7 | 8 | func TestValidateDomainName(t *testing.T) { 9 | tests := []struct { 10 | name string 11 | expected error 12 | }{ 13 | {"example.com", nil}, 14 | {"a-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-long-domain-name-that-exceeds-the-maximum-allowed-length-for-a-domain-name.com", ErrNameTooLong}, 15 | {"valid-domain.local", nil}, 16 | {"another.valid-domain.local", nil}, 17 | {"invalid_domain_with_underscores.com", nil}, // Assuming underscores are allowed in this context 18 | {"", nil}, // Empty domain name should be valid 19 | } 20 | 21 | for _, test := range tests { 22 | t.Run(test.name, func(t *testing.T) { 23 | err := ValidateDomainName(test.name) 24 | if err != test.expected { 25 | t.Errorf("ValidateDomainName = %v; want %v", err, test.expected) 26 | } 27 | }) 28 | } 29 | } 30 | 31 | func TestEncodeDomainName(t *testing.T) { 32 | tests := []struct { 33 | name string 34 | expected []byte 35 | }{ 36 | {"example.com", []byte{7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0}}, 37 | } 38 | 39 | for _, test := range tests { 40 | t.Run("EncodeDomainName", func(t *testing.T) { 41 | encoded, err := EncodeDomainName(test.name) 42 | if err != nil { 43 | t.Fatalf("failed to encode domain name: %v", err) 44 | } 45 | if !bytes.Equal(encoded, test.expected) { 46 | t.Errorf("EncodeDomainName = %v; want %v", encoded, test.expected) 47 | } 48 | }) 49 | } 50 | } 51 | 52 | func TestDecodeDomainName(t *testing.T) { 53 | tests := []struct { 54 | data []byte 55 | expected string 56 | }{ 57 | { 58 | data: []byte{7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0}, 59 | expected: "example.com", 60 | }, 61 | } 62 | 63 | for _, test := range tests { 64 | t.Run("DecodeDomainName", func(t *testing.T) { 65 | var offset int 66 | decoded, _, err := DecodeDomainName(test.data, offset) 67 | if err != nil { 68 | t.Fatalf("failed to decode domain name: %v", err) 69 | } 70 | if decoded != test.expected { 71 | t.Errorf("DecodeDomainName = %v; want %v", decoded, test.expected) 72 | } 73 | }) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /network/llmnr/handler.go: -------------------------------------------------------------------------------- 1 | package llmnr 2 | 3 | import "net" 4 | 5 | // Handler defines the interface for processing LLMNR queries 6 | type Handler interface { 7 | Run(server *Server, remoteAddr net.Addr, writer ResponseWriter, message *Message) bool 8 | } 9 | 10 | // HandlerFunc is an adapter to allow regular functions to serve as LLMNR handlers 11 | type HandlerFunc func(*Server, net.Addr, ResponseWriter, *Message) bool 12 | 13 | // Run executes the handler function to process an LLMNR query. 14 | // 15 | // Parameters: 16 | // - server: The Server instance that received the query. 17 | // - remoteAddr: The address of the client that sent the query. 18 | // - writer: The ResponseWriter used to send responses back to the client. 19 | // - message: The Message received from the client. 20 | // 21 | // The function calls the handler function with the provided ResponseWriter and Message. 22 | // It allows regular functions to be used as LLMNR handlers by adapting them to the Handler interface. 23 | // 24 | // Example usage: 25 | // 26 | // handlerFunc := func(w llmnr.ResponseWriter, r *llmnr.Message) { 27 | // // Process the LLMNR query and write a response 28 | // } 29 | // handler := llmnr.HandlerFunc(handlerFunc) 30 | // server.RegisterHandler(handler) 31 | // 32 | // This function is typically called internally by the Server when a new LLMNR query is received. 33 | func (f HandlerFunc) Run(server *Server, remoteAddr net.Addr, writer ResponseWriter, message *Message) bool { 34 | return f(server, remoteAddr, writer, message) 35 | } 36 | 37 | // RegisterHandler registers a new handler to the LLMNR server. 38 | // 39 | // Parameters: 40 | // - handler: The Handler to be registered. It must implement the Handler interface. 41 | // 42 | // The function appends the provided handler to the server's list of handlers. These handlers 43 | // will be invoked to process incoming LLMNR queries. Handlers are executed in the order they 44 | // are registered. 45 | // 46 | // Example usage: 47 | // 48 | // handler := &MyHandler{} 49 | // server.RegisterHandler(handler) 50 | // 51 | // This function is typically called before starting the server to ensure that all necessary 52 | // handlers are in place to process incoming queries. 53 | func (s *Server) RegisterHandler(handler Handler) { 54 | s.Handlers = append(s.Handlers, handler) 55 | } 56 | -------------------------------------------------------------------------------- /network/llmnr/llmnr.go: -------------------------------------------------------------------------------- 1 | package llmnr 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | const ( 8 | // LLMNR uses port 5355 as specified in RFC 4795 9 | LLMNRPort = 5355 10 | 11 | // Multicast addresses for LLMNR 12 | IPv4MulticastAddr = "224.0.0.252" 13 | IPv6MulticastAddr = "FF02::1:3" 14 | 15 | MaxLabelLength = 63 // Maximum length of a single label 16 | MaxDomainLength = 255 // Maximum length of entire domain name 17 | HeaderSize = 12 // Size of LLMNR header in bytes 18 | 19 | // DNS wire format related constants 20 | labelPointer = 0xC0 21 | MaxPacketSize = 512 22 | ) 23 | 24 | // LLMNR Header Flags 25 | const ( 26 | FlagQR = 1 << 15 // Query/Response flag 27 | FlagOP = 1 << 14 // Operation code 28 | FlagC = 1 << 13 // Conflict flag 29 | FlagTC = 1 << 12 // Truncation flag 30 | FlagT = 1 << 11 // Tentative flag 31 | ) 32 | 33 | func FlagToString(f uint16) string { 34 | switch f { 35 | case FlagQR: 36 | return "QR" 37 | case FlagOP: 38 | return "OP" 39 | case FlagC: 40 | return "C" 41 | case FlagTC: 42 | return "TC" 43 | case FlagT: 44 | return "T" 45 | } 46 | return "Unknown" 47 | } 48 | 49 | // Common errors 50 | var ( 51 | ErrInvalidQuestion = errors.New("invalid question format") 52 | ErrInvalidMessage = errors.New("invalid message format") 53 | ) 54 | -------------------------------------------------------------------------------- /network/llmnr/question_test.go: -------------------------------------------------------------------------------- 1 | package llmnr_test 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/TheManticoreProject/Manticore/network/llmnr" 8 | ) 9 | 10 | func TestEncodeQuestions(t *testing.T) { 11 | tests := []struct { 12 | question llmnr.Question 13 | expected []byte 14 | }{ 15 | { 16 | question: llmnr.Question{ 17 | Name: "example.com", 18 | Type: llmnr.TypeA, 19 | Class: llmnr.ClassIN, 20 | }, 21 | expected: []byte{ 22 | 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0, 0, 1, 0, 1, 23 | }, 24 | }, 25 | } 26 | 27 | for _, test := range tests { 28 | t.Run("EncodeQuestions", func(t *testing.T) { 29 | var buf []byte 30 | encoded, err := llmnr.EncodeQuestion(test.question) 31 | if err != nil { 32 | t.Fatalf("failed to encode question: %v", err) 33 | } 34 | buf = append(buf, encoded...) 35 | if !bytes.Equal(buf, test.expected) { 36 | t.Errorf("EncodeQuestions = %v; want %v", buf, test.expected) 37 | } 38 | }) 39 | } 40 | } 41 | 42 | func TestDecodeQuestions(t *testing.T) { 43 | tests := []struct { 44 | data []byte 45 | expected llmnr.Question 46 | }{ 47 | { 48 | data: []byte{ 49 | 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0, 0, 1, 0, 1, 50 | }, 51 | expected: llmnr.Question{ 52 | Name: "example.com", 53 | Type: llmnr.TypeA, 54 | Class: llmnr.ClassIN, 55 | }, 56 | }, 57 | } 58 | 59 | for _, test := range tests { 60 | t.Run("DecodeQuestions", func(t *testing.T) { 61 | var offset int 62 | var question llmnr.Question 63 | question, _, err := llmnr.DecodeQuestion(test.data, offset) 64 | if err != nil { 65 | t.Fatalf("failed to decode question: %v", err) 66 | } 67 | if question != test.expected { 68 | t.Errorf("DecodeQuestions = %v; want %v", question, test.expected) 69 | } 70 | }) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /network/llmnr/response_writer.go: -------------------------------------------------------------------------------- 1 | package llmnr 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | // ResponseWriter interface is used by an LLMNR handler to construct a response 9 | type ResponseWriter interface { 10 | WriteMessage(*Message) error 11 | GetRemoteAddr() net.Addr 12 | } 13 | 14 | type responseWriter struct { 15 | Server *Server 16 | RemoteAddr net.Addr 17 | } 18 | 19 | func (w *responseWriter) GetRemoteAddr() net.Addr { 20 | return w.RemoteAddr 21 | } 22 | 23 | // NewResponseWriter creates a new ResponseWriter instance. 24 | // 25 | // Parameters: 26 | // - server: The Server instance that received the query. 27 | // - remoteAddr: The address of the client that sent the query. 28 | // 29 | // Returns: 30 | // - A new ResponseWriter instance. 31 | func NewResponseWriter(server *Server, remoteAddr net.Addr) ResponseWriter { 32 | return &responseWriter{ 33 | Server: server, 34 | RemoteAddr: remoteAddr, 35 | } 36 | } 37 | 38 | // WriteMessage sends a response message to the remote address associated with the responseWriter. 39 | // 40 | // Parameters: 41 | // - msg: The message to be sent. It must not be nil. 42 | // 43 | // Returns: 44 | // - An error if the message is nil, if encoding the message fails, or if sending the message fails. 45 | // 46 | // The function sets the message as a response, encodes it, and sends it to the remote address using the server's UDP connection. 47 | func (w *responseWriter) WriteMessage(msg *Message) error { 48 | if msg == nil { 49 | return fmt.Errorf("message cannot be nil") 50 | } 51 | 52 | msg.SetResponse() 53 | 54 | encoded, err := msg.Encode() 55 | if err != nil { 56 | return fmt.Errorf("failed to encode message: %w", err) 57 | } 58 | 59 | _, err = w.Server.Conn.WriteToUDP(encoded, w.RemoteAddr.(*net.UDPAddr)) 60 | 61 | return err 62 | } 63 | -------------------------------------------------------------------------------- /network/netbios/docs/RFC-1001.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/network/netbios/docs/RFC-1001.pdf -------------------------------------------------------------------------------- /network/netbios/docs/RFC-1002.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/network/netbios/docs/RFC-1002.pdf -------------------------------------------------------------------------------- /network/netbios/nbf/nbf.go: -------------------------------------------------------------------------------- 1 | package nbf 2 | -------------------------------------------------------------------------------- /network/netbios/nbf/nbf_test.go: -------------------------------------------------------------------------------- 1 | package nbf_test 2 | -------------------------------------------------------------------------------- /network/netbios/nbt/nbt_test.go: -------------------------------------------------------------------------------- 1 | package nbt_test 2 | -------------------------------------------------------------------------------- /network/netbios/nbtns/redirect.go: -------------------------------------------------------------------------------- 1 | package nbtns 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | // RedirectInfo contains information about where to redirect a client 8 | type RedirectInfo struct { 9 | ServerIP net.IP 10 | ServerPort uint16 11 | } 12 | 13 | // RedirectManager handles NBNS redirection 14 | type RedirectManager struct { 15 | redirectMap map[string]RedirectInfo // Maps scope to redirect info 16 | } 17 | 18 | // NewRedirectManager creates a new redirect manager 19 | func NewRedirectManager() *RedirectManager { 20 | return &RedirectManager{ 21 | redirectMap: make(map[string]RedirectInfo), 22 | } 23 | } 24 | 25 | // AddRedirect adds or updates a redirect mapping 26 | func (r *RedirectManager) AddRedirect(scope string, serverIP net.IP, port uint16) { 27 | r.redirectMap[scope] = RedirectInfo{ 28 | ServerIP: serverIP, 29 | ServerPort: port, 30 | } 31 | } 32 | 33 | // RemoveRedirect removes a redirect mapping 34 | func (r *RedirectManager) RemoveRedirect(scope string) { 35 | delete(r.redirectMap, scope) 36 | } 37 | 38 | // GetRedirect returns redirect information for a scope 39 | func (r *RedirectManager) GetRedirect(scope string) (RedirectInfo, bool) { 40 | info, exists := r.redirectMap[scope] 41 | return info, exists 42 | } 43 | 44 | // HandleRedirect modifies a response packet for redirection if needed 45 | func (r *RedirectManager) HandleRedirect(request *NBTNSPacket, response *NBTNSPacket) bool { 46 | // Only redirect name queries 47 | if request.Header.Flags&0xF000 != OpNameQuery { 48 | return false 49 | } 50 | 51 | // Check if we have any questions 52 | if len(request.Questions) == 0 { 53 | return false 54 | } 55 | 56 | // Get scope from first question 57 | scope := request.Questions[0].Name.ScopeID 58 | 59 | // Look up redirect information 60 | info, exists := r.GetRedirect(scope) 61 | if !exists { 62 | return false 63 | } 64 | 65 | // Modify response for redirection 66 | response.Header.Flags = FlagResponse | OpRedirect 67 | response.Additional = []NBTNSResourceRecord{ 68 | { 69 | Name: request.Questions[0].Name, 70 | Type: 0x20, // NB record 71 | Class: 1, // IN class 72 | TTL: 600, // 10 minutes 73 | RDLength: uint16(len(info.ServerIP) + 2), // IP + port 74 | RData: append(info.ServerIP, byte(info.ServerPort>>8), byte(info.ServerPort)), 75 | }, 76 | } 77 | response.Header.Additional = 1 78 | 79 | return true 80 | } 81 | -------------------------------------------------------------------------------- /network/netbios/netbios.go: -------------------------------------------------------------------------------- 1 | package netbios 2 | -------------------------------------------------------------------------------- /network/netbios/session.go: -------------------------------------------------------------------------------- 1 | package netbios 2 | 3 | // Session message types 4 | // Source: RFC 1002 page 30 5 | 6 | type SESSION_MESSAGE_TYPE uint8 7 | 8 | const ( 9 | SESSION_MESSAGE SESSION_MESSAGE_TYPE = 0x00 10 | SESSION_REQUEST SESSION_MESSAGE_TYPE = 0x81 11 | SESSION_POSITIVE_RESPONSE SESSION_MESSAGE_TYPE = 0x82 12 | SESSION_NEGATIVE_RESPONSE SESSION_MESSAGE_TYPE = 0x83 13 | SESSION_RETARGET_RESPONSE SESSION_MESSAGE_TYPE = 0x84 14 | SESSION_KEEP_ALIVE SESSION_MESSAGE_TYPE = 0x85 15 | ) 16 | 17 | var SessionMessageTypeToString = map[SESSION_MESSAGE_TYPE]string{ 18 | SESSION_MESSAGE: "SESSION_MESSAGE", 19 | SESSION_REQUEST: "SESSION_REQUEST", 20 | SESSION_POSITIVE_RESPONSE: "SESSION_POSITIVE_RESPONSE", 21 | SESSION_NEGATIVE_RESPONSE: "SESSION_NEGATIVE_RESPONSE", 22 | SESSION_RETARGET_RESPONSE: "SESSION_RETARGET_RESPONSE", 23 | SESSION_KEEP_ALIVE: "SESSION_KEEP_ALIVE", 24 | } 25 | 26 | func (s SESSION_MESSAGE_TYPE) String() string { 27 | if str, exists := SessionMessageTypeToString[s]; exists { 28 | return str 29 | } 30 | return "UNKNOWN" 31 | } 32 | -------------------------------------------------------------------------------- /network/netbios/session_test.go: -------------------------------------------------------------------------------- 1 | package netbios_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/TheManticoreProject/Manticore/network/netbios" 7 | ) 8 | 9 | func TestSessionMessageTypeString(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | message netbios.SESSION_MESSAGE_TYPE 13 | expected string 14 | }{ 15 | { 16 | name: "SESSION_MESSAGE", 17 | message: netbios.SESSION_MESSAGE, 18 | expected: "SESSION_MESSAGE", 19 | }, 20 | { 21 | name: "SESSION_REQUEST", 22 | message: netbios.SESSION_REQUEST, 23 | expected: "SESSION_REQUEST", 24 | }, 25 | { 26 | name: "SESSION_POSITIVE_RESPONSE", 27 | message: netbios.SESSION_POSITIVE_RESPONSE, 28 | expected: "SESSION_POSITIVE_RESPONSE", 29 | }, 30 | { 31 | name: "SESSION_NEGATIVE_RESPONSE", 32 | message: netbios.SESSION_NEGATIVE_RESPONSE, 33 | expected: "SESSION_NEGATIVE_RESPONSE", 34 | }, 35 | { 36 | name: "SESSION_RETARGET_RESPONSE", 37 | message: netbios.SESSION_RETARGET_RESPONSE, 38 | expected: "SESSION_RETARGET_RESPONSE", 39 | }, 40 | { 41 | name: "SESSION_KEEP_ALIVE", 42 | message: netbios.SESSION_KEEP_ALIVE, 43 | expected: "SESSION_KEEP_ALIVE", 44 | }, 45 | { 46 | name: "UNKNOWN", 47 | message: netbios.SESSION_MESSAGE_TYPE(0xFF), 48 | expected: "UNKNOWN", 49 | }, 50 | } 51 | 52 | for _, tt := range tests { 53 | t.Run(tt.name, func(t *testing.T) { 54 | if got := tt.message.String(); got != tt.expected { 55 | t.Errorf("SESSION_MESSAGE_TYPE.String() = %v, want %v", got, tt.expected) 56 | } 57 | }) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /network/smb/smb_v10/client/client_functions.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | 7 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/transport" 8 | ) 9 | 10 | // NewClientUsingNBTTransport creates a new SMB v1.0 client using NBT transport 11 | // 12 | // Returns: 13 | // - A pointer to the initialized SMB client 14 | // - An error if the client initialization fails 15 | func NewClientUsingNBTTransport(host net.IP, port int) *Client { 16 | return &Client{ 17 | Transport: transport.NewTransport("nbt"), 18 | Connection: &Connection{ 19 | Server: &Server{ 20 | Host: host, 21 | Port: port, 22 | }, 23 | }, 24 | TreeConnect: nil, 25 | Session: nil, 26 | } 27 | } 28 | 29 | // Connect establishes a connection to an SMB server 30 | // 31 | // Returns: 32 | // - An error if the connection fails 33 | func (c *Client) Connect(ipaddr net.IP, port int) error { 34 | err := c.Transport.Connect(ipaddr, port) 35 | if err != nil { 36 | return fmt.Errorf("failed to connect to SMB server: %v", err) 37 | } 38 | 39 | err = c.Negotiate() 40 | if err != nil { 41 | return fmt.Errorf("failed to negotiate with SMB server: %v", err) 42 | } 43 | 44 | return nil 45 | } 46 | 47 | // SetHost sets the host IP address for the SMB client 48 | func (c *Client) SetHost(host net.IP) { 49 | c.Connection.Server.Host = host 50 | } 51 | 52 | // GetHost returns the current host IP address of the SMB client 53 | func (c *Client) GetHost() net.IP { 54 | return c.Connection.Server.Host 55 | } 56 | 57 | // SetPort sets the port number for the SMB client 58 | func (c *Client) SetPort(port int) { 59 | c.Connection.Server.Port = port 60 | } 61 | 62 | // GetPort returns the current port number of the SMB client 63 | func (c *Client) GetPort() int { 64 | return c.Connection.Server.Port 65 | } 66 | -------------------------------------------------------------------------------- /network/smb/smb_v10/client/client_test.go: -------------------------------------------------------------------------------- 1 | package client_test 2 | -------------------------------------------------------------------------------- /network/smb/smb_v10/client/infos.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // GetRemoteServerTime retrieves the current time from the remote server. 8 | // 9 | // This function sends an SMB_COM_QUERY_TIME_REQUEST message to the server 10 | // and receives the server's current time in UTC. 11 | // 12 | // The query process: 13 | // 1. Creates and sends an SMB_COM_NEGOTIATE_REQUEST message 14 | // 2. Receives the SMB_COM_NEGOTIATE_RESPONSE from the server 15 | // 3. Validates the response command type 16 | // 4. Processes server capabilities and configuration 17 | // 18 | // Returns: 19 | // - nil if negotiation is successful 20 | // - An error if any step in the negotiation process fails (connection issues, 21 | // message creation/marshalling errors, transport errors, or unexpected responses) 22 | func (c *Client) GetRemoteServerTime() (time.Time, error) { 23 | return time.Time{}, nil 24 | } 25 | -------------------------------------------------------------------------------- /network/smb/smb_v10/client/tree.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | // TreeConnect represents an established tree connect between the client and share on the server 4 | type TreeConnect struct { 5 | Connection *Connection // The SMB connection associated with this tree connect 6 | ShareName string // The share name corresponding to this tree connect 7 | TreeID uint16 // The TreeID (TID) that identifies this tree connect 8 | Session *Session // A reference to the session on which this tree connect was established 9 | IsDfsShare bool // A Boolean that, if set, indicates that the tree connect was established to a DFS share 10 | } 11 | -------------------------------------------------------------------------------- /network/smb/smb_v10/docs/[MS-CIFS]-250113.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/network/smb/smb_v10/docs/[MS-CIFS]-250113.pdf -------------------------------------------------------------------------------- /network/smb/smb_v10/docs/[MS-SMB].pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/network/smb/smb_v10/docs/[MS-SMB].pdf -------------------------------------------------------------------------------- /network/smb/smb_v10/errors/errors_test.go: -------------------------------------------------------------------------------- 1 | package errors_test 2 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_FIND_FILE_NAMES_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_FIND_FILE_NAMES_INFO 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/88b9968b-a36f-482a-bb30-c7a51a3e290d 10 | type SMB_FIND_FILE_NAMES_INFO struct { 11 | // NextEntryOffset: (4 bytes): This field contains the offset, in bytes, from this 12 | // entry in the list to the next entry in the list. If there are no additional 13 | // entries, the value MUST be zero (0x00000000). 14 | Nextentryoffset types.ULONG 15 | // FileIndex: (4 bytes): This field SHOULD be set to zero when sent in a 16 | // response and SHOULD be ignored when received by the client. 17 | Fileindex types.ULONG 18 | // FileNameLength: (4 bytes): This field MUST contain the length of the FileName 19 | // field, in bytes. 20 | Filenamelength types.ULONG 21 | } 22 | 23 | // Marshal serializes the SMB_FIND_FILE_NAMES_INFO into a byte slice. 24 | // 25 | // This method marshals the information level structure according to the format 26 | // specified in MS-CIFS documentation. Information levels are used in various 27 | // SMB operations to determine the format of data being exchanged. 28 | // 29 | // The marshalled data follows the specific format required for this information level. 30 | // 31 | // Returns: 32 | // - A byte slice containing the marshalled information level structure 33 | // - An error if marshalling any component fails 34 | func (s *SMB_FIND_FILE_NAMES_INFO) Marshal() ([]byte, error) { 35 | marshalled_struct := []byte{} 36 | 37 | return marshalled_struct, nil 38 | } 39 | 40 | // Unmarshal deserializes a byte slice into the SMB_FIND_FILE_NAMES_INFO structure. 41 | // 42 | // This method unmarshals the information level structure according to the format 43 | // specified in MS-CIFS documentation. Information levels are used in various 44 | // SMB operations to determine the format of data being exchanged. 45 | // 46 | // The data is expected to follow the specific format required for this information level. 47 | // 48 | // Parameters: 49 | // - data: A byte slice containing the serialized SMB_FIND_FILE_NAMES_INFO structure 50 | // 51 | // Returns: 52 | // - An error if unmarshalling any component fails or if the data format is invalid 53 | func (s *SMB_FIND_FILE_NAMES_INFO) Unmarshal(data []byte) (int, error) { 54 | return 0, nil 55 | } 56 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_INFO_ALLOCATION.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_INFO_ALLOCATION 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/194f7dd3-a019-4789-a70c-b28e029e6409 10 | type SMB_INFO_ALLOCATION struct { 11 | // idFileSystem: (4 bytes): This field contains a file system identifier. 12 | Idfilesystem types.ULONG 13 | // cSectorUnit: (4 bytes): This field contains the number of sectors per allocation 14 | // unit. 15 | Csectorunit types.ULONG 16 | // cUnit: (4 bytes): This field contains the total number of allocation units. 17 | Cunit types.ULONG 18 | // cUnitAvailable: (4 bytes): This field contains the total number of available 19 | // allocation units. 20 | Cunitavailable types.ULONG 21 | // cbSector: (2 bytes): This field contains the number of bytes per sector. 22 | Cbsector types.USHORT 23 | } 24 | 25 | // Marshal serializes the SMB_INFO_ALLOCATION into a byte slice. 26 | // 27 | // This method marshals the information level structure according to the format 28 | // specified in MS-CIFS documentation. Information levels are used in various 29 | // SMB operations to determine the format of data being exchanged. 30 | // 31 | // The marshalled data follows the specific format required for this information level. 32 | // 33 | // Returns: 34 | // - A byte slice containing the marshalled information level structure 35 | // - An error if marshalling any component fails 36 | func (s *SMB_INFO_ALLOCATION) Marshal() ([]byte, error) { 37 | marshalled_struct := []byte{} 38 | 39 | return marshalled_struct, nil 40 | } 41 | 42 | // Unmarshal deserializes a byte slice into the SMB_INFO_ALLOCATION structure. 43 | // 44 | // This method unmarshals the information level structure according to the format 45 | // specified in MS-CIFS documentation. Information levels are used in various 46 | // SMB operations to determine the format of data being exchanged. 47 | // 48 | // The data is expected to follow the specific format required for this information level. 49 | // 50 | // Parameters: 51 | // - data: A byte slice containing the serialized SMB_INFO_ALLOCATION structure 52 | // 53 | // Returns: 54 | // - An error if unmarshalling any component fails or if the data format is invalid 55 | func (s *SMB_INFO_ALLOCATION) Unmarshal(data []byte) (int, error) { 56 | return 0, nil 57 | } 58 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_INFO_IS_NAME_VALID.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | // SMB_INFO_IS_NAME_VALID 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/67188e6f-1d62-41d2-a9bd-d325e5f75cc1 5 | type SMB_INFO_IS_NAME_VALID struct { 6 | // TODO: Implement this struct 7 | } 8 | 9 | // Marshal serializes the SMB_INFO_IS_NAME_VALID into a byte slice. 10 | // 11 | // This method marshals the information level structure according to the format 12 | // specified in MS-CIFS documentation. Information levels are used in various 13 | // SMB operations to determine the format of data being exchanged. 14 | // 15 | // The marshalled data follows the specific format required for this information level. 16 | // 17 | // Returns: 18 | // - A byte slice containing the marshalled information level structure 19 | // - An error if marshalling any component fails 20 | func (s *SMB_INFO_IS_NAME_VALID) Marshal() ([]byte, error) { 21 | marshalled_struct := []byte{} 22 | 23 | return marshalled_struct, nil 24 | } 25 | 26 | // Unmarshal deserializes a byte slice into the SMB_INFO_IS_NAME_VALID structure. 27 | // 28 | // This method unmarshals the information level structure according to the format 29 | // specified in MS-CIFS documentation. Information levels are used in various 30 | // SMB operations to determine the format of data being exchanged. 31 | // 32 | // The data is expected to follow the specific format required for this information level. 33 | // 34 | // Parameters: 35 | // - data: A byte slice containing the serialized SMB_INFO_IS_NAME_VALID structure 36 | // 37 | // Returns: 38 | // - An error if unmarshalling any component fails or if the data format is invalid 39 | func (s *SMB_INFO_IS_NAME_VALID) Unmarshal(data []byte) (int, error) { 40 | return 0, nil 41 | } 42 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_INFO_QUERY_ALL_EAS.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_INFO_QUERY_ALL_EAS 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/2db63466-bdbf-45c4-96fc-dff83ebda893 10 | type SMB_INFO_QUERY_ALL_EAS struct { 11 | // ExtendedAttributeList: (variable): A list of all of the extended attribute (EA) 12 | // name/value pairs assigned to the file. 13 | Extendedattributelist types.SMB_FEA_LIST 14 | } 15 | 16 | // Marshal serializes the SMB_INFO_QUERY_ALL_EAS into a byte slice. 17 | // 18 | // This method marshals the information level structure according to the format 19 | // specified in MS-CIFS documentation. Information levels are used in various 20 | // SMB operations to determine the format of data being exchanged. 21 | // 22 | // The marshalled data follows the specific format required for this information level. 23 | // 24 | // Returns: 25 | // - A byte slice containing the marshalled information level structure 26 | // - An error if marshalling any component fails 27 | func (s *SMB_INFO_QUERY_ALL_EAS) Marshal() ([]byte, error) { 28 | marshalled_struct := []byte{} 29 | 30 | return marshalled_struct, nil 31 | } 32 | 33 | // Unmarshal deserializes a byte slice into the SMB_INFO_QUERY_ALL_EAS structure. 34 | // 35 | // This method unmarshals the information level structure according to the format 36 | // specified in MS-CIFS documentation. Information levels are used in various 37 | // SMB operations to determine the format of data being exchanged. 38 | // 39 | // The data is expected to follow the specific format required for this information level. 40 | // 41 | // Parameters: 42 | // - data: A byte slice containing the serialized SMB_INFO_QUERY_ALL_EAS structure 43 | // 44 | // Returns: 45 | // - An error if unmarshalling any component fails or if the data format is invalid 46 | func (s *SMB_INFO_QUERY_ALL_EAS) Unmarshal(data []byte) (int, error) { 47 | return 0, nil 48 | } 49 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_INFO_QUERY_EAS_FROM_LIST.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_INFO_QUERY_EAS_FROM_LIST 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/0cf863b2-0f6a-470b-b02a-6a21441e2c4a 10 | type SMB_INFO_QUERY_EAS_FROM_LIST struct { 11 | // ExtendedAttributeList: (variable): A list of extended attribute (EA) name/value 12 | // pairs where the AttributeName field values match those that were provided in the 13 | // request. 14 | Extendedattributelist types.SMB_FEA_LIST 15 | } 16 | 17 | // Marshal serializes the SMB_INFO_QUERY_EAS_FROM_LIST into a byte slice. 18 | // 19 | // This method marshals the information level structure according to the format 20 | // specified in MS-CIFS documentation. Information levels are used in various 21 | // SMB operations to determine the format of data being exchanged. 22 | // 23 | // The marshalled data follows the specific format required for this information level. 24 | // 25 | // Returns: 26 | // - A byte slice containing the marshalled information level structure 27 | // - An error if marshalling any component fails 28 | func (s *SMB_INFO_QUERY_EAS_FROM_LIST) Marshal() ([]byte, error) { 29 | marshalled_struct := []byte{} 30 | 31 | return marshalled_struct, nil 32 | } 33 | 34 | // Unmarshal deserializes a byte slice into the SMB_INFO_QUERY_EAS_FROM_LIST structure. 35 | // 36 | // This method unmarshals the information level structure according to the format 37 | // specified in MS-CIFS documentation. Information levels are used in various 38 | // SMB operations to determine the format of data being exchanged. 39 | // 40 | // The data is expected to follow the specific format required for this information level. 41 | // 42 | // Parameters: 43 | // - data: A byte slice containing the serialized SMB_INFO_QUERY_EAS_FROM_LIST structure 44 | // 45 | // Returns: 46 | // - An error if unmarshalling any component fails or if the data format is invalid 47 | func (s *SMB_INFO_QUERY_EAS_FROM_LIST) Unmarshal(data []byte) (int, error) { 48 | return 0, nil 49 | } 50 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_INFO_SET_EAS.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_INFO_SET_EAS 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/417809e1-82ff-4acf-bc99-9de5bf7455d4 10 | type SMB_INFO_SET_EAS struct { 11 | // ExtendedAttributeList: (variable): A list of EA name/value pairs. 12 | Extendedattributelist types.SMB_FEA_LIST 13 | } 14 | 15 | // Marshal serializes the SMB_INFO_SET_EAS into a byte slice. 16 | // 17 | // This method marshals the information level structure according to the format 18 | // specified in MS-CIFS documentation. Information levels are used in various 19 | // SMB operations to determine the format of data being exchanged. 20 | // 21 | // The marshalled data follows the specific format required for this information level. 22 | // 23 | // Returns: 24 | // - A byte slice containing the marshalled information level structure 25 | // - An error if marshalling any component fails 26 | func (s *SMB_INFO_SET_EAS) Marshal() ([]byte, error) { 27 | marshalled_struct := []byte{} 28 | 29 | return marshalled_struct, nil 30 | } 31 | 32 | // Unmarshal deserializes a byte slice into the SMB_INFO_SET_EAS structure. 33 | // 34 | // This method unmarshals the information level structure according to the format 35 | // specified in MS-CIFS documentation. Information levels are used in various 36 | // SMB operations to determine the format of data being exchanged. 37 | // 38 | // The data is expected to follow the specific format required for this information level. 39 | // 40 | // Parameters: 41 | // - data: A byte slice containing the serialized SMB_INFO_SET_EAS structure 42 | // 43 | // Returns: 44 | // - An error if unmarshalling any component fails or if the data format is invalid 45 | func (s *SMB_INFO_SET_EAS) Unmarshal(data []byte) (int, error) { 46 | return 0, nil 47 | } 48 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_INFO_STANDARD.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_INFO_STANDARD 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/3e6f3a13-6a40-4f76-af70-bb514554ea5b 10 | type SMB_INFO_STANDARD struct { 11 | // CreationDate: (2 bytes): This field contains the date when the file was created. 12 | Creationdate types.SMB_DATE 13 | // CreationTime: (2 bytes): This field contains the time when the file was created. 14 | Creationtime types.SMB_TIME 15 | // LastAccessDate: (2 bytes): This field contains the date when the file was last 16 | // accessed. 17 | Lastaccessdate types.SMB_DATE 18 | // LastAccessTime: (2 bytes): This field contains the time when the file was last 19 | // accessed. 20 | Lastaccesstime types.SMB_TIME 21 | // LastWriteDate: (2 bytes): This field contains the date when data was last 22 | // written to the file. 23 | Lastwritedate types.SMB_DATE 24 | // LastWriteTime: (2 bytes): This field contains the time when data was last 25 | // written to the file. 26 | Lastwritetime types.SMB_TIME 27 | } 28 | 29 | // Marshal serializes the SMB_INFO_STANDARD into a byte slice. 30 | // 31 | // This method marshals the information level structure according to the format 32 | // specified in MS-CIFS documentation. Information levels are used in various 33 | // SMB operations to determine the format of data being exchanged. 34 | // 35 | // The marshalled data follows the specific format required for this information level. 36 | // 37 | // Returns: 38 | // - A byte slice containing the marshalled information level structure 39 | // - An error if marshalling any component fails 40 | func (s *SMB_INFO_STANDARD) Marshal() ([]byte, error) { 41 | marshalled_struct := []byte{} 42 | 43 | return marshalled_struct, nil 44 | } 45 | 46 | // Unmarshal deserializes a byte slice into the SMB_INFO_STANDARD structure. 47 | // 48 | // This method unmarshals the information level structure according to the format 49 | // specified in MS-CIFS documentation. Information levels are used in various 50 | // SMB operations to determine the format of data being exchanged. 51 | // 52 | // The data is expected to follow the specific format required for this information level. 53 | // 54 | // Parameters: 55 | // - data: A byte slice containing the serialized SMB_INFO_STANDARD structure 56 | // 57 | // Returns: 58 | // - An error if unmarshalling any component fails or if the data format is invalid 59 | func (s *SMB_INFO_STANDARD) Unmarshal(data []byte) (int, error) { 60 | return 0, nil 61 | } 62 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_INFO_VOLUME.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_INFO_VOLUME 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/13d589f5-67e9-49e8-8c33-7b04b8f7cd8c 10 | type SMB_INFO_VOLUME struct { 11 | // ulVolSerialNbr: (4 bytes): This field contains the serial number of the volume. 12 | Ulvolserialnbr types.ULONG 13 | // cCharCount: (1 byte): This field contains the number of characters in the 14 | // VolumeLabel field. 15 | Ccharcount types.UCHAR 16 | // VolumeLabel: (variable): This field contains the volume label. 17 | Volumelabel types.SMB_STRING 18 | } 19 | 20 | // Marshal serializes the SMB_INFO_VOLUME into a byte slice. 21 | // 22 | // This method marshals the information level structure according to the format 23 | // specified in MS-CIFS documentation. Information levels are used in various 24 | // SMB operations to determine the format of data being exchanged. 25 | // 26 | // The marshalled data follows the specific format required for this information level. 27 | // 28 | // Returns: 29 | // - A byte slice containing the marshalled information level structure 30 | // - An error if marshalling any component fails 31 | func (s *SMB_INFO_VOLUME) Marshal() ([]byte, error) { 32 | marshalled_struct := []byte{} 33 | 34 | return marshalled_struct, nil 35 | } 36 | 37 | // Unmarshal deserializes a byte slice into the SMB_INFO_VOLUME structure. 38 | // 39 | // This method unmarshals the information level structure according to the format 40 | // specified in MS-CIFS documentation. Information levels are used in various 41 | // SMB operations to determine the format of data being exchanged. 42 | // 43 | // The data is expected to follow the specific format required for this information level. 44 | // 45 | // Parameters: 46 | // - data: A byte slice containing the serialized SMB_INFO_VOLUME structure 47 | // 48 | // Returns: 49 | // - An error if unmarshalling any component fails or if the data format is invalid 50 | func (s *SMB_INFO_VOLUME) Unmarshal(data []byte) (int, error) { 51 | return 0, nil 52 | } 53 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_QUERY_FILE_ALT_NAME_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_QUERY_FILE_ALT_NAME_INFO 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/3edd12e7-f407-4b46-9465-c6ed20e24c1a 10 | type SMB_QUERY_FILE_ALT_NAME_INFO struct { 11 | // FileNameLength: (4 bytes): This field contains the length, in bytes, of the 12 | // FileName field. 13 | Filenamelength types.ULONG 14 | } 15 | 16 | // Marshal serializes the SMB_QUERY_FILE_ALT_NAME_INFO into a byte slice. 17 | // 18 | // This method marshals the information level structure according to the format 19 | // specified in MS-CIFS documentation. Information levels are used in various 20 | // SMB operations to determine the format of data being exchanged. 21 | // 22 | // The marshalled data follows the specific format required for this information level. 23 | // 24 | // Returns: 25 | // - A byte slice containing the marshalled information level structure 26 | // - An error if marshalling any component fails 27 | func (s *SMB_QUERY_FILE_ALT_NAME_INFO) Marshal() ([]byte, error) { 28 | marshalled_struct := []byte{} 29 | 30 | return marshalled_struct, nil 31 | } 32 | 33 | // Unmarshal deserializes a byte slice into the SMB_QUERY_FILE_ALT_NAME_INFO structure. 34 | // 35 | // This method unmarshals the information level structure according to the format 36 | // specified in MS-CIFS documentation. Information levels are used in various 37 | // SMB operations to determine the format of data being exchanged. 38 | // 39 | // The data is expected to follow the specific format required for this information level. 40 | // 41 | // Parameters: 42 | // - data: A byte slice containing the serialized SMB_QUERY_FILE_ALT_NAME_INFO structure 43 | // 44 | // Returns: 45 | // - An error if unmarshalling any component fails or if the data format is invalid 46 | func (s *SMB_QUERY_FILE_ALT_NAME_INFO) Unmarshal(data []byte) (int, error) { 47 | return 0, nil 48 | } 49 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_QUERY_FILE_EA_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_QUERY_FILE_EA_INFO 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/3e85d60e-696a-4436-8757-84233d9f0245 10 | type SMB_QUERY_FILE_EA_INFO struct { 11 | // EaSize: (4 bytes): This field MUST contain the length of a file's list of 12 | // extended attributes in bytes. 13 | Easize types.ULONG 14 | } 15 | 16 | // Marshal serializes the SMB_QUERY_FILE_EA_INFO into a byte slice. 17 | // 18 | // This method marshals the information level structure according to the format 19 | // specified in MS-CIFS documentation. Information levels are used in various 20 | // SMB operations to determine the format of data being exchanged. 21 | // 22 | // The marshalled data follows the specific format required for this information level. 23 | // 24 | // Returns: 25 | // - A byte slice containing the marshalled information level structure 26 | // - An error if marshalling any component fails 27 | func (s *SMB_QUERY_FILE_EA_INFO) Marshal() ([]byte, error) { 28 | marshalled_struct := []byte{} 29 | 30 | return marshalled_struct, nil 31 | } 32 | 33 | // Unmarshal deserializes a byte slice into the SMB_QUERY_FILE_EA_INFO structure. 34 | // 35 | // This method unmarshals the information level structure according to the format 36 | // specified in MS-CIFS documentation. Information levels are used in various 37 | // SMB operations to determine the format of data being exchanged. 38 | // 39 | // The data is expected to follow the specific format required for this information level. 40 | // 41 | // Parameters: 42 | // - data: A byte slice containing the serialized SMB_QUERY_FILE_EA_INFO structure 43 | // 44 | // Returns: 45 | // - An error if unmarshalling any component fails or if the data format is invalid 46 | func (s *SMB_QUERY_FILE_EA_INFO) Unmarshal(data []byte) (int, error) { 47 | return 0, nil 48 | } 49 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_QUERY_FILE_NAME_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_QUERY_FILE_NAME_INFO 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/0cdd9e53-bc92-4f26-8b22-ed11fc06a6d7 10 | type SMB_QUERY_FILE_NAME_INFO struct { 11 | // FileNameLength: (4 bytes): This field MUST contain the length of the FileName 12 | // field in bytes. 13 | Filenamelength types.ULONG 14 | } 15 | 16 | // Marshal serializes the SMB_QUERY_FILE_NAME_INFO into a byte slice. 17 | // 18 | // This method marshals the information level structure according to the format 19 | // specified in MS-CIFS documentation. Information levels are used in various 20 | // SMB operations to determine the format of data being exchanged. 21 | // 22 | // The marshalled data follows the specific format required for this information level. 23 | // 24 | // Returns: 25 | // - A byte slice containing the marshalled information level structure 26 | // - An error if marshalling any component fails 27 | func (s *SMB_QUERY_FILE_NAME_INFO) Marshal() ([]byte, error) { 28 | marshalled_struct := []byte{} 29 | 30 | return marshalled_struct, nil 31 | } 32 | 33 | // Unmarshal deserializes a byte slice into the SMB_QUERY_FILE_NAME_INFO structure. 34 | // 35 | // This method unmarshals the information level structure according to the format 36 | // specified in MS-CIFS documentation. Information levels are used in various 37 | // SMB operations to determine the format of data being exchanged. 38 | // 39 | // The data is expected to follow the specific format required for this information level. 40 | // 41 | // Parameters: 42 | // - data: A byte slice containing the serialized SMB_QUERY_FILE_NAME_INFO structure 43 | // 44 | // Returns: 45 | // - An error if unmarshalling any component fails or if the data format is invalid 46 | func (s *SMB_QUERY_FILE_NAME_INFO) Unmarshal(data []byte) (int, error) { 47 | return 0, nil 48 | } 49 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_QUERY_FILE_STANDARD_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_QUERY_FILE_STANDARD_INFO 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/3bdd080c-f8a4-4a09-acf1-0f8bd00152e4 10 | type SMB_QUERY_FILE_STANDARD_INFO struct { 11 | Allocationsize types.LARGE_INTEGER 12 | // EndOfFile: (8 bytes): This field contains the offset, in bytes, from the start 13 | // of the file to the first byte after the end of the file. 14 | Endoffile types.LARGE_INTEGER 15 | // NumberOfLinks: (4 bytes): This field contains the number of hard links to the 16 | // file. 17 | Numberoflinks types.ULONG 18 | // DeletePending: (1 byte): This field indicates whether there is a delete action 19 | // pending for the file. 20 | Deletepending types.UCHAR 21 | // Directory: (1 byte): This field indicates whether the file is a directory. 22 | Directory types.UCHAR 23 | } 24 | 25 | // Marshal serializes the SMB_QUERY_FILE_STANDARD_INFO into a byte slice. 26 | // 27 | // This method marshals the information level structure according to the format 28 | // specified in MS-CIFS documentation. Information levels are used in various 29 | // SMB operations to determine the format of data being exchanged. 30 | // 31 | // The marshalled data follows the specific format required for this information level. 32 | // 33 | // Returns: 34 | // - A byte slice containing the marshalled information level structure 35 | // - An error if marshalling any component fails 36 | func (s *SMB_QUERY_FILE_STANDARD_INFO) Marshal() ([]byte, error) { 37 | marshalled_struct := []byte{} 38 | 39 | return marshalled_struct, nil 40 | } 41 | 42 | // Unmarshal deserializes a byte slice into the SMB_QUERY_FILE_STANDARD_INFO structure. 43 | // 44 | // This method unmarshals the information level structure according to the format 45 | // specified in MS-CIFS documentation. Information levels are used in various 46 | // SMB operations to determine the format of data being exchanged. 47 | // 48 | // The data is expected to follow the specific format required for this information level. 49 | // 50 | // Parameters: 51 | // - data: A byte slice containing the serialized SMB_QUERY_FILE_STANDARD_INFO structure 52 | // 53 | // Returns: 54 | // - An error if unmarshalling any component fails or if the data format is invalid 55 | func (s *SMB_QUERY_FILE_STANDARD_INFO) Unmarshal(data []byte) (int, error) { 56 | return 0, nil 57 | } 58 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_QUERY_FS_ATTRIBUTE_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | // SMB_QUERY_FS_ATTRIBUTE_INFO 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/1011206a-55c5-4dbf-aff0-119514136940 5 | type SMB_QUERY_FS_ATTRIBUTE_INFO struct { 6 | // TODO: Implement this struct 7 | } 8 | 9 | // Marshal serializes the SMB_QUERY_FS_ATTRIBUTE_INFO into a byte slice. 10 | // 11 | // This method marshals the information level structure according to the format 12 | // specified in MS-CIFS documentation. Information levels are used in various 13 | // SMB operations to determine the format of data being exchanged. 14 | // 15 | // The marshalled data follows the specific format required for this information level. 16 | // 17 | // Returns: 18 | // - A byte slice containing the marshalled information level structure 19 | // - An error if marshalling any component fails 20 | func (s *SMB_QUERY_FS_ATTRIBUTE_INFO) Marshal() ([]byte, error) { 21 | marshalled_struct := []byte{} 22 | 23 | return marshalled_struct, nil 24 | } 25 | 26 | // Unmarshal deserializes a byte slice into the SMB_QUERY_FS_ATTRIBUTE_INFO structure. 27 | // 28 | // This method unmarshals the information level structure according to the format 29 | // specified in MS-CIFS documentation. Information levels are used in various 30 | // SMB operations to determine the format of data being exchanged. 31 | // 32 | // The data is expected to follow the specific format required for this information level. 33 | // 34 | // Parameters: 35 | // - data: A byte slice containing the serialized SMB_QUERY_FS_ATTRIBUTE_INFO structure 36 | // 37 | // Returns: 38 | // - An error if unmarshalling any component fails or if the data format is invalid 39 | func (s *SMB_QUERY_FS_ATTRIBUTE_INFO) Unmarshal(data []byte) (int, error) { 40 | return 0, nil 41 | } 42 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_QUERY_FS_DEVICE_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_QUERY_FS_DEVICE_INFO 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/d7ea6e1a-6526-4230-b566-e9588c7498f1 10 | type SMB_QUERY_FS_DEVICE_INFO struct { 11 | // DeviceType: (4 bytes): This field contains the device type on which the volume 12 | // resides. 13 | Devicetype types.ULONG 14 | // DeviceCharacteristics: (4 bytes): This 32-bit field of flags contains the device 15 | // characteristics. The individual flags are as follows. 16 | Devicecharacteristics types.ULONG 17 | } 18 | 19 | // Marshal serializes the SMB_QUERY_FS_DEVICE_INFO into a byte slice. 20 | // 21 | // This method marshals the information level structure according to the format 22 | // specified in MS-CIFS documentation. Information levels are used in various 23 | // SMB operations to determine the format of data being exchanged. 24 | // 25 | // The marshalled data follows the specific format required for this information level. 26 | // 27 | // Returns: 28 | // - A byte slice containing the marshalled information level structure 29 | // - An error if marshalling any component fails 30 | func (s *SMB_QUERY_FS_DEVICE_INFO) Marshal() ([]byte, error) { 31 | marshalled_struct := []byte{} 32 | 33 | return marshalled_struct, nil 34 | } 35 | 36 | // Unmarshal deserializes a byte slice into the SMB_QUERY_FS_DEVICE_INFO structure. 37 | // 38 | // This method unmarshals the information level structure according to the format 39 | // specified in MS-CIFS documentation. Information levels are used in various 40 | // SMB operations to determine the format of data being exchanged. 41 | // 42 | // The data is expected to follow the specific format required for this information level. 43 | // 44 | // Parameters: 45 | // - data: A byte slice containing the serialized SMB_QUERY_FS_DEVICE_INFO structure 46 | // 47 | // Returns: 48 | // - An error if unmarshalling any component fails or if the data format is invalid 49 | func (s *SMB_QUERY_FS_DEVICE_INFO) Unmarshal(data []byte) (int, error) { 50 | return 0, nil 51 | } 52 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_QUERY_FS_SIZE_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_QUERY_FS_SIZE_INFO 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/3045d7df-7757-4725-9ffd-20227978cc46 10 | type SMB_QUERY_FS_SIZE_INFO struct { 11 | // TotalAllocationUnits: (8 bytes): This field contains the total number of 12 | // allocation units assigned to the volume. 13 | Totalallocationunits types.LARGE_INTEGER 14 | // TotalFreeAllocationUnits: (8 bytes): This field contains the total number of 15 | // unallocated or free allocation units for the volume. 16 | Totalfreeallocationunits types.LARGE_INTEGER 17 | // SectorsPerAllocationUnit: (4 bytes): This field contains the number of sectors 18 | // per allocation unit. 19 | Sectorsperallocationunit types.ULONG 20 | // BytesPerSector: (4 bytes): This field contains the bytes per sector. 21 | Bytespersector types.ULONG 22 | } 23 | 24 | // Marshal serializes the SMB_QUERY_FS_SIZE_INFO into a byte slice. 25 | // 26 | // This method marshals the information level structure according to the format 27 | // specified in MS-CIFS documentation. Information levels are used in various 28 | // SMB operations to determine the format of data being exchanged. 29 | // 30 | // The marshalled data follows the specific format required for this information level. 31 | // 32 | // Returns: 33 | // - A byte slice containing the marshalled information level structure 34 | // - An error if marshalling any component fails 35 | func (s *SMB_QUERY_FS_SIZE_INFO) Marshal() ([]byte, error) { 36 | marshalled_struct := []byte{} 37 | 38 | return marshalled_struct, nil 39 | } 40 | 41 | // Unmarshal deserializes a byte slice into the SMB_QUERY_FS_SIZE_INFO structure. 42 | // 43 | // This method unmarshals the information level structure according to the format 44 | // specified in MS-CIFS documentation. Information levels are used in various 45 | // SMB operations to determine the format of data being exchanged. 46 | // 47 | // The data is expected to follow the specific format required for this information level. 48 | // 49 | // Parameters: 50 | // - data: A byte slice containing the serialized SMB_QUERY_FS_SIZE_INFO structure 51 | // 52 | // Returns: 53 | // - An error if unmarshalling any component fails or if the data format is invalid 54 | func (s *SMB_QUERY_FS_SIZE_INFO) Unmarshal(data []byte) (int, error) { 55 | return 0, nil 56 | } 57 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_QUERY_FS_VOLUME_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_QUERY_FS_VOLUME_INFO 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/879f3ae2-b029-4b3b-8043-c830fc517b28 10 | type SMB_QUERY_FS_VOLUME_INFO struct { 11 | // VolumeCreationTime: (8 bytes): This field contains the date and time when the 12 | // volume was created. 13 | Volumecreationtime types.FILETIME 14 | // SerialNumber: (4 bytes): This field contains the serial number of the volume. 15 | Serialnumber types.ULONG 16 | // VolumeLabelSize: (4 bytes): This field contains the size of the VolumeLabel 17 | // field, in bytes. 18 | Volumelabelsize types.ULONG 19 | Reserved types.USHORT 20 | } 21 | 22 | // Marshal serializes the SMB_QUERY_FS_VOLUME_INFO into a byte slice. 23 | // 24 | // This method marshals the information level structure according to the format 25 | // specified in MS-CIFS documentation. Information levels are used in various 26 | // SMB operations to determine the format of data being exchanged. 27 | // 28 | // The marshalled data follows the specific format required for this information level. 29 | // 30 | // Returns: 31 | // - A byte slice containing the marshalled information level structure 32 | // - An error if marshalling any component fails 33 | func (s *SMB_QUERY_FS_VOLUME_INFO) Marshal() ([]byte, error) { 34 | marshalled_struct := []byte{} 35 | 36 | return marshalled_struct, nil 37 | } 38 | 39 | // Unmarshal deserializes a byte slice into the SMB_QUERY_FS_VOLUME_INFO structure. 40 | // 41 | // This method unmarshals the information level structure according to the format 42 | // specified in MS-CIFS documentation. Information levels are used in various 43 | // SMB operations to determine the format of data being exchanged. 44 | // 45 | // The data is expected to follow the specific format required for this information level. 46 | // 47 | // Parameters: 48 | // - data: A byte slice containing the serialized SMB_QUERY_FS_VOLUME_INFO structure 49 | // 50 | // Returns: 51 | // - An error if unmarshalling any component fails or if the data format is invalid 52 | func (s *SMB_QUERY_FS_VOLUME_INFO) Unmarshal(data []byte) (int, error) { 53 | return 0, nil 54 | } 55 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_SET_FILE_ALLOCATION_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_SET_FILE_ALLOCATION_INFO 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/d362c412-dcd0-463d-93e4-3e09aa8cacc5 10 | type SMB_SET_FILE_ALLOCATION_INFO struct { 11 | // AllocationSize: (8 bytes): A 64-bit signed integer containing the file 12 | // allocation size, in bytes. Usually, this value is a multiple of the sector or 13 | // cluster size of the underlying physical device. This value MUST be greater than 14 | // or equal to 0x0000000000000000. All unused allocation (beyond EOF) is freed. 15 | Allocationsize types.LARGE_INTEGER 16 | } 17 | 18 | // Marshal serializes the SMB_SET_FILE_ALLOCATION_INFO into a byte slice. 19 | // 20 | // This method marshals the information level structure according to the format 21 | // specified in MS-CIFS documentation. Information levels are used in various 22 | // SMB operations to determine the format of data being exchanged. 23 | // 24 | // The marshalled data follows the specific format required for this information level. 25 | // 26 | // Returns: 27 | // - A byte slice containing the marshalled information level structure 28 | // - An error if marshalling any component fails 29 | func (s *SMB_SET_FILE_ALLOCATION_INFO) Marshal() ([]byte, error) { 30 | marshalled_struct := []byte{} 31 | 32 | return marshalled_struct, nil 33 | } 34 | 35 | // Unmarshal deserializes a byte slice into the SMB_SET_FILE_ALLOCATION_INFO structure. 36 | // 37 | // This method unmarshals the information level structure according to the format 38 | // specified in MS-CIFS documentation. Information levels are used in various 39 | // SMB operations to determine the format of data being exchanged. 40 | // 41 | // The data is expected to follow the specific format required for this information level. 42 | // 43 | // Parameters: 44 | // - data: A byte slice containing the serialized SMB_SET_FILE_ALLOCATION_INFO structure 45 | // 46 | // Returns: 47 | // - An error if unmarshalling any component fails or if the data format is invalid 48 | func (s *SMB_SET_FILE_ALLOCATION_INFO) Unmarshal(data []byte) (int, error) { 49 | return 0, nil 50 | } 51 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_SET_FILE_DISPOSITION_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_SET_FILE_DISPOSITION_INFO 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/bb8e952b-d293-4fc3-bc47-67ce1a8f8655 10 | type SMB_SET_FILE_DISPOSITION_INFO struct { 11 | // DeletePending: (1 byte): An 8-bit field that is set to 0x01 to indicate that a 12 | // file SHOULD be deleted when it is closed; otherwise, to 0x00. 13 | Deletepending types.UCHAR 14 | } 15 | 16 | // Marshal serializes the SMB_SET_FILE_DISPOSITION_INFO into a byte slice. 17 | // 18 | // This method marshals the information level structure according to the format 19 | // specified in MS-CIFS documentation. Information levels are used in various 20 | // SMB operations to determine the format of data being exchanged. 21 | // 22 | // The marshalled data follows the specific format required for this information level. 23 | // 24 | // Returns: 25 | // - A byte slice containing the marshalled information level structure 26 | // - An error if marshalling any component fails 27 | func (s *SMB_SET_FILE_DISPOSITION_INFO) Marshal() ([]byte, error) { 28 | marshalled_struct := []byte{} 29 | 30 | return marshalled_struct, nil 31 | } 32 | 33 | // Unmarshal deserializes a byte slice into the SMB_SET_FILE_DISPOSITION_INFO structure. 34 | // 35 | // This method unmarshals the information level structure according to the format 36 | // specified in MS-CIFS documentation. Information levels are used in various 37 | // SMB operations to determine the format of data being exchanged. 38 | // 39 | // The data is expected to follow the specific format required for this information level. 40 | // 41 | // Parameters: 42 | // - data: A byte slice containing the serialized SMB_SET_FILE_DISPOSITION_INFO structure 43 | // 44 | // Returns: 45 | // - An error if unmarshalling any component fails or if the data format is invalid 46 | func (s *SMB_SET_FILE_DISPOSITION_INFO) Unmarshal(data []byte) (int, error) { 47 | return 0, nil 48 | } 49 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/SMB_SET_FILE_END_OF_FILE_INFO.go: -------------------------------------------------------------------------------- 1 | package informationlevels 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/types" 5 | ) 6 | 7 | 8 | // SMB_SET_FILE_END_OF_FILE_INFO 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/4735b3d3-cb3b-4c9d-b11c-482d7bc48722 10 | type SMB_SET_FILE_END_OF_FILE_INFO struct { 11 | // EndOfFile: (8 bytes): A 64-bit signed integer that contains the absolute new 12 | // end-of-file position as a byte offset from the start of the file. EndOfFile 13 | // specifies the offset from the beginning of the file to the byte following the 14 | // last byte in the file. It is the offset from the beginning of the file at which 15 | // new bytes appended to the file are to be written. The value of this field MUST 16 | // be greater than or equal to 0x0000000000000000. 17 | Endoffile types.LARGE_INTEGER 18 | } 19 | 20 | // Marshal serializes the SMB_SET_FILE_END_OF_FILE_INFO into a byte slice. 21 | // 22 | // This method marshals the information level structure according to the format 23 | // specified in MS-CIFS documentation. Information levels are used in various 24 | // SMB operations to determine the format of data being exchanged. 25 | // 26 | // The marshalled data follows the specific format required for this information level. 27 | // 28 | // Returns: 29 | // - A byte slice containing the marshalled information level structure 30 | // - An error if marshalling any component fails 31 | func (s *SMB_SET_FILE_END_OF_FILE_INFO) Marshal() ([]byte, error) { 32 | marshalled_struct := []byte{} 33 | 34 | return marshalled_struct, nil 35 | } 36 | 37 | // Unmarshal deserializes a byte slice into the SMB_SET_FILE_END_OF_FILE_INFO structure. 38 | // 39 | // This method unmarshals the information level structure according to the format 40 | // specified in MS-CIFS documentation. Information levels are used in various 41 | // SMB operations to determine the format of data being exchanged. 42 | // 43 | // The data is expected to follow the specific format required for this information level. 44 | // 45 | // Parameters: 46 | // - data: A byte slice containing the serialized SMB_SET_FILE_END_OF_FILE_INFO structure 47 | // 48 | // Returns: 49 | // - An error if unmarshalling any component fails or if the data format is invalid 50 | func (s *SMB_SET_FILE_END_OF_FILE_INFO) Unmarshal(data []byte) (int, error) { 51 | return 0, nil 52 | } 53 | -------------------------------------------------------------------------------- /network/smb/smb_v10/informationlevels/informationlevels_test.go: -------------------------------------------------------------------------------- 1 | package informationlevels_test 2 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/commands/ReadRawResponse.go: -------------------------------------------------------------------------------- 1 | package commands 2 | 3 | // ReadRawResponse 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/3f3914f6-d251-48ab-89c0-35349cb6d1c8 5 | 6 | // The server's "raw" response 7 | // - No SMB Header at all. Instead, the server uses the underlying SMB transport's session-service framing 8 | // (4-byte NetBIOS header: 1-byte MessageType + 3-byte Length) and then emits only the file-data bytes. There is: 9 | // [NetBIOS Session Service header: 10 | // - MessageType = 0x00 (session message) 11 | // - Length = N (the number of data bytes) 12 | // ] 13 | // [Raw data payload: N bytes of file or pipe data] 14 | 15 | // There is no SMB Status/Flags fields, no WordCount, no DataOffset-just a single contiguous byte-stream whose length 16 | // is inferred from the transport header. 17 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/07e4a838-0137-4405-b534-1e5eeaf16812 18 | // - If the server can't fulfill the read (error or EOF), it simply returns a zero-length payload (Length=0) 19 | 20 | // Why "no SMB Header" on the response? 21 | 22 | // Because SMB_COM_READ_RAW is optimized for bulk reads, the designers stripped away the per-message header to avoid 23 | // extra framing overhead and allow messages larger than the negotiated buffer size. The only framing is done by the 24 | // NetBIOS session layer, so the client must quiesce all other requests until it has received exactly the number of 25 | // bytes (or fewer, on EOF) that it asked for 26 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/commands/andx/andx.go: -------------------------------------------------------------------------------- 1 | package andx 2 | 3 | import ( 4 | "encoding/binary" 5 | "errors" 6 | 7 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/message/commands/codes" 8 | ) 9 | 10 | // AndX Messages contain a construct, conceptually similar to a linked-list, that is used to connect the batched block pairs. 11 | // Source: 2.2.3.4 Batched Messages ("AndX" Messages) https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/fc4d19f7-8040-426d-9154-7219c57453c8 12 | type AndX struct { 13 | AndXCommand codes.CommandCode 14 | AndXReserved uint8 15 | AndXOffset uint16 16 | } 17 | 18 | // NewAndX creates a new AndX structure 19 | func NewAndX() *AndX { 20 | return &AndX{ 21 | AndXCommand: 0, 22 | AndXReserved: 0, 23 | AndXOffset: 0, 24 | } 25 | } 26 | 27 | // GetParameters returns the parameters of the AndX structure 28 | // Returns: 29 | // - A byte array containing the parameters of the AndX structure 30 | func (a *AndX) GetParameters() []uint16 { 31 | return []uint16{uint16(a.AndXCommand)<<8 | uint16(a.AndXReserved), a.AndXOffset} 32 | } 33 | 34 | // Marshal marshals the AndX structure into a byte array 35 | // Returns: 36 | // - A byte array containing the marshalled AndX structure 37 | // - An error if the marshalling process fails, or nil if successful 38 | func (a *AndX) Marshal() ([]byte, error) { 39 | marshalled_andx := []byte{} 40 | 41 | marshalled_andx = append(marshalled_andx, byte(a.AndXCommand)) 42 | 43 | marshalled_andx = append(marshalled_andx, a.AndXReserved) 44 | 45 | buf2 := make([]byte, 2) 46 | binary.BigEndian.PutUint16(buf2, a.AndXOffset) 47 | marshalled_andx = append(marshalled_andx, buf2...) 48 | 49 | return marshalled_andx, nil 50 | } 51 | 52 | // Unmarshal unmarshals the AndX structure from a byte array 53 | // Returns: 54 | // - The number of bytes read 55 | // - An error if the unmarshalling process fails, or nil if successful 56 | func (a *AndX) Unmarshal(data []byte) (int, error) { 57 | if len(data) < 4 { 58 | return 0, errors.New("data is too short to unmarshal AndX") 59 | } 60 | 61 | a.AndXCommand = codes.CommandCode(data[0]) 62 | 63 | a.AndXReserved = data[1] 64 | 65 | a.AndXOffset = binary.BigEndian.Uint16(data[2:4]) 66 | 67 | return 4, nil 68 | } 69 | 70 | // GetCommandCode returns the command code of the AndX structure 71 | // Returns: 72 | // - The command code of the AndX structure 73 | func (a *AndX) GetCommandCode() codes.CommandCode { 74 | return a.AndXCommand 75 | } 76 | 77 | // GetOffset returns the offset of the AndX structure 78 | // Returns: 79 | // - The offset of the AndX structure 80 | func (a *AndX) GetOffset() uint16 { 81 | return a.AndXOffset 82 | } 83 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/commands/codes/codes_test.go: -------------------------------------------------------------------------------- 1 | package codes_test 2 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/commands/commands_test.go: -------------------------------------------------------------------------------- 1 | package commands_test 2 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/commands/utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | // GetNullTerminatedUnicodeString returns the null-terminated Unicode string from the data 4 | // and the offset of the next byte after the null terminator 5 | // 6 | // Parameters: 7 | // - data: The data to extract the null-terminated Unicode string from 8 | // 9 | // Returns: 10 | // - The null-terminated Unicode string 11 | // - The offset of the next byte after the null terminator 12 | func GetNullTerminatedUnicodeString(data []byte) (string, int) { 13 | bytesString := []byte{} 14 | for i := 0; i < len(data); i += 2 { 15 | if data[i] == 0 && data[i+1] == 0 { 16 | break 17 | } else { 18 | bytesString = append(bytesString, data[i]) 19 | bytesString = append(bytesString, data[i+1]) 20 | } 21 | } 22 | return string(bytesString), len(bytesString) + 2 23 | } 24 | 25 | // GetNullTerminatedString returns the null-terminated string from the data 26 | // and the offset of the next byte after the null terminator 27 | // 28 | // Parameters: 29 | // - data: The data to extract the null-terminated string from 30 | // 31 | // Returns: 32 | // - The null-terminated string 33 | // - The offset of the next byte after the null terminator 34 | func GetNullTerminatedString(data []byte) (string, int) { 35 | bytesString := []byte{} 36 | for i := 0; i < len(data); i++ { 37 | if data[i] == 0 { 38 | break 39 | } else { 40 | bytesString = append(bytesString, data[i]) 41 | } 42 | } 43 | return string(bytesString), len(bytesString) + 1 44 | } 45 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/header/header_functions.go: -------------------------------------------------------------------------------- 1 | package header 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/message/header/flags" 5 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/message/header/flags2" 6 | ) 7 | 8 | // SetFlags sets the flags field in the SMB Header. 9 | // The flags field is an 8-bit field of 1-bit flags describing various features in effect for the message. 10 | // 11 | // Parameters: 12 | // - flags: The byte value to set as flags 13 | func (h *Header) SetFlags(value uint8) { 14 | h.Flags = flags.Flags(value) 15 | } 16 | 17 | // SetFlags2 sets the flags2 field in the SMB Header. 18 | // The flags2 field is a 16-bit field of 1-bit flags that represent various features in effect for the message. 19 | // 20 | // Parameters: 21 | // - flags2: The uint16 value to set as flags2 22 | func (h *Header) SetFlags2(value uint16) { 23 | h.Flags2 = flags2.Flags2(value) 24 | } 25 | 26 | // IsResponse returns true if the header is a response, false otherwise. 27 | // 28 | // Returns: 29 | // - bool: True if the header is a response, false otherwise 30 | func (h *Header) IsResponse() bool { 31 | return h.Flags&flags.FLAGS_REPLY == flags.FLAGS_REPLY 32 | } 33 | 34 | // IsRequest returns true if the header is a request, false otherwise. 35 | // 36 | // Returns: 37 | // - bool: True if the header is a request, false otherwise 38 | func (h *Header) IsRequest() bool { 39 | return !h.IsResponse() 40 | } 41 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/message_test.go: -------------------------------------------------------------------------------- 1 | package message_test 2 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/securityfeatures/SecurityFeatures.go: -------------------------------------------------------------------------------- 1 | package securityfeatures 2 | 3 | // SecurityFeatures is an interface that represents the 8-byte security features field in the SMB header 4 | // This interface allows for different implementations of the security features field based on the context: 5 | // - SecurityFeaturesSecuritySignature: Used when SMB signing has been negotiated 6 | // - SecurityFeaturesConnectionlessTransport: Used for connectionless transports 7 | // - SecurityFeaturesReserved: Used when neither of the above applies 8 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/69a29f73-de0c-45a6-a1aa-8ceeea42217f 9 | type SecurityFeatures interface { 10 | // Marshal serializes the security features into a byte slice 11 | Marshal() ([]byte, error) 12 | 13 | // Unmarshal deserializes a byte slice into the security features 14 | Unmarshal([]byte) (int, error) 15 | } 16 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/securityfeatures/SecurityFeaturesConnectionlessTransport.go: -------------------------------------------------------------------------------- 1 | package securityfeatures 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | ) 7 | 8 | // SecurityFeatures represents the 8-byte security features field in the SMB header 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/69a29f73-de0c-45a6-a1aa-8ceeea42217f 10 | type SecurityFeaturesConnectionlessTransport struct { 11 | // Key (4 bytes): An encryption key used for validating messages over connectionless transports. 12 | Key uint32 13 | // CID (2 bytes): A connection identifier (CID). 14 | CID uint16 15 | // SequenceNumber (2 bytes): A number used to identify the sequence of a message over connectionless transports. 16 | SequenceNumber uint16 17 | } 18 | 19 | func NewSecurityFeaturesConnectionlessTransport() *SecurityFeaturesConnectionlessTransport { 20 | return &SecurityFeaturesConnectionlessTransport{ 21 | Key: 0x00000000, 22 | CID: 0x0000, 23 | SequenceNumber: 0x0000, 24 | } 25 | } 26 | 27 | func (s *SecurityFeaturesConnectionlessTransport) Marshal() ([]byte, error) { 28 | buf := []byte{} 29 | 30 | bufUint32 := make([]byte, 4) 31 | binary.LittleEndian.PutUint32(bufUint32, s.Key) 32 | buf = append(buf, bufUint32...) 33 | 34 | bufUint16 := make([]byte, 2) 35 | binary.LittleEndian.PutUint16(bufUint16, s.CID) 36 | buf = append(buf, bufUint16...) 37 | 38 | bufUint16 = make([]byte, 2) 39 | binary.LittleEndian.PutUint16(bufUint16, s.SequenceNumber) 40 | buf = append(buf, bufUint16...) 41 | 42 | return buf, nil 43 | } 44 | 45 | func (s *SecurityFeaturesConnectionlessTransport) Unmarshal(data []byte) (int, error) { 46 | if len(data) < 8 { 47 | return 0, fmt.Errorf("invalid security features length: %d", len(data)) 48 | } 49 | 50 | s.Key = binary.LittleEndian.Uint32(data[:4]) 51 | 52 | s.CID = binary.LittleEndian.Uint16(data[4:6]) 53 | 54 | s.SequenceNumber = binary.LittleEndian.Uint16(data[6:8]) 55 | 56 | return 8, nil 57 | } 58 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/securityfeatures/SecurityFeaturesReserved.go: -------------------------------------------------------------------------------- 1 | package securityfeatures 2 | 3 | import "fmt" 4 | 5 | // SecurityFeaturesReserved represents the 8-byte security features field in the SMB header 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/69a29f73-de0c-45a6-a1aa-8ceeea42217f 7 | type SecurityFeaturesReserved struct { 8 | // Finally, if neither of the above two cases applies,the SecurityFeatures field is treated as a reserved field, 9 | // which MUST be set to zero by the client and MUST be ignored by the server. 10 | Reserved [8]byte 11 | } 12 | 13 | func NewSecurityFeaturesReserved() *SecurityFeaturesReserved { 14 | return &SecurityFeaturesReserved{ 15 | Reserved: [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 16 | } 17 | } 18 | 19 | func (s *SecurityFeaturesReserved) Marshal() ([]byte, error) { 20 | return s.Reserved[:], nil 21 | } 22 | 23 | func (s *SecurityFeaturesReserved) Unmarshal(data []byte) (int, error) { 24 | if len(data) < 8 { 25 | return 0, fmt.Errorf("invalid security features length: %d", len(data)) 26 | } 27 | 28 | copy(s.Reserved[:], data[:8]) 29 | 30 | return 8, nil 31 | } 32 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/securityfeatures/SecurityFeaturesSecuritySignature.go: -------------------------------------------------------------------------------- 1 | package securityfeatures 2 | 3 | import "fmt" 4 | 5 | // SecurityFeaturesSecuritySignature represents the 8-byte security features field in the SMB header 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/69a29f73-de0c-45a6-a1aa-8ceeea42217f 7 | type SecurityFeaturesSecuritySignature struct { 8 | // SecuritySignature (8 bytes): If SMB signing has been negotiated, this field MUST contain an 9 | // 8-byte cryptographic message signature that can be used to detect whether the message was modified 10 | // while in transit. The use of message signing is mutually exclusive with connectionless transport. 11 | SecuritySignature [8]byte 12 | } 13 | 14 | // NewSecurityFeaturesSecuritySignature creates a new SecurityFeaturesSecuritySignature with a zeroed 8-byte security signature 15 | func NewSecurityFeaturesSecuritySignature() *SecurityFeaturesSecuritySignature { 16 | return &SecurityFeaturesSecuritySignature{ 17 | SecuritySignature: [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 18 | } 19 | } 20 | 21 | // Marshal marshals the 8-byte security signature into a byte slice 22 | func (s *SecurityFeaturesSecuritySignature) Marshal() ([]byte, error) { 23 | return s.SecuritySignature[:], nil 24 | } 25 | 26 | // Unmarshal unmarshals the 8-byte security signature from the given data 27 | func (s *SecurityFeaturesSecuritySignature) Unmarshal(data []byte) (int, error) { 28 | if len(data) < 8 { 29 | return 0, fmt.Errorf("expected 8 bytes, got %d", len(data)) 30 | } 31 | 32 | copy(s.SecuritySignature[:], data[:8]) 33 | 34 | return 8, nil 35 | } 36 | 37 | // GetSecuritySignature returns the 8-byte security signature 38 | func (s *SecurityFeaturesSecuritySignature) GetSecuritySignature() [8]byte { 39 | return s.SecuritySignature 40 | } 41 | 42 | // SetSecuritySignature sets the 8-byte security signature 43 | func (s *SecurityFeaturesSecuritySignature) SetSecuritySignature(signature [8]byte) { 44 | s.SecuritySignature = signature 45 | } 46 | -------------------------------------------------------------------------------- /network/smb/smb_v10/message/securityfeatures/SecurityFeaturesSecuritySignature_test.go: -------------------------------------------------------------------------------- 1 | package securityfeatures_test 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/message/securityfeatures" 8 | ) 9 | 10 | func TestNewSecurityFeaturesSecuritySignature(t *testing.T) { 11 | sf := securityfeatures.NewSecurityFeaturesSecuritySignature() 12 | if !bytes.Equal(sf.SecuritySignature[:], []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) { 13 | t.Errorf("Expected SecuritySignature to be [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], got %v", sf.SecuritySignature) 14 | } 15 | } 16 | 17 | func TestSecurityFeaturesSecuritySignature_Marshal(t *testing.T) { 18 | sf := &securityfeatures.SecurityFeaturesSecuritySignature{ 19 | SecuritySignature: [8]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 20 | } 21 | 22 | data, err := sf.Marshal() 23 | if err != nil { 24 | t.Fatalf("Marshal failed: %v", err) 25 | } 26 | 27 | expected := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08} 28 | if len(data) != len(expected) { 29 | t.Fatalf("Expected data length %d, got %d", len(expected), len(data)) 30 | } 31 | 32 | if !bytes.Equal(data, expected) { 33 | t.Errorf("Expected data %v, got %v", expected, data) 34 | } 35 | } 36 | 37 | func TestSecurityFeaturesSecuritySignature_Unmarshal(t *testing.T) { 38 | testCases := []struct { 39 | name string 40 | data []byte 41 | expected [8]byte 42 | expectError bool 43 | }{ 44 | { 45 | name: "Valid data", 46 | data: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 47 | expected: [8]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 48 | expectError: false, 49 | }, 50 | { 51 | name: "Invalid length", 52 | data: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, 53 | expected: [8]byte{}, 54 | expectError: true, 55 | }, 56 | } 57 | 58 | for _, tc := range testCases { 59 | t.Run(tc.name, func(t *testing.T) { 60 | sf := securityfeatures.NewSecurityFeaturesSecuritySignature() 61 | _, err := sf.Unmarshal(tc.data) 62 | 63 | if tc.expectError && err == nil { 64 | t.Errorf("Expected error but got none") 65 | } else if !tc.expectError && err != nil { 66 | t.Errorf("Unexpected error: %v", err) 67 | } 68 | 69 | if !tc.expectError { 70 | for i, b := range sf.SecuritySignature { 71 | if b != tc.expected[i] { 72 | t.Errorf("Byte %d: expected 0x%02x, got 0x%02x", i, tc.expected[i], b) 73 | } 74 | } 75 | } 76 | }) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /network/smb/smb_v10/spnego/negotiate.go: -------------------------------------------------------------------------------- 1 | package spnego 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/spnego/ntlm" 8 | ) 9 | 10 | // CreateNegotiateToken creates the initial SPNEGO token with NTLM negotiate message 11 | // Parameters: 12 | // - ctx: The authentication context containing domain, username, password, and other settings 13 | // 14 | // Returns: 15 | // - []byte: The SPNEGO token containing the NTLM negotiate message 16 | // - error: An error if token creation fails 17 | func (ctx *AuthContext) CreateNegotiateToken() ([]byte, error) { 18 | switch ctx.Type { 19 | case AuthTypeNTLM: 20 | // Create NTLM NEGOTIATE message 21 | ntlmNegotiate, err := ntlm.CreateNegotiateMessage(ctx.Domain, ctx.Workstation, ctx.UseUnicode) 22 | if err != nil { 23 | return nil, fmt.Errorf("failed to create NTLM NEGOTIATE message: %v", err) 24 | } 25 | 26 | // Wrap in SPNEGO 27 | return CreateNegTokenInit(ntlmNegotiate) 28 | 29 | case AuthTypeKerberos: 30 | return nil, errors.New("kerberos authentication is not yet implemented") 31 | 32 | default: 33 | return nil, fmt.Errorf("unsupported authentication type: %v", ctx.Type) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /network/smb/smb_v10/spnego/spnego_test.go: -------------------------------------------------------------------------------- 1 | package spnego_test 2 | 3 | import ( 4 | "encoding/hex" 5 | "testing" 6 | 7 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/spnego" 8 | "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/spnego/ntlm" 9 | ) 10 | 11 | func TestCreateNegTokenInit(t *testing.T) { 12 | // Create a simple NTLM NEGOTIATE message 13 | ntlmNegotiate, err := ntlm.CreateNegotiateMessage("DOMAIN", "WORKSTATION", true) 14 | if err != nil { 15 | t.Fatalf("Failed to create NTLM NEGOTIATE message: %v", err) 16 | } 17 | 18 | // Wrap it in SPNEGO 19 | token, err := spnego.CreateNegTokenInit(ntlmNegotiate) 20 | if err != nil { 21 | t.Fatalf("Failed to create SPNEGO token: %v", err) 22 | } 23 | 24 | // Verify the token starts with the GSS-API header 25 | if token[0] != spnego.GSS_API_SPNEGO { 26 | t.Errorf("Expected token to start with GSS-API header 0x60, got 0x%02x", token[0]) 27 | } 28 | 29 | // Extract the NTLM token 30 | extractedToken, err := spnego.ExtractNTLMToken(token) 31 | if err != nil { 32 | t.Fatalf("Failed to extract NTLM token: %v", err) 33 | } 34 | 35 | // Verify it's the same as the original 36 | if len(extractedToken) != len(ntlmNegotiate) { 37 | t.Errorf("Extracted token length %d doesn't match original %d", len(extractedToken), len(ntlmNegotiate)) 38 | } 39 | 40 | // Check the NTLM signature 41 | if string(extractedToken[:8]) != "NTLMSSP\x00" { 42 | t.Errorf("Expected NTLM signature, got %s", hex.EncodeToString(extractedToken[:8])) 43 | } 44 | } 45 | 46 | func TestAuthContext(t *testing.T) { 47 | // Create an auth context 48 | ctx := spnego.NewAuthContext( 49 | spnego.AuthTypeNTLM, 50 | "DOMAIN", 51 | "user", 52 | "password", 53 | "WORKSTATION", 54 | true, 55 | ) 56 | 57 | // Create negotiate token 58 | token, err := ctx.CreateNegotiateToken() 59 | if err != nil { 60 | t.Fatalf("Failed to create negotiate token: %v", err) 61 | } 62 | 63 | // Verify the token 64 | if token[0] != spnego.GSS_API_SPNEGO { 65 | t.Errorf("Expected token to start with GSS-API header 0x60, got 0x%02x", token[0]) 66 | } 67 | 68 | // Extract and verify the NTLM token 69 | ntlmToken, err := spnego.ExtractNTLMToken(token) 70 | if err != nil { 71 | t.Fatalf("Failed to extract NTLM token: %v", err) 72 | } 73 | 74 | if string(ntlmToken[:8]) != "NTLMSSP\x00" { 75 | t.Errorf("Expected NTLM signature, got %s", hex.EncodeToString(ntlmToken[:8])) 76 | } 77 | 78 | // Verify message type is NEGOTIATE (1) 79 | messageType := ntlmToken[8] 80 | if messageType != 1 { 81 | t.Errorf("Expected message type 1 (NEGOTIATE), got %d", messageType) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /network/smb/smb_v10/subcommands/nt_transact_subcommands.go: -------------------------------------------------------------------------------- 1 | package subcommands 2 | 3 | // NT Transact Subcommands 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/c2bf4e09-c0e2-42bd-8f7b-6432f1f44d91 5 | 6 | type NtTransactSubcommand uint16 7 | 8 | const ( 9 | NT_TRANSACT_CREATE NtTransactSubcommand = 0x0001 10 | NT_TRANSACT_IOCTL NtTransactSubcommand = 0x0002 11 | NT_TRANSACT_SET_SECURITY_DESC NtTransactSubcommand = 0x0003 12 | NT_TRANSACT_NOTIFY_CHANGE NtTransactSubcommand = 0x0004 13 | NT_TRANSACT_RENAME NtTransactSubcommand = 0x0005 14 | NT_TRANSACT_QUERY_SECURITY_DESC NtTransactSubcommand = 0x0006 15 | NT_TRANSACT_QUERY_QUOTA NtTransactSubcommand = 0x0007 16 | NT_TRANSACT_SET_QUOTA NtTransactSubcommand = 0x0008 17 | ) 18 | 19 | var NtTransactSubcommandsToString = map[NtTransactSubcommand]string{ 20 | NT_TRANSACT_CREATE: "CREATE", 21 | NT_TRANSACT_IOCTL: "IOCTL", 22 | NT_TRANSACT_SET_SECURITY_DESC: "SET_SECURITY_DESC", 23 | NT_TRANSACT_NOTIFY_CHANGE: "NOTIFY_CHANGE", 24 | NT_TRANSACT_RENAME: "RENAME", 25 | NT_TRANSACT_QUERY_SECURITY_DESC: "QUERY_SECURITY_DESC", 26 | NT_TRANSACT_QUERY_QUOTA: "QUERY_QUOTA", 27 | NT_TRANSACT_SET_QUOTA: "SET_QUOTA", 28 | } 29 | 30 | func (t NtTransactSubcommand) String() string { 31 | if str, exists := NtTransactSubcommandsToString[t]; exists { 32 | return str 33 | } 34 | return "UNKNOWN" 35 | } 36 | -------------------------------------------------------------------------------- /network/smb/smb_v10/subcommands/nt_transact_subcommands_test.go: -------------------------------------------------------------------------------- 1 | package subcommands_test 2 | 3 | import ( 4 | "testing" 5 | 6 | smb_v10 "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/subcommands" 7 | ) 8 | 9 | func TestNtTransactSubcommandString(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | subCmd smb_v10.NtTransactSubcommand 13 | expected string 14 | }{ 15 | { 16 | name: "CREATE", 17 | subCmd: smb_v10.NT_TRANSACT_CREATE, 18 | expected: "CREATE", 19 | }, 20 | { 21 | name: "IOCTL", 22 | subCmd: smb_v10.NT_TRANSACT_IOCTL, 23 | expected: "IOCTL", 24 | }, 25 | { 26 | name: "SET_SECURITY_DESC", 27 | subCmd: smb_v10.NT_TRANSACT_SET_SECURITY_DESC, 28 | expected: "SET_SECURITY_DESC", 29 | }, 30 | { 31 | name: "NOTIFY_CHANGE", 32 | subCmd: smb_v10.NT_TRANSACT_NOTIFY_CHANGE, 33 | expected: "NOTIFY_CHANGE", 34 | }, 35 | { 36 | name: "RENAME", 37 | subCmd: smb_v10.NT_TRANSACT_RENAME, 38 | expected: "RENAME", 39 | }, 40 | { 41 | name: "QUERY_SECURITY_DESC", 42 | subCmd: smb_v10.NT_TRANSACT_QUERY_SECURITY_DESC, 43 | expected: "QUERY_SECURITY_DESC", 44 | }, 45 | { 46 | name: "QUERY_QUOTA", 47 | subCmd: smb_v10.NT_TRANSACT_QUERY_QUOTA, 48 | expected: "QUERY_QUOTA", 49 | }, 50 | { 51 | name: "SET_QUOTA", 52 | subCmd: smb_v10.NT_TRANSACT_SET_QUOTA, 53 | expected: "SET_QUOTA", 54 | }, 55 | { 56 | name: "Unknown subcommand", 57 | subCmd: smb_v10.NtTransactSubcommand(0xFFFF), 58 | expected: "UNKNOWN", 59 | }, 60 | } 61 | 62 | for _, tt := range tests { 63 | t.Run(tt.name, func(t *testing.T) { 64 | result := tt.subCmd.String() 65 | if result != tt.expected { 66 | t.Errorf("String() = %v, want %v", result, tt.expected) 67 | } 68 | }) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /network/smb/smb_v10/subcommands/transaction_subcommands.go: -------------------------------------------------------------------------------- 1 | package subcommands 2 | 3 | // Transaction Subcommands 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/227cb147-3c09-4c4b-b145-6c94b04c8231 5 | 6 | type TransactionSubcommand uint16 7 | 8 | const ( 9 | TRANS_SET_NMPIPE_STATE TransactionSubcommand = 0x0001 10 | TRANS_RAW_READ_NMPIPE TransactionSubcommand = 0x0011 11 | TRANS_QUERY_NMPIPE_STATE TransactionSubcommand = 0x0021 12 | TRANS_QUERY_NMPIPE_INFO TransactionSubcommand = 0x0022 13 | TRANS_PEEK_NMPIPE TransactionSubcommand = 0x0023 14 | TRANS_TRANSACT_NMPIPE TransactionSubcommand = 0x0026 15 | TRANS_RAW_WRITE_NMPIPE TransactionSubcommand = 0x0031 16 | TRANS_READ_NMPIPE TransactionSubcommand = 0x0036 17 | TRANS_WRITE_NMPIPE TransactionSubcommand = 0x0037 18 | TRANS_WAIT_NMPIPE TransactionSubcommand = 0x0053 19 | TRANS_CALL_NMPIPE TransactionSubcommand = 0x0054 20 | TRANS_MAILSLOT_WRITE TransactionSubcommand = 0x0001 21 | ) 22 | 23 | var TransactionSubcommandsToString = map[TransactionSubcommand]string{ 24 | TRANS_SET_NMPIPE_STATE: "SET_NMPIPE_STATE", 25 | TRANS_RAW_READ_NMPIPE: "RAW_READ_NMPIPE", 26 | TRANS_QUERY_NMPIPE_STATE: "QUERY_NMPIPE_STATE", 27 | TRANS_QUERY_NMPIPE_INFO: "QUERY_NMPIPE_INFO", 28 | TRANS_PEEK_NMPIPE: "PEEK_NMPIPE", 29 | TRANS_TRANSACT_NMPIPE: "TRANSACT_NMPIPE", 30 | TRANS_RAW_WRITE_NMPIPE: "RAW_WRITE_NMPIPE", 31 | TRANS_READ_NMPIPE: "READ_NMPIPE", 32 | TRANS_WRITE_NMPIPE: "WRITE_NMPIPE", 33 | TRANS_WAIT_NMPIPE: "WAIT_NMPIPE", 34 | TRANS_CALL_NMPIPE: "CALL_NMPIPE", 35 | // TRANS_MAILSLOT_WRITE: "MAILSLOT_WRITE", 36 | } 37 | 38 | func (t TransactionSubcommand) String() string { 39 | if str, exists := TransactionSubcommandsToString[t]; exists { 40 | return str 41 | } 42 | return "UNKNOWN" 43 | } 44 | -------------------------------------------------------------------------------- /network/smb/smb_v10/subcommands/transaction_subcommands_test.go: -------------------------------------------------------------------------------- 1 | package subcommands_test 2 | 3 | import ( 4 | "testing" 5 | 6 | smb_v10 "github.com/TheManticoreProject/Manticore/network/smb/smb_v10/subcommands" 7 | ) 8 | 9 | func TestTransactionSubcommandString(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | subCmd smb_v10.TransactionSubcommand 13 | expected string 14 | }{ 15 | { 16 | name: "SET_NMPIPE_STATE", 17 | subCmd: smb_v10.TRANS_SET_NMPIPE_STATE, 18 | expected: "SET_NMPIPE_STATE", 19 | }, 20 | { 21 | name: "RAW_READ_NMPIPE", 22 | subCmd: smb_v10.TRANS_RAW_READ_NMPIPE, 23 | expected: "RAW_READ_NMPIPE", 24 | }, 25 | { 26 | name: "QUERY_NMPIPE_STATE", 27 | subCmd: smb_v10.TRANS_QUERY_NMPIPE_STATE, 28 | expected: "QUERY_NMPIPE_STATE", 29 | }, 30 | { 31 | name: "QUERY_NMPIPE_INFO", 32 | subCmd: smb_v10.TRANS_QUERY_NMPIPE_INFO, 33 | expected: "QUERY_NMPIPE_INFO", 34 | }, 35 | { 36 | name: "PEEK_NMPIPE", 37 | subCmd: smb_v10.TRANS_PEEK_NMPIPE, 38 | expected: "PEEK_NMPIPE", 39 | }, 40 | { 41 | name: "TRANSACT_NMPIPE", 42 | subCmd: smb_v10.TRANS_TRANSACT_NMPIPE, 43 | expected: "TRANSACT_NMPIPE", 44 | }, 45 | { 46 | name: "RAW_WRITE_NMPIPE", 47 | subCmd: smb_v10.TRANS_RAW_WRITE_NMPIPE, 48 | expected: "RAW_WRITE_NMPIPE", 49 | }, 50 | { 51 | name: "READ_NMPIPE", 52 | subCmd: smb_v10.TRANS_READ_NMPIPE, 53 | expected: "READ_NMPIPE", 54 | }, 55 | { 56 | name: "WRITE_NMPIPE", 57 | subCmd: smb_v10.TRANS_WRITE_NMPIPE, 58 | expected: "WRITE_NMPIPE", 59 | }, 60 | { 61 | name: "WAIT_NMPIPE", 62 | subCmd: smb_v10.TRANS_WAIT_NMPIPE, 63 | expected: "WAIT_NMPIPE", 64 | }, 65 | { 66 | name: "CALL_NMPIPE", 67 | subCmd: smb_v10.TRANS_CALL_NMPIPE, 68 | expected: "CALL_NMPIPE", 69 | }, 70 | { 71 | name: "Unknown subcommand", 72 | subCmd: smb_v10.TransactionSubcommand(0xFFFF), 73 | expected: "UNKNOWN", 74 | }, 75 | } 76 | 77 | for _, tt := range tests { 78 | t.Run(tt.name, func(t *testing.T) { 79 | result := tt.subCmd.String() 80 | if result != tt.expected { 81 | t.Errorf("String() = %v, want %v", result, tt.expected) 82 | } 83 | }) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /network/smb/smb_v10/transport/transport.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "net" 5 | "strings" 6 | 7 | "github.com/TheManticoreProject/Manticore/network/netbios/nbt" 8 | ) 9 | 10 | type Transport interface { 11 | Connect(ipaddr net.IP, port int) error 12 | 13 | Close() error 14 | 15 | Send(data []byte) (int, error) 16 | 17 | Receive() ([]byte, error) 18 | 19 | IsConnected() bool 20 | } 21 | 22 | func NewTransport(transportType string) Transport { 23 | switch strings.ToLower(transportType) { 24 | case "nbt": 25 | return nbt.NewNBTTransport() 26 | } 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /network/smb/smb_v10/types/LOCKING_ANDX_RANGE32.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | ) 7 | 8 | // LOCKING_ANDX_RANGE32 9 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/b5c6eae7-976b-4444-b52e-c76c68c861ad 10 | type LOCKING_ANDX_RANGE32 struct { 11 | // PID (2 bytes): The PID of the process requesting the locking change. 12 | PID USHORT 13 | 14 | // ByteOffset (4 bytes): The 32-bit unsigned integer value that is the offset into the file at which 15 | // the locking change MUST begin. 16 | ByteOffset ULONG 17 | 18 | // LengthInBytes (4 bytes): The 32-bit unsigned integer value that is the number of bytes, beginning 19 | // at OffsetInBytes, that MUST be locked or unlocked. 20 | LengthInBytes ULONG 21 | } 22 | 23 | // Marshal marshals the LOCKING_ANDX_RANGE32 structure into a byte array 24 | // 25 | // Returns: 26 | // - A byte array representing the LOCKING_ANDX_RANGE32 structure 27 | // - An error if the marshaling fails 28 | func (l *LOCKING_ANDX_RANGE32) Marshal() ([]byte, error) { 29 | result := make([]byte, 10) // 2 + 4 + 4 bytes 30 | 31 | // Marshal PID (2 bytes) 32 | binary.LittleEndian.PutUint16(result[0:2], uint16(l.PID)) 33 | 34 | // Marshal ByteOffset (4 bytes) 35 | binary.LittleEndian.PutUint32(result[2:6], uint32(l.ByteOffset)) 36 | 37 | // Marshal LengthInBytes (4 bytes) 38 | binary.LittleEndian.PutUint32(result[6:10], uint32(l.LengthInBytes)) 39 | 40 | return result, nil 41 | } 42 | 43 | // Unmarshal unmarshals a byte array into the LOCKING_ANDX_RANGE32 structure 44 | // 45 | // Parameters: 46 | // - data: The byte array to unmarshal 47 | // 48 | // Returns: 49 | // - The number of bytes unmarshalled 50 | // - An error if the unmarshaling fails 51 | func (l *LOCKING_ANDX_RANGE32) Unmarshal(data []byte) (int, error) { 52 | if len(data) < 10 { 53 | return 0, fmt.Errorf("data too short for LOCKING_ANDX_RANGE32") 54 | } 55 | 56 | // Unmarshal PID (2 bytes) 57 | l.PID = USHORT(binary.LittleEndian.Uint16(data[0:2])) 58 | 59 | // Unmarshal ByteOffset (4 bytes) 60 | l.ByteOffset = ULONG(binary.LittleEndian.Uint32(data[2:6])) 61 | 62 | // Unmarshal LengthInBytes (4 bytes) 63 | l.LengthInBytes = ULONG(binary.LittleEndian.Uint32(data[6:10])) 64 | 65 | return 10, nil 66 | } 67 | -------------------------------------------------------------------------------- /network/smb/smb_v10/types/OEM_STRING.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // OEM_STRING 4 | // Source: https://learn.microsoft.com/en-us/previous-versions/windows/hardware/kernel/ff558741(v=vs.85) 5 | type OEM_STRING struct { 6 | SMB_STRING 7 | } 8 | 9 | // NewOEM_STRING creates a new OEM_STRING 10 | // 11 | // Returns: 12 | // - A pointer to the new OEM_STRING 13 | func NewOEM_STRING() *OEM_STRING { 14 | return &OEM_STRING{ 15 | SMB_STRING: SMB_STRING{ 16 | BufferFormat: SMB_STRING_BUFFER_FORMAT_NULL_TERMINATED_ASCII_STRING, 17 | Length: 0, 18 | Buffer: []UCHAR{}, 19 | }, 20 | } 21 | } 22 | 23 | // NewOEM_STRINGFromString creates a new OEM_STRING from a string 24 | // 25 | // Parameters: 26 | // - str: The string to create the OEM_STRING from 27 | // 28 | // Returns: 29 | // - The new OEM_STRING 30 | func NewOEM_STRINGFromString(str string) *OEM_STRING { 31 | return &OEM_STRING{ 32 | SMB_STRING: SMB_STRING{ 33 | BufferFormat: SMB_STRING_BUFFER_FORMAT_NULL_TERMINATED_ASCII_STRING, 34 | Length: uint16(len(str)), 35 | Buffer: []UCHAR(str), 36 | }, 37 | } 38 | } 39 | 40 | // Marshal marshals the SMB_RESUME_KEY structure 41 | // 42 | // Returns: 43 | // - A byte array representing the SMB_RESUME_KEY structure 44 | // - An error if the marshaling fails 45 | func (o *OEM_STRING) Marshal() ([]byte, error) { 46 | // This field MUST be 0x05, which indicates that a variable block is to follow. 47 | o.SetBufferFormat(SMB_STRING_BUFFER_FORMAT_NULL_TERMINATED_ASCII_STRING) 48 | return o.SMB_STRING.Marshal() 49 | } 50 | 51 | // Unmarshal unmarshals the SMB_RESUME_KEY structure 52 | // 53 | // Parameters: 54 | // - data: The byte array to unmarshal 55 | // 56 | // Returns: 57 | // - The number of bytes unmarshalled 58 | // - An error if the unmarshaling fails 59 | func (o *OEM_STRING) Unmarshal(data []byte) (int, error) { 60 | bytesRead, err := o.SMB_STRING.Unmarshal(data) 61 | if err != nil { 62 | return 0, err 63 | } 64 | 65 | return bytesRead, nil 66 | } 67 | 68 | // GetString returns the string of the OEM_STRING 69 | // 70 | // Returns: 71 | // - The string of the OEM_STRING 72 | func (o *OEM_STRING) GetString() string { 73 | return string(o.Buffer) 74 | } 75 | 76 | // SetString sets the string of the OEM_STRING 77 | // 78 | // Parameters: 79 | // - str: The string to set 80 | func (o *OEM_STRING) SetString(str string) { 81 | o.Buffer = []UCHAR(str) 82 | o.Length = uint16(len(str)) 83 | } 84 | -------------------------------------------------------------------------------- /network/smb/smb_v10/types/SMB_FEA_LIST.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // SMB_FEA_LIST 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/1ca1684e-6552-432c-bdd0-f559814bbaef 7 | type SMB_FEA_LIST struct { 8 | SizeOfListInBytes data_types.ULONG 9 | FEAList []data_types.UCHAR 10 | } 11 | -------------------------------------------------------------------------------- /network/smb/smb_v10/types/SMB_FILE_ATTRIBUTES.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "encoding/binary" 4 | 5 | // SMB_FILE_ATTRIBUTES is a structure that contains the attributes of a file 6 | // Sourc: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/2198f480-e047-4df0-ba64-f28eadef00b9 7 | type SMB_FILE_ATTRIBUTES struct { 8 | Attributes uint16 9 | } 10 | 11 | // GetAttributes returns the attributes of the SMB_FILE_ATTRIBUTES structure 12 | // 13 | // Returns: 14 | // - The attributes of the SMB_FILE_ATTRIBUTES structure 15 | func (s *SMB_FILE_ATTRIBUTES) GetAttributes() uint16 { 16 | return s.Attributes 17 | } 18 | 19 | // SetAttributes sets the attributes of the SMB_FILE_ATTRIBUTES structure 20 | // 21 | // Parameters: 22 | // - attributes: The attributes to set 23 | func (s *SMB_FILE_ATTRIBUTES) SetAttributes(attributes uint16) { 24 | s.Attributes = attributes 25 | } 26 | 27 | // Marshal marshals the SMB_FILE_ATTRIBUTES structure into a byte array 28 | // 29 | // Returns: 30 | // - A byte array representing the SMB_FILE_ATTRIBUTES structure 31 | // - An error if the marshaling fails 32 | func (s *SMB_FILE_ATTRIBUTES) Marshal() ([]byte, error) { 33 | buf := make([]byte, 2) 34 | binary.BigEndian.PutUint16(buf, s.Attributes) 35 | return buf, nil 36 | } 37 | 38 | // Unmarshal unmarshals a byte array into the SMB_FILE_ATTRIBUTES structure 39 | // 40 | // Parameters: 41 | // - data: The byte array to unmarshal 42 | // 43 | // Returns: 44 | // - The number of bytes unmarshalled 45 | func (s *SMB_FILE_ATTRIBUTES) Unmarshal(data []byte) (int, error) { 46 | s.Attributes = binary.BigEndian.Uint16(data) 47 | return 2, nil 48 | } 49 | -------------------------------------------------------------------------------- /network/smb/smb_v10/types/SMB_TIME.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_structures" 7 | ) 8 | 9 | type SMB_TIME = data_structures.FILETIME 10 | 11 | // NewSMB_TIMEFromTime creates a new SMB_TIME from a time.Time 12 | // 13 | // Parameters: 14 | // - t: The time.Time to create the SMB_TIME from 15 | // 16 | // Returns: 17 | // - The new SMB_TIME 18 | func NewSMB_TIMEFromTime(t time.Time) *SMB_TIME { 19 | return data_structures.NewFILETIMEFromTime(t) 20 | } 21 | -------------------------------------------------------------------------------- /network/smb/smb_v10/types/ms_dtyp_passthrough.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_structures" 5 | "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 6 | ) 7 | 8 | type UCHAR = data_types.UCHAR 9 | type USHORT = data_types.USHORT 10 | type ULONG = data_types.ULONG 11 | 12 | type CHAR = data_types.CHAR 13 | type SHORT = data_types.SHORT 14 | type LONG = data_types.LONG 15 | 16 | type DWORD = data_types.DWORD 17 | 18 | type LARGE_INTEGER = data_structures.LARGE_INTEGER 19 | 20 | type FILETIME = data_structures.FILETIME 21 | -------------------------------------------------------------------------------- /network/smb/smb_v10/types/ms_dtyp_passthrough_functions.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | func StringToUCHAR(str string) []UCHAR { 4 | return []UCHAR(str) 5 | } 6 | -------------------------------------------------------------------------------- /network/smb/smb_v20/docs/[MS-SMB2].pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/network/smb/smb_v20/docs/[MS-SMB2].pdf -------------------------------------------------------------------------------- /network/smb/smb_v21/docs/[MS-SMB2].pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/network/smb/smb_v21/docs/[MS-SMB2].pdf -------------------------------------------------------------------------------- /network/smb/smb_v30/docs/[MS-SMB2].pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/network/smb/smb_v30/docs/[MS-SMB2].pdf -------------------------------------------------------------------------------- /network/smb/smb_v302/docs/[MS-SMB2].pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/network/smb/smb_v302/docs/[MS-SMB2].pdf -------------------------------------------------------------------------------- /network/smb/smb_v311/docs/[MS-SMB2].pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheManticoreProject/Manticore/c6dfaad16eb076c19d159de53c537228d916dc2f/network/smb/smb_v311/docs/[MS-SMB2].pdf -------------------------------------------------------------------------------- /network/smb/versions.go: -------------------------------------------------------------------------------- 1 | package smb 2 | 3 | import "fmt" 4 | 5 | type SMBProtocolVersion uint16 6 | 7 | const ( 8 | SMB_VERSION_1_0 SMBProtocolVersion = 0x0100 9 | SMB_VERSION_2_0 SMBProtocolVersion = 0x0200 10 | SMB_VERSION_2_1 SMBProtocolVersion = 0x0210 11 | SMB_VERSION_3_0 SMBProtocolVersion = 0x0300 12 | SMB_VERSION_3_1_1 SMBProtocolVersion = 0x0311 13 | ) 14 | 15 | func (v SMBProtocolVersion) String() string { 16 | return fmt.Sprintf("SMB v%d.%d.%d", v>>8&0xF, v>>4&0xF, v&0xF) 17 | } 18 | 19 | func (v SMBProtocolVersion) IsSupported() bool { 20 | return v == SMB_VERSION_1_0 || v == SMB_VERSION_2_0 || v == SMB_VERSION_2_1 || v == SMB_VERSION_3_0 || v == SMB_VERSION_3_1_1 21 | } 22 | 23 | func (v SMBProtocolVersion) IsSMB2() bool { 24 | return v == SMB_VERSION_2_0 || v == SMB_VERSION_2_1 || v == SMB_VERSION_3_0 || v == SMB_VERSION_3_1_1 25 | } 26 | -------------------------------------------------------------------------------- /network/smb/versions_test.go: -------------------------------------------------------------------------------- 1 | package smb 2 | 3 | import "testing" 4 | 5 | func TestSMBProtocolVersion_String(t *testing.T) { 6 | tests := []struct { 7 | name string 8 | v SMBProtocolVersion 9 | want string 10 | }{ 11 | {name: "SMB 1.0", v: SMB_VERSION_1_0, want: "SMB v1.0.0"}, 12 | {name: "SMB 2.0", v: SMB_VERSION_2_0, want: "SMB v2.0.0"}, 13 | {name: "SMB 2.1", v: SMB_VERSION_2_1, want: "SMB v2.1.0"}, 14 | {name: "SMB 3.0", v: SMB_VERSION_3_0, want: "SMB v3.0.0"}, 15 | {name: "SMB 3.1.1", v: SMB_VERSION_3_1_1, want: "SMB v3.1.1"}, 16 | } 17 | 18 | for _, tt := range tests { 19 | t.Run(tt.name, func(t *testing.T) { 20 | if got := tt.v.String(); got != tt.want { 21 | t.Errorf("SMBProtocolVersion.String() = %v, want %v", got, tt.want) 22 | } 23 | }) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /utils/encoding/utf16/utf16le.go: -------------------------------------------------------------------------------- 1 | package utf16 2 | 3 | import ( 4 | "unicode/utf16" 5 | ) 6 | 7 | // EncodeUTF16LE encodes a string to UTF-16 little endian bytes 8 | // 9 | // This function takes a string and encodes it to UTF-16 little endian bytes. 10 | // It uses the utf16.Encode function to convert the string to a slice of uint16 values. 11 | // Then, it creates a byte slice with twice the length of the utf16le slice, 12 | // and fills it with the UTF-16 little endian encoded values. 13 | // 14 | // Returns: 15 | // - A byte slice representing the UTF-16 little endian encoded string. 16 | func EncodeUTF16LE(s string) []byte { 17 | utf16le := utf16.Encode([]rune(s)) 18 | bytes := make([]byte, len(utf16le)*2) 19 | for i, r := range utf16le { 20 | bytes[i*2] = byte(r) 21 | bytes[i*2+1] = byte(r >> 8) 22 | } 23 | return bytes 24 | } 25 | 26 | // DecodeUTF16LE decodes UTF-16 little endian bytes to a string 27 | // 28 | // This function takes a byte slice and decodes it to a string. 29 | // It creates a slice of uint16 values with half the length of the byte slice, 30 | // and fills it with the UTF-16 little endian decoded values. 31 | // Then, it uses the utf16.Decode function to convert the uint16 slice to a string. 32 | // 33 | // Returns: 34 | // - A string representing the UTF-16 little endian decoded byte slice. 35 | func DecodeUTF16LE(b []byte) string { 36 | utf16le := make([]uint16, len(b)/2) 37 | for i := 0; i < len(b); i += 2 { 38 | utf16le[i/2] = uint16(b[i]) | (uint16(b[i+1]) << 8) 39 | } 40 | return string(utf16.Decode(utf16le)) 41 | } 42 | -------------------------------------------------------------------------------- /utils/encoding/utf16/utf16le_test.go: -------------------------------------------------------------------------------- 1 | package utf16 2 | 3 | import ( 4 | "bytes" 5 | "encoding/hex" 6 | "testing" 7 | ) 8 | 9 | func TestEncodeUTF16LE(t *testing.T) { 10 | tests := []struct { 11 | input string 12 | expected string 13 | }{ 14 | {"hello", "680065006c006c006f00"}, 15 | } 16 | 17 | for _, test := range tests { 18 | result := EncodeUTF16LE(test.input) 19 | rawExpected, err := hex.DecodeString(test.expected) 20 | if err != nil { 21 | t.Errorf("Could not decode hex string: %q", test.expected) 22 | } 23 | if !bytes.Equal(result, rawExpected) { 24 | t.Errorf("EncodeUTF16LE(%q) = %q; expected %q", test.input, result, rawExpected) 25 | } 26 | } 27 | } 28 | 29 | func TestDecodeUTF16LE(t *testing.T) { 30 | tests := []struct { 31 | input string 32 | expected string 33 | }{ 34 | {"680065006c006c006f00", "hello"}, 35 | } 36 | 37 | for _, test := range tests { 38 | rawUTF16LE, err := hex.DecodeString(test.input) 39 | if err != nil { 40 | t.Errorf("Could not decode hex string: %q", test.input) 41 | } 42 | result := DecodeUTF16LE(rawUTF16LE) 43 | if result != test.expected { 44 | t.Errorf("DecodeUTF16LE(%q) = %q; expected %q", test.input, result, rawUTF16LE) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /utils/strings_test.go: -------------------------------------------------------------------------------- 1 | package utils_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/TheManticoreProject/Manticore/utils" 7 | ) 8 | 9 | func TestPadStringLeft(t *testing.T) { 10 | tests := []struct { 11 | input string 12 | padChar string 13 | length int 14 | expected string 15 | }{ 16 | {"hello", "*", 8, "***hello"}, 17 | {"world", "-", 10, "-----world"}, 18 | {"test", " ", 6, " test"}, 19 | {"", "#", 5, "#####"}, 20 | {"short", "0", 5, "short"}, 21 | } 22 | 23 | for _, tt := range tests { 24 | t.Run(tt.input, func(t *testing.T) { 25 | result := utils.PadStringLeft(tt.input, tt.padChar, tt.length) 26 | if result != tt.expected { 27 | t.Errorf("PadStringLeft(%q, %q, %d) = %q; want %q", tt.input, tt.padChar, tt.length, result, tt.expected) 28 | } 29 | }) 30 | } 31 | } 32 | 33 | func TestSizeInBytes(t *testing.T) { 34 | tests := []struct { 35 | size uint64 36 | expected string 37 | }{ 38 | {512, "512 bytes"}, 39 | {1024, "1.00 KiB"}, 40 | {1048576, "1.00 MiB"}, 41 | {1073741824, "1.00 GiB"}, 42 | {1099511627776, "1.00 TiB"}, 43 | {1125899906842624, "1.00 PiB"}, 44 | } 45 | 46 | for _, tt := range tests { 47 | t.Run(tt.expected, func(t *testing.T) { 48 | result := utils.SizeInBytes(tt.size) 49 | if result != tt.expected { 50 | t.Errorf("SizeInBytes(%d) = %q; want %q", tt.size, result, tt.expected) 51 | } 52 | }) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /windows/keycredential/DNWithBinary.go: -------------------------------------------------------------------------------- 1 | package keycredentiallink 2 | 3 | import ( 4 | "bytes" 5 | "encoding/hex" 6 | "errors" 7 | "fmt" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | type DNWithBinary struct { 13 | DistinguishedName string 14 | BinaryData []byte 15 | 16 | // Internal 17 | RawBytes []byte 18 | RawBytesSize uint32 19 | } 20 | 21 | const ( 22 | StringFormatPrefix = "B:" 23 | StringFormatSeparator = ":" 24 | ) 25 | 26 | func (d *DNWithBinary) Parse(rawBytes []byte) error { 27 | d.RawBytes = rawBytes 28 | d.RawBytesSize = uint32(len(rawBytes)) 29 | 30 | parts := bytes.Split(rawBytes, []byte(StringFormatSeparator)) 31 | if len(parts) != 4 { 32 | return errors.New("rawBytes should have exactly four parts separated by colons (:)") 33 | } 34 | 35 | size, err := strconv.Atoi(string(parts[1])) 36 | if err != nil { 37 | return errors.New("invalid size in rawBytes") 38 | } 39 | 40 | binaryPart, err := hex.DecodeString(string(parts[2])) 41 | if err != nil { 42 | return errors.New("invalid hexadecimal string in rawBytes") 43 | } 44 | 45 | if (len(binaryPart) * 2) != size { 46 | return fmt.Errorf("invalid BinaryData length. The length specified in the header (%d) does not match the actual data length (%d)", size, len(binaryPart)) 47 | } 48 | 49 | d.DistinguishedName = string(parts[3]) 50 | d.BinaryData = binaryPart 51 | 52 | return nil 53 | } 54 | 55 | func (d *DNWithBinary) ToString() string { 56 | hexData := hex.EncodeToString(d.BinaryData) 57 | return fmt.Sprintf(StringFormatPrefix+"%d"+StringFormatSeparator+"%s"+StringFormatSeparator+"%s", len(d.BinaryData)*2, hexData, d.DistinguishedName) 58 | } 59 | 60 | func (d *DNWithBinary) String() string { 61 | return d.ToString() 62 | } 63 | 64 | // Describe prints a detailed description of the DNWithBinary structure. 65 | // 66 | // Parameters: 67 | // - indent: An integer value specifying the indentation level for the output. 68 | func (d *DNWithBinary) Describe(indent int) { 69 | indentPrompt := strings.Repeat(" │ ", indent) 70 | fmt.Printf("%s\n", indentPrompt) 71 | fmt.Printf("%s │ \x1b[93mDistinguishedName\x1b[0m: %s\n", indentPrompt, d.DistinguishedName) 72 | fmt.Printf("%s │ \x1b[93mBinaryData\x1b[0m: %s\n", indentPrompt, hex.EncodeToString(d.BinaryData)) 73 | fmt.Printf("%s └───\n", indentPrompt) 74 | } 75 | -------------------------------------------------------------------------------- /windows/keycredential/DNWithBinary_test.go: -------------------------------------------------------------------------------- 1 | package keycredentiallink 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | ) 7 | 8 | func TestParse(t *testing.T) { 9 | tests := []struct { 10 | name string 11 | rawBytes []byte 12 | expectError bool 13 | expectedDN string 14 | expectedBin []byte 15 | }{ 16 | { 17 | name: "Valid input", 18 | rawBytes: []byte("B:10:48656c6c6f:CN=John Doe,OU=Users,DC=example,DC=com"), 19 | expectError: false, 20 | expectedDN: "CN=John Doe,OU=Users,DC=example,DC=com", 21 | expectedBin: []byte("Hello"), 22 | }, 23 | { 24 | name: "Invalid size", 25 | rawBytes: []byte("B:5:48656c6c6f:CN=John Doe,OU=Users,DC=example,DC=com"), 26 | expectError: true, 27 | }, 28 | { 29 | name: "Invalid hex string", 30 | rawBytes: []byte("B:10:ZZZZ:CN=John Doe,OU=Users,DC=example,DC=com"), 31 | expectError: true, 32 | }, 33 | { 34 | name: "Invalid parts count", 35 | rawBytes: []byte("B:10:48656c6c6f"), 36 | expectError: true, 37 | }, 38 | } 39 | 40 | for _, tt := range tests { 41 | t.Run(tt.name, func(t *testing.T) { 42 | d := &DNWithBinary{} 43 | err := d.Parse(tt.rawBytes) 44 | if (err != nil) != tt.expectError { 45 | t.Errorf("Parse() error = %v, expectError %v", err, tt.expectError) 46 | return 47 | } 48 | if !tt.expectError { 49 | if d.DistinguishedName != tt.expectedDN { 50 | t.Errorf("Expected DistinguishedName = %v, got %v", tt.expectedDN, d.DistinguishedName) 51 | } 52 | if !bytes.Equal(d.BinaryData, tt.expectedBin) { 53 | t.Errorf("Expected BinaryData = %v, got %v", tt.expectedBin, d.BinaryData) 54 | } 55 | } 56 | }) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /windows/keycredential/crypto/PrivateKeyEncryptionType.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | type PrivateKeyEncryptionType int 4 | 5 | const ( 6 | NONE PrivateKeyEncryptionType = iota 7 | PasswordRC4 8 | PasswordRC2CBC 9 | ) 10 | 11 | func (pket PrivateKeyEncryptionType) String() string { 12 | return [...]string{"NONE", "PasswordRC4", "PasswordRC2CBC"}[pket] 13 | } 14 | -------------------------------------------------------------------------------- /windows/keycredential/crypto/RSAKeyMaterial_test.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | ) 7 | 8 | func TestRSAKeyMaterial_ToBytes_FromBytes(t *testing.T) { 9 | tests := []struct { 10 | name string 11 | input RSAKeyMaterial 12 | wantErr bool 13 | }{ 14 | { 15 | name: "Valid RSA key material", 16 | input: RSAKeyMaterial{ 17 | KeySize: 8, 18 | Exponent: 0b10000000000000001, 19 | Modulus: []byte{0x11, 0x11, 0x11, 0x11}, 20 | Prime1: []byte{0x22, 0x22, 0x22, 0x22}, 21 | Prime2: []byte{0x33, 0x33, 0x33, 0x33}, 22 | }, 23 | wantErr: false, 24 | }, 25 | } 26 | 27 | for _, tt := range tests { 28 | t.Run(tt.name, func(t *testing.T) { 29 | rk := &RSAKeyMaterial{} 30 | err := rk.FromBytes(tt.input.ToBytes()) 31 | if (err != nil) != tt.wantErr { 32 | t.Errorf("FromBytes() error = %v, wantErr %v", err, tt.wantErr) 33 | } 34 | 35 | if tt.input.KeySize != rk.KeySize { 36 | t.Errorf("KeySize = %v, want %v", rk.KeySize, tt.input.KeySize) 37 | } 38 | if tt.input.Exponent != rk.Exponent { 39 | t.Errorf("Exponent = %v, want %v", rk.Exponent, tt.input.Exponent) 40 | } 41 | if !bytes.Equal(tt.input.Modulus, rk.Modulus) { 42 | t.Errorf("Modulus = %v, want %v", rk.Modulus, tt.input.Modulus) 43 | } 44 | if !bytes.Equal(tt.input.Prime1, rk.Prime1) { 45 | t.Errorf("Prime1 = %v, want %v", rk.Prime1, tt.input.Prime1) 46 | } 47 | if !bytes.Equal(tt.input.Prime2, rk.Prime2) { 48 | t.Errorf("Prime2 = %v, want %v", rk.Prime2, tt.input.Prime2) 49 | } 50 | }) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /windows/keycredential/crypto/SecretEncryptionType.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import "encoding/binary" 4 | 5 | type SecretEncryptionType struct { 6 | Value int 7 | 8 | // Internal 9 | RawBytes []byte 10 | RawBytesSize uint32 11 | } 12 | 13 | const ( 14 | // TODO: Add support for SAM encryption types 15 | 16 | // Database secret encryption using PEK without salt. 17 | // Used until Windows Server 2000 Beta 2 18 | SecretEncryptionType_DatabaseRC4 int = 0x10 19 | 20 | // Database secret encryption using PEK with salt. 21 | // Used in Windows Server 2000 - Windows Server 2012 R2. 22 | SecretEncryptionType_DatabaseRC4WithSalt int = 0x11 23 | 24 | // Replicated secret encryption using Session Key with salt. 25 | SecretEncryptionType_ReplicationRC4WithSalt int = 0x12 26 | 27 | // Database secret encryption using PEK and AES. 28 | // Used since Windows Server 2016 TP4. 29 | SecretEncryptionType_DatabaseAES int = 0x13 30 | ) 31 | 32 | // FromBytes parses the SecretEncryptionType from a byte array. 33 | // 34 | // Parameters: 35 | // - value: A byte array containing the SecretEncryptionType to be parsed. 36 | func (set *SecretEncryptionType) FromBytes(value []byte) { 37 | set.RawBytes = value[:4] 38 | set.RawBytesSize = 4 39 | 40 | set.Value = int(binary.LittleEndian.Uint32(value[:4])) 41 | } 42 | 43 | // ToBytes returns the raw bytes of the SecretEncryptionType. 44 | // 45 | // Returns: 46 | // - A byte array containing the raw bytes of the SecretEncryptionType. 47 | func (set *SecretEncryptionType) ToBytes() []byte { 48 | blob := make([]byte, 4) 49 | binary.LittleEndian.PutUint32(blob, uint32(set.Value)) 50 | return blob 51 | } 52 | 53 | // String returns the string representation of the SecretEncryptionType. 54 | func (set *SecretEncryptionType) String() string { 55 | switch set.Value { 56 | case SecretEncryptionType_DatabaseRC4: 57 | return "DatabaseRC4" 58 | case SecretEncryptionType_DatabaseRC4WithSalt: 59 | return "DatabaseRC4WithSalt" 60 | case SecretEncryptionType_ReplicationRC4WithSalt: 61 | return "ReplicationRC4WithSalt" 62 | case SecretEncryptionType_DatabaseAES: 63 | return "DatabaseAES" 64 | default: 65 | return "Unknown" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /windows/keycredential/crypto/SecretEncryptionType_test.go: -------------------------------------------------------------------------------- 1 | package crypto_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/TheManticoreProject/Manticore/windows/keycredential/crypto" 7 | ) 8 | 9 | func TestPrivateKeyEncryptionTypeString(t *testing.T) { 10 | tests := []struct { 11 | encryptionType crypto.PrivateKeyEncryptionType 12 | expected string 13 | }{ 14 | {crypto.NONE, "NONE"}, 15 | {crypto.PasswordRC4, "PasswordRC4"}, 16 | {crypto.PasswordRC2CBC, "PasswordRC2CBC"}, 17 | } 18 | 19 | for _, test := range tests { 20 | t.Run(test.expected, func(t *testing.T) { 21 | result := test.encryptionType.String() 22 | if result != test.expected { 23 | t.Errorf("Expected %s, but got %s", test.expected, result) 24 | } 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /windows/keycredential/key/CustomKeyInformationFlags.go: -------------------------------------------------------------------------------- 1 | package key 2 | 3 | // CustomKeyInformationFlags represents custom key flags. 4 | // 5 | // See: https://msdn.microsoft.com/en-us/library/mt220496.aspx 6 | type CustomKeyInformationFlags struct { 7 | Value uint8 8 | Name []string 9 | 10 | // Internal 11 | RawBytes []byte 12 | RawBytesSize uint32 13 | } 14 | 15 | const ( 16 | // No flags specified. 17 | CustomKeyInformationFlags_None uint8 = 0 18 | 19 | // Reserved for future use. (CUSTOMKEYINFO_FLAGS_ATTESTATION) 20 | CustomKeyInformationFlags_Attestation uint8 = 0x01 21 | 22 | // During creation of this key, the requesting client authenticated using 23 | // only a single credential. (CUSTOMKEYINFO_FLAGS_MFA_NOT_USED) 24 | CustomKeyInformationFlags_MFANotUsed uint8 = 0x02 25 | ) 26 | 27 | // Parse parses the provided byte slice into the CustomKeyInformationFlags structure. 28 | // 29 | // Parameters: 30 | // - value: A byte slice containing the raw key flags to be parsed. 31 | // 32 | // Note: 33 | // The function expects the byte slice to contain a single byte representing the key flags. 34 | // It extracts the flags value from the byte slice and assigns it to the CustomKeyInformationFlags structure. 35 | func (kf *CustomKeyInformationFlags) FromBytes(value byte) { 36 | kf.Value = value 37 | 38 | kf.Name = []string{} 39 | if kf.Value&CustomKeyInformationFlags_Attestation == CustomKeyInformationFlags_Attestation { 40 | kf.Name = append(kf.Name, "Attestation") 41 | } 42 | if kf.Value&CustomKeyInformationFlags_MFANotUsed == CustomKeyInformationFlags_MFANotUsed { 43 | kf.Name = append(kf.Name, "MFA not used") 44 | } 45 | 46 | if len(kf.Name) == 0 { 47 | kf.Name = append(kf.Name, "None") 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /windows/keycredential/key/KeyCredentialVersion.go: -------------------------------------------------------------------------------- 1 | package key 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | ) 7 | 8 | type KeyCredentialVersion struct { 9 | Value uint32 10 | 11 | // Internal 12 | RawBytes []byte 13 | RawBytesSize uint32 14 | } 15 | 16 | const ( 17 | KeyCredentialVersion_0 uint32 = 0x0 18 | KeyCredentialVersion_1 uint32 = 0x00000100 19 | KeyCredentialVersion_2 uint32 = 0x00000200 20 | ) 21 | 22 | // Parse parses the KeyCredentialVersion from a byte array. 23 | // 24 | // Parameters: 25 | // - value: A byte array representing the KeyCredentialVersion. 26 | func (kcv *KeyCredentialVersion) FromBytes(value []byte) { 27 | kcv.RawBytes = value[:4] 28 | kcv.RawBytesSize = 4 29 | 30 | kcv.Value = binary.LittleEndian.Uint32(value[:4]) 31 | } 32 | 33 | // String returns a string representation of the KeyCredentialVersion. 34 | // 35 | // Returns: 36 | // - A string representing the KeyCredentialVersion. 37 | func (kcv *KeyCredentialVersion) String() string { 38 | switch kcv.Value { 39 | case KeyCredentialVersion_0: 40 | return "KeyCredential_v0" 41 | case KeyCredentialVersion_1: 42 | return "KeyCredential_v1" 43 | case KeyCredentialVersion_2: 44 | return "KeyCredential_v2" 45 | } 46 | 47 | return fmt.Sprintf("Unknown version: %d", int(kcv.Value)) 48 | } 49 | 50 | // ToBytes returns the raw bytes of the KeyCredentialVersion structure. 51 | // 52 | // Returns: 53 | // - A byte slice representing the raw bytes of the KeyCredentialVersion structure. 54 | func (kcv *KeyCredentialVersion) ToBytes() []byte { 55 | buffer := make([]byte, 4) 56 | binary.LittleEndian.PutUint32(buffer, kcv.Value) 57 | return buffer 58 | } 59 | -------------------------------------------------------------------------------- /windows/keycredential/key/KeyCredentialVersion_test.go: -------------------------------------------------------------------------------- 1 | package key_test 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "testing" 7 | 8 | "github.com/TheManticoreProject/Manticore/windows/keycredential/key" 9 | ) 10 | 11 | func TestKeyCredentialVersionFromBytes(t *testing.T) { 12 | tests := []struct { 13 | input []byte 14 | expected uint32 15 | }{ 16 | {[]byte{0x00, 0x00, 0x00, 0x00}, key.KeyCredentialVersion_0}, 17 | {[]byte{0x00, 0x01, 0x00, 0x00}, key.KeyCredentialVersion_1}, 18 | {[]byte{0x00, 0x02, 0x00, 0x00}, key.KeyCredentialVersion_2}, 19 | } 20 | 21 | for _, test := range tests { 22 | t.Run(fmt.Sprintf("input: %v", test.input), func(t *testing.T) { 23 | var kcv key.KeyCredentialVersion 24 | kcv.FromBytes(test.input) 25 | if kcv.Value != test.expected { 26 | t.Errorf("Expected %d, but got %d", test.expected, kcv.Value) 27 | } 28 | }) 29 | } 30 | } 31 | 32 | func TestKeyCredentialVersionString(t *testing.T) { 33 | tests := []struct { 34 | version key.KeyCredentialVersion 35 | expected string 36 | }{ 37 | {key.KeyCredentialVersion{Value: key.KeyCredentialVersion_0}, "KeyCredential_v0"}, 38 | {key.KeyCredentialVersion{Value: key.KeyCredentialVersion_1}, "KeyCredential_v1"}, 39 | {key.KeyCredentialVersion{Value: key.KeyCredentialVersion_2}, "KeyCredential_v2"}, 40 | {key.KeyCredentialVersion{Value: 0x00000300}, "Unknown version: 768"}, 41 | } 42 | 43 | for _, test := range tests { 44 | t.Run(test.expected, func(t *testing.T) { 45 | result := test.version.String() 46 | if result != test.expected { 47 | t.Errorf("Expected %s, but got %s", test.expected, result) 48 | } 49 | }) 50 | } 51 | } 52 | 53 | func TestKeyCredentialVersionToBytes(t *testing.T) { 54 | tests := []struct { 55 | version key.KeyCredentialVersion 56 | expected []byte 57 | }{ 58 | {key.KeyCredentialVersion{Value: key.KeyCredentialVersion_0}, []byte{0x00, 0x00, 0x00, 0x00}}, 59 | {key.KeyCredentialVersion{Value: key.KeyCredentialVersion_1}, []byte{0x00, 0x01, 0x00, 0x00}}, 60 | {key.KeyCredentialVersion{Value: key.KeyCredentialVersion_2}, []byte{0x00, 0x02, 0x00, 0x00}}, 61 | } 62 | 63 | for _, test := range tests { 64 | t.Run(fmt.Sprintf("version: %d", test.version.Value), func(t *testing.T) { 65 | result := test.version.ToBytes() 66 | if !bytes.Equal(result, test.expected) { 67 | t.Errorf("Expected %v, but got %v", test.expected, result) 68 | } 69 | }) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /windows/keycredential/key/KeySource.go: -------------------------------------------------------------------------------- 1 | package key 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | ) 7 | 8 | // KeySource represents the source of the key. 9 | // See: https://msdn.microsoft.com/en-us/library/mt220501.aspx 10 | type KeySource int 11 | 12 | const ( 13 | // On Premises Key Trust 14 | KeySource_AD KeySource = 0x00 15 | 16 | // Hybrid Azure AD Key Trust 17 | KeySource_AzureAD KeySource = 0x01 18 | ) 19 | 20 | // String returns the string representation of the KeySource. 21 | // 22 | // Returns: 23 | // - A string representing the key source. 24 | func (ks KeySource) String() string { 25 | switch ks { 26 | case KeySource_AD: 27 | return "Active Directory (AD)" 28 | case KeySource_AzureAD: 29 | return "Azure Active Directory (AAD)" 30 | default: 31 | return fmt.Sprintf("Unknown KeySource: %d", int(ks)) 32 | } 33 | } 34 | 35 | // Parse parses the key source from a byte array. 36 | // 37 | // Parameters: 38 | // - value: A byte array representing the key source. 39 | // 40 | // Returns: 41 | // - A KeySource object. 42 | func (ks KeySource) FromBytes(value []byte) KeySource { 43 | return KeySource(binary.LittleEndian.Uint16(value)) 44 | } 45 | -------------------------------------------------------------------------------- /windows/keycredential/key/KeyStrength.go: -------------------------------------------------------------------------------- 1 | package key 2 | 3 | import "encoding/binary" 4 | 5 | // KeyStrength specifies the strength of the NGC key. 6 | // See: https://msdn.microsoft.com/en-us/library/mt220496.aspx 7 | type KeyStrength struct { 8 | Name string 9 | Value uint32 10 | 11 | // Internal 12 | RawBytes []byte 13 | RawBytesSize uint32 14 | } 15 | 16 | const ( 17 | // Key strength is unknown. 18 | KeyStrength_Unknown uint32 = 0x00 19 | 20 | // Key strength is weak. 21 | KeyStrength_Weak uint32 = 0x01 22 | 23 | // Key strength is normal. 24 | KeyStrength_Normal uint32 = 0x02 25 | ) 26 | 27 | func (ks *KeyStrength) FromBytes(value []byte) { 28 | ks.RawBytes = value[:4] 29 | ks.RawBytesSize = 4 30 | 31 | ks.Value = binary.LittleEndian.Uint32(value[:4]) 32 | 33 | switch ks.Value { 34 | case KeyStrength_Unknown: 35 | ks.Name = "Unknown" 36 | case KeyStrength_Weak: 37 | ks.Name = "Weak" 38 | case KeyStrength_Normal: 39 | ks.Name = "Normal" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /windows/keycredential/key/KeyUsage.go: -------------------------------------------------------------------------------- 1 | package key 2 | 3 | import "fmt" 4 | 5 | type KeyUsage struct { 6 | Value uint8 7 | 8 | // Internal 9 | RawBytes []byte 10 | RawBytesSize uint8 11 | } 12 | 13 | const ( 14 | // Key Usage 15 | // See: https://msdn.microsoft.com/en-us/library/mt220501.aspx 16 | 17 | // Admin key (pin-reset key) 18 | KeyUsage_AdminKey uint8 = 0 19 | 20 | // NGC key attached to a user object (KEY_USAGE_NGC) 21 | KeyUsage_NGC uint8 = 0x01 22 | 23 | // Transport key attached to a device object 24 | KeyUsage_STK uint8 = 0x02 25 | 26 | // BitLocker recovery key 27 | KeyUsage_BitlockerRecovery uint8 = 0x03 28 | 29 | // Unrecognized key usage 30 | KeyUsage_Other uint8 = 0x04 31 | 32 | // Fast IDentity Online Key (KEY_USAGE_FIDO) 33 | KeyUsage_FIDO uint8 = 0x07 34 | 35 | // File Encryption Key (KEY_USAGE_FEK) 36 | KeyUsage_FEK uint8 = 0x08 37 | 38 | // DPAPI Key 39 | // TODO: The DPAPI enum needs to be mapped to a proper integer value. 40 | KeyUsage_DPAPI uint8 = 0x09 41 | ) 42 | 43 | // Parse parses the key usage from a byte array. 44 | // 45 | // Parameters: 46 | // - value: A byte array representing the key usage. 47 | func (ku *KeyUsage) FromBytes(value byte) { 48 | ku.RawBytes = []byte{value} 49 | ku.RawBytesSize = 1 50 | 51 | ku.Value = value 52 | } 53 | 54 | // String returns a string representation of the key usage. 55 | // 56 | // Returns: 57 | // - A string representing the key usage. 58 | func (ku *KeyUsage) String() string { 59 | switch ku.Value { 60 | case KeyUsage_AdminKey: 61 | return "AdminKey" 62 | case KeyUsage_NGC: 63 | return "New Generation Credential (NGC)" 64 | case KeyUsage_STK: 65 | return "Smart Token Key (STK)" 66 | case KeyUsage_BitlockerRecovery: 67 | return "Bitlocker Recovery" 68 | case KeyUsage_Other: 69 | return "Other" 70 | case KeyUsage_FIDO: 71 | return "Fast IDentity Online (FIDO)" 72 | case KeyUsage_FEK: 73 | return "File Encryption Key (FEK)" 74 | case KeyUsage_DPAPI: 75 | return "Data Protection API (DPAPI)" 76 | } 77 | 78 | return fmt.Sprintf("Unknown KeyUsage: %d", ku.Value) 79 | } 80 | -------------------------------------------------------------------------------- /windows/keycredential/key/KeyUsage_test.go: -------------------------------------------------------------------------------- 1 | package key_test 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "testing" 7 | 8 | "github.com/TheManticoreProject/Manticore/windows/keycredential/key" 9 | ) 10 | 11 | func TestKeyUsage_Parse(t *testing.T) { 12 | tests := []struct { 13 | input byte 14 | expected key.KeyUsage 15 | }{ 16 | {0x00, key.KeyUsage{Value: 0x00, RawBytes: []byte{0x00}, RawBytesSize: 1}}, 17 | {0x01, key.KeyUsage{Value: 0x01, RawBytes: []byte{0x01}, RawBytesSize: 1}}, 18 | {0x02, key.KeyUsage{Value: 0x02, RawBytes: []byte{0x02}, RawBytesSize: 1}}, 19 | {0x03, key.KeyUsage{Value: 0x03, RawBytes: []byte{0x03}, RawBytesSize: 1}}, 20 | {0x04, key.KeyUsage{Value: 0x04, RawBytes: []byte{0x04}, RawBytesSize: 1}}, 21 | {0x07, key.KeyUsage{Value: 0x07, RawBytes: []byte{0x07}, RawBytesSize: 1}}, 22 | {0x08, key.KeyUsage{Value: 0x08, RawBytes: []byte{0x08}, RawBytesSize: 1}}, 23 | {0x09, key.KeyUsage{Value: 0x09, RawBytes: []byte{0x09}, RawBytesSize: 1}}, 24 | } 25 | 26 | for _, tt := range tests { 27 | t.Run(fmt.Sprintf("input=%x", tt.input), func(t *testing.T) { 28 | var ku key.KeyUsage 29 | ku.FromBytes(tt.input) 30 | if ku.Value != tt.expected.Value || !bytes.Equal(ku.RawBytes, tt.expected.RawBytes) || ku.RawBytesSize != tt.expected.RawBytesSize { 31 | t.Errorf("got %+v, want %+v", ku, tt.expected) 32 | } 33 | }) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /windows/keycredential/utils/DateTime_test.go: -------------------------------------------------------------------------------- 1 | package utils_test 2 | -------------------------------------------------------------------------------- /windows/keycredential/utils/utils_test.go: -------------------------------------------------------------------------------- 1 | package utils_test 2 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/EVENT_DESCRIPTOR.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // The EVENT_DESCRIPTOR structure specifies the metadata that defines an event. 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/a6110d36-28c1-4290-b79e-26aa95a0b1a0 7 | type EVENT_DESCRIPTOR struct { 8 | Id data_types.USHORT 9 | Version data_types.UCHAR 10 | Channel data_types.UCHAR 11 | Level data_types.UCHAR 12 | Opcode data_types.UCHAR 13 | Task data_types.USHORT 14 | Keyword data_types.ULONGLONG 15 | } 16 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/EVENT_HEADER.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import ( 4 | "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 5 | ) 6 | 7 | // The EVENT_HEADER structure defines the main parameters of an event. 8 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/fa4f7836-06ee-4ab6-8688-386a5a85f8c5 9 | type EVENT_HEADER struct { 10 | Size data_types.USHORT 11 | HeaderType data_types.USHORT 12 | Flags data_types.USHORT 13 | EventProperty data_types.USHORT 14 | ThreadId data_types.ULONG 15 | ProcessId data_types.ULONG 16 | TimeStamp LARGE_INTEGER 17 | ProviderId GUID 18 | EventDescriptor EVENT_DESCRIPTOR 19 | KernelTime data_types.ULONG 20 | UserTime data_types.ULONG 21 | ProcessorTime data_types.ULONG64 22 | ActivityId GUID 23 | } 24 | 25 | type PEVENT_HEADER *EVENT_HEADER 26 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/GUID.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/guid" 4 | 5 | // GUID 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/4926e530-816e-41c2-b251-ec5c7aca018a 7 | type GUID = guid.GUID 8 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/GUID_test.go: -------------------------------------------------------------------------------- 1 | package data_structures_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/TheManticoreProject/Manticore/windows/guid" 7 | "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_structures" 8 | ) 9 | 10 | func TestGUID_Compatibility(t *testing.T) { 11 | // Test that GUID is properly aliased to guid.GUID 12 | var msGUID data_structures.GUID 13 | var windowsGUID guid.GUID 14 | 15 | // Both types should be the same 16 | var _ = msGUID == windowsGUID // This will fail to compile if types are incompatible 17 | 18 | // Create a GUID and verify it works with the underlying implementation 19 | testGUID := data_structures.GUID{ 20 | A: 0x12345678, 21 | B: 0x1234, 22 | C: 0x5678, 23 | D: 0x9abc, 24 | E: 0xdef012345678, 25 | } 26 | 27 | // Test string representation 28 | expected := "12345678-1234-5678-9abc-def012345678" 29 | if result := testGUID.ToFormatD(); result != expected { 30 | t.Errorf("Expected %s, but got %s", expected, result) 31 | } 32 | 33 | // Test byte conversion 34 | expectedBytes := []byte{ 35 | 0x78, 0x56, 0x34, 0x12, 36 | 0x34, 0x12, 37 | 0x78, 0x56, 38 | 0x9a, 0xbc, 39 | 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 40 | } 41 | resultBytes := testGUID.ToBytes() 42 | for i, b := range resultBytes { 43 | if b != expectedBytes[i] { 44 | t.Errorf("Expected byte %x at position %d, but got %x", expectedBytes[i], i, b) 45 | } 46 | } 47 | 48 | // Test involution (conversion to bytes and back) 49 | var reconstructedGUID data_structures.GUID 50 | reconstructedGUID.FromRawBytes(resultBytes) 51 | if !reconstructedGUID.Equal(&testGUID) { 52 | t.Errorf("GUIDs are not equal after involution. Before: %s, After: %s", 53 | testGUID.ToFormatD(), reconstructedGUID.ToFormatD()) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/LARGE_INTEGER.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // LARGE_INTEGER 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/e904b1ba-f774-4203-ba1b-66485165ab1a 7 | type LARGE_INTEGER struct { 8 | QuadPart data_types.ULONGLONG 9 | } 10 | 11 | type PLARGE_INTEGER *LARGE_INTEGER 12 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/LCID.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // A language code identifier structure is stored as a DWORD. The lower word contains the language identifier, 6 | // and the upper word contains both the sorting identifier (ID) and a reserved value. For additional details about 7 | // the structure and possible values, see [MS-LCID]. 8 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/e8e4255f-5b6d-472b-8a98-ae3950bfdb9a 9 | type LCID = data_types.DWORD 10 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/LUID.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // The LUID structure is 64-bit value guaranteed to be unique only on the system on which it was generated. 6 | // The uniqueness of a locally unique identifier (LUID) is guaranteed only until the system is restarted. 7 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/48cbee2a-0790-45f2-8269-931d7083b2c3 8 | type LUID struct { 9 | // LowPart: The low-order bits of the structure. 10 | LowPart data_types.DWORD 11 | // HighPart: The high-order bits of the structure. 12 | HighPart data_types.LONG 13 | } 14 | 15 | type PLUID *LUID 16 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/MULTI_SZ.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // The MULTI_SZ structure defines an implementation-specific type that contains a sequence of null-terminated strings, 6 | // terminated by an empty string (\0) so that the last two characters are both null terminators. 7 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/fd7b2d81-b1d7-414f-a3df-c66fabc578db 8 | type MULTI_SZ struct { 9 | // Value: A data buffer, which is a string literal containing multiple null-terminated strings serially. 10 | Value data_types.WCHAR 11 | // NChar: The length, in characters, including the two terminating nulls. 12 | NChar data_types.DWORD 13 | } 14 | 15 | type PMULTI_SZ *MULTI_SZ 16 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/OBJECT_TYPE_LIST.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // OBJECT_TYPE_LIST 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/6f04f1f2-d070-4f70-aae7-5f98ed63e1ba 7 | type OBJECT_TYPE_LIST struct { 8 | // Level: Specifies the level of the object type in the hierarchy of an object and its sub-objects. Level zero 9 | // indicates the object itself. Level one indicates a sub-object of the object, such as a property set. Level two 10 | // indicates a sub-object of the level one sub-object, such as a property. There can be a maximum of five levels 11 | // numbered zero through four. 12 | Level data_types.WORD 13 | // Remaining: Remaining access bits for this element, used by the access check algorithm, as specified in section 2.5.3.2. 14 | Remaining data_types.UINT32 // data_types.ACCESS_MASK 15 | // ObjectType: A pointer to the GUID for the object or sub-object. 16 | ObjectType *GUID 17 | } 18 | 19 | type POBJECT_TYPE_LIST *OBJECT_TYPE_LIST 20 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/RPC_UNICODE_STRING.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // RPC_UNICODE_STRING 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/94a16bb6-c610-4cb9-8db6-26f15f560061 7 | type RPC_UNICODE_STRING struct { 8 | // Length: The length, in bytes, of the string pointed to by the Buffer member. 9 | // The length MUST be a multiple of 2. The length MUST equal the entire size of the buffer. 10 | Length data_types.WORD 11 | // MaximumLength: The maximum size, in bytes, of the string pointed to by Buffer. The size MUST be a multiple of 2. 12 | // If not, the size MUST be decremented by 1 prior to use. This value MUST not be less than Length. 13 | MaximumLength data_types.WORD 14 | // Buffer: A pointer to a string buffer. The string pointed to by the buffer member MUST NOT include a terminating null character. 15 | Buffer data_types.WCHAR 16 | } 17 | 18 | type PRPC_UNICODE_STRING *RPC_UNICODE_STRING 19 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/SERVER_INFO_100.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // SERVER_INFO_100 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/007c654b-7d78-49d4-9f4d-0da7c1889727 7 | type SERVER_INFO_100 struct { 8 | // Sv100PlatformId: The platform ID. 9 | Sv100PlatformId data_types.DWORD 10 | // Sv100Name: The server name. 11 | Sv100Name data_types.WCHAR 12 | } 13 | 14 | type PSERVER_INFO_100 *SERVER_INFO_100 15 | type LPSERVER_INFO_100 *SERVER_INFO_100 16 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/SERVER_INFO_101.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // SERVER_INFO_101 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/39c502dd-022b-4a68-9367-89fd76a23bc3 7 | type SERVER_INFO_101 struct { 8 | // sv101_platform_id: Specifies the information level to use for platform-specific information. 9 | Sv101PlatformId data_types.DWORD 10 | // sv101_name: A pointer to a null-terminated Unicode UTF-16 Internet host name or NetBIOS host name of a server. 11 | Sv101Name data_types.STRING 12 | // sv101_version_major: Specifies the major release version number of the operating system. The server MUST set this 13 | // field to an implementation-specific major release version number that corresponds to the host operating system as 14 | // specified in the following table. 15 | Sv101VersionMajor data_types.DWORD 16 | // sv101_version_minor: Specifies the minor release version number of the operating system. The server MUST set this 17 | // field to an implementation-specific minor release version number that corresponds to the host operating system as 18 | // specified in the following table. 19 | Sv101VersionMinor data_types.DWORD 20 | // sv101_version_type: The sv101_version_type field specifies the SV_TYPE flags, which indicate the software services 21 | // that are available (but not necessarily running) on the server. This member MUST be a combination of one or more of 22 | // the following values. 23 | Sv101VersionType data_types.DWORD 24 | // sv101_comment: A pointer to a null-terminated Unicode UTF-16 string that specifies a comment that describes the server. 25 | Sv101Comment data_types.STRING 26 | } 27 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/SYSTEMTIME.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // SYSTEMTIME 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/2fefe8dd-ab48-4e33-a7d5-7171455a9289 7 | type SYSTEMTIME struct { 8 | // WYear: The year. 9 | WYear data_types.WORD 10 | // WMonth: The month. 11 | WMonth data_types.WORD 12 | // WDayOfWeek: The day of the week. 13 | WDayOfWeek data_types.WORD 14 | // WDay: The day. 15 | WDay data_types.WORD 16 | // WHour: The hour. 17 | WHour data_types.WORD 18 | // WMinute: The minute. 19 | WMinute data_types.WORD 20 | // WSecond: The second. 21 | WSecond data_types.WORD 22 | // WMilliseconds: The milliseconds. 23 | WMilliseconds data_types.WORD 24 | } 25 | 26 | type PSYSTEMTIME *SYSTEMTIME 27 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/UINT128.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // UINT128 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/3b5c1a61-ece4-4dce-9c9f-c15388ba9032 7 | type UINT128 struct { 8 | // Lower: The lower 64 bits of the 128-bit value. 9 | Lower data_types.UINT64 10 | // Upper: The upper 64 bits of the 128-bit value. 11 | Upper data_types.UINT64 12 | } 13 | 14 | type PUINT128 *UINT128 15 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_structures/ULARGE_INTEGER.go: -------------------------------------------------------------------------------- 1 | package data_structures 2 | 3 | import "github.com/TheManticoreProject/Manticore/windows/ms_dtyp/common/data_types" 4 | 5 | // ULARGE_INTEGER 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/d37e0ce7-a358-4c07-a5c4-59c8b5da8b08 7 | type ULARGE_INTEGER struct { 8 | // QuadPart: The 64-bit value. 9 | QuadPart data_types.UINT64 10 | } 11 | 12 | type PULARGE_INTEGER *ULARGE_INTEGER 13 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/ADCONNECTION_HANDLE.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // ADCONNECTION_HANDLE 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/5faf669e-34a9-471b-aaff-8591b9650189 5 | type ADCONNECTION_HANDLE = uintptr 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/BOOL.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A BOOL is a 32-bit field that is set to 1 to indicate TRUE, or 0 to indicate FALSE 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/9d81be47-232e-42cf-8f0d-7a3b29bf2eb2 5 | type BOOL = uint32 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/BOOLEAN.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A BOOLEAN is an 8-bit field that is set to 1 to indicate TRUE, or 0 to indicate FALSE. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/51bbfbb1-08e2-4c13-a95e-1eaa7d310670 5 | type BOOLEAN = uint8 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/BSTR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A BSTR is a pointer to a null-terminated character string in which the string length is stored with the string. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/692a42a9-06ce-4394-b9bc-5d2a50440168 5 | type BSTR = []WCHAR 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/BYTE.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A BYTE is an 8-bit unsigned value that corresponds to a single octet in a network protocol. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/d7edc080-e499-4219-a837-1bc40b64bb04 5 | type BYTE = UCHAR 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/CHAR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A CHAR is an 8-bit block of data that typically contains an ANSI character, as specified in [ISO/IEC-8859-1]. 4 | // For information on the char keyword, see [C706] section 4.2.9.3. 5 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/77e1033f-b31d-4bd2-b3d5-9f3c9faa22eb 6 | type CHAR = byte 7 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/DOUBLE.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A DOUBLE is an 8-byte, double-precision, floating-point number that represents a double-precision, 64-bit [IEEE754] 4 | // value with the approximate range: +/-5.0 x 10-324 through +/-1.7 x 10308. 5 | // The DOUBLE type can also represent not a number (NAN); positive and negative infinity; or positive and negative 0. 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/40beeef3-303a-40de-895c-11379fc42c15 7 | type DOUBLE = float64 8 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/DWORD.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A DWORD is a 32-bit unsigned integer (range: 0 through 4294967295 decimal). Because a DWORD is unsigned, 4 | // its first bit (Most Significant Bit (MSB)) is not reserved for signing. 5 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/262627d8-3418-4627-9218-4ffe110850b2 6 | type DWORD = uint32 7 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/DWORD32.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A DWORD32 is a 32-bit unsigned integer. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/e359fcc1-35c6-4bcd-964d-d59927aeea98 5 | type DWORD32 = uint32 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/DWORD64.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A DWORD64 is a 64-bit unsigned integer. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/3f3bd817-6fdd-4db9-b542-f800f876007d 5 | type DWORD64 = uint64 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/DWORDLONG.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A DWORDLONG is a 64-bit unsigned integer (range: 0 through 18446744073709551615 decimal). 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/c575fb47-166c-48cd-a37c-e44cac05c3d6 5 | type DWORDLONG = uint64 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/DWORD_PTR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A DWORD_PTR is a pointer to a DWORD. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/66d61dd8-2191-4a37-b963-e49bf0dc2579 5 | type DWORD_PTR = *DWORD 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/ERROR_STATUS_T.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // ERROR_STATUS_T 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/802ada7f-c5fc-415e-8438-c7369bb4193b 5 | type ERROR_STATUS_T = ULONG 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/FLOAT.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A FLOAT is a base type that is specified the IEEE Format section of [C706].section 14.2. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/73ba97b0-bbe5-483d-a0a8-46298ebcb160 5 | type FLOAT = float32 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/HANDLE.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // HANDLE 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/929187f0-f25c-4b05-9497-16b066d8a912 5 | type HANDLE = uintptr 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/HCALL.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // HCALL 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/4958db44-2d75-4ccf-a4ba-3b8b1ec56360 5 | type HCALL = DWORD 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/HRESULT.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // HRESULT 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/a9046ed2-bfb2-4d56-a719-2824afce59ac 5 | type HRESULT = LONG 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/INT.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // INT 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/2d70b269-ed8e-4a5d-8384-b3cd4d9e24f8 5 | type INT = int32 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/INT16.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // INT16 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/c19c7f85-a511-4407-a7bf-5da9fa79d026 5 | type INT16 = int16 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/INT32.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // INT32 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/b9218cdd-e76a-4c13-bb2d-c322dc39505b 5 | type INT32 = int32 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/INT64.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // INT64 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/cfb2030b-0d7a-4808-8539-32f35bd9325f 5 | type INT64 = int64 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/INT8.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // INT8 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/fc85cdcc-92f3-46ef-a2aa-501f44d0968a 5 | type INT8 = int8 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LDAP_UDP_HANDLE.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // LDAP_UDP_HANDLE 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/b0e4f011-fea4-473f-a678-be5e5a33f4cf 5 | type LDAP_UDP_HANDLE = uintptr 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LMCSTR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // LMCSTR 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/34971db0-e83a-473e-aa5e-c4f3691c7f6d 5 | type LMCSTR = []WCHAR 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LMSTR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // LMSTR 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/783140f9-5cb9-499e-a7a7-722214b27733 5 | type LMSTR = []WCHAR 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LONG.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A LONG is a 32-bit signed integer, in twos-complement format (range: -2147483648 through 2147483647 decimal). 4 | // The first bit (Most Significant Bit (MSB)) is the signing bit. 5 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/29d44d70-382f-4998-9d76-8a1fe93e445c 6 | type LONG = int32 7 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LONG32.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A LONG32 is a 32-bit signed integer. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/286e80a4-16fa-45d5-b97d-aeac136ef3f0 5 | type LONG32 = int32 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LONG64.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A LONG64 is a 64-bit signed integer. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/7dc8dc9c-9d54-417a-933e-173933f0c329 5 | type LONG64 = int64 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LONGLONG.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A LONGLONG is a 64-bit signed integer (range: -9223372036854775808 through 9223372036854775807 decimal). 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/e34f8048-e2d0-4f5b-99fd-0b6489ee0295 5 | type LONGLONG = int64 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LONG_PTR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A LONG_PTR is a long type used for pointer precision. It is used when casting a pointer to a long type to perform pointer arithmetic. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/bbcfb0af-8349-4e98-ad26-957e1363f714 5 | type LONG_PTR = uintptr 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LPCSTR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // An LPCSTR is a 32-bit pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/f8d4fe46-6be8-44c9-8823-615a21d17a61 5 | type LPCSTR = *CHAR 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LPCVOID.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // An LPCVOID is a 32-bit pointer to a constant of any type. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/66996877-9dd4-477d-a811-30e6c1a5525d 5 | type LPCVOID = uintptr 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LPCWSTR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // An LPCWSTR is a 32-bit pointer to a constant string of 16-bit Unicode characters, which MAY be null-terminated. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/76f10dd8-699d-45e6-a53c-5aefc586da20 5 | type LPCWSTR = *WCHAR 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LPSTR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // The LPSTR type and its alias PSTR specify a pointer to an array of 8-bit characters, which MAY be terminated by a null character. 4 | // In some protocols, it is acceptable to not terminate with a null character, and this option will be indicated in the specification. In this case, the LPSTR or PSTR type MUST either be tagged with the IDL modifier [string], that indicates string semantics, or be accompanied by an explicit length specifier, for example [size_is()]. 5 | // The format of the characters MUST be specified by the protocol that uses them. Two common 8-bit formats are ANSI and UTF-8. 6 | // A 32-bit pointer to a string of 8-bit characters, which MAY be null-terminated. 7 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/3f6cc0e2-1303-4088-a26b-fb9582f29197 8 | type LPSTR = *CHAR 9 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/LPWSTR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // The LPWSTR type is a 32-bit pointer to a string of 16-bit Unicode characters, which MAY be null-terminated. 4 | // The LPWSTR type specifies a pointer to a sequence of Unicode characters, which MAY be terminated by a null character 5 | // (usually referred to as "null-terminated Unicode"). 6 | // In some protocols, an acceptable option is to not terminate a sequence of Unicode characters with a null character. 7 | // Where this option applies, it is indicated in the protocol specification. In this situation, the LPWSTR or PWSTR type 8 | // MUST either be tagged with the IDL modifier [string], which indicates string semantics, or MUST be accompanied by an 9 | // explicit length specifier, as specified in the RPC_UNICODE_STRING (section 2.3.10) structure. 10 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/50e9ef83-d6fd-4e22-a34a-2c6b4e3c24f3 11 | type LPWSTR = *WCHAR 12 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/NET_API_STATUS.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // NET_API_STATUS 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/19cdb498-c67b-42b7-a540-4bc6a73c04f6 5 | type NET_API_STATUS = DWORD 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/NTSTATUS.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // NTSTATUS is a standard 32-bit datatype for system-supplied status code values. 4 | // NTSTATUS values are used to communicate system information. They are of four types: 5 | // success values, information values, warnings, and error values, as specified in [MS-ERREF]. 6 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/c8b512d5-70b1-4028-95f1-ec92d35cb51e 7 | type NTSTATUS = LONG 8 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/PCONTEXT_HANDLE.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // The PCONTEXT_HANDLE type keeps state information associated with a given client on a server. The state information is called the server's context. Clients can obtain a context handle to identify the server's context for their individual RPC sessions. 4 | // A context handle must be of the void * type, or a type that resolves to void *. The server program casts it to the required type. 5 | // The IDL attribute [context_handle], as specified in [C706], is used to declare PCONTEXT_HANDLE. 6 | // An interface that uses a context handle must have a binding handle for the initial binding, which has to take place before the server can return a context handle. The handle_t type is one of the predefined types of the interface definition language (IDL), which is used to create a binding handle. 7 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/b8d08028-e73f-4bb8-b3bf-bc8ba4734c4c 8 | type PCONTEXT_HANDLE = uintptr 9 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/QWORD.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A QWORD is a 64-bit unsigned integer. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/ac050bbf-a821-4fab-bccf-d95d892f428f 5 | type QWORD = uint64 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/RPC_BINDING_HANDLE.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // An RPC_BINDING_HANDLE is an untyped 32-bit pointer containing information that the RPC run-time library uses to access binding information. 4 | // It is directly equivalent to the type rpc_binding_handle_t described in [C706] section 3.1.4. 5 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/d0dffa33-812f-4214-a987-4ee149328eec 6 | type RPC_BINDING_HANDLE = uintptr 7 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/SHORT.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A SHORT is a 16-bit signed integer(range: -32768 through 32767 decimal). The first bit (Most Significant Bit (MSB)) is the signing bit. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/47b1e7d6-b5a1-48c3-986e-b5e5eb3f06d2 5 | type SHORT = int16 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/SIZE_T.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // SIZE_T is a ULONG_PTR representing the maximum number of bytes to which a pointer can point. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/1dc2ff19-6fef-4c5f-b4fd-afbc2557fd81 5 | type SIZE_T = ULONG_PTR 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/STRING.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // Unless otherwise noted, a STRING is a UCHAR buffer that represents a null-terminated string of 8-bit characters. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/08460486-bacc-48af-8520-195ff7f80db5 5 | type STRING = []UCHAR 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/UCHAR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A UCHAR is an 8-bit integer with the range: 0 through 255 decimal. Because a UCHAR is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/050baef1-f978-4851-a3c7-ad701a90e54a 5 | type UCHAR = uint8 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/UINT.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A UINT is a 32-bit unsigned integer (range: 0 through 4294967295 decimal). 4 | // Because a UINT is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing. 5 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/52ddd4c3-55b9-4e03-8287-5392aac0627f 6 | type UINT = uint32 7 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/UINT16.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A UINT16 is a 16-bit unsigned integer (range: 0 through 65535 decimal). Because a UINT16 is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/6c1609ad-8592-45d3-9dfa-38e6a30ff203 5 | type UINT16 = uint16 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/UINT32.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A UINT32 is a 32-bit unsigned integer (range: 0 through 4294967295 decimal). 4 | // Because a UINT32 is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing. 5 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/362b8d72-2245-4c33-84a8-08c69f4c302f 6 | type UINT32 = uint32 7 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/UINT64.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A UINT64 is a 64-bit unsigned integer (range: 0 through 18446744073709551615 decimal). 4 | // Because a UINT64 is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing. 5 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/a7b7720f-87eb-4add-9bcb-c6ff652778ae 6 | type UINT64 = uint64 7 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/UINT8.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A UINT8 is an 8-bit unsigned integer (range: 0 through 255 decimal). 4 | // Because a UINT8 is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing. 5 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/a88ed362-a905-4ed2-85f5-cfc8692c9842 6 | type UINT8 = uint8 7 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/ULONG.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A ULONG is a 32-bit unsigned integer (range: 0 through 4294967295 decimal). Because a ULONG is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/32862b84-f6e6-40f9-85ca-c4faf985b822 5 | type ULONG = uint32 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/ULONG32.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A ULONG32 is an unsigned LONG32. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/c9346e52-0765-4247-ab74-89c24ad3517b 5 | type ULONG32 = uint32 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/ULONG64.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A ULONG64 is a 64-bit unsigned integer (range: 0 through 18446744073709551615 decimal). 4 | // Because a ULONG64 is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing. 5 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/2dc4c492-95db-4fa6-ae2b-8546b13c9141 6 | type ULONG64 = uint64 7 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/ULONGLONG.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A ULONGLONG is a 64-bit unsigned integer (range: 0 through 18446744073709551615 decimal). 4 | // Because a ULONGLONG is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing. 5 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/c57d9fba-12ef-4853-b0d5-a6f472b50388 6 | type ULONGLONG = uint64 7 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/ULONG_PTR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A ULONG_PTR is an unsigned long type used for pointer precision. It is used when casting a pointer to a long type to perform pointer arithmetic. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/21eec394-630d-49ed-8b4a-ab74a1614611 5 | type ULONG_PTR = uintptr 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/UNC.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // UNC 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/62e862f4-2a51-452e-8eeb-dc4ff5ee33cc 5 | type UNC = string 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/UNICODE.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A single Unicode character. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/845b6fa4-c34a-4b90-824d-60e98533dfb5 5 | type UNICODE = uint16 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/USHORT.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A USHORT is a 16-bit unsigned integer (range: 0 through 65535 decimal). Because a USHORT is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/c0618c5b-362b-4e06-9cb0-8720d240cf12 5 | type USHORT = uint16 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/VOID.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // VOID is an alias for void. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/c0b7741b-f577-4eed-aff3-2e909df10a4d 5 | type VOID = struct{} 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/WCHAR.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A WCHAR is a 16-bit Unicode character. 4 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/7df7c1d5-492c-4db4-a992-5cd9e887c5d7 5 | type WCHAR = UNICODE 6 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/WORD.go: -------------------------------------------------------------------------------- 1 | package data_types 2 | 3 | // A WORD is a 16-bit unsigned integer (range: 0 through 65535 decimal). 4 | // Because a WORD is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing. 5 | // Source: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/f8573df3-a44a-4a50-b070-ac4c3aa78e3c 6 | type WORD = uint16 7 | -------------------------------------------------------------------------------- /windows/ms_dtyp/common/data_types/data_types_test.go: -------------------------------------------------------------------------------- 1 | package data_types_test 2 | -------------------------------------------------------------------------------- /windows/nt_status/nt_status_test.go: -------------------------------------------------------------------------------- 1 | package nt_status_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/TheManticoreProject/Manticore/windows/nt_status" 7 | ) 8 | 9 | func TestNTStatusString(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | status nt_status.NT_STATUS 13 | expected string 14 | }{ 15 | { 16 | name: "NT_STATUS_SUCCESS", 17 | status: nt_status.NT_STATUS_SUCCESS, 18 | expected: "SUCCESS", 19 | }, 20 | { 21 | name: "NT_STATUS_PENDING", 22 | status: nt_status.NT_STATUS_PENDING, 23 | expected: "PENDING", 24 | }, 25 | { 26 | name: "NT_STATUS_TIMEOUT", 27 | status: nt_status.NT_STATUS_TIMEOUT, 28 | expected: "TIMEOUT", 29 | }, 30 | { 31 | name: "NT_STATUS_BUFFER_ALL_ZEROS", 32 | status: nt_status.NT_STATUS_BUFFER_ALL_ZEROS, 33 | expected: "BUFFER_ALL_ZEROS", 34 | }, 35 | { 36 | name: "Unknown status", 37 | status: nt_status.NT_STATUS(0xFFFFFFFF), 38 | expected: "UNKNOWN", 39 | }, 40 | } 41 | 42 | for _, tt := range tests { 43 | t.Run(tt.name, func(t *testing.T) { 44 | result := tt.status.String() 45 | if result != tt.expected { 46 | t.Errorf("String() = %v, want %v", result, tt.expected) 47 | } 48 | }) 49 | } 50 | } 51 | 52 | func TestNTStatusError(t *testing.T) { 53 | tests := []struct { 54 | name string 55 | status nt_status.NT_STATUS 56 | expectedError bool 57 | }{ 58 | { 59 | name: "NT_STATUS_SUCCESS", 60 | status: nt_status.NT_STATUS_SUCCESS, 61 | expectedError: false, 62 | }, 63 | { 64 | name: "NT_STATUS_PENDING", 65 | status: nt_status.NT_STATUS_PENDING, 66 | expectedError: true, 67 | }, 68 | { 69 | name: "NT_STATUS_TIMEOUT", 70 | status: nt_status.NT_STATUS_TIMEOUT, 71 | expectedError: true, 72 | }, 73 | { 74 | name: "Unknown status", 75 | status: nt_status.NT_STATUS(0xFFFFFFFF), 76 | expectedError: false, 77 | }, 78 | } 79 | 80 | for _, tt := range tests { 81 | t.Run(tt.name, func(t *testing.T) { 82 | err := tt.status.Error() 83 | if (err != nil) != tt.expectedError { 84 | t.Errorf("Error() returned %v, expectedError: %v", err, tt.expectedError) 85 | } 86 | }) 87 | } 88 | } 89 | --------------------------------------------------------------------------------