Skip to content

Commit cd6c5ad

Browse files
committed
fix(rem): remove --rem-link flag, add nil safety, update docs
- remove redundant --rem-link flag (direct URL via --rem suffices) - update --rem help text to describe pipeline name and URL modes - rpc-rem: add agentID empty check, lns error check, GetRem nil guard - rpc-rem: add req nil check to RemAgentStop - build-beacon: deduplicate "rem" in ThirdModules - docs: update build.md and proxy.md with direct URL usage examples
1 parent 72db438 commit cd6c5ad

4 files changed

Lines changed: 50 additions & 21 deletions

File tree

client/command/build/build-beacon.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,10 @@ func BeaconFlagSet(f *pflag.FlagSet) {
7373

7474
// Network target flags
7575
f.String("addresses", "", "Target addresses (comma-separated)")
76-
f.String("rem-link", "", "Override REM link address (e.g., for CDN scenarios)")
7776

7877
// Legacy flags for backward compatibility
7978
//f.String("proxy", "", "Legacy proxy override (use --proxy-url instead)")
80-
f.String("rem", "", "REM pipeline name or link address (contains :// for direct link)")
79+
f.String("rem", "", "REM pipeline name or direct link address (e.g., rem_default or tcp://cdn:5555)")
8180
f.Bool("auto-download", false, "Auto download artifact after build")
8281
f.Uint32("artifact-id", 0, "Artifact ID for pulse builds")
8382
//f.Uint32("relink", 0, "Relink beacon ID")
@@ -166,15 +165,10 @@ func prepareBuildConfig(cmd *cobra.Command, con *core.Console, buildType string)
166165
if link == "" {
167166
return nil, fmt.Errorf("REM pipeline %q has no link address", remValue)
168167
}
169-
// --rem-link overrides the pipeline link (CDN scenario)
170-
if cmd.Flags().Changed("rem-link") {
171-
remLinkOverride, _ := cmd.Flags().GetString("rem-link")
172-
if remLinkOverride != "" {
173-
link = remLinkOverride
174-
}
175-
}
176168
// rewrite --rem flag value to resolved link so parseBuildFlags sees a real address
177-
cmd.Flags().Set("rem", link)
169+
if err := cmd.Flags().Set("rem", link); err != nil {
170+
return nil, fmt.Errorf("failed to set resolved REM link: %w", err)
171+
}
178172
}
179173
}
180174

