From ddda1bd13ec28a999d03c58619b435b5bf74f423 Mon Sep 17 00:00:00 2001 From: Vadim Frolov Date: Tue, 10 Mar 2020 19:18:31 +0100 Subject: [PATCH 1/5] Update 3rd party dependencies and tests * Nine tests are failing with TestNG --- pom.xml | 14 +++---- .../com/rapid7/client/dcerpc/Test_Header.java | 39 ++++++++++-------- .../client/dcerpc/messages/Test_Request.java | 41 ++++++++++--------- .../client/dcerpc/messages/Test_Response.java | 2 - .../client/dcerpc/mslsad/Test_LookupSIDs.java | 5 +-- .../msrrp/messages/Test_BaseRegCloseKey.java | 2 +- .../messages/Test_BaseRegEnumKeyRequest.java | 2 +- .../Test_BaseRegEnumValueRequest.java | 5 ++- .../msrrp/messages/Test_BaseRegOpenKey.java | 19 +++++---- .../Test_BaseRegQueryInfoKeyRequest.java | 5 ++- .../Test_BaseRegQueryValueRequest.java | 6 +-- .../msrrp/messages/Test_HandleRequest.java | 7 ++-- .../messages/Test_SamrCloseHandleRequest.java | 6 +-- .../messages/Test_SamrConnect2Request.java | 7 ++-- ...amrEnumerateDomainsInSamServerRequest.java | 11 +++-- .../Test_SamrGetAliasMembershipRequest.java | 16 ++++---- .../Test_SamrGetGroupsForUserRequest.java | 10 +++-- .../Test_SamrGetMembersForGroupRequest.java | 12 +++--- .../mssamr/messages/Test_SamrOpenAlias.java | 7 ++-- .../messages/Test_SamrOpenDomainRequest.java | 8 ++-- .../mssamr/messages/Test_SamrOpenUser.java | 8 ++-- ...t_SamrQueryDisplayInformation2Request.java | 10 +++-- .../mssrvs/Test_NetPrPathCanonicalize.java | 2 - .../dcerpc/mssrvs/Test_ServerService.java | 2 - .../messages/Test_RChangeServiceConfig.java | 2 - .../messages/Test_RQueryServiceConfig.java | 2 - .../msvcctl/messages/Test_RStartService.java | 2 - .../dcerpc/transport/Test_RPCTransport.java | 12 +++--- 28 files changed, 137 insertions(+), 127 deletions(-) diff --git a/pom.xml b/pom.xml index 3a9e81b5..13b39bc8 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 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/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 From 8e448536a3c43e055da9a798118ae7b5a470c298 Mon Sep 17 00:00:00 2001 From: Vadim Frolov Date: Sun, 22 Mar 2020 20:37:07 +0100 Subject: [PATCH 2/5] Add InitShutdown Interface * This is an RPC interface that allows to shutdown/reboot a remote PC. * Added tests and a usage example, see usage/ShutdownExample.java. --- .../com/rapid7/client/dcerpc/Interface.java | 3 +- .../dcerpc/initshutdown/ShutdownService.java | 73 ++++++ .../initshutdown/dto/ShutdownReason.java | 97 ++++++++ .../messages/BaseAbortShutdown.java | 64 +++++ .../messages/BaseInitiateShutdownRequest.java | 97 ++++++++ .../BaseInitiateShutdownRequestEx.java | 107 +++++++++ .../client/dcerpc/io/PrimitiveOutput.java | 6 + .../dcerpc/objects/RegUnicodeString.java | 224 ++++++++++++++++++ .../client/dcerpc/objects/ShortChar.java | 222 +++++++++++++++++ .../transport/SMBTransportFactories.java | 3 +- .../com/rapid7/usage/ShutdownExample.java | 54 +++++ .../initshutdown/Test_ShutdownService.java | 61 +++++ .../initshutdown/dto/Test_ShutdownReason.java | 66 ++++++ .../messages/Test_BaseAbortShutdown.java | 50 ++++ .../Test_BaseInitiateShutdownRequest.java | 54 +++++ .../Test_BaseInitiateShutdownRequestEx.java | 59 +++++ 16 files changed, 1238 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/rapid7/client/dcerpc/initshutdown/ShutdownService.java create mode 100644 src/main/java/com/rapid7/client/dcerpc/initshutdown/dto/ShutdownReason.java create mode 100644 src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseAbortShutdown.java create mode 100644 src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequest.java create mode 100644 src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequestEx.java create mode 100644 src/main/java/com/rapid7/client/dcerpc/objects/RegUnicodeString.java create mode 100644 src/main/java/com/rapid7/client/dcerpc/objects/ShortChar.java create mode 100644 src/main/java/com/rapid7/usage/ShutdownExample.java create mode 100644 src/test/java/com/rapid7/client/dcerpc/initshutdown/Test_ShutdownService.java create mode 100644 src/test/java/com/rapid7/client/dcerpc/initshutdown/dto/Test_ShutdownReason.java create mode 100644 src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseAbortShutdown.java create mode 100644 src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseInitiateShutdownRequest.java create mode 100644 src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseInitiateShutdownRequestEx.java 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..80efa45b --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/ShutdownService.java @@ -0,0 +1,73 @@ +/** + * 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 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; + +import java.io.IOException; +import java.util.EnumSet; + +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..8c7742a8 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/dto/ShutdownReason.java @@ -0,0 +1,97 @@ +/** + * 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 java.util.HashMap; +import java.util.Map; + +/* + * @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..bbc86f90 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseAbortShutdown.java @@ -0,0 +1,64 @@ +/** + * 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 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; + +import java.io.IOException; + +/** + * 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..667a5e33 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequest.java @@ -0,0 +1,97 @@ +/** + * 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 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; + +import java.io.IOException; + +/** + * 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..0389c3dc --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequestEx.java @@ -0,0 +1,107 @@ +/** + * 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 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; + +import java.io.IOException; +import java.util.EnumSet; + +/** + * 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/objects/RegUnicodeString.java b/src/main/java/com/rapid7/client/dcerpc/objects/RegUnicodeString.java new file mode 100644 index 00000000..897123bf --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/objects/RegUnicodeString.java @@ -0,0 +1,224 @@ +/* + * 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 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; + +import java.io.IOException; +import java.util.Objects; + +/** + * 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..cebf6810 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/objects/ShortChar.java @@ -0,0 +1,222 @@ +/* + * 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 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; + +import java.io.IOException; +import java.rmi.UnmarshalException; +import java.util.Objects; + +/** + * 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/initshutdown/Test_ShutdownService.java b/src/test/java/com/rapid7/client/dcerpc/initshutdown/Test_ShutdownService.java new file mode 100644 index 00000000..4878393b --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/initshutdown/Test_ShutdownService.java @@ -0,0 +1,61 @@ +/** + * 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 com.rapid7.client.dcerpc.messages.EmptyResponse; +import com.rapid7.client.dcerpc.messages.RequestCall; +import com.rapid7.client.dcerpc.transport.RPCTransport; +import org.testng.annotations.Test; + +import java.io.IOException; + +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.*; + +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..8cc34287 --- /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 org.junit.Test; + +import java.util.EnumSet; + +import static com.rapid7.client.dcerpc.initshutdown.dto.ShutdownReason.*; +import static org.junit.Assert.*; + +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..4c8f4b75 --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseAbortShutdown.java @@ -0,0 +1,50 @@ +/** + * 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 com.rapid7.client.dcerpc.messages.EmptyResponse; +import com.rapid7.client.dcerpc.objects.RegUnicodeString; +import com.rapid7.client.dcerpc.objects.WChar; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; + +import java.io.IOException; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.*; + +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..40e0e334 --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseInitiateShutdownRequest.java @@ -0,0 +1,54 @@ +/** + * 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 com.rapid7.client.dcerpc.messages.EmptyResponse; +import com.rapid7.client.dcerpc.objects.RegUnicodeString; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; + +import java.io.IOException; + +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..f337fc9f --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/initshutdown/messages/Test_BaseInitiateShutdownRequestEx.java @@ -0,0 +1,59 @@ +/** + * 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 com.rapid7.client.dcerpc.initshutdown.dto.ShutdownReason; +import com.rapid7.client.dcerpc.messages.EmptyResponse; +import com.rapid7.client.dcerpc.objects.RegUnicodeString; +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_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)); + } +} From bc91e57f18a8c0d6c684fdec5d5e44b8a7e75013 Mon Sep 17 00:00:00 2001 From: Vadim Frolov Date: Sun, 22 Mar 2020 21:37:03 +0100 Subject: [PATCH 3/5] Apply code style --- .../dcerpc/initshutdown/ShutdownService.java | 33 +++++-------------- .../initshutdown/dto/ShutdownReason.java | 5 +-- .../messages/BaseAbortShutdown.java | 3 +- .../messages/BaseInitiateShutdownRequest.java | 8 ++--- .../BaseInitiateShutdownRequestEx.java | 11 ++----- .../dcerpc/objects/RegUnicodeString.java | 19 +++++------ .../client/dcerpc/objects/ShortChar.java | 26 +++++++-------- .../initshutdown/Test_ShutdownService.java | 22 +++++++------ .../initshutdown/dto/Test_ShutdownReason.java | 24 +++++++------- .../messages/Test_BaseAbortShutdown.java | 23 +++++++------ .../Test_BaseInitiateShutdownRequest.java | 25 +++++++------- .../Test_BaseInitiateShutdownRequestEx.java | 30 +++++++---------- 12 files changed, 94 insertions(+), 135 deletions(-) diff --git a/src/main/java/com/rapid7/client/dcerpc/initshutdown/ShutdownService.java b/src/main/java/com/rapid7/client/dcerpc/initshutdown/ShutdownService.java index 80efa45b..68e39ec1 100644 --- a/src/main/java/com/rapid7/client/dcerpc/initshutdown/ShutdownService.java +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/ShutdownService.java @@ -18,6 +18,8 @@ */ 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; @@ -27,46 +29,29 @@ import com.rapid7.client.dcerpc.service.Service; import com.rapid7.client.dcerpc.transport.RPCTransport; -import java.io.IOException; -import java.util.EnumSet; - 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 { + 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 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 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 { + 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 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 index 8c7742a8..b695586c 100644 --- a/src/main/java/com/rapid7/client/dcerpc/initshutdown/dto/ShutdownReason.java +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/dto/ShutdownReason.java @@ -19,8 +19,6 @@ package com.rapid7.client.dcerpc.initshutdown.dto; import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; /* * @see 2.3 Shutdown Reasons @@ -86,8 +84,7 @@ public long getReason() { 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)); + return ShutdownReason.getReason(EnumSet.of(ShutdownReason.SHTDN_REASON_MAJOR_OTHER, ShutdownReason.SHTDN_REASON_MINOR_OTHER)); } for (ShutdownReason shReason : reasons) { finalReason |= shReason.getReason(); 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 index bbc86f90..d08f96d2 100644 --- a/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseAbortShutdown.java +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseAbortShutdown.java @@ -18,13 +18,12 @@ */ 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; -import java.io.IOException; - /** * 3.2.4.2 BaseAbortShutdown (Opnum 1)
*
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 index 667a5e33..e450fc87 100644 --- a/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequest.java @@ -18,6 +18,7 @@ */ 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; @@ -25,8 +26,6 @@ import com.rapid7.client.dcerpc.objects.RegUnicodeString; import com.rapid7.client.dcerpc.objects.WChar; -import java.io.IOException; - /** * 3.2.4.1 BaseInitiateShutdown (Opnum 0)
*
@@ -54,10 +53,7 @@ public class BaseInitiateShutdownRequest extends RequestCall { 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) { + 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; 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 index 0389c3dc..0b0143af 100644 --- a/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequestEx.java +++ b/src/main/java/com/rapid7/client/dcerpc/initshutdown/messages/BaseInitiateShutdownRequestEx.java @@ -18,6 +18,8 @@ */ 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; @@ -26,9 +28,6 @@ import com.rapid7.client.dcerpc.objects.RegUnicodeString; import com.rapid7.client.dcerpc.objects.WChar; -import java.io.IOException; -import java.util.EnumSet; - /** * 3.2.4.3 BaseInitiateShutdownEx (Opnum 2)
*
@@ -58,11 +57,7 @@ public class BaseInitiateShutdownRequestEx extends RequestCall { 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) { + 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; diff --git a/src/main/java/com/rapid7/client/dcerpc/objects/RegUnicodeString.java b/src/main/java/com/rapid7/client/dcerpc/objects/RegUnicodeString.java index 897123bf..b72d93ba 100644 --- a/src/main/java/com/rapid7/client/dcerpc/objects/RegUnicodeString.java +++ b/src/main/java/com/rapid7/client/dcerpc/objects/RegUnicodeString.java @@ -18,15 +18,14 @@ */ 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; -import java.io.IOException; -import java.util.Objects; - /** * Represents a counted string of Unicode (UTF-16) characters. *
@@ -107,6 +106,7 @@ ShortChar createShortChar() { } private ShortChar shortChar; + abstract ShortChar createShortChar(); /** @@ -114,14 +114,13 @@ ShortChar createShortChar() { * May be null. Will never include a null terminator. */ public String getValue() { - if (this.shortChar == null) - return null; + 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. + * May be null. Must not include a null terminator. */ public void setValue(String value) { if (value == null) { @@ -189,10 +188,8 @@ public void unmarshalEntity(PacketInput in) throws IOException { 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; + if (in.readReferentID() != 0) this.shortChar = createShortChar(); + else this.shortChar = null; } @Override @@ -211,7 +208,7 @@ public int hashCode() { public boolean equals(Object obj) { if (this == obj) { return true; - } else if (! (obj instanceof RPCUnicodeString)) { + } else if (!(obj instanceof RPCUnicodeString)) { return false; } return Objects.equals(shortChar, ((RegUnicodeString) obj).shortChar); diff --git a/src/main/java/com/rapid7/client/dcerpc/objects/ShortChar.java b/src/main/java/com/rapid7/client/dcerpc/objects/ShortChar.java index cebf6810..c93638d4 100644 --- a/src/main/java/com/rapid7/client/dcerpc/objects/ShortChar.java +++ b/src/main/java/com/rapid7/client/dcerpc/objects/ShortChar.java @@ -18,16 +18,15 @@ */ 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; -import java.io.IOException; -import java.rmi.UnmarshalException; -import java.util.Objects; - /** * Represents a UTF-16 encoded unicode string as a character array. * Alignment: 4 @@ -131,8 +130,7 @@ public void marshalDeferrals(PacketOutput out) throws IOException { // Entities for conformant+varying array // Alignment 1 - Already aligned out.writeCharsAsShort(value); - if (isNullTerminated()) - out.writeShort(0); + if (isNullTerminated()) out.writeShort(0); } @Override @@ -166,8 +164,7 @@ public void unmarshalDeferrals(PacketInput in) throws IOException { if (isNullTerminated() && this.actualCount > 0) { length = this.actualCount - 1; nullTerminated = true; - } - else { + } else { length = this.actualCount; nullTerminated = false; } @@ -180,8 +177,7 @@ public void unmarshalDeferrals(PacketInput in) throws IOException { this.value = sb.toString(); // Skip null terminator (if any) // Alignment: 2 - Already aligned - if (nullTerminated) - in.fullySkipBytes(2); + if (nullTerminated) in.fullySkipBytes(2); } @Override @@ -193,12 +189,11 @@ public int hashCode() { public boolean equals(Object obj) { if (this == obj) { return true; - } else if (! (obj instanceof ShortChar)) { + } else if (!(obj instanceof ShortChar)) { return false; } final ShortChar other = (ShortChar) obj; - return isNullTerminated() == other.isNullTerminated() - && Objects.equals(getValue(), other.getValue()); + return isNullTerminated() == other.isNullTerminated() && Objects.equals(getValue(), other.getValue()); } @Override @@ -209,7 +204,10 @@ public String toString() { private int getCodePoints() { return getValue().length() + (isNullTerminated() ? 1 : 0); } - private int getContentLength() { return getValue().length(); } + + private int getContentLength() { + return getValue().length(); + } private int readIndex(String name, PacketInput in) throws IOException { final long ret = in.readUnsignedInt(); 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 index 4878393b..f1e0d192 100644 --- a/src/test/java/com/rapid7/client/dcerpc/initshutdown/Test_ShutdownService.java +++ b/src/test/java/com/rapid7/client/dcerpc/initshutdown/Test_ShutdownService.java @@ -1,38 +1,40 @@ /** * 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 org.testng.annotations.Test; - -import java.io.IOException; 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.*; +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") + @Test(expectedExceptions = {IllegalArgumentException.class}, expectedExceptionsMessageRegExp = "Expecting non-null transport") public void constructorNullTransport() { new ShutdownService(null); } 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 index 8cc34287..eb19307c 100644 --- 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 @@ -1,29 +1,31 @@ /** * 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 org.junit.Test; - import java.util.EnumSet; +import org.junit.Test; -import static com.rapid7.client.dcerpc.initshutdown.dto.ShutdownReason.*; -import static org.junit.Assert.*; +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 @@ -34,8 +36,7 @@ public void 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 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); } @@ -51,8 +52,7 @@ public void MAJOR_POWER() { @Test public void SOFTWARE_DISK() { final int expected = 0x00030007; - final EnumSet flags = EnumSet.of(SHTDN_REASON_MAJOR_SOFTWARE, - SHTDN_REASON_MINOR_DISK); + final EnumSet flags = EnumSet.of(SHTDN_REASON_MAJOR_SOFTWARE, SHTDN_REASON_MINOR_DISK); final int actual = ShutdownReason.getReason(flags); 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 index 4c8f4b75..ec545b61 100644 --- 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 @@ -1,40 +1,39 @@ /** * 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 com.rapid7.client.dcerpc.messages.EmptyResponse; -import com.rapid7.client.dcerpc.objects.RegUnicodeString; -import com.rapid7.client.dcerpc.objects.WChar; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Test; - 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.*; +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()); } + public void getOpNum() { + assertEquals(1, request.getOpNum()); + } @Test public void getStub() throws IOException { 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 index 40e0e334..84b5e984 100644 --- 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 @@ -1,29 +1,28 @@ /** * 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 com.rapid7.client.dcerpc.messages.EmptyResponse; -import com.rapid7.client.dcerpc.objects.RegUnicodeString; +import java.io.IOException; import org.bouncycastle.util.encoders.Hex; import org.junit.Test; - -import java.io.IOException; +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; @@ -33,14 +32,12 @@ 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 - ); + private final BaseInitiateShutdownRequest request = new BaseInitiateShutdownRequest(null, RegUnicodeString.NullTerminated.of(null), 30, true, false); @Test - public void getOpNum() { assertEquals(0, request.getOpNum()); } + public void getOpNum() { + assertEquals(0, request.getOpNum()); + } @Test public void getStub() throws IOException { 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 index f337fc9f..306d762a 100644 --- 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 @@ -1,31 +1,30 @@ /** * 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 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; @@ -35,17 +34,12 @@ 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) - ); + 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()); } + public void getOpNum() { + assertEquals(2, request.getOpNum()); + } @Test public void getStub() throws IOException { From 8ebe4558684b27266ce5d7f05f2b77c0274f66e1 Mon Sep 17 00:00:00 2001 From: Vadim Frolov Date: Sun, 22 Mar 2020 21:43:28 +0100 Subject: [PATCH 4/5] Update README * Added list of implemented protocols, added Vadim Frolov to the contributors list. --- CONTRIBUTORS | 1 + README.md | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) 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: From f6bfbee2b042684f1757e6f1ce4f6ae5c11ae37e Mon Sep 17 00:00:00 2001 From: Vadim Frolov Date: Mon, 23 Mar 2020 20:33:29 +0100 Subject: [PATCH 5/5] Update dependencies and javadoc configuration for successful builds * This changes allow to run `mvn clean package` without errors. --- pom.xml | 13 +++++++++++-- .../mslsad/objects/LSAPRPolicyAuditEventsInfo.java | 8 +++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 13b39bc8..5ae37b45 100644 --- a/pom.xml +++ b/pom.xml @@ -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/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 {