From 82e55c4919ad26f7fd7b9493cb3f6e0804c0be3f Mon Sep 17 00:00:00 2001 From: moloch-- <875022+moloch--@users.noreply.github.com> Date: Sat, 28 Feb 2026 10:14:25 -0800 Subject: [PATCH] Update sliver submodule to v1.7.3 --- src/client.ts | 11 +- src/pb/clientpb/client.ts | 1089 ++++++++++++++++- src/pb/commonpb/common.ts | 2 +- src/pb/dnspb/dns.ts | 2 +- src/pb/rpcpb/services.ts | 19 +- src/pb/sliverpb/sliver.ts | 21 +- .../__snapshots__/rpc-definition.test.ts.snap | 6 + src/tests/rpc-wrappers.test.ts | 32 +- 8 files changed, 1171 insertions(+), 11 deletions(-) diff --git a/src/client.ts b/src/client.ts index 735b687..79cd241 100644 --- a/src/client.ts +++ b/src/client.ts @@ -17,6 +17,7 @@ import type { Beacons, Jobs, Beacon, + GenerateSpoofMetadataReq, ImplantConfig, ImplantProfile, Loot, @@ -447,8 +448,8 @@ export class SliverClient { const creds = createSliverRpcCredentials(this.config); this.channel = createChannel(this.rpcHost(), creds, { - "grpc.max_send_message_length": 2 * GiB, - "grpc.max_receive_message_length": 2 * GiB, + "grpc.max_send_message_length": (2 * GiB) -1, + "grpc.max_receive_message_length": (2 * GiB) -1, }); this.rpcClient = createClient(SliverRPCDefinition, this.channel); @@ -615,6 +616,12 @@ export class SliverClient { return res.File; } + generateSpoofMetadata(req: GenerateSpoofMetadataReq, timeoutSeconds = DEFAULT_TIMEOUT_SECONDS): Promise { + return withTimeoutSignal(timeoutSeconds, async (signal) => { + await this.rpc.generateSpoofMetadata(req, { signal }); + }); + } + async regenerate(implantName: string, timeoutSeconds = DEFAULT_TIMEOUT_SECONDS) { const res = await withTimeoutSignal(timeoutSeconds, (signal) => this.rpc.regenerate({ ImplantName: implantName }, { signal }), diff --git a/src/pb/clientpb/client.ts b/src/pb/clientpb/client.ts index cdd6739..ad9f4da 100644 --- a/src/pb/clientpb/client.ts +++ b/src/pb/clientpb/client.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.2 -// protoc v3.15.8 +// protoc v6.33.4 // source: clientpb/client.proto /* eslint-disable */ @@ -1647,6 +1647,73 @@ export interface ImplantConfig { Assets: File[]; } +export interface SpoofMetadataFile { + Name: string; + Data: Buffer; +} + +export interface imageResourceDirectory { + Characteristics: number; + TimeDateStamp: number; + /** uint16 in PE headers; encoded as uint32 for protobuf transport. */ + MajorVersion: number; + /** uint16 in PE headers; encoded as uint32 for protobuf transport. */ + MinorVersion: number; + /** uint16 in PE headers; encoded as uint32 for protobuf transport. */ + NumberOfNamedEntries: number; + /** uint16 in PE headers; encoded as uint32 for protobuf transport. */ + NumberOfIdEntries: number; +} + +export interface imageResourceDirectoryEntry { + Name: number; + OffsetToData: number; +} + +export interface imageResourceDataEntry { + OffsetToData: number; + Size: number; + CodePage: number; + Reserved: number; +} + +export interface imageExportDirectory { + Characteristics: number; + TimeDateStamp: number; + /** uint16 in PE headers; encoded as uint32 for protobuf transport. */ + MajorVersion: number; + /** uint16 in PE headers; encoded as uint32 for protobuf transport. */ + MinorVersion: number; + Name: number; + Base: number; + NumberOfFunctions: number; + NumberOfNames: number; + AddressOfFunctions: number; + AddressOfNames: number; + AddressOfNameOrdinals: number; +} + +export interface PESpoofMetadataConfig { + /** Reference PE used to clone metadata/resources/timestamps. */ + Source?: + | SpoofMetadataFile + | undefined; + /** Reserved for future standalone icon mutation support. */ + Icon?: SpoofMetadataFile | undefined; + ResourceDirectory?: imageResourceDirectory | undefined; + ResourceDirectoryEntries: imageResourceDirectoryEntry[]; + ResourceDataEntries: imageResourceDataEntry[]; + ExportDirectory?: imageExportDirectory | undefined; +} + +export interface SpoofMetadataConfig { + /** + * Keep executable formats separated so additional formats can be added later + * without changing request semantics. + */ + PE?: PESpoofMetadataConfig | undefined; +} + export interface TrafficEncoder { ID: string; Wasm?: File | undefined; @@ -1949,6 +2016,15 @@ export interface GenerateStageReq { export interface Generate { File?: File | undefined; + ImplantName: string; + ImplantBuildID: string; +} + +export interface GenerateSpoofMetadataReq { + ImplantBuildID: string; + ImplantName: string; + ResourceID: string; + SpoofMetadata?: SpoofMetadataConfig | undefined; } export interface MSFReq { @@ -5552,6 +5628,869 @@ export const ImplantConfig: MessageFns = { }, }; +function createBaseSpoofMetadataFile(): SpoofMetadataFile { + return { Name: "", Data: Buffer.alloc(0) }; +} + +export const SpoofMetadataFile: MessageFns = { + encode(message: SpoofMetadataFile, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.Name !== "") { + writer.uint32(10).string(message.Name); + } + if (message.Data.length !== 0) { + writer.uint32(18).bytes(message.Data); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): SpoofMetadataFile { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseSpoofMetadataFile(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.Name = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.Data = Buffer.from(reader.bytes()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): SpoofMetadataFile { + return { + Name: isSet(object.Name) ? globalThis.String(object.Name) : "", + Data: isSet(object.Data) ? Buffer.from(bytesFromBase64(object.Data)) : Buffer.alloc(0), + }; + }, + + toJSON(message: SpoofMetadataFile): unknown { + const obj: any = {}; + if (message.Name !== "") { + obj.Name = message.Name; + } + if (message.Data.length !== 0) { + obj.Data = base64FromBytes(message.Data); + } + return obj; + }, + + create(base?: DeepPartial): SpoofMetadataFile { + return SpoofMetadataFile.fromPartial(base ?? {}); + }, + fromPartial(object: DeepPartial): SpoofMetadataFile { + const message = createBaseSpoofMetadataFile(); + message.Name = object.Name ?? ""; + message.Data = object.Data ?? Buffer.alloc(0); + return message; + }, +}; + +function createBaseimageResourceDirectory(): imageResourceDirectory { + return { + Characteristics: 0, + TimeDateStamp: 0, + MajorVersion: 0, + MinorVersion: 0, + NumberOfNamedEntries: 0, + NumberOfIdEntries: 0, + }; +} + +export const imageResourceDirectory: MessageFns = { + encode(message: imageResourceDirectory, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.Characteristics !== 0) { + writer.uint32(8).uint32(message.Characteristics); + } + if (message.TimeDateStamp !== 0) { + writer.uint32(16).uint32(message.TimeDateStamp); + } + if (message.MajorVersion !== 0) { + writer.uint32(24).uint32(message.MajorVersion); + } + if (message.MinorVersion !== 0) { + writer.uint32(32).uint32(message.MinorVersion); + } + if (message.NumberOfNamedEntries !== 0) { + writer.uint32(40).uint32(message.NumberOfNamedEntries); + } + if (message.NumberOfIdEntries !== 0) { + writer.uint32(48).uint32(message.NumberOfIdEntries); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): imageResourceDirectory { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseimageResourceDirectory(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } + + message.Characteristics = reader.uint32(); + continue; + } + case 2: { + if (tag !== 16) { + break; + } + + message.TimeDateStamp = reader.uint32(); + continue; + } + case 3: { + if (tag !== 24) { + break; + } + + message.MajorVersion = reader.uint32(); + continue; + } + case 4: { + if (tag !== 32) { + break; + } + + message.MinorVersion = reader.uint32(); + continue; + } + case 5: { + if (tag !== 40) { + break; + } + + message.NumberOfNamedEntries = reader.uint32(); + continue; + } + case 6: { + if (tag !== 48) { + break; + } + + message.NumberOfIdEntries = reader.uint32(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): imageResourceDirectory { + return { + Characteristics: isSet(object.Characteristics) ? globalThis.Number(object.Characteristics) : 0, + TimeDateStamp: isSet(object.TimeDateStamp) ? globalThis.Number(object.TimeDateStamp) : 0, + MajorVersion: isSet(object.MajorVersion) ? globalThis.Number(object.MajorVersion) : 0, + MinorVersion: isSet(object.MinorVersion) ? globalThis.Number(object.MinorVersion) : 0, + NumberOfNamedEntries: isSet(object.NumberOfNamedEntries) ? globalThis.Number(object.NumberOfNamedEntries) : 0, + NumberOfIdEntries: isSet(object.NumberOfIdEntries) ? globalThis.Number(object.NumberOfIdEntries) : 0, + }; + }, + + toJSON(message: imageResourceDirectory): unknown { + const obj: any = {}; + if (message.Characteristics !== 0) { + obj.Characteristics = Math.round(message.Characteristics); + } + if (message.TimeDateStamp !== 0) { + obj.TimeDateStamp = Math.round(message.TimeDateStamp); + } + if (message.MajorVersion !== 0) { + obj.MajorVersion = Math.round(message.MajorVersion); + } + if (message.MinorVersion !== 0) { + obj.MinorVersion = Math.round(message.MinorVersion); + } + if (message.NumberOfNamedEntries !== 0) { + obj.NumberOfNamedEntries = Math.round(message.NumberOfNamedEntries); + } + if (message.NumberOfIdEntries !== 0) { + obj.NumberOfIdEntries = Math.round(message.NumberOfIdEntries); + } + return obj; + }, + + create(base?: DeepPartial): imageResourceDirectory { + return imageResourceDirectory.fromPartial(base ?? {}); + }, + fromPartial(object: DeepPartial): imageResourceDirectory { + const message = createBaseimageResourceDirectory(); + message.Characteristics = object.Characteristics ?? 0; + message.TimeDateStamp = object.TimeDateStamp ?? 0; + message.MajorVersion = object.MajorVersion ?? 0; + message.MinorVersion = object.MinorVersion ?? 0; + message.NumberOfNamedEntries = object.NumberOfNamedEntries ?? 0; + message.NumberOfIdEntries = object.NumberOfIdEntries ?? 0; + return message; + }, +}; + +function createBaseimageResourceDirectoryEntry(): imageResourceDirectoryEntry { + return { Name: 0, OffsetToData: 0 }; +} + +export const imageResourceDirectoryEntry: MessageFns = { + encode(message: imageResourceDirectoryEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.Name !== 0) { + writer.uint32(8).uint32(message.Name); + } + if (message.OffsetToData !== 0) { + writer.uint32(16).uint32(message.OffsetToData); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): imageResourceDirectoryEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseimageResourceDirectoryEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } + + message.Name = reader.uint32(); + continue; + } + case 2: { + if (tag !== 16) { + break; + } + + message.OffsetToData = reader.uint32(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): imageResourceDirectoryEntry { + return { + Name: isSet(object.Name) ? globalThis.Number(object.Name) : 0, + OffsetToData: isSet(object.OffsetToData) ? globalThis.Number(object.OffsetToData) : 0, + }; + }, + + toJSON(message: imageResourceDirectoryEntry): unknown { + const obj: any = {}; + if (message.Name !== 0) { + obj.Name = Math.round(message.Name); + } + if (message.OffsetToData !== 0) { + obj.OffsetToData = Math.round(message.OffsetToData); + } + return obj; + }, + + create(base?: DeepPartial): imageResourceDirectoryEntry { + return imageResourceDirectoryEntry.fromPartial(base ?? {}); + }, + fromPartial(object: DeepPartial): imageResourceDirectoryEntry { + const message = createBaseimageResourceDirectoryEntry(); + message.Name = object.Name ?? 0; + message.OffsetToData = object.OffsetToData ?? 0; + return message; + }, +}; + +function createBaseimageResourceDataEntry(): imageResourceDataEntry { + return { OffsetToData: 0, Size: 0, CodePage: 0, Reserved: 0 }; +} + +export const imageResourceDataEntry: MessageFns = { + encode(message: imageResourceDataEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.OffsetToData !== 0) { + writer.uint32(8).uint32(message.OffsetToData); + } + if (message.Size !== 0) { + writer.uint32(16).uint32(message.Size); + } + if (message.CodePage !== 0) { + writer.uint32(24).uint32(message.CodePage); + } + if (message.Reserved !== 0) { + writer.uint32(32).uint32(message.Reserved); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): imageResourceDataEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseimageResourceDataEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } + + message.OffsetToData = reader.uint32(); + continue; + } + case 2: { + if (tag !== 16) { + break; + } + + message.Size = reader.uint32(); + continue; + } + case 3: { + if (tag !== 24) { + break; + } + + message.CodePage = reader.uint32(); + continue; + } + case 4: { + if (tag !== 32) { + break; + } + + message.Reserved = reader.uint32(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): imageResourceDataEntry { + return { + OffsetToData: isSet(object.OffsetToData) ? globalThis.Number(object.OffsetToData) : 0, + Size: isSet(object.Size) ? globalThis.Number(object.Size) : 0, + CodePage: isSet(object.CodePage) ? globalThis.Number(object.CodePage) : 0, + Reserved: isSet(object.Reserved) ? globalThis.Number(object.Reserved) : 0, + }; + }, + + toJSON(message: imageResourceDataEntry): unknown { + const obj: any = {}; + if (message.OffsetToData !== 0) { + obj.OffsetToData = Math.round(message.OffsetToData); + } + if (message.Size !== 0) { + obj.Size = Math.round(message.Size); + } + if (message.CodePage !== 0) { + obj.CodePage = Math.round(message.CodePage); + } + if (message.Reserved !== 0) { + obj.Reserved = Math.round(message.Reserved); + } + return obj; + }, + + create(base?: DeepPartial): imageResourceDataEntry { + return imageResourceDataEntry.fromPartial(base ?? {}); + }, + fromPartial(object: DeepPartial): imageResourceDataEntry { + const message = createBaseimageResourceDataEntry(); + message.OffsetToData = object.OffsetToData ?? 0; + message.Size = object.Size ?? 0; + message.CodePage = object.CodePage ?? 0; + message.Reserved = object.Reserved ?? 0; + return message; + }, +}; + +function createBaseimageExportDirectory(): imageExportDirectory { + return { + Characteristics: 0, + TimeDateStamp: 0, + MajorVersion: 0, + MinorVersion: 0, + Name: 0, + Base: 0, + NumberOfFunctions: 0, + NumberOfNames: 0, + AddressOfFunctions: 0, + AddressOfNames: 0, + AddressOfNameOrdinals: 0, + }; +} + +export const imageExportDirectory: MessageFns = { + encode(message: imageExportDirectory, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.Characteristics !== 0) { + writer.uint32(8).uint32(message.Characteristics); + } + if (message.TimeDateStamp !== 0) { + writer.uint32(16).uint32(message.TimeDateStamp); + } + if (message.MajorVersion !== 0) { + writer.uint32(24).uint32(message.MajorVersion); + } + if (message.MinorVersion !== 0) { + writer.uint32(32).uint32(message.MinorVersion); + } + if (message.Name !== 0) { + writer.uint32(40).uint32(message.Name); + } + if (message.Base !== 0) { + writer.uint32(48).uint32(message.Base); + } + if (message.NumberOfFunctions !== 0) { + writer.uint32(56).uint32(message.NumberOfFunctions); + } + if (message.NumberOfNames !== 0) { + writer.uint32(64).uint32(message.NumberOfNames); + } + if (message.AddressOfFunctions !== 0) { + writer.uint32(72).uint32(message.AddressOfFunctions); + } + if (message.AddressOfNames !== 0) { + writer.uint32(80).uint32(message.AddressOfNames); + } + if (message.AddressOfNameOrdinals !== 0) { + writer.uint32(88).uint32(message.AddressOfNameOrdinals); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): imageExportDirectory { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseimageExportDirectory(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } + + message.Characteristics = reader.uint32(); + continue; + } + case 2: { + if (tag !== 16) { + break; + } + + message.TimeDateStamp = reader.uint32(); + continue; + } + case 3: { + if (tag !== 24) { + break; + } + + message.MajorVersion = reader.uint32(); + continue; + } + case 4: { + if (tag !== 32) { + break; + } + + message.MinorVersion = reader.uint32(); + continue; + } + case 5: { + if (tag !== 40) { + break; + } + + message.Name = reader.uint32(); + continue; + } + case 6: { + if (tag !== 48) { + break; + } + + message.Base = reader.uint32(); + continue; + } + case 7: { + if (tag !== 56) { + break; + } + + message.NumberOfFunctions = reader.uint32(); + continue; + } + case 8: { + if (tag !== 64) { + break; + } + + message.NumberOfNames = reader.uint32(); + continue; + } + case 9: { + if (tag !== 72) { + break; + } + + message.AddressOfFunctions = reader.uint32(); + continue; + } + case 10: { + if (tag !== 80) { + break; + } + + message.AddressOfNames = reader.uint32(); + continue; + } + case 11: { + if (tag !== 88) { + break; + } + + message.AddressOfNameOrdinals = reader.uint32(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): imageExportDirectory { + return { + Characteristics: isSet(object.Characteristics) ? globalThis.Number(object.Characteristics) : 0, + TimeDateStamp: isSet(object.TimeDateStamp) ? globalThis.Number(object.TimeDateStamp) : 0, + MajorVersion: isSet(object.MajorVersion) ? globalThis.Number(object.MajorVersion) : 0, + MinorVersion: isSet(object.MinorVersion) ? globalThis.Number(object.MinorVersion) : 0, + Name: isSet(object.Name) ? globalThis.Number(object.Name) : 0, + Base: isSet(object.Base) ? globalThis.Number(object.Base) : 0, + NumberOfFunctions: isSet(object.NumberOfFunctions) ? globalThis.Number(object.NumberOfFunctions) : 0, + NumberOfNames: isSet(object.NumberOfNames) ? globalThis.Number(object.NumberOfNames) : 0, + AddressOfFunctions: isSet(object.AddressOfFunctions) ? globalThis.Number(object.AddressOfFunctions) : 0, + AddressOfNames: isSet(object.AddressOfNames) ? globalThis.Number(object.AddressOfNames) : 0, + AddressOfNameOrdinals: isSet(object.AddressOfNameOrdinals) ? globalThis.Number(object.AddressOfNameOrdinals) : 0, + }; + }, + + toJSON(message: imageExportDirectory): unknown { + const obj: any = {}; + if (message.Characteristics !== 0) { + obj.Characteristics = Math.round(message.Characteristics); + } + if (message.TimeDateStamp !== 0) { + obj.TimeDateStamp = Math.round(message.TimeDateStamp); + } + if (message.MajorVersion !== 0) { + obj.MajorVersion = Math.round(message.MajorVersion); + } + if (message.MinorVersion !== 0) { + obj.MinorVersion = Math.round(message.MinorVersion); + } + if (message.Name !== 0) { + obj.Name = Math.round(message.Name); + } + if (message.Base !== 0) { + obj.Base = Math.round(message.Base); + } + if (message.NumberOfFunctions !== 0) { + obj.NumberOfFunctions = Math.round(message.NumberOfFunctions); + } + if (message.NumberOfNames !== 0) { + obj.NumberOfNames = Math.round(message.NumberOfNames); + } + if (message.AddressOfFunctions !== 0) { + obj.AddressOfFunctions = Math.round(message.AddressOfFunctions); + } + if (message.AddressOfNames !== 0) { + obj.AddressOfNames = Math.round(message.AddressOfNames); + } + if (message.AddressOfNameOrdinals !== 0) { + obj.AddressOfNameOrdinals = Math.round(message.AddressOfNameOrdinals); + } + return obj; + }, + + create(base?: DeepPartial): imageExportDirectory { + return imageExportDirectory.fromPartial(base ?? {}); + }, + fromPartial(object: DeepPartial): imageExportDirectory { + const message = createBaseimageExportDirectory(); + message.Characteristics = object.Characteristics ?? 0; + message.TimeDateStamp = object.TimeDateStamp ?? 0; + message.MajorVersion = object.MajorVersion ?? 0; + message.MinorVersion = object.MinorVersion ?? 0; + message.Name = object.Name ?? 0; + message.Base = object.Base ?? 0; + message.NumberOfFunctions = object.NumberOfFunctions ?? 0; + message.NumberOfNames = object.NumberOfNames ?? 0; + message.AddressOfFunctions = object.AddressOfFunctions ?? 0; + message.AddressOfNames = object.AddressOfNames ?? 0; + message.AddressOfNameOrdinals = object.AddressOfNameOrdinals ?? 0; + return message; + }, +}; + +function createBasePESpoofMetadataConfig(): PESpoofMetadataConfig { + return { + Source: undefined, + Icon: undefined, + ResourceDirectory: undefined, + ResourceDirectoryEntries: [], + ResourceDataEntries: [], + ExportDirectory: undefined, + }; +} + +export const PESpoofMetadataConfig: MessageFns = { + encode(message: PESpoofMetadataConfig, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.Source !== undefined) { + SpoofMetadataFile.encode(message.Source, writer.uint32(10).fork()).join(); + } + if (message.Icon !== undefined) { + SpoofMetadataFile.encode(message.Icon, writer.uint32(18).fork()).join(); + } + if (message.ResourceDirectory !== undefined) { + imageResourceDirectory.encode(message.ResourceDirectory, writer.uint32(82).fork()).join(); + } + for (const v of message.ResourceDirectoryEntries) { + imageResourceDirectoryEntry.encode(v!, writer.uint32(90).fork()).join(); + } + for (const v of message.ResourceDataEntries) { + imageResourceDataEntry.encode(v!, writer.uint32(98).fork()).join(); + } + if (message.ExportDirectory !== undefined) { + imageExportDirectory.encode(message.ExportDirectory, writer.uint32(106).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): PESpoofMetadataConfig { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePESpoofMetadataConfig(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.Source = SpoofMetadataFile.decode(reader, reader.uint32()); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.Icon = SpoofMetadataFile.decode(reader, reader.uint32()); + continue; + } + case 10: { + if (tag !== 82) { + break; + } + + message.ResourceDirectory = imageResourceDirectory.decode(reader, reader.uint32()); + continue; + } + case 11: { + if (tag !== 90) { + break; + } + + message.ResourceDirectoryEntries.push(imageResourceDirectoryEntry.decode(reader, reader.uint32())); + continue; + } + case 12: { + if (tag !== 98) { + break; + } + + message.ResourceDataEntries.push(imageResourceDataEntry.decode(reader, reader.uint32())); + continue; + } + case 13: { + if (tag !== 106) { + break; + } + + message.ExportDirectory = imageExportDirectory.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): PESpoofMetadataConfig { + return { + Source: isSet(object.Source) ? SpoofMetadataFile.fromJSON(object.Source) : undefined, + Icon: isSet(object.Icon) ? SpoofMetadataFile.fromJSON(object.Icon) : undefined, + ResourceDirectory: isSet(object.ResourceDirectory) + ? imageResourceDirectory.fromJSON(object.ResourceDirectory) + : undefined, + ResourceDirectoryEntries: globalThis.Array.isArray(object?.ResourceDirectoryEntries) + ? object.ResourceDirectoryEntries.map((e: any) => imageResourceDirectoryEntry.fromJSON(e)) + : [], + ResourceDataEntries: globalThis.Array.isArray(object?.ResourceDataEntries) + ? object.ResourceDataEntries.map((e: any) => imageResourceDataEntry.fromJSON(e)) + : [], + ExportDirectory: isSet(object.ExportDirectory) + ? imageExportDirectory.fromJSON(object.ExportDirectory) + : undefined, + }; + }, + + toJSON(message: PESpoofMetadataConfig): unknown { + const obj: any = {}; + if (message.Source !== undefined) { + obj.Source = SpoofMetadataFile.toJSON(message.Source); + } + if (message.Icon !== undefined) { + obj.Icon = SpoofMetadataFile.toJSON(message.Icon); + } + if (message.ResourceDirectory !== undefined) { + obj.ResourceDirectory = imageResourceDirectory.toJSON(message.ResourceDirectory); + } + if (message.ResourceDirectoryEntries?.length) { + obj.ResourceDirectoryEntries = message.ResourceDirectoryEntries.map((e) => imageResourceDirectoryEntry.toJSON(e)); + } + if (message.ResourceDataEntries?.length) { + obj.ResourceDataEntries = message.ResourceDataEntries.map((e) => imageResourceDataEntry.toJSON(e)); + } + if (message.ExportDirectory !== undefined) { + obj.ExportDirectory = imageExportDirectory.toJSON(message.ExportDirectory); + } + return obj; + }, + + create(base?: DeepPartial): PESpoofMetadataConfig { + return PESpoofMetadataConfig.fromPartial(base ?? {}); + }, + fromPartial(object: DeepPartial): PESpoofMetadataConfig { + const message = createBasePESpoofMetadataConfig(); + message.Source = (object.Source !== undefined && object.Source !== null) + ? SpoofMetadataFile.fromPartial(object.Source) + : undefined; + message.Icon = (object.Icon !== undefined && object.Icon !== null) + ? SpoofMetadataFile.fromPartial(object.Icon) + : undefined; + message.ResourceDirectory = (object.ResourceDirectory !== undefined && object.ResourceDirectory !== null) + ? imageResourceDirectory.fromPartial(object.ResourceDirectory) + : undefined; + message.ResourceDirectoryEntries = + object.ResourceDirectoryEntries?.map((e) => imageResourceDirectoryEntry.fromPartial(e)) || []; + message.ResourceDataEntries = object.ResourceDataEntries?.map((e) => imageResourceDataEntry.fromPartial(e)) || []; + message.ExportDirectory = (object.ExportDirectory !== undefined && object.ExportDirectory !== null) + ? imageExportDirectory.fromPartial(object.ExportDirectory) + : undefined; + return message; + }, +}; + +function createBaseSpoofMetadataConfig(): SpoofMetadataConfig { + return { PE: undefined }; +} + +export const SpoofMetadataConfig: MessageFns = { + encode(message: SpoofMetadataConfig, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.PE !== undefined) { + PESpoofMetadataConfig.encode(message.PE, writer.uint32(10).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): SpoofMetadataConfig { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseSpoofMetadataConfig(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.PE = PESpoofMetadataConfig.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): SpoofMetadataConfig { + return { PE: isSet(object.PE) ? PESpoofMetadataConfig.fromJSON(object.PE) : undefined }; + }, + + toJSON(message: SpoofMetadataConfig): unknown { + const obj: any = {}; + if (message.PE !== undefined) { + obj.PE = PESpoofMetadataConfig.toJSON(message.PE); + } + return obj; + }, + + create(base?: DeepPartial): SpoofMetadataConfig { + return SpoofMetadataConfig.fromPartial(base ?? {}); + }, + fromPartial(object: DeepPartial): SpoofMetadataConfig { + const message = createBaseSpoofMetadataConfig(); + message.PE = (object.PE !== undefined && object.PE !== null) + ? PESpoofMetadataConfig.fromPartial(object.PE) + : undefined; + return message; + }, +}; + function createBaseTrafficEncoder(): TrafficEncoder { return { ID: "0", Wasm: undefined, SkipTests: false, TestID: "" }; } @@ -10141,7 +11080,7 @@ export const GenerateStageReq: MessageFns = { }; function createBaseGenerate(): Generate { - return { File: undefined }; + return { File: undefined, ImplantName: "", ImplantBuildID: "" }; } export const Generate: MessageFns = { @@ -10149,6 +11088,12 @@ export const Generate: MessageFns = { if (message.File !== undefined) { File.encode(message.File, writer.uint32(10).fork()).join(); } + if (message.ImplantName !== "") { + writer.uint32(18).string(message.ImplantName); + } + if (message.ImplantBuildID !== "") { + writer.uint32(26).string(message.ImplantBuildID); + } return writer; }, @@ -10167,6 +11112,22 @@ export const Generate: MessageFns = { message.File = File.decode(reader, reader.uint32()); continue; } + case 2: { + if (tag !== 18) { + break; + } + + message.ImplantName = reader.string(); + continue; + } + case 3: { + if (tag !== 26) { + break; + } + + message.ImplantBuildID = reader.string(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -10177,7 +11138,11 @@ export const Generate: MessageFns = { }, fromJSON(object: any): Generate { - return { File: isSet(object.File) ? File.fromJSON(object.File) : undefined }; + return { + File: isSet(object.File) ? File.fromJSON(object.File) : undefined, + ImplantName: isSet(object.ImplantName) ? globalThis.String(object.ImplantName) : "", + ImplantBuildID: isSet(object.ImplantBuildID) ? globalThis.String(object.ImplantBuildID) : "", + }; }, toJSON(message: Generate): unknown { @@ -10185,6 +11150,12 @@ export const Generate: MessageFns = { if (message.File !== undefined) { obj.File = File.toJSON(message.File); } + if (message.ImplantName !== "") { + obj.ImplantName = message.ImplantName; + } + if (message.ImplantBuildID !== "") { + obj.ImplantBuildID = message.ImplantBuildID; + } return obj; }, @@ -10194,6 +11165,118 @@ export const Generate: MessageFns = { fromPartial(object: DeepPartial): Generate { const message = createBaseGenerate(); message.File = (object.File !== undefined && object.File !== null) ? File.fromPartial(object.File) : undefined; + message.ImplantName = object.ImplantName ?? ""; + message.ImplantBuildID = object.ImplantBuildID ?? ""; + return message; + }, +}; + +function createBaseGenerateSpoofMetadataReq(): GenerateSpoofMetadataReq { + return { ImplantBuildID: "", ImplantName: "", ResourceID: "0", SpoofMetadata: undefined }; +} + +export const GenerateSpoofMetadataReq: MessageFns = { + encode(message: GenerateSpoofMetadataReq, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.ImplantBuildID !== "") { + writer.uint32(10).string(message.ImplantBuildID); + } + if (message.ImplantName !== "") { + writer.uint32(18).string(message.ImplantName); + } + if (message.ResourceID !== "0") { + writer.uint32(24).uint64(message.ResourceID); + } + if (message.SpoofMetadata !== undefined) { + SpoofMetadataConfig.encode(message.SpoofMetadata, writer.uint32(82).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GenerateSpoofMetadataReq { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGenerateSpoofMetadataReq(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.ImplantBuildID = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.ImplantName = reader.string(); + continue; + } + case 3: { + if (tag !== 24) { + break; + } + + message.ResourceID = reader.uint64().toString(); + continue; + } + case 10: { + if (tag !== 82) { + break; + } + + message.SpoofMetadata = SpoofMetadataConfig.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GenerateSpoofMetadataReq { + return { + ImplantBuildID: isSet(object.ImplantBuildID) ? globalThis.String(object.ImplantBuildID) : "", + ImplantName: isSet(object.ImplantName) ? globalThis.String(object.ImplantName) : "", + ResourceID: isSet(object.ResourceID) ? globalThis.String(object.ResourceID) : "0", + SpoofMetadata: isSet(object.SpoofMetadata) ? SpoofMetadataConfig.fromJSON(object.SpoofMetadata) : undefined, + }; + }, + + toJSON(message: GenerateSpoofMetadataReq): unknown { + const obj: any = {}; + if (message.ImplantBuildID !== "") { + obj.ImplantBuildID = message.ImplantBuildID; + } + if (message.ImplantName !== "") { + obj.ImplantName = message.ImplantName; + } + if (message.ResourceID !== "0") { + obj.ResourceID = message.ResourceID; + } + if (message.SpoofMetadata !== undefined) { + obj.SpoofMetadata = SpoofMetadataConfig.toJSON(message.SpoofMetadata); + } + return obj; + }, + + create(base?: DeepPartial): GenerateSpoofMetadataReq { + return GenerateSpoofMetadataReq.fromPartial(base ?? {}); + }, + fromPartial(object: DeepPartial): GenerateSpoofMetadataReq { + const message = createBaseGenerateSpoofMetadataReq(); + message.ImplantBuildID = object.ImplantBuildID ?? ""; + message.ImplantName = object.ImplantName ?? ""; + message.ResourceID = object.ResourceID ?? "0"; + message.SpoofMetadata = (object.SpoofMetadata !== undefined && object.SpoofMetadata !== null) + ? SpoofMetadataConfig.fromPartial(object.SpoofMetadata) + : undefined; return message; }, }; diff --git a/src/pb/commonpb/common.ts b/src/pb/commonpb/common.ts index 5cdb507..0004748 100644 --- a/src/pb/commonpb/common.ts +++ b/src/pb/commonpb/common.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.2 -// protoc v3.15.8 +// protoc v6.33.4 // source: commonpb/common.proto /* eslint-disable */ diff --git a/src/pb/dnspb/dns.ts b/src/pb/dnspb/dns.ts index b9caf9b..e94f7a6 100644 --- a/src/pb/dnspb/dns.ts +++ b/src/pb/dnspb/dns.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.2 -// protoc v3.15.8 +// protoc v6.33.4 // source: dnspb/dns.proto /* eslint-disable */ diff --git a/src/pb/rpcpb/services.ts b/src/pb/rpcpb/services.ts index b7278b1..8fbc106 100644 --- a/src/pb/rpcpb/services.ts +++ b/src/pb/rpcpb/services.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.2 -// protoc v3.15.8 +// protoc v6.33.4 // source: rpcpb/services.proto /* eslint-disable */ @@ -46,6 +46,7 @@ import { ExternalImplantConfig, Generate, GenerateReq, + GenerateSpoofMetadataReq, GenerateStageReq, GetSystemReq, Host, @@ -637,6 +638,14 @@ export const SliverRPCDefinition = { responseStream: false, options: {}, }, + generateSpoofMetadata: { + name: "GenerateSpoofMetadata", + requestType: GenerateSpoofMetadataReq, + requestStream: false, + responseType: Empty, + responseStream: false, + options: {}, + }, generateExternal: { name: "GenerateExternal", requestType: ExternalGenerateReq, @@ -1799,6 +1808,10 @@ export interface SliverRPCServiceImplementation { hostIOCRm(request: IOC, context: CallContext & CallContextExt): Promise>; /** ** Implants *** */ generate(request: GenerateReq, context: CallContext & CallContextExt): Promise>; + generateSpoofMetadata( + request: GenerateSpoofMetadataReq, + context: CallContext & CallContextExt, + ): Promise>; generateExternal( request: ExternalGenerateReq, context: CallContext & CallContextExt, @@ -2152,6 +2165,10 @@ export interface SliverRPCClient { hostIOCRm(request: DeepPartial, options?: CallOptions & CallOptionsExt): Promise; /** ** Implants *** */ generate(request: DeepPartial, options?: CallOptions & CallOptionsExt): Promise; + generateSpoofMetadata( + request: DeepPartial, + options?: CallOptions & CallOptionsExt, + ): Promise; generateExternal( request: DeepPartial, options?: CallOptions & CallOptionsExt, diff --git a/src/pb/sliverpb/sliver.ts b/src/pb/sliverpb/sliver.ts index afbba75..b0e6315 100644 --- a/src/pb/sliverpb/sliver.ts +++ b/src/pb/sliverpb/sliver.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.2 -// protoc v3.15.8 +// protoc v6.33.4 // source: sliverpb/sliver.proto /* eslint-disable */ @@ -1102,6 +1102,7 @@ export interface ReconfigureReq { ReconnectInterval: string; BeaconInterval: string; BeaconJitter: string; + C2URI: string; Request?: Request | undefined; } @@ -16153,7 +16154,7 @@ export const WGTCPForwarders: MessageFns = { }; function createBaseReconfigureReq(): ReconfigureReq { - return { ReconnectInterval: "0", BeaconInterval: "0", BeaconJitter: "0", Request: undefined }; + return { ReconnectInterval: "0", BeaconInterval: "0", BeaconJitter: "0", C2URI: "", Request: undefined }; } export const ReconfigureReq: MessageFns = { @@ -16167,6 +16168,9 @@ export const ReconfigureReq: MessageFns = { if (message.BeaconJitter !== "0") { writer.uint32(24).int64(message.BeaconJitter); } + if (message.C2URI !== "") { + writer.uint32(34).string(message.C2URI); + } if (message.Request !== undefined) { Request.encode(message.Request, writer.uint32(74).fork()).join(); } @@ -16204,6 +16208,14 @@ export const ReconfigureReq: MessageFns = { message.BeaconJitter = reader.int64().toString(); continue; } + case 4: { + if (tag !== 34) { + break; + } + + message.C2URI = reader.string(); + continue; + } case 9: { if (tag !== 74) { break; @@ -16226,6 +16238,7 @@ export const ReconfigureReq: MessageFns = { ReconnectInterval: isSet(object.ReconnectInterval) ? globalThis.String(object.ReconnectInterval) : "0", BeaconInterval: isSet(object.BeaconInterval) ? globalThis.String(object.BeaconInterval) : "0", BeaconJitter: isSet(object.BeaconJitter) ? globalThis.String(object.BeaconJitter) : "0", + C2URI: isSet(object.C2URI) ? globalThis.String(object.C2URI) : "", Request: isSet(object.Request) ? Request.fromJSON(object.Request) : undefined, }; }, @@ -16241,6 +16254,9 @@ export const ReconfigureReq: MessageFns = { if (message.BeaconJitter !== "0") { obj.BeaconJitter = message.BeaconJitter; } + if (message.C2URI !== "") { + obj.C2URI = message.C2URI; + } if (message.Request !== undefined) { obj.Request = Request.toJSON(message.Request); } @@ -16255,6 +16271,7 @@ export const ReconfigureReq: MessageFns = { message.ReconnectInterval = object.ReconnectInterval ?? "0"; message.BeaconInterval = object.BeaconInterval ?? "0"; message.BeaconJitter = object.BeaconJitter ?? "0"; + message.C2URI = object.C2URI ?? ""; message.Request = (object.Request !== undefined && object.Request !== null) ? Request.fromPartial(object.Request) : undefined; diff --git a/src/tests/__snapshots__/rpc-definition.test.ts.snap b/src/tests/__snapshots__/rpc-definition.test.ts.snap index f024982..4d2a30c 100644 --- a/src/tests/__snapshots__/rpc-definition.test.ts.snap +++ b/src/tests/__snapshots__/rpc-definition.test.ts.snap @@ -304,6 +304,12 @@ exports[`RPC definition includes all methods (snapshot) 1`] = ` "requestStream": false, "responseStream": false, }, + { + "key": "generateSpoofMetadata", + "name": "GenerateSpoofMetadata", + "requestStream": false, + "responseStream": false, + }, { "key": "generateStage", "name": "GenerateStage", diff --git a/src/tests/rpc-wrappers.test.ts b/src/tests/rpc-wrappers.test.ts index 1d4e917..6b39493 100644 --- a/src/tests/rpc-wrappers.test.ts +++ b/src/tests/rpc-wrappers.test.ts @@ -2,7 +2,18 @@ import { Subject } from "rxjs"; import { SliverClient, InteractiveBeacon } from "../client"; import type { SliverClientConfig } from "../config"; -import { BeaconTask, type Event, ListenerJob, Operators, Sessions, Session, KillJob, Loot, WebContent } from "../pb/clientpb/client"; +import { + BeaconTask, + type Event, + type GenerateSpoofMetadataReq, + ListenerJob, + Operators, + Sessions, + Session, + KillJob, + Loot, + WebContent, +} from "../pb/clientpb/client"; import { Empty } from "../pb/commonpb/common"; import { Ls } from "../pb/sliverpb/sliver"; @@ -111,6 +122,25 @@ test("SliverClient.websiteUpdateContent() forwards to rpc.websiteUpdateContent() ); }); +test("SliverClient.generateSpoofMetadata() forwards to rpc.generateSpoofMetadata()", async () => { + const generateSpoofMetadata = jest.fn(async () => Empty.create({})); + + const client = new SliverClient(dummyConfig()); + (client as any).rpcClient = { generateSpoofMetadata }; + + const req: GenerateSpoofMetadataReq = { + ImplantBuildID: "build-1", + ImplantName: "implant-1", + ResourceID: "42", + }; + + await client.generateSpoofMetadata(req, 5); + expect(generateSpoofMetadata).toHaveBeenCalledWith( + req, + expect.objectContaining({ signal: expect.any(AbortSignal) }), + ); +}); + test("InteractiveBeacon.lsTask().wait() decodes beacon task results", async () => { const taskId = "task-1"; const beaconId = "beacon-1";