@@ -453,7 +447,16 @@ func parseBuildFlags(cmd *cobra.Command, profile *implanttypes.ProfileConfig) (*
453447

454448
if cmd.Flags().Changed("rem") && cmd.Flags().Changed("addresses") {
455449
profile.Implant.Enable3rd = true
456-
profile.Implant.ThirdModules = append(profile.Implant.ThirdModules, "rem")
450+
hasRem := false
451+
for _, m := range profile.Implant.ThirdModules {
452+
if m == "rem" {
453+
hasRem = true
454+
break
455+
}
456+
}
457+
if !hasRem {
458+
profile.Implant.ThirdModules = append(profile.Implant.ThirdModules, "rem")
459+
}
457460
}
458461

459462
ollvm, _ := cmd.Flags().GetBool("ollvm")

docs/operations/build.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,14 @@ build beacon --target x86_64-pc-windows-gnu --profile tcp_default --modules exec
227227
build beacon --profile tcp_default --target x86_64-unknown-linux-musl --interval 1 --jitter 0.2
228228
```
229229

230-
若您需要在beacon中使用rem插件时,可以使用 `--rem` 来配置。
230+
若您需要在beacon中使用rem插件时,可以使用 `--rem` 来配置。`--rem` 支持两种用法:
231+
231232
```bash
232-
build beacon --profile tcp_default --target x86_64-unknown-linux-musl --rem
233+
# 通过 pipeline 名自动解析 link
234+
build beacon --profile tcp_default --target x86_64-unknown-linux-musl --addresses tcp://10.0.0.1:5001 --rem rem_default
235+
236+
# 直接指定 link 地址
237+
build beacon --profile tcp_default --target x86_64-unknown-linux-musl --addresses tcp://10.0.0.1:5001 --rem tcp://cdn.example.com:5555
233238
```
234239

235240
!!!tip "更多有关 `build beacon` 命令的编译选项,请参阅 [构建操作](build.md)"

docs/operations/proxy.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@ execute_shellcode rem.exe -- -c [rem_link] ...
4747
# 加载rem dll
4848
rem_community load
4949

50-
# 选择对应的rem pipeline, 搭建了反向代理隧道
50+
# 通过 pipeline
5151
rem_community socks5 rem_pipeline
52+
53+
# 通过直接 link 地址
54+
rem_community socks5 tcp://10.0.0.1:5555
5255
```
5356

5457
!!! example "优点"
@@ -147,9 +150,9 @@ debug 模式下的日志。 可以看到IoM的implant基于通过rem的构建的
147150

148151
### portfwd(本地端口转发)
149152
```bash
150-
portfwd [pipeline] [flags]
153+
portfwd [pipeline|url] [flags]
151154
```
152-
将本地端口的流量通过 implant 转发到远程目标。
155+
将本地端口的流量通过 implant 转发到远程目标。`[pipeline|url]` 可以是 pipeline 名称或直接的 link 地址(如 `tcp://1.2.3.4:5555`)。
153156

154157
**选项:**
155158

@@ -161,11 +164,12 @@ portfwd [pipeline] [flags]
161164
**示例:**
162165
```bash
163166
portfwd rem_default --port 8080 --target 192.168.1.1:80
167+
portfwd tcp://10.0.0.1:5555 --port 8080 --target 192.168.1.1:80
164168
```
165169

166170
### rportfwd(远程端口转发)
167171
```bash
168-
rportfwd [pipeline] [flags]
172+
rportfwd [pipeline|url] [flags]
169173
```
170174
在 implant 端监听端口,将流量转发回本地。
171175

@@ -179,6 +183,7 @@ rportfwd [pipeline] [flags]
179183
**示例:**
180184
```bash
181185
rportfwd rem_default --port 8080 --remote 10.0.0.1:3389
186+
rportfwd tcp://10.0.0.1:5555 --port 8080 --remote 10.0.0.1:3389
182187
```
183188

184189
### portfwd_local(本地端口转发到客户端)
@@ -209,7 +214,7 @@ rportfwd_local [pipeline] [agent] [flags]
209214

210215
### proxy(代理服务器)
211216
```bash
212-
proxy [pipeline] [flags]
217+
proxy [pipeline|url] [flags]
213218
```
214219
通过 implant 创建代理服务器,支持 socks5/http 协议和认证。
215220

@@ -226,11 +231,12 @@ proxy [pipeline] [flags]
226231
```bash
227232
proxy rem_default --port 1080
228233
proxy rem_default --port 1080 --username admin --password pass
234+
proxy tcp://10.0.0.1:5555 --port 1080
229235
```
230236

231237
### reverse(反向代理)
232238
```bash
233-
reverse [pipeline] [flags]
239+
reverse [pipeline|url] [flags]
234240
```
235241
通过 implant 创建反向代理,implant 主动连接回本地。
236242

@@ -246,11 +252,12 @@ reverse [pipeline] [flags]
246252
**示例:**
247253
```bash
248254
reverse rem_default --port 12345
255+
reverse tcp://10.0.0.1:5555 --port 12345
249256
```
250257

251258
### rem_dial(直接执行 rem 命令)
252259
```bash
253-
rem_dial [pipeline] [args]
260+
rem_dial [pipeline|url] [args]
254261
```
255262
在 implant 上直接执行 rem 命令,适用于需要自定义 rem 参数的高级场景。
256263

server/rpc/rpc-rem.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ func (rpc *Server) RemDial(ctx context.Context, req *implantpb.Request) (*client
210210

211211
greq.HandlerResponse(ch, types.MsgResponse, func(spite *implantpb.Spite) {
212212
agentID := spite.GetResponse().GetOutput()
213+
if agentID == "" {
214+
logs.Log.Warnf("RemDial response has empty agent ID for pipeline %s", pid)
215+
return
216+
}
213217

214218
// resolve pipeline: by name first, fallback to agent ID search
215219
pipe, ok := core.Listeners.Find(pid)
@@ -220,7 +224,11 @@ func (rpc *Server) RemDial(ctx context.Context, req *implantpb.Request) (*client
220224
return
221225
}
222226
}
223-
lns, _ := core.Listeners.Get(pipe.ListenerId)
227+
lns, err := core.Listeners.Get(pipe.ListenerId)
228+
if err != nil {
229+
logs.Log.Warnf("listener %s not found for pipeline %s", pipe.ListenerId, pipe.Name)
230+
return
231+
}
224232
i := lns.PushCtrl(&clientpb.JobCtrl{
225233
Ctrl: consts.CtrlPipelineSync,
226234
Job: &clientpb.Job{
@@ -237,6 +245,9 @@ func (rpc *Server) RemDial(ctx context.Context, req *implantpb.Request) (*client
237245
Spite: spite,
238246
}
239247

248+
if pipe.GetRem() == nil {
249+
return
250+
}
240251
if remOpt, ok := pipe.GetRem().Agents[agentID]; ok {
241252
pivot := output.NewPivotingWithRem(remOpt, pipe)
242253
event.Op = "pivot_" + pivot.InboundSide
@@ -370,6 +381,9 @@ func (rpc *Server) RemAgentLog(ctx context.Context, req *clientpb.REMAgent) (*cl
370381
}
371382

372383
func (rpc *Server) RemAgentStop(ctx context.Context, req *clientpb.REMAgent) (*clientpb.Empty, error) {
384+
if req == nil {
385+
return nil, types.ErrMissingRequestField
386+
}
373387
pipe, ok := core.Listeners.Find(req.PipelineId)
374388
if !ok {
375389
pipe, ok = core.Listeners.FindByRemAgent(req.Id)

0 commit comments

Comments
 (0)