diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 134aa30f..9243e8a0 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1 +1,2 @@ Paul-Andrew Joseph Miseiko +Vadim Frolov diff --git a/README.md b/README.md index 03b56483..2ef8252e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,13 @@ DCE-RPC implementation capable of using SMBv2 via SMBJ to invoke remote procedure calls (RPC) over the IPC$ named pipe. -Partial support for the Windows Remote Registry Protocol (MS-RRP) specification (https://msdn.microsoft.com/en-us/library/cc244877.aspx). +Supports the following protocols (some support is partial): +* [MS-RSP]: [Remote shutdown protocol](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rsp/43a7d8d6-307d-445c-8678-d209a19926fe). +* [MS-LSAD]: [Local Security Authority (Domain Policy) Remote Protocol](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lsad/1b5471ef-4c33-4a91-b079-dfcbb82f05cc). +* [MS-RRP]: [Windows Remote Registry Protocol](https://msdn.microsoft.com/en-us/library/cc244877.aspx). +* [MS-SAMR]: [Security Account Manager (SAM) Remote Protocol (Client-to-Server)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/4df07fab-1bbc-452f-8e92-7853a3c7e380). +* [MS-SRVS]: [Server Service Remote Protocol](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-srvs/accf23b0-0f57-441c-9185-43041f1b0ee9). +* [MS-SCMR]: [Service Control Manager Remote Protocol](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/705b624a-13de-43cc-b8a2-99573da3635f). Special thank you to Jeroen van Erp for SMBJ (https://github.com/hierynomus/smbj). @@ -78,6 +84,10 @@ try (final Connection smbConnection = smbClient.connect("aaa.bbb.ccc.ddd")) { } ``` +#### [MS-RSP]: Remote Shutdown Protocol + +See file `usage/ShutdownExample.java` inside the project. + # NDR Types All objects are assigned to a type hierarchy: diff --git a/pom.xml b/pom.xml index 3a9e81b5..5ae37b45 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.rapid7.client dcerpc jar - 0.8.3-SNAPSHOT + 0.8.4-SNAPSHOT dcerpc https://www.rapid7.com DCE-RPC implementation capable of using SMBv2 via SMBJ to invoke remote procedure calls (RPC) over the IPC$ named pipe. @@ -43,14 +43,14 @@ - 2.5 - 3.4 - 18.0 + 2.6 + 3.9 + 28.2-jre 1.3 - 4.12 + 4.13 1.10.19 - 0.8.0 - 6.11 + 0.10.0 + 7.1.0 1.7 1.7 UTF-8 @@ -78,6 +78,11 @@ smbj ${thirdparty.smbj.version} + + javax.activation + activation + 1.1.1 + @@ -121,7 +126,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.20.1 + 3.0.0-M4 org.sonatype.plugins @@ -150,7 +155,11 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.9.1 + 3.2.0 + + none + 8 + attach-javadocs diff --git a/src/main/java/com/rapid7/client/dcerpc/Interface.java b/src/main/java/com/rapid7/client/dcerpc/Interface.java index e21ba640..dd6f7bc8 100644 --- a/src/main/java/com/rapid7/client/dcerpc/Interface.java +++ b/src/main/java/com/rapid7/client/dcerpc/Interface.java @@ -24,7 +24,8 @@ public enum Interface { LSASVC_V0_0("lsarpc interface", "12345778-1234-ABCD-EF00-0123456789AB:v0.0"), SAMSVC_V1_0("samr interface", "12345778-1234-ABCD-EF00-0123456789AC:v1.0"), SVCCTL_V2_0("svcctl_interface", "367abb81-9844-35f1-ad32-98f038001003:v2.0"), - NDR_32BIT_V2("NDR transfer syntax identifier", "8a885d04-1ceb-11c9-9fe8-08002b104860:v2.0"); + NDR_32BIT_V2("NDR transfer syntax identifier", "8a885d04-1ceb-11c9-9fe8-08002b104860:v2.0"), + INITSHUTDOWN_V1_0("initshutdown interface", "894de0c0-0d55-11d3-a322-00c04fa321a1:v1.0"); private final String name; private final String repr; diff --git a/src/main/java/com/rapid7/client/dcerpc/initshutdown/ShutdownService.java b/src/main/java/com/rapid7/client/dcerpc/initshutdown/ShutdownService.java new file mode 100644 index 00000000..68e39ec1 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/ShutdownService.java @@ -0,0 +1,58 @@ +/** + * Copyright 2020, Vadim Frolov. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + */ +package com.rapid7.client.dcerpc.initshutdown; + +import java.io.IOException; +import java.util.EnumSet; +import com.rapid7.client.dcerpc.initshutdown.dto.ShutdownReason; +import com.rapid7.client.dcerpc.initshutdown.messages.BaseAbortShutdown; +import com.rapid7.client.dcerpc.initshutdown.messages.BaseInitiateShutdownRequest; +import com.rapid7.client.dcerpc.initshutdown.messages.BaseInitiateShutdownRequestEx; +import com.rapid7.client.dcerpc.messages.EmptyResponse; +import com.rapid7.client.dcerpc.objects.RegUnicodeString; +import com.rapid7.client.dcerpc.service.Service; +import com.rapid7.client.dcerpc.transport.RPCTransport; + +public class ShutdownService extends Service { + public ShutdownService(final RPCTransport transport) { + super(transport); + } + + public int shutdown(final String msg, final int timeout, final boolean forceAppsClosed, final boolean rebootAfterShutdown) + throws IOException { + + final BaseInitiateShutdownRequest request = new BaseInitiateShutdownRequest(parseWCharNT(null), RegUnicodeString.NullTerminated.of(msg), timeout, forceAppsClosed, rebootAfterShutdown); + final EmptyResponse response = callExpectSuccess(request, "BaseInitiateShutdownRequest"); + return response.getReturnValue(); + } + + public int abortShutdown() throws IOException { + final BaseAbortShutdown request = new BaseAbortShutdown(parseWCharNT(null)); + final EmptyResponse response = callExpectSuccess(request, "BaseAbortShutdown"); + return response.getReturnValue(); + } + + public int shutdownEx(final String msg, final int timeout, final boolean forceAppsClosed, final boolean rebootAfterShutdown, final EnumSet reasons) + throws IOException { + + final BaseInitiateShutdownRequestEx request = new BaseInitiateShutdownRequestEx(parseWCharNT(null), RegUnicodeString.NullTerminated.of(msg), timeout, forceAppsClosed, rebootAfterShutdown, reasons); + final EmptyResponse response = callExpectSuccess(request, "BaseInitiateShutdownRequestEx"); + return response.getReturnValue(); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/initshutdown/dto/ShutdownReason.java b/src/main/java/com/rapid7/client/dcerpc/initshutdown/dto/ShutdownReason.java new file mode 100644 index 00000000..b695586c --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/dto/ShutdownReason.java @@ -0,0 +1,94 @@ +/** + * Copyright 2020, Vadim Frolov. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + */ +package com.rapid7.client.dcerpc.initshutdown.dto; + +import java.util.EnumSet; + +/* + * @see 2.3 Shutdown Reasons + *
+ * Usage:
+ *   EnumSet flags = EnumSet.of(ShutdownReason.SHTDN_REASON_MAJOR_APPLICATION,
+ *           ShutdownReason.SHTDN_REASON_MINOR_BLUESCREEN);
+ *   int reason = ShutdownReason.getReason(flags);
+ *   System.out.printf("0x%08X\n", reason);
+ * 
+ */ +public enum ShutdownReason { + SHTDN_REASON_MAJOR_APPLICATION(0x00040000), + SHTDN_REASON_MAJOR_HARDWARE(0x00010000), + SHTDN_REASON_MAJOR_LEGACY_API(0x00070000), + SHTDN_REASON_MAJOR_OPERATINGSYSTEM(0x00020000), + SHTDN_REASON_MAJOR_OTHER(0x00000000), + SHTDN_REASON_MAJOR_POWER(0x00060000), + SHTDN_REASON_MAJOR_SOFTWARE(0x00030000), + SHTDN_REASON_MAJOR_SYSTEM(0x00050000), + + SHTDN_REASON_MINOR_BLUESCREEN(0x0000000F), + SHTDN_REASON_MINOR_CORDUNPLUGGED(0x0000000b), + SHTDN_REASON_MINOR_DISK(0x00000007), + SHTDN_REASON_MINOR_ENVIRONMENT(0x0000000c), + SHTDN_REASON_MINOR_HARDWARE_DRIVER(0x0000000d), + SHTDN_REASON_MINOR_HOTFIX(0x00000011), + SHTDN_REASON_MINOR_HOTFIX_UNINSTALL(0x00000017), + SHTDN_REASON_MINOR_HUNG(0x00000005), + SHTDN_REASON_MINOR_INSTALLATION(0x00000002), + SHTDN_REASON_MINOR_MAINTENANCE(0x00000001), + SHTDN_REASON_MINOR_MMC(0x00000019), + SHTDN_REASON_MINOR_NETWORK_CONNECTIVITY(0x00000014), + SHTDN_REASON_MINOR_NETWORKCARD(0x00000009), + SHTDN_REASON_MINOR_OTHER(0x00000000), + SHTDN_REASON_MINOR_OTHERDRIVER(0x0000000e), + SHTDN_REASON_MINOR_POWER_SUPPLY(0x0000000a), + SHTDN_REASON_MINOR_PROCESSOR(0x00000008), + SHTDN_REASON_MINOR_RECONFIG(0x00000004), + SHTDN_REASON_MINOR_SECURITY(0x00000013), + SHTDN_REASON_MINOR_SECURITYFIX(0x00000012), + SHTDN_REASON_MINOR_SECURITYFIX_UNINSTALL(0x00000018), + SHTDN_REASON_MINOR_SERVICEPACK(0x00000010), + SHTDN_REASON_MINOR_SERVICEPACK_UNINSTALL(0x00000016), + SHTDN_REASON_MINOR_TERMSRV(0x00000020), + SHTDN_REASON_MINOR_UNSTABLE(0x00000006), + SHTDN_REASON_MINOR_UPGRADE(0x00000003), + SHTDN_REASON_MINOR_WMI(0x00000015), + + SHTDN_REASON_FLAG_USER_DEFINED(0x40000000), + SHTDN_REASON_FLAG_PLANNED(0x80000000); + + private final int reasonID; + + ShutdownReason(final int reasonID) { + this.reasonID = reasonID; + } + + public long getReason() { + return reasonID; + } + + public static int getReason(final EnumSet reasons) { + int finalReason = 0; + if (reasons == null) { + return ShutdownReason.getReason(EnumSet.of(ShutdownReason.SHTDN_REASON_MAJOR_OTHER, ShutdownReason.SHTDN_REASON_MINOR_OTHER)); + } + for (ShutdownReason shReason : reasons) { + finalReason |= shReason.getReason(); + } + return finalReason; + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseAbortShutdown.java b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseAbortShutdown.java new file mode 100644 index 00000000..d08f96d2 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseAbortShutdown.java @@ -0,0 +1,63 @@ +/** + * Copyright 2020, Vadim Frolov. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + */ +package com.rapid7.client.dcerpc.initshutdown.messages; + +import java.io.IOException; +import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.messages.EmptyResponse; +import com.rapid7.client.dcerpc.messages.RequestCall; +import com.rapid7.client.dcerpc.objects.WChar; + +/** + * 3.2.4.2 BaseAbortShutdown (Opnum 1)
+ *
+ * The BaseAbortShutdown method is used to terminate the shutdown of the remote computer within the waiting period. + * + *
+ * unsigned long BaseAbortShutdown(
+ *    [in, unique] PREGISTRY_SERVER_NAME ServerName
+ * );
+ * 
+ * + * ServerName: The value may be NULL as the actual server name is taken from the request details. + * Return Values: The method returns 0 (ERROR_SUCCESS) to indicate success; otherwise, it returns a nonzero error code. + * + * @see 3.2.4.2 BaseAbortShutdown (Opnum 1) + */ + +public class BaseAbortShutdown extends RequestCall { + private final WChar.NullTerminated serverName; + + public BaseAbortShutdown(final WChar.NullTerminated serverName) { + super((short) 1); + this.serverName = serverName; + } + + @Override + public EmptyResponse getResponseObject() { + return new EmptyResponse(); + } + + @Override + public void marshal(PacketOutput packetOut) throws IOException { + if (packetOut.writeReferentID(this.serverName)) { + packetOut.writeMarshallable(serverName); + } + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequest.java b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequest.java new file mode 100644 index 00000000..e450fc87 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequest.java @@ -0,0 +1,93 @@ +/** + * Copyright 2020, Vadim Frolov. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + */ +package com.rapid7.client.dcerpc.initshutdown.messages; + +import java.io.IOException; +import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; +import com.rapid7.client.dcerpc.messages.EmptyResponse; +import com.rapid7.client.dcerpc.messages.RequestCall; +import com.rapid7.client.dcerpc.objects.RegUnicodeString; +import com.rapid7.client.dcerpc.objects.WChar; + +/** + * 3.2.4.1 BaseInitiateShutdown (Opnum 0)
+ *
+ * The BaseInitiateShutdown method is used to initiate the shutdown of the remote computer. + * + *
+ * unsigned long BaseInitiateShutdown(
+ *    [in, unique] PREGISTRY_SERVER_NAME ServerName,
+ *    [in, unique] PREG_UNICODE_STRING lpMessage,
+ *    [in] unsigned long dwTimeout,
+ *    [in] unsigned char bForceAppsClosed,
+ *    [in] unsigned char bRebootAfterShutdown
+ * );
+ * 
+ * + * Return values: Return Values: The method returns ERROR_SUCCESS (0x00000000) on success; otherwise, it returns + * a nonzero error code. + * + * @see 3.2.4.1 BaseInitiateShutdown (Opnum 0) + */ +public class BaseInitiateShutdownRequest extends RequestCall { + private final WChar.NullTerminated serverName; + private final RegUnicodeString.NullTerminated messageToUser; + private final int timeout; + private final boolean forceAppsClosed; + private final boolean rebootAfterShutdown; + + public BaseInitiateShutdownRequest(final WChar.NullTerminated serverName, final RegUnicodeString.NullTerminated messageToUser, final int timeout, final boolean forceAppsClosed, final boolean rebootAfterShutdown) { + super((short) 0); + this.serverName = serverName; + this.messageToUser = messageToUser; + this.timeout = timeout; + this.forceAppsClosed = forceAppsClosed; + this.rebootAfterShutdown = rebootAfterShutdown; + } + + @Override + public EmptyResponse getResponseObject() { + return new EmptyResponse(); + } + + @Override + public void marshal(PacketOutput packetOut) throws IOException { + // Server name is a pointer, thus writeReferentID. + // Alignment is by four for structs and variable-length data. + if (packetOut.writeReferentID(this.serverName)) { + packetOut.writeMarshallable(serverName); + packetOut.align(Alignment.FOUR); + } + + // [in, unique] PREG_UNICODE_STRING lpMessage + if (packetOut.writeReferentID(this.messageToUser)) { + packetOut.writeMarshallable(messageToUser); + packetOut.align(Alignment.FOUR); + } + + // [in] unisnged long dwTimeout + packetOut.writeInt(timeout); + + packetOut.align(Alignment.ONE); + packetOut.writeBoolean(forceAppsClosed); + // Alignment: 1 - Already aligned + packetOut.writeBoolean(rebootAfterShutdown); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequestEx.java b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequestEx.java new file mode 100644 index 00000000..0b0143af --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequestEx.java @@ -0,0 +1,102 @@ +/** + * Copyright 2020, Vadim Frolov. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + */ +package com.rapid7.client.dcerpc.initshutdown.messages; + +import java.io.IOException; +import java.util.EnumSet; +import com.rapid7.client.dcerpc.initshutdown.dto.ShutdownReason; +import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; +import com.rapid7.client.dcerpc.messages.EmptyResponse; +import com.rapid7.client.dcerpc.messages.RequestCall; +import com.rapid7.client.dcerpc.objects.RegUnicodeString; +import com.rapid7.client.dcerpc.objects.WChar; + +/** + * 3.2.4.3 BaseInitiateShutdownEx (Opnum 2)
+ *
+ * The BaseInitiateShutdownEx method is used to initiate the shutdown of the remote computer. + * + *
+ * unsigned long BaseInitiateShutdown(
+ *    [in, unique] PREGISTRY_SERVER_NAME ServerName,
+ *    [in, unique] PREG_UNICODE_STRING lpMessage,
+ *    [in] unsigned long dwTimeout,
+ *    [in] unsigned char bForceAppsClosed,
+ *    [in] unsigned char bRebootAfterShutdown,
+ *    [in] unsingned long dwReason
+ * );
+ * 
+ * + * Return values: Return Values: The method returns ERROR_SUCCESS (0x00000000) on success; otherwise, it returns + * a nonzero error code. + * + * @see 3.2.4.3 BaseInitiateShutdownEx (Opnum 2) + */ +public class BaseInitiateShutdownRequestEx extends RequestCall { + private final WChar.NullTerminated serverName; + private final RegUnicodeString.NullTerminated messageToUser; + private final int timeout; + private final boolean forceAppsClosed; + private final boolean rebootAfterShutdown; + private final EnumSet reasons; + + public BaseInitiateShutdownRequestEx(final WChar.NullTerminated serverName, final RegUnicodeString.NullTerminated messageToUser, final int timeout, final boolean forceAppsClosed, final boolean rebootAfterShutdown, final EnumSet reasons) { + super((short) 2); + this.serverName = serverName; + this.messageToUser = messageToUser; + this.timeout = timeout; + this.forceAppsClosed = forceAppsClosed; + this.rebootAfterShutdown = rebootAfterShutdown; + this.reasons = reasons; + } + + @Override + public EmptyResponse getResponseObject() { + return new EmptyResponse(); + } + + @Override + public void marshal(PacketOutput packetOut) throws IOException { + // Server name is a pointer, thus writeReferentID. + // Alignment is by four for structs and variable-length data. + if (packetOut.writeReferentID(this.serverName)) { + packetOut.writeMarshallable(serverName); + packetOut.align(Alignment.FOUR); + } + + // [in, unique] PREG_UNICODE_STRING lpMessage + if (packetOut.writeReferentID(this.messageToUser)) { + packetOut.writeMarshallable(messageToUser); + packetOut.align(Alignment.FOUR); + } + + // [in] unisnged long dwTimeout + packetOut.writeInt(timeout); + + packetOut.align(Alignment.ONE); + packetOut.writeBoolean(forceAppsClosed); + // Alignment: 1 - Already aligned + packetOut.writeBoolean(rebootAfterShutdown); + + // [in] unisnged long dwReason + packetOut.align(Alignment.FOUR); + packetOut.writeInt(ShutdownReason.getReason(reasons)); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveOutput.java b/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveOutput.java index ec5bd26f..9a07fb2a 100644 --- a/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveOutput.java +++ b/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveOutput.java @@ -109,4 +109,10 @@ public void writeBytes(final String s) throws IOException { public void writeChars(final String s) throws IOException { dataOut.writeChars(s); } + + public void writeCharsAsShort(final String s) throws IOException { + for (int i = 0; i < s.length(); i++) { + dataOut.writeShort(s.charAt(i)); + } + } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRPolicyAuditEventsInfo.java b/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRPolicyAuditEventsInfo.java index 3d866c53..17417bef 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRPolicyAuditEventsInfo.java +++ b/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRPolicyAuditEventsInfo.java @@ -26,11 +26,13 @@ import com.rapid7.client.dcerpc.io.ndr.Unmarshallable; /** - * Alignment: 4 (Max[1,4,4])
+ * Alignment: 4 (Max[1,4,4])
+ * 
  *      unsigned char AuditingMode;: 1
  *      [size_is(MaximumAuditEventCount)] unsigned long* EventAuditingOptions;: 4
- *      [range(0,1000)] unsigned long MaximumAuditEventCount;: 4
- * LSAPR_POLICY_AUDIT_EVENTS_INFO + * [range(0,1000)] unsigned long MaximumAuditEventCount;: 4 + *
+ * LSAPR_POLICY_AUDIT_EVENTS_INFO *
  * The LSAPR_POLICY_AUDIT_EVENTS_INFO structure contains auditing options on the server.
  *      typedef struct _LSAPR_POLICY_AUDIT_EVENTS_INFO {
diff --git a/src/main/java/com/rapid7/client/dcerpc/objects/RegUnicodeString.java b/src/main/java/com/rapid7/client/dcerpc/objects/RegUnicodeString.java
new file mode 100644
index 00000000..b72d93ba
--- /dev/null
+++ b/src/main/java/com/rapid7/client/dcerpc/objects/RegUnicodeString.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2020, Vadim Frolov.
+ *
+ * License: BSD-3-clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ */
+package com.rapid7.client.dcerpc.objects;
+
+import java.io.IOException;
+import java.util.Objects;
+import com.rapid7.client.dcerpc.io.PacketInput;
+import com.rapid7.client.dcerpc.io.PacketOutput;
+import com.rapid7.client.dcerpc.io.ndr.Alignment;
+import com.rapid7.client.dcerpc.io.ndr.Marshallable;
+import com.rapid7.client.dcerpc.io.ndr.Unmarshallable;
+
+/**
+ * Represents a counted string of Unicode (UTF-16) characters.
+ * 
+ * Alignment 4:
+ *    unsigned short Length;: 2
+ *    unsigned short MaximumLength;: 2
+ *    [size_is(MaximumLength/2), length_is(Length/2)] unsigned short* Buffer;: 4
+ *
+ * RegUnicodeString: + *
+ *  The RegUnicodeString structure specifies a Unicode string. This structure is defined in IDL as follows:
+ *      typedef struct _REG_UNICODE_STRING {
+ *          unsigned short Length;
+ *          unsigned short MaximumLength;
+ *          [size_is(MaximumLength/2), length_is(Length/2)] unsigned short* Buffer;
+ *      } REG_UNICODE_STRING,
+ *      *PREG_UNICODE_STRING;
+ *  Length: The number of bytes actually used by the string. Because all UTF-16 characters occupy 2 bytes, this MUST be an even number in the range [0...65534]. The behavior for odd values is unspecified.
+ *  MaximumLength: The number of bytes allocated for the string. This MUST be an even number in the range [Length...65534].
+ *  Buffer:  The Unicode UTF-16 characters comprising the string described by the structure. Note that counted strings might be terminated by a 0x0000 character, by convention; if such a terminator is present, it SHOULD NOT count toward the Length (but MUST, of course, be included in the MaximumLength).
+ * 
+ * NOTE: This class is based on RPCUnicodeString. + *
+ * An REG_UNICODE_STRING can be null terminated. However this is abstracted away from the client and is only + * used during marshalling or unmarshalling. + * You should not provide a null terminator to your String when marshalling this object, and should + * not expect one in return. + *
+ * Marshalling Usage:
+ *      String myValue = "some string";
+ *      RegUnicodeString regUnicodeString = RegUnicodeString.NullTerminated.of(myValue);
+ *      packetOut.writeMarshallable(regUnicodeString);
+ * Unmarshalling Usage:
+ *      RegUnicodeString regUnicodeString = new RegUnicodeString.NullTerminated();
+ *      packetIn.readUnmarshallable(regUnicodeString);
+ *      String myValue = regUnicodeString.getValue();
+ */ +public abstract class RegUnicodeString implements Unmarshallable, Marshallable { + + /** + * An REG_UNICODE_STRING which is expected to be null terminated during marshalling/unmarshalling. + */ + public static class NullTerminated extends RegUnicodeString { + /** + * @param value The value; may be null. + * @return A new {@link NullTerminated} {@link RegUnicodeString} with the provided value. + */ + public static NullTerminated of(String value) { + final NullTerminated str = new NullTerminated(); + str.setValue(value); + return str; + } + + @Override + ShortChar createShortChar() { + return new ShortChar.NullTerminated(); + } + } + + /** + * An REG_UNICODE_STRING which is not expected to be null terminated during marshalling/unmarshalling. + */ + public static class NonNullTerminated extends RegUnicodeString { + /** + * @param value The value; may be null. + * @return A new {@link NonNullTerminated} {@link RegUnicodeString} with the provided value. + */ + public static NonNullTerminated of(String value) { + final NonNullTerminated str = new NonNullTerminated(); + str.setValue(value); + return str; + } + + @Override + ShortChar createShortChar() { + return new ShortChar.NonNullTerminated(); + } + } + + private ShortChar shortChar; + + abstract ShortChar createShortChar(); + + /** + * @return The {@link String} representation of this {@link RPCUnicodeString}. + * May be null. Will never include a null terminator. + */ + public String getValue() { + if (this.shortChar == null) return null; + return this.shortChar.getValue(); + } + + /** + * @param value The {@link String} representation for this {@link RPCUnicodeString}. + * May be null. Must not include a null terminator. + */ + public void setValue(String value) { + if (value == null) { + this.shortChar = null; + } else { + this.shortChar = createShortChar(); + this.shortChar.setValue(value); + } + } + + @Override + public void marshalPreamble(PacketOutput out) throws IOException { + // No preamble. Conformant array of `unsigned short*` is a reference, and so preamble is not required. + } + + @Override + public void marshalEntity(PacketOutput out) throws IOException { + // Structure Alignment + out.align(Alignment.FOUR); + if (this.shortChar == null) { + // unsigned short Length; + // Alignment 2 - Already aligned + out.writeShort(0); + // unsigned short MaximumLength; + // Alignment 2 - Already aligned + out.writeShort(0); + } else { + // UTF-16 encoded string is 2 bytes per count point + // Null terminator must also be considered + final int byteLength = 2 * this.shortChar.getValue().length(); + final int maxLength = byteLength + (this.shortChar.isNullTerminated() ? 2 : 0); + // unsigned short Length; + // Alignment 2 - Already aligned + out.writeShort(byteLength); + // unsigned short MaximumLength; + // Alignment 2 - Already aligned + out.writeShort(maxLength); + } + // [size_is(MaximumLength/2), length_is(Length/2)] WCHAR* Buffer; + // Alignment 4 - Already aligned + out.writeReferentID(this.shortChar); + } + + @Override + public void marshalDeferrals(PacketOutput out) throws IOException { + if (this.shortChar != null) { + out.writeMarshallable(this.shortChar); + } + } + + @Override + public void unmarshalPreamble(PacketInput in) throws IOException { + // No preamble. Conformant array of `WCHAR*` is a reference, and so preamble is not required. + } + + @Override + public void unmarshalEntity(PacketInput in) throws IOException { + // Structure Alignment: 4 + in.align(Alignment.FOUR); + // unsigned short Length; + // Alignment: 2 - Already aligned + in.fullySkipBytes(2); + // unsigned short MaximumLength; + // Alignment: 2 - Already aligned + in.fullySkipBytes(2); + // [size_is(MaximumLength/2), length_is(Length/2)] WCHAR* Buffer; + // Alignment: 4 - Already aligned + if (in.readReferentID() != 0) this.shortChar = createShortChar(); + else this.shortChar = null; + } + + @Override + public void unmarshalDeferrals(PacketInput in) throws IOException { + if (this.shortChar != null) { + in.readUnmarshallable(this.shortChar); + } + } + + @Override + public int hashCode() { + return Objects.hash(shortChar); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (!(obj instanceof RPCUnicodeString)) { + return false; + } + return Objects.equals(shortChar, ((RegUnicodeString) obj).shortChar); + } + + @Override + public String toString() { + return getValue() == null ? "null" : String.format("\"%s\"", getValue()); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/objects/ShortChar.java b/src/main/java/com/rapid7/client/dcerpc/objects/ShortChar.java new file mode 100644 index 00000000..c93638d4 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/objects/ShortChar.java @@ -0,0 +1,220 @@ +/* + * Copyright 2020, Vadim Frolov. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + */ +package com.rapid7.client.dcerpc.objects; + +import java.io.IOException; +import java.rmi.UnmarshalException; +import java.util.Objects; +import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; +import com.rapid7.client.dcerpc.io.ndr.Marshallable; +import com.rapid7.client.dcerpc.io.ndr.Unmarshallable; + +/** + * Represents a UTF-16 encoded unicode string as a character array. + * Alignment: 4 + * + * Marshalling Usage:
+ *      String myValue = "some string";
+ *      ShortChar wChar = ShortChar.NonNullTerminated.of(myValue);
+ *      packetOut.writeMarshallable(wChar);
+ * Unmarshalling Usage:
+ *      ShortChar wChar = new ShortChar.NonNullTerminated();
+ *      packetIn.readUnmarshallable(wChar);
+ *      String myValue = wChar.getValue();
+ */ +public abstract class ShortChar implements Unmarshallable, Marshallable { + + /** + * An ShortChar which is expected to be null terminated during marshalling/unmarshalling. + */ + public static class NullTerminated extends ShortChar { + /** + * @param value The value, must not be null. + * @return A new {@link NullTerminated} {@link ShortChar} with the provided value. + */ + public static NullTerminated of(String value) { + final NullTerminated ret = new NullTerminated(); + ret.setValue(value); + return ret; + } + + @Override + public boolean isNullTerminated() { + return true; + } + } + + /** + * An ShortChar which is not expected to be null terminated during marshalling/unmarshalling. + */ + public static class NonNullTerminated extends ShortChar { + /** + * @param value The value, must not be null. + * @return A new {@link NonNullTerminated} {@link ShortChar} with the provided value. + */ + public static NonNullTerminated of(String value) { + final NonNullTerminated ret = new NonNullTerminated(); + ret.setValue(value); + return ret; + } + + @Override + public boolean isNullTerminated() { + return false; + } + } + + private String value = ""; + // Stored for unmarshalling purposes only + private int offset; + private int actualCount; + + public abstract boolean isNullTerminated(); + + /** + * @return The non-null String representation of this {@link ShortChar}. + */ + public String getValue() { + return this.value; + } + + /** + * @param value The non-null String representation for this {@link ShortChar}. + */ + public void setValue(String value) { + if (value == null) { + throw new IllegalArgumentException("Expected non-null value"); + } + this.value = value; + } + + @Override + public void marshalPreamble(PacketOutput out) throws IOException { + // MaximumCount for conformant array + out.align(Alignment.FOUR); + out.writeInt(getCodePoints()); + } + + @Override + public void marshalEntity(PacketOutput out) throws IOException { + // Structure Alignment: 4 + out.align(Alignment.FOUR); + // Offset for varying array + // Alignment 4 - Already aligned + out.writeInt(0); + // Actual content length for varying array + // Alignment 4 - Already aligned + out.writeInt(getContentLength()); + } + + @Override + public void marshalDeferrals(PacketOutput out) throws IOException { + // Entities for conformant+varying array + // Alignment 1 - Already aligned + out.writeCharsAsShort(value); + if (isNullTerminated()) out.writeShort(0); + } + + @Override + public void unmarshalPreamble(PacketInput in) throws IOException { + // MaximumCount for conformant array + in.align(Alignment.FOUR); + in.fullySkipBytes(4); + } + + @Override + public void unmarshalEntity(PacketInput in) throws IOException { + // Structure Alignment: 4 + in.align(Alignment.FOUR); + // Offset for varying array + // Alignment 4 - Already aligned + this.offset = readIndex("Offset", in); + // ActualCount for varying array + // Alignment 4 - Already aligned + this.actualCount = readIndex("ActualCount", in); + } + + @Override + public void unmarshalDeferrals(PacketInput in) throws IOException { + // Read prefix (if any) + in.align(Alignment.TWO); + in.fullySkipBytes(2 * offset); + // Entities for conformant array + // If we expect a null terminator, then skip it when reading the string + final int length; + final boolean nullTerminated; + if (isNullTerminated() && this.actualCount > 0) { + length = this.actualCount - 1; + nullTerminated = true; + } else { + length = this.actualCount; + nullTerminated = false; + } + final StringBuilder sb = new StringBuilder(length); + for (int i = 0; i < length; i++) { + // + // Alignment: 2 - Already aligned + sb.append(in.readByte()); + } + this.value = sb.toString(); + // Skip null terminator (if any) + // Alignment: 2 - Already aligned + if (nullTerminated) in.fullySkipBytes(2); + } + + @Override + public int hashCode() { + return Objects.hash(isNullTerminated(), getValue()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (!(obj instanceof ShortChar)) { + return false; + } + final ShortChar other = (ShortChar) obj; + return isNullTerminated() == other.isNullTerminated() && Objects.equals(getValue(), other.getValue()); + } + + @Override + public String toString() { + return getValue() == null ? "null" : String.format("\"%s\"", getValue()); + } + + private int getCodePoints() { + return getValue().length() + (isNullTerminated() ? 1 : 0); + } + + private int getContentLength() { + return getValue().length(); + } + + private int readIndex(String name, PacketInput in) throws IOException { + final long ret = in.readUnsignedInt(); + // Don't allow array length or index values bigger than signed int + if (ret > Integer.MAX_VALUE) { + throw new UnmarshalException(String.format("%s %d > %d", name, ret, Integer.MAX_VALUE)); + } + return (int) ret; + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/transport/SMBTransportFactories.java b/src/main/java/com/rapid7/client/dcerpc/transport/SMBTransportFactories.java index 7b272946..a40e658c 100644 --- a/src/main/java/com/rapid7/client/dcerpc/transport/SMBTransportFactories.java +++ b/src/main/java/com/rapid7/client/dcerpc/transport/SMBTransportFactories.java @@ -37,7 +37,8 @@ public enum SMBTransportFactories { LSASVC("lsarpc", Interface.LSASVC_V0_0, Interface.NDR_32BIT_V2), SAMSVC("samr", Interface.SAMSVC_V1_0, Interface.NDR_32BIT_V2), BROWSER_SRVSVC("browser", Interface.SRVSVC_V3_0, Interface.NDR_32BIT_V2), - SVCCTL("svcctl", Interface.SVCCTL_V2_0, Interface.NDR_32BIT_V2); + SVCCTL("svcctl", Interface.SVCCTL_V2_0, Interface.NDR_32BIT_V2), + INITSHUTDOWN("InitShutdown", Interface.INITSHUTDOWN_V1_0, Interface.NDR_32BIT_V2); private final static int STATUS_PIPE_NOT_AVAILABLE_BACKOFF_TIME_MS = 3000; private final static int STATUS_PIPE_NOT_AVAILABLE_RETRIES = 1; diff --git a/src/main/java/com/rapid7/usage/ShutdownExample.java b/src/main/java/com/rapid7/usage/ShutdownExample.java new file mode 100644 index 00000000..5faaf64c --- /dev/null +++ b/src/main/java/com/rapid7/usage/ShutdownExample.java @@ -0,0 +1,54 @@ +package com.rapid7.usage; + +import com.hierynomus.smbj.SMBClient; +import com.hierynomus.smbj.auth.AuthenticationContext; +import com.hierynomus.smbj.connection.Connection; +import com.hierynomus.smbj.session.Session; +import com.rapid7.client.dcerpc.initshutdown.ShutdownService; +import com.rapid7.client.dcerpc.initshutdown.dto.ShutdownReason; +import com.rapid7.client.dcerpc.transport.RPCTransport; +import com.rapid7.client.dcerpc.transport.SMBTransportFactories; + +import java.io.IOException; +import java.util.EnumSet; + +public class ShutdownExample { + public static void main(String[] args) { + final SMBClient smbClient = new SMBClient(); + + // TODO: Change the values below! + final String username = ""; + final String pwd = ""; + final String domain = "WORKGROUP"; + final String serverAddress = "0.0.0.0"; + final String msg = "Bye-Bye"; + // seconds + final int timeout = 30; + final boolean forceAppsClosed = true; + final boolean reboot = false; + EnumSet flags = EnumSet.of(ShutdownReason.SHTDN_REASON_MAJOR_APPLICATION, + ShutdownReason.SHTDN_REASON_MINOR_BLUESCREEN, ShutdownReason.SHTDN_REASON_FLAG_PLANNED); + + try { + final Connection smbConnection = smbClient.connect(serverAddress); + final AuthenticationContext smbAuthenticationContext = new AuthenticationContext( + username, pwd.toCharArray(), domain); + final Session session = smbConnection.authenticate(smbAuthenticationContext); + + final RPCTransport transport = SMBTransportFactories.INITSHUTDOWN.getTransport(session); + final ShutdownService shutdownService = new ShutdownService(transport); + + shutdownService.shutdown(msg, timeout, forceAppsClosed, reboot); + // Call abort right after shutdown. Just for usage demonstration. + shutdownService.abortShutdown(); + + shutdownService.shutdownEx(msg, timeout, forceAppsClosed, reboot, flags); + // Call abort right after shutdown. Just for usage demonstration. + shutdownService.abortShutdown(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/test/java/com/rapid7/client/dcerpc/Test_Header.java b/src/test/java/com/rapid7/client/dcerpc/Test_Header.java index 0aac54e8..d048b5a3 100644 --- a/src/test/java/com/rapid7/client/dcerpc/Test_Header.java +++ b/src/test/java/com/rapid7/client/dcerpc/Test_Header.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.util.EnumSet; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -33,8 +34,6 @@ import static org.junit.Assert.assertEquals; public class Test_Header { - @Rule - public final ExpectedException thrown = ExpectedException.none(); @Test public void getMajorVersion() throws IOException { @@ -187,27 +186,31 @@ public void marshal() throws IOException { @Test public void marshalNoPDUType() throws IOException { - thrown.expect(IllegalStateException.class); - thrown.expectMessage("Invalid PDU type: null"); + try { + final Header header = new Header(); + final ByteArrayOutputStream packetOutputStream = new ByteArrayOutputStream(); + final PacketOutput packetOut = new PacketOutput(packetOutputStream); - final Header header = new Header(); - final ByteArrayOutputStream packetOutputStream = new ByteArrayOutputStream(); - final PacketOutput packetOut = new PacketOutput(packetOutputStream); - - header.marshal(packetOut); + header.marshal(packetOut); + Assert.fail(); + } catch (IllegalStateException ex) { + Assert.assertEquals("Invalid PDU type: null", ex.getMessage()); + } } @Test public void marshalNoPFCFlags() throws IOException { - thrown.expect(IllegalStateException.class); - thrown.expectMessage("Invalid PFC flag(s): null"); - - final Header header = new Header(); - final ByteArrayOutputStream packetOutputStream = new ByteArrayOutputStream(); - final PacketOutput packetOut = new PacketOutput(packetOutputStream); - - header.setPDUType(PDUType.ACK); - header.marshal(packetOut); + try { + final Header header = new Header(); + final ByteArrayOutputStream packetOutputStream = new ByteArrayOutputStream(); + final PacketOutput packetOut = new PacketOutput(packetOutputStream); + + header.setPDUType(PDUType.ACK); + header.marshal(packetOut); + Assert.fail(); + } catch (IllegalStateException ex) { + Assert.assertEquals("Invalid PFC flag(s): null", ex.getMessage()); + } } private Header unmarshalHeader(final String hexString) throws IOException { diff --git a/src/test/java/com/rapid7/client/dcerpc/initshutdown/Test_ShutdownService.java b/src/test/java/com/rapid7/client/dcerpc/initshutdown/Test_ShutdownService.java new file mode 100644 index 00000000..f1e0d192 --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/initshutdown/Test_ShutdownService.java @@ -0,0 +1,63 @@ +/** + * Copyright 2020, Vadim Frolov. + *

+ * License: BSD-3-clause + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + *

+ * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + *

+ * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + */ +package com.rapid7.client.dcerpc.initshutdown; + +import java.io.IOException; +import org.testng.annotations.Test; +import com.rapid7.client.dcerpc.messages.EmptyResponse; +import com.rapid7.client.dcerpc.messages.RequestCall; +import com.rapid7.client.dcerpc.transport.RPCTransport; + +import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.ERROR_SUCCESS; +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +public class Test_ShutdownService { + @Test(expectedExceptions = {IllegalArgumentException.class}, expectedExceptionsMessageRegExp = "Expecting non-null transport") + public void constructorNullTransport() { + new ShutdownService(null); + } + + @Test + public void isRequestCorrect() throws IOException { + final RPCTransport transport = mock(RPCTransport.class); + final EmptyResponse response = mock(EmptyResponse.class); + final ShutdownService service = new ShutdownService(transport); + + when(transport.call(any(RequestCall.class))).thenReturn(response); + when(response.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); + + final String msg = "Bye-Bye"; + final int timeout = 130; + final boolean forceAppsClosed = true; + final boolean reboot = true; + + final int returnCode = service.shutdown(msg, timeout, forceAppsClosed, reboot); + assertEquals(returnCode, ERROR_SUCCESS.getValue()); + + verify(transport, times(1)).call(any(RequestCall.class)); + verify(response, times(2)).getReturnValue(); + verifyNoMoreInteractions(transport, response); + } +} diff --git a/src/test/java/com/rapid7/client/dcerpc/initshutdown/dto/Test_ShutdownReason.java b/src/test/java/com/rapid7/client/dcerpc/initshutdown/dto/Test_ShutdownReason.java new file mode 100644 index 00000000..eb19307c --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/initshutdown/dto/Test_ShutdownReason.java @@ -0,0 +1,66 @@ +/** + * Copyright 2020, Vadim Frolov. + *

+ * License: BSD-3-clause + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + *

+ * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + *

+ * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + */ +package com.rapid7.client.dcerpc.initshutdown.dto; + +import java.util.EnumSet; +import org.junit.Test; + +import static com.rapid7.client.dcerpc.initshutdown.dto.ShutdownReason.SHTDN_REASON_MAJOR_APPLICATION; +import static com.rapid7.client.dcerpc.initshutdown.dto.ShutdownReason.SHTDN_REASON_MAJOR_POWER; +import static com.rapid7.client.dcerpc.initshutdown.dto.ShutdownReason.SHTDN_REASON_MAJOR_SOFTWARE; +import static com.rapid7.client.dcerpc.initshutdown.dto.ShutdownReason.SHTDN_REASON_MINOR_DISK; +import static org.junit.Assert.assertEquals; + +public class Test_ShutdownReason { + @Test + public void MAJOR_APPLICATION_getReason() { + assertEquals(0x00040000, SHTDN_REASON_MAJOR_APPLICATION.getReason()); + } + + @Test + public void MAJOR_MINOR_OPTIONAL() { + final int expected = 0x8004000F; + final EnumSet flags = EnumSet.of(ShutdownReason.SHTDN_REASON_MAJOR_APPLICATION, ShutdownReason.SHTDN_REASON_MINOR_BLUESCREEN, ShutdownReason.SHTDN_REASON_FLAG_PLANNED); + final int actual = ShutdownReason.getReason(flags); + assertEquals(expected, actual); + } + + @Test + public void MAJOR_POWER() { + final int expected = 0x00060000; + final EnumSet flags = EnumSet.of(SHTDN_REASON_MAJOR_POWER); + final int actual = ShutdownReason.getReason(flags); + assertEquals(expected, actual); + } + + @Test + public void SOFTWARE_DISK() { + final int expected = 0x00030007; + final EnumSet flags = EnumSet.of(SHTDN_REASON_MAJOR_SOFTWARE, SHTDN_REASON_MINOR_DISK); + final int actual = ShutdownReason.getReason(flags); + assertEquals(expected, actual); + } + + @Test + public void NullReason() { + final int expected = 0; + final int actual = ShutdownReason.getReason(null); + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseAbortShutdown.java b/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseAbortShutdown.java new file mode 100644 index 00000000..ec545b61 --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseAbortShutdown.java @@ -0,0 +1,49 @@ +/** + * Copyright 2020, Vadim Frolov. + *

+ * License: BSD-3-clause + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + *

+ * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + *

+ * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + */ +package com.rapid7.client.dcerpc.initshutdown.messages; + +import java.io.IOException; +import org.junit.Test; +import com.rapid7.client.dcerpc.messages.EmptyResponse; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class Test_BaseAbortShutdown { + private final BaseAbortShutdown request = new BaseAbortShutdown(null); + + @Test + public void getOpNum() { + assertEquals(1, request.getOpNum()); + } + + @Test + public void getStub() throws IOException { + // getStub returns a pointer, which is different on every run + assertTrue(true); + System.out.println(request.getStub()); + } + + @Test + public void getResponseObject() throws IOException { + assertThat(request.getResponseObject(), instanceOf(EmptyResponse.class)); + } +} diff --git a/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseInitiateShutdownRequest.java b/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseInitiateShutdownRequest.java new file mode 100644 index 00000000..84b5e984 --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseInitiateShutdownRequest.java @@ -0,0 +1,51 @@ +/** + * Copyright 2020, Vadim Frolov. + *

+ * License: BSD-3-clause + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + *

+ * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + *

+ * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + */ +package com.rapid7.client.dcerpc.initshutdown.messages; + +import java.io.IOException; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; +import com.rapid7.client.dcerpc.messages.EmptyResponse; +import com.rapid7.client.dcerpc.objects.RegUnicodeString; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +public class Test_BaseInitiateShutdownRequest { + // Actual bytes in the request + private final byte[] defaultStub = Hex.decode("000000000000020000000000000000001e0000000100"); + private final BaseInitiateShutdownRequest request = new BaseInitiateShutdownRequest(null, RegUnicodeString.NullTerminated.of(null), 30, true, false); + + @Test + public void getOpNum() { + assertEquals(0, request.getOpNum()); + } + + @Test + public void getStub() throws IOException { + assertArrayEquals(defaultStub, request.getStub()); + } + + @Test + public void getResponseObject() throws IOException { + assertThat(request.getResponseObject(), instanceOf(EmptyResponse.class)); + } +} diff --git a/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseInitiateShutdownRequestEx.java b/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseInitiateShutdownRequestEx.java new file mode 100644 index 00000000..306d762a --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseInitiateShutdownRequestEx.java @@ -0,0 +1,53 @@ +/** + * Copyright 2020, Vadim Frolov. + *

+ * License: BSD-3-clause + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + *

+ * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + *

+ * * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + */ +package com.rapid7.client.dcerpc.initshutdown.messages; + +import java.io.IOException; +import java.util.EnumSet; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; +import com.rapid7.client.dcerpc.initshutdown.dto.ShutdownReason; +import com.rapid7.client.dcerpc.messages.EmptyResponse; +import com.rapid7.client.dcerpc.objects.RegUnicodeString; + +import static org.bouncycastle.util.encoders.Hex.toHexString; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + +public class Test_BaseInitiateShutdownRequestEx { + // Actual bytes in the request + private final byte[] stub = Hex.decode("000000000000020000000000000000001e000000010000000a000680"); + private final BaseInitiateShutdownRequestEx request = new BaseInitiateShutdownRequestEx(null, RegUnicodeString.NullTerminated.of(null), 30, true, false, EnumSet.of(ShutdownReason.SHTDN_REASON_MAJOR_POWER, ShutdownReason.SHTDN_REASON_MINOR_POWER_SUPPLY, ShutdownReason.SHTDN_REASON_FLAG_PLANNED)); + + @Test + public void getOpNum() { + assertEquals(2, request.getOpNum()); + } + + @Test + public void getStub() throws IOException { + assertEquals(toHexString(stub), toHexString(request.getStub())); + } + + @Test + public void getResponseObject() throws IOException { + assertThat(request.getResponseObject(), instanceOf(EmptyResponse.class)); + } +} diff --git a/src/test/java/com/rapid7/client/dcerpc/messages/Test_Request.java b/src/test/java/com/rapid7/client/dcerpc/messages/Test_Request.java index c2cbcb2a..dc07a67d 100644 --- a/src/test/java/com/rapid7/client/dcerpc/messages/Test_Request.java +++ b/src/test/java/com/rapid7/client/dcerpc/messages/Test_Request.java @@ -22,6 +22,7 @@ import java.util.EnumSet; import org.junit.Rule; import org.junit.Test; +import org.junit.Assert; import org.junit.rules.ExpectedException; import com.rapid7.client.dcerpc.PDUType; import com.rapid7.client.dcerpc.PFCFlag; @@ -29,39 +30,37 @@ import static org.junit.Assert.*; public class Test_Request { - @Rule - public final ExpectedException thrown = ExpectedException.none(); @Test public void pduType() { final Request request = new Request(); - assertEquals(PDUType.REQUEST, request.getPDUType()); + Assert.assertEquals(PDUType.REQUEST, request.getPDUType()); } @Test public void getOpNum() { final Request request = new Request(); - assertEquals(0, request.getOpNum()); + Assert.assertEquals(0, request.getOpNum()); } @Test public void getStub() { final Request request = new Request(); - assertNull(request.getStub()); + Assert.assertNull(request.getStub()); } @Test public void setOpNum() { final Request request = new Request(); request.setOpNum((short) 1); - assertEquals(1, request.getOpNum()); + Assert.assertEquals(1, request.getOpNum()); } @Test public void setStub() { final Request request = new Request(); request.setStub(new byte[]{0x00}); - assertArrayEquals(new byte[]{0x00}, request.getStub()); + Assert.assertArrayEquals(new byte[]{0x00}, request.getStub()); } @Test @@ -71,25 +70,29 @@ public void marshal() throws IOException { request.setPFCFlags(EnumSet.of(PFCFlag.FIRST_FRAGMENT, PFCFlag.LAST_FRAGMENT)); request.setStub(new byte[0]); - assertEquals("050000031000000018000000000000000000000000000000", request.toHexString()); + Assert.assertEquals("050000031000000018000000000000000000000000000000", request.toHexString()); } @Test public void marshalNullStub() throws IOException { - thrown.expect(IllegalStateException.class); - thrown.expectMessage("Invalid stub: null"); - - final Request request = new Request(); - - request.setPFCFlags(EnumSet.of(PFCFlag.FIRST_FRAGMENT, PFCFlag.LAST_FRAGMENT)); - request.toHexString(); + try { + final Request request = new Request(); + + request.setPFCFlags(EnumSet.of(PFCFlag.FIRST_FRAGMENT, PFCFlag.LAST_FRAGMENT)); + request.toHexString(); + Assert.fail(); + } catch (IllegalStateException ex) { + Assert.assertEquals("Invalid stub: null", ex.getMessage()); + } } @Test public void unmarshal() throws IOException { - thrown.expect(UnsupportedOperationException.class); - thrown.expectMessage("Unmarshal Not Implemented."); - - new Request().unmarshal(null); + try { + new Request().unmarshal(null); + Assert.fail(); + } catch (UnsupportedOperationException ex) { + Assert.assertEquals("Unmarshal Not Implemented.", ex.getMessage()); + } } } diff --git a/src/test/java/com/rapid7/client/dcerpc/messages/Test_Response.java b/src/test/java/com/rapid7/client/dcerpc/messages/Test_Response.java index 6e8007ee..8ed734c4 100644 --- a/src/test/java/com/rapid7/client/dcerpc/messages/Test_Response.java +++ b/src/test/java/com/rapid7/client/dcerpc/messages/Test_Response.java @@ -29,8 +29,6 @@ import static org.junit.Assert.*; public class Test_Response { - @Rule - public final ExpectedException thrown = ExpectedException.none(); @Test public void getStub() { diff --git a/src/test/java/com/rapid7/client/dcerpc/mslsad/Test_LookupSIDs.java b/src/test/java/com/rapid7/client/dcerpc/mslsad/Test_LookupSIDs.java index e72945b7..9b672ca9 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mslsad/Test_LookupSIDs.java +++ b/src/test/java/com/rapid7/client/dcerpc/mslsad/Test_LookupSIDs.java @@ -32,10 +32,7 @@ import com.rapid7.client.dcerpc.mslsad.objects.LSAPRTranslatedName; import com.rapid7.client.dcerpc.objects.RPCSID; -public class Test_LookupSIDs -{ - @Rule - public final ExpectedException thrown = ExpectedException.none(); +public class Test_LookupSIDs { @Test public void parseLookupSIDsResponse() throws IOException { diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegCloseKey.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegCloseKey.java index 18aa0a69..1df15811 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegCloseKey.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegCloseKey.java @@ -25,8 +25,8 @@ import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; public class Test_BaseRegCloseKey { private final byte[] contextHandle = Hex.decode("0000000032daf234b77c86409d29efe60d326683"); diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyRequest.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyRequest.java index a1d88237..7d3593d8 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyRequest.java @@ -26,8 +26,8 @@ import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; public class Test_BaseRegEnumKeyRequest { private final byte[] contextHandle = Hex.decode("0000000032daf234b77c86409d29efe60d326683"); diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumValueRequest.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumValueRequest.java index 7484420d..6dc2cbf8 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumValueRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumValueRequest.java @@ -18,14 +18,15 @@ */ package com.rapid7.client.dcerpc.msrrp.messages; -import java.io.IOException; import org.bouncycastle.util.encoders.Hex; import org.junit.Test; +import java.io.IOException; + import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; public class Test_BaseRegEnumValueRequest { private final byte[] contextHandle = Hex.decode("000000000a665393f4666e49a68cd99f269d020f"); diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegOpenKey.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegOpenKey.java index 95d7cc28..148872d1 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegOpenKey.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegOpenKey.java @@ -18,19 +18,20 @@ */ package com.rapid7.client.dcerpc.msrrp.messages; -import static org.bouncycastle.util.encoders.Hex.toHexString; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import java.io.IOException; -import java.util.EnumSet; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Test; import com.hierynomus.msdtyp.AccessMask; import com.hierynomus.protocol.commons.EnumWithValue.EnumUtils; import com.rapid7.client.dcerpc.messages.HandleResponse; import com.rapid7.client.dcerpc.objects.RPCUnicodeString; -import com.rapid7.client.dcerpc.objects.WChar; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; + +import java.io.IOException; +import java.util.EnumSet; + +import static org.bouncycastle.util.encoders.Hex.toHexString; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; public class Test_BaseRegOpenKey { private final byte[] contextHandle = Hex.decode("0000000032daf234b77c86409d29efe60d326683"); diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryInfoKeyRequest.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryInfoKeyRequest.java index a20ac9da..8564119c 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryInfoKeyRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryInfoKeyRequest.java @@ -18,14 +18,15 @@ */ package com.rapid7.client.dcerpc.msrrp.messages; -import java.io.IOException; import org.bouncycastle.util.encoders.Hex; import org.junit.Test; +import java.io.IOException; + import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; public class Test_BaseRegQueryInfoKeyRequest { private final byte[] contextHandle = Hex.decode("0000000032daf234b77c86409d29efe60d326683"); diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueRequest.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueRequest.java index 00339cab..1d547ca2 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueRequest.java @@ -18,16 +18,16 @@ */ package com.rapid7.client.dcerpc.msrrp.messages; -import java.io.IOException; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; import org.bouncycastle.util.encoders.Hex; import org.junit.Test; -import com.rapid7.client.dcerpc.objects.RPCUnicodeString; +import java.io.IOException; import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; public class Test_BaseRegQueryValueRequest { private final byte[] contextHandle = Hex.decode("000000000a665393f4666e49a68cd99f269d020f"); diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_HandleRequest.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_HandleRequest.java index 73962333..bafe3d65 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_HandleRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_HandleRequest.java @@ -18,14 +18,15 @@ */ package com.rapid7.client.dcerpc.msrrp.messages; -import java.io.IOException; -import org.junit.Test; import com.rapid7.client.dcerpc.messages.HandleResponse; +import org.junit.Test; + +import java.io.IOException; import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; public class Test_HandleRequest { private final HandleRequest request = new HandleRequest(OpenLocalMachine.OP_NUM, 33554432); diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrCloseHandleRequest.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrCloseHandleRequest.java index d7455517..573d695f 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrCloseHandleRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrCloseHandleRequest.java @@ -18,16 +18,16 @@ */ package com.rapid7.client.dcerpc.mssamr.messages; -import java.io.IOException; +import com.rapid7.client.dcerpc.messages.HandleResponse; import org.bouncycastle.util.encoders.Hex; import org.junit.Test; -import com.rapid7.client.dcerpc.messages.HandleResponse; +import java.io.IOException; import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; public class Test_SamrCloseHandleRequest { SamrCloseHandleRequest request = new SamrCloseHandleRequest(Hex.decode("0000000032daf234b77c86409d29efe60d326683")); diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrConnect2Request.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrConnect2Request.java index dd978bf3..ff30982e 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrConnect2Request.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrConnect2Request.java @@ -18,16 +18,17 @@ */ package com.rapid7.client.dcerpc.mssamr.messages; -import java.io.IOException; -import org.junit.Test; import com.hierynomus.msdtyp.AccessMask; import com.rapid7.client.dcerpc.messages.HandleResponse; import com.rapid7.client.dcerpc.objects.WChar; +import org.junit.Test; + +import java.io.IOException; import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; public class Test_SamrConnect2Request { private final SamrConnect2Request request = new SamrConnect2Request(WChar.NullTerminated.of(""), (int) AccessMask.MAXIMUM_ALLOWED.getValue()); diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrEnumerateDomainsInSamServerRequest.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrEnumerateDomainsInSamServerRequest.java index 93d01edc..868c6b64 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrEnumerateDomainsInSamServerRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrEnumerateDomainsInSamServerRequest.java @@ -18,13 +18,16 @@ */ package com.rapid7.client.dcerpc.mssamr.messages; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; + +import java.io.IOException; + import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import java.io.IOException; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Test; + public class Test_SamrEnumerateDomainsInSamServerRequest { @Test diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipRequest.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipRequest.java index 11e839e8..db20d022 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipRequest.java @@ -18,16 +18,18 @@ */ package com.rapid7.client.dcerpc.mssamr.messages; -import static org.bouncycastle.util.encoders.Hex.toHexString; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import java.io.IOException; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Test; import com.rapid7.client.dcerpc.dto.SID; import com.rapid7.client.dcerpc.mssamr.objects.SAMPRPSIDArray; import com.rapid7.client.dcerpc.objects.RPCSID; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; + +import java.io.IOException; + +import static org.bouncycastle.util.encoders.Hex.toHexString; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; public class Test_SamrGetAliasMembershipRequest { diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetGroupsForUserRequest.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetGroupsForUserRequest.java index 40f5063b..a046f517 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetGroupsForUserRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetGroupsForUserRequest.java @@ -18,13 +18,15 @@ */ package com.rapid7.client.dcerpc.mssamr.messages; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; + +import java.io.IOException; + import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import java.io.IOException; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Test; public class Test_SamrGetGroupsForUserRequest { diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetMembersForGroupRequest.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetMembersForGroupRequest.java index 06b56b6e..556647b6 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetMembersForGroupRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetMembersForGroupRequest.java @@ -18,14 +18,16 @@ */ package com.rapid7.client.dcerpc.mssamr.messages; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; + +import java.io.IOException; + import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import java.io.IOException; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Test; -import com.rapid7.client.dcerpc.mssamr.dto.GroupHandle; + public class Test_SamrGetMembersForGroupRequest { @Test diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenAlias.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenAlias.java index ac4fbf9a..a0efbf34 100755 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenAlias.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenAlias.java @@ -18,14 +18,15 @@ */ package com.rapid7.client.dcerpc.mssamr.messages; -import java.io.IOException; -import org.junit.Test; import com.rapid7.client.dcerpc.messages.HandleResponse; +import org.junit.Test; + +import java.io.IOException; import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; public class Test_SamrOpenAlias { diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenDomainRequest.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenDomainRequest.java index 82b6aaf5..e005fc9f 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenDomainRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenDomainRequest.java @@ -18,16 +18,18 @@ */ package com.rapid7.client.dcerpc.mssamr.messages; -import java.io.IOException; -import org.junit.Test; import com.hierynomus.msdtyp.AccessMask; import com.rapid7.client.dcerpc.messages.HandleResponse; import com.rapid7.client.dcerpc.objects.RPCSID; +import org.junit.Test; + +import java.io.IOException; import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; + public class Test_SamrOpenDomainRequest { @Test diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenUser.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenUser.java index 1efcc3c8..6f98b276 100755 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenUser.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrOpenUser.java @@ -18,15 +18,15 @@ */ package com.rapid7.client.dcerpc.mssamr.messages; -import java.io.IOException; -import org.junit.Test; import com.rapid7.client.dcerpc.messages.HandleResponse; -import com.rapid7.client.dcerpc.mssamr.dto.DomainHandle; +import org.junit.Test; + +import java.io.IOException; import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; public class Test_SamrOpenUser { // https://msdn.microsoft.com/en-us/library/cc980032.aspx diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryDisplayInformation2Request.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryDisplayInformation2Request.java index 7e79f0eb..ea05dfaa 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryDisplayInformation2Request.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryDisplayInformation2Request.java @@ -18,13 +18,15 @@ */ package com.rapid7.client.dcerpc.mssamr.messages; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; + +import java.io.IOException; + import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import java.io.IOException; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Test; public class Test_SamrQueryDisplayInformation2Request { diff --git a/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_NetPrPathCanonicalize.java b/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_NetPrPathCanonicalize.java index b8e3c0fb..f5dcc747 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_NetPrPathCanonicalize.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_NetPrPathCanonicalize.java @@ -31,8 +31,6 @@ import static org.junit.Assert.assertEquals; public class Test_NetPrPathCanonicalize { - @Rule - public final ExpectedException thrown = ExpectedException.none(); @SuppressWarnings("unchecked") @Test diff --git a/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_ServerService.java b/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_ServerService.java index 553a519e..692e7fa0 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_ServerService.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_ServerService.java @@ -40,8 +40,6 @@ import static org.testng.Assert.assertEquals; public class Test_ServerService { - @Rule - public final ExpectedException thrown = ExpectedException.none(); @SuppressWarnings("unchecked") @Test diff --git a/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RChangeServiceConfig.java b/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RChangeServiceConfig.java index 1cdb2573..bc38b412 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RChangeServiceConfig.java +++ b/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RChangeServiceConfig.java @@ -35,8 +35,6 @@ import static org.junit.Assert.assertTrue; public class Test_RChangeServiceConfig { - @Rule - public final ExpectedException thrown = ExpectedException.none(); @SuppressWarnings("unchecked") @Test diff --git a/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RQueryServiceConfig.java b/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RQueryServiceConfig.java index 3f640f29..892a96f6 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RQueryServiceConfig.java +++ b/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RQueryServiceConfig.java @@ -28,8 +28,6 @@ import static org.junit.Assert.assertTrue; public class Test_RQueryServiceConfig { - @Rule - public final ExpectedException thrown = ExpectedException.none(); @SuppressWarnings("unchecked") @Test diff --git a/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RStartService.java b/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RStartService.java index 3b6d7553..23a5f2be 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RStartService.java +++ b/src/test/java/com/rapid7/client/dcerpc/msvcctl/messages/Test_RStartService.java @@ -30,8 +30,6 @@ import static org.junit.Assert.assertTrue; public class Test_RStartService { - @Rule - public final ExpectedException thrown = ExpectedException.none(); @SuppressWarnings("unchecked") @Test diff --git a/src/test/java/com/rapid7/client/dcerpc/transport/Test_RPCTransport.java b/src/test/java/com/rapid7/client/dcerpc/transport/Test_RPCTransport.java index 195b0f5b..0d88a612 100644 --- a/src/test/java/com/rapid7/client/dcerpc/transport/Test_RPCTransport.java +++ b/src/test/java/com/rapid7/client/dcerpc/transport/Test_RPCTransport.java @@ -23,6 +23,7 @@ import java.util.LinkedList; import java.util.Queue; import org.bouncycastle.util.encoders.Hex; +import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -39,8 +40,6 @@ import static org.mockito.Mockito.*; public class Test_RPCTransport { - @Rule - public final ExpectedException thrown = ExpectedException.none(); @Test public void bindACK() throws IOException { @@ -109,10 +108,11 @@ public int transact(final byte[] packetOut, final byte[] packetIn) throws IOExce } }; - thrown.expect(IOException.class); - thrown.expectMessage("BIND winreg interface (338cd001-2244-31f1-aaaa-900038001003:v1.0) failed."); - - transport.bind(Interface.WINREG_V1_0, Interface.NDR_32BIT_V2); + try { + transport.bind(Interface.WINREG_V1_0, Interface.NDR_32BIT_V2); + } catch (IOException ex) { + Assert.assertEquals("BIND winreg interface (338cd001-2244-31f1-aaaa-900038001003:v1.0) failed.", ex.getMessage()); + } } @Test