diff --git a/package.json b/package.json index 2b70c31..46ba5e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sliver-script", - "version": "1.2.4", + "version": "1.2.5", "description": "TypeScript/JavaScript Sliver client library", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/src/client.ts b/src/client.ts index 74ca441..136df6e 100644 --- a/src/client.ts +++ b/src/client.ts @@ -66,7 +66,7 @@ class BaseCommands { return uint8Array; } - ping(nonce: number, timeout = TIMEOUT): Promise { + ping(nonce: number, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const ping = new sliverpb.Ping(); ping.Request = this.request(timeout); @@ -77,7 +77,7 @@ class BaseCommands { }); } - ps(timeout = TIMEOUT): Promise { + ps(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.PsReq(); req.Request = this.request(timeout); @@ -87,7 +87,7 @@ class BaseCommands { }); } - terminate(pid: number, timeout = TIMEOUT): Promise { + terminate(pid: number, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.TerminateReq(); req.Pid = pid; @@ -98,7 +98,7 @@ class BaseCommands { }); } - ifconfig(timeout = TIMEOUT): Promise { + ifconfig(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.IfconfigReq(); req.Request = this.request(timeout); @@ -108,7 +108,7 @@ class BaseCommands { }); } - netstat(timeout = TIMEOUT): Promise { + netstat(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.NetstatReq(); req.Request = this.request(timeout); @@ -118,7 +118,7 @@ class BaseCommands { }); } - ls(path = '.', timeout = TIMEOUT): Promise { + ls(path = '.', timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.LsReq(); req.Path = path; @@ -129,7 +129,7 @@ class BaseCommands { }); } - cd(path: string, timeout = TIMEOUT): Promise { + cd(path: string, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.CdReq(); req.Path = path; @@ -140,7 +140,7 @@ class BaseCommands { }); } - pwd(timeout = TIMEOUT): Promise { + pwd(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.PwdReq(); req.Request = this.request(timeout); @@ -150,7 +150,7 @@ class BaseCommands { }); } - rm(path: string, timeout = TIMEOUT): Promise { + rm(path: string, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.RmReq(); req.Path = path; @@ -161,7 +161,7 @@ class BaseCommands { }); } - mkdir(path: string, timeout = TIMEOUT): Promise { + mkdir(path: string, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.MkdirReq(); req.Path = path; @@ -192,7 +192,7 @@ class BaseCommands { }); } - upload(path: string, data: Buffer, timeout = TIMEOUT): Promise { + upload(path: string, data: Buffer, timeout = TIMEOUT): Promise { return new Promise(async (resolve, reject) => { const req = new sliverpb.UploadReq(); req.Path = path; @@ -206,7 +206,7 @@ class BaseCommands { }); } - processDump(pid: number, timeout = TIMEOUT): Promise { + processDump(pid: number, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.ProcessDumpReq(); req.Pid = pid; @@ -217,7 +217,7 @@ class BaseCommands { }); } - runAs(userName: string, processName: string, args: string, timeout = TIMEOUT): Promise { + runAs(userName: string, processName: string, args: string, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.RunAsReq(); req.Username = userName; @@ -230,7 +230,7 @@ class BaseCommands { }); } - impersonate(userName: string, timeout = TIMEOUT): Promise { + impersonate(userName: string, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.ImpersonateReq(); req.Username = userName; @@ -241,7 +241,7 @@ class BaseCommands { }); } - revToSelf(timeout = TIMEOUT): Promise { + revToSelf(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.RevToSelfReq(); req.Request = this.request(timeout); @@ -251,7 +251,7 @@ class BaseCommands { }); } - getSystem(hostingProcess: string, config: clientpb.ImplantConfig, timeout = TIMEOUT): Promise { + getSystem(hostingProcess: string, config: clientpb.ImplantConfig, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new clientpb.GetSystemReq(); req.HostingProcess = hostingProcess; @@ -264,7 +264,7 @@ class BaseCommands { } // 'shellcode' aka "task" - executeShellcode(pid: number, shellcode: Buffer, encoder: string, rwx: boolean, timeout = TIMEOUT): Promise { + executeShellcode(pid: number, shellcode: Buffer, encoder: string, rwx: boolean, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.TaskReq(); req.Encoder = encoder; @@ -309,7 +309,7 @@ class BaseCommands { }); } - executeAssembly(assembly: Buffer, args: string, process: string, timeout = TIMEOUT): Promise { + executeAssembly(assembly: Buffer, args: string, process: string, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.ExecuteAssemblyReq(); req.Assembly = assembly; @@ -322,7 +322,7 @@ class BaseCommands { }); } - migrate(pid: number, config: clientpb.ImplantConfig, timeout = TIMEOUT): Promise { + migrate(pid: number, config: clientpb.ImplantConfig, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new clientpb.MigrateReq(); req.Pid = pid; @@ -334,7 +334,7 @@ class BaseCommands { }); } - execute(exe: string, args: string[], output: boolean, timeout = TIMEOUT): Promise { + execute(exe: string, args: string[], output: boolean, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.ExecuteReq(); req.Path = exe; @@ -347,7 +347,7 @@ class BaseCommands { }); } - sideload(data: Buffer, processName: string, args: string, entryPoint: string, timeout = TIMEOUT): Promise { + sideload(data: Buffer, processName: string, args: string, entryPoint: string, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.SideloadReq(); req.Data = data; @@ -361,7 +361,7 @@ class BaseCommands { }); } - spawnDLL(data: Buffer, entrypoint: string, processName: string, args: string, timeout = TIMEOUT): Promise { + spawnDLL(data: Buffer, entrypoint: string, processName: string, args: string, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.InvokeSpawnDllReq(); req.Data = data; @@ -375,7 +375,7 @@ class BaseCommands { }); } - screenshot(timeout = TIMEOUT): Promise { + screenshot(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new sliverpb.ScreenshotReq(); req.Request = this.request(timeout); @@ -419,7 +419,7 @@ export class InteractiveBeacon extends BaseCommands { if (beaconTask.ID === lsTask?.Response?.TaskID) { this._pendingTasks.get(beaconTask.ID)?.unsubscribe(); this._pendingTasks.delete(beaconTask.ID); - const taskReq = new clientpb.BeaconTask({ID: beaconTask.ID}); + const taskReq = new clientpb.BeaconTask({ ID: beaconTask.ID }); this._rpc.GetBeaconTaskContent(taskReq, async (err, taskContent) => { if (err || !taskContent) { reject(err); @@ -469,7 +469,7 @@ export class InteractiveSession extends BaseCommands { const tunnelData = new sliverpb.TunnelData(); tunnelData.SessionID = this._sessionID; tunnelData.TunnelID = tunnelId; - + this._tunnelStream.write(tunnelData, () => { const req = new sliverpb.ShellReq(); req.TunnelID = tunnelId; @@ -493,7 +493,9 @@ export class InteractiveSession extends BaseCommands { } producer.complete(); } else { - producer.next(Buffer.from(tunnelData.Data)); + if (tunnelData?.Data.length) { + producer.next(Buffer.from(tunnelData.Data)); + } } }); }); @@ -543,7 +545,7 @@ export class SliverClient { taskresult$ = this.event$.pipe(filter(event => event.EventType === this.BEACON_TASKRESULT)); // Filter anything that doesn't match one of the loot event types - loot$ = this.event$.pipe(filter(event => this.lootEventTypes.some(lootEventType => { + loot$ = this.event$.pipe(filter(event => this.lootEventTypes.some(lootEventType => { lootEventType === event.EventType }))); @@ -561,7 +563,7 @@ export class SliverClient { const ca = Buffer.from(this._config.ca_certificate); const privateKey = Buffer.from(this._config.private_key); const certificate = Buffer.from(this._config.certificate); - + return grpc.credentials.combineChannelCredentials( grpc.credentials.createSsl(ca, privateKey, certificate, { checkServerIdentity: () => undefined, @@ -648,7 +650,7 @@ export class SliverClient { // ---- Version ---- - getVersion(timeout = TIMEOUT): Promise { + getVersion(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.GetVersion(this.empty, this.deadline(timeout), (err, version) => { err ? reject(err) : resolve(version); @@ -658,7 +660,7 @@ export class SliverClient { // ---- Operators ---- - getOperators(timeout = TIMEOUT): Promise { + getOperators(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.GetOperators(this.empty, this.deadline(timeout), (err, operators) => { err ? reject(err) : resolve(operators?.Operators); @@ -668,7 +670,7 @@ export class SliverClient { // ---- Sessions ---- - sessions(timeout = TIMEOUT): Promise { + sessions(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.GetSessions(this.empty, this.deadline(timeout), (err, sessions) => { err ? reject(err) : resolve(sessions?.Sessions); @@ -680,7 +682,7 @@ export class SliverClient { return new InteractiveSession(this.rpc, this.tunnelStream, sessionID); } - beacons(timeout = TIMEOUT): Promise { + beacons(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.GetBeacons(this.empty, this.deadline(timeout), (err, beacons) => { err ? reject(err) : resolve(beacons?.Beacons); @@ -694,7 +696,7 @@ export class SliverClient { // ---- Jobs ---- - jobs(timeout = TIMEOUT): Promise { + jobs(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.GetJobs(this.empty, this.deadline(timeout), (err, jobs) => { err ? reject(err) : resolve(jobs?.Active); @@ -702,7 +704,7 @@ export class SliverClient { }); } - killJob(jobId: number, timeout = TIMEOUT): Promise { + killJob(jobId: number, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const killJob = new clientpb.KillJobReq(); killJob.ID = jobId; @@ -714,7 +716,7 @@ export class SliverClient { // ---- Listeners ---- - startMTLSListener(host: string, port: number, persistent = false, timeout = TIMEOUT): Promise { + startMTLSListener(host: string, port: number, persistent = false, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const mtls = new clientpb.MTLSListenerReq(); mtls.Host = host; @@ -726,7 +728,7 @@ export class SliverClient { }); } - startDNSListener(domains: string[], canaries: boolean, host: string, port: number, persistent = false, timeout = TIMEOUT): Promise { + startDNSListener(domains: string[], canaries: boolean, host: string, port: number, persistent = false, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const dns = new clientpb.DNSListenerReq(); dns.Domains = domains; @@ -740,7 +742,7 @@ export class SliverClient { }); } - startHTTPListener(domain: string, host: string, port: number, website = '', persistent = false, timeout = TIMEOUT): Promise { + startHTTPListener(domain: string, host: string, port: number, website = '', persistent = false, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const http = new clientpb.HTTPListenerReq(); http.Domain = domain; @@ -756,7 +758,7 @@ export class SliverClient { } startHTTPSListener(domain: string, host: string, port: number, acme = false, website = '', - cert?: Buffer, key?: Buffer, persistent = false, timeout = TIMEOUT): Promise { + cert?: Buffer, key?: Buffer, persistent = false, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const https = new clientpb.HTTPListenerReq(); https.Domain = domain; @@ -774,7 +776,7 @@ export class SliverClient { }); } - startWGListener(port: number, nPort: number, keyPort: number, persistent = false, timeout = TIMEOUT): Promise { + startWGListener(port: number, nPort: number, keyPort: number, persistent = false, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new clientpb.WGListenerReq(); req.Port = port; @@ -787,7 +789,7 @@ export class SliverClient { }); } - startTCPStagerListener(host: string, port: number, data: Buffer, timeout = TIMEOUT): Promise { + startTCPStagerListener(host: string, port: number, data: Buffer, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new clientpb.StagerListenerReq(); req.Protocol = clientpb.StageProtocol.TCP; @@ -800,7 +802,7 @@ export class SliverClient { }); } - startHTTPStagerListener(host: string, port: number, data: Buffer, timeout = TIMEOUT): Promise { + startHTTPStagerListener(host: string, port: number, data: Buffer, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new clientpb.StagerListenerReq(); req.Protocol = clientpb.StageProtocol.HTTP; @@ -813,7 +815,7 @@ export class SliverClient { }); } - startHTTPSStagerListener(host: string, port: number, data: Buffer, timeout = TIMEOUT): Promise { + startHTTPSStagerListener(host: string, port: number, data: Buffer, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new clientpb.StagerListenerReq(); req.Protocol = clientpb.StageProtocol.HTTPS; @@ -828,7 +830,7 @@ export class SliverClient { // ---- Implants ---- - generate(config: clientpb.ImplantConfig, timeout = TIMEOUT): Promise { + generate(config: clientpb.ImplantConfig, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new clientpb.GenerateReq(); req.Config = config; @@ -838,7 +840,7 @@ export class SliverClient { }); } - compilerInfo(timeout = TIMEOUT): Promise { + compilerInfo(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.GetCompiler(new commonpb.Empty(), this.deadline(timeout), (err, info) => { err ? reject(err) : resolve(info); @@ -846,7 +848,7 @@ export class SliverClient { }); } - regenerate(name: string, timeout = TIMEOUT): Promise { + regenerate(name: string, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const req = new clientpb.RegenerateReq(); req.ImplantName = name; @@ -856,7 +858,7 @@ export class SliverClient { }); } - implantBuilds(timeout = TIMEOUT): Promise { + implantBuilds(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.ImplantBuilds(this.empty, this.deadline(timeout), (err, builds) => { err ? reject(err) : resolve(builds); @@ -874,7 +876,7 @@ export class SliverClient { }); } - canaries(timeout = TIMEOUT): Promise { + canaries(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.Canaries(this.empty, this.deadline(timeout), (err, canaries) => { err ? reject(err) : resolve(canaries?.Canaries); @@ -882,7 +884,7 @@ export class SliverClient { }); } - implantProfiles(timeout = TIMEOUT): Promise { + implantProfiles(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.ImplantProfiles(this.empty, this.deadline(timeout), (err, profiles) => { err ? reject(err) : resolve(profiles?.Profiles); @@ -890,7 +892,7 @@ export class SliverClient { }); } - saveImplantProfile(profile: clientpb.ImplantProfile, timeout = TIMEOUT): Promise { + saveImplantProfile(profile: clientpb.ImplantProfile, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.SaveImplantProfile(profile, this.deadline(timeout), (err, profile) => { err ? reject(err) : resolve(profile); @@ -909,7 +911,7 @@ export class SliverClient { } // ---- Loot ---- - lootAll(timeout = TIMEOUT): Promise { + lootAll(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.LootAll(this.empty, this.deadline(timeout), (err, loot) => { err ? reject(err) : resolve(loot?.Loot); @@ -917,7 +919,7 @@ export class SliverClient { }); } - lootAllOf(lootType: string, timeout = TIMEOUT): Promise { + lootAllOf(lootType: string, timeout = TIMEOUT): Promise { // There doesn't seem to be a good way to strongly type this parameter const loot = new clientpb.Loot(); @@ -947,7 +949,7 @@ export class SliverClient { }); } - lootAdd(loot: clientpb.Loot, timeout = TIMEOUT): Promise { + lootAdd(loot: clientpb.Loot, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.LootAdd(loot, this.deadline(timeout), (err, loot) => { err ? reject(err) : resolve(loot); @@ -955,7 +957,7 @@ export class SliverClient { }); } - lootUpdate(lootID: string, name: string, timeout = TIMEOUT): Promise { + lootUpdate(lootID: string, name: string, timeout = TIMEOUT): Promise { const loot = new clientpb.Loot(); loot.LootID = lootID; loot.Name = name; @@ -976,7 +978,7 @@ export class SliverClient { }); } - lootContent(lootID: string, timeout = TIMEOUT): Promise { + lootContent(lootID: string, timeout = TIMEOUT): Promise { const loot = new clientpb.Loot(); loot.LootID = lootID; return new Promise((resolve, reject) => { @@ -987,8 +989,8 @@ export class SliverClient { } // ---- Websites ---- - - websites(timeout = TIMEOUT): Promise { + + websites(timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { this.rpc.Websites(this.empty, this.deadline(timeout), (err, websites) => { err ? reject(err) : resolve(websites?.Websites); @@ -996,7 +998,7 @@ export class SliverClient { }); } - website(name: string, timeout = TIMEOUT): Promise { + website(name: string, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const web = new clientpb.Website(); web.Name = name; @@ -1016,7 +1018,7 @@ export class SliverClient { }); } - websiteAddContent(name: string, contents: Map, timeout = TIMEOUT): Promise { + websiteAddContent(name: string, contents: Map, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const addContent = new clientpb.WebsiteAddContent(); addContent.Name = name; @@ -1027,7 +1029,7 @@ export class SliverClient { }); } - websiteUpdateContent(name: string, contents: Map, timeout = TIMEOUT): Promise { + websiteUpdateContent(name: string, contents: Map, timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const addContent = new clientpb.WebsiteAddContent(); addContent.Name = name; @@ -1038,7 +1040,7 @@ export class SliverClient { }); } - websiteRemoveContent(name: string, paths: string[], timeout = TIMEOUT): Promise { + websiteRemoveContent(name: string, paths: string[], timeout = TIMEOUT): Promise { return new Promise((resolve, reject) => { const rm = new clientpb.WebsiteRemoveContent(); rm.Name = name;