fix: 修复-user/-pwd凭据参数不生效的问题

问题原因:
- Parse()解析凭据后更新globalConfig
- 但BuildConfigFromFlags()创建新Config时使用默认字典
- 导致解析的UserPassPairs等凭据信息被丢弃

修复内容:
1. initialize.go: 将Parse解析的凭据结果应用到新Config
2. credential.go: 单用户密码对时创建UserPassPairs
3. rdp.go: 单凭据测试时跳过指纹识别,减少连接次数
This commit is contained in:
ZacharyZcR
2026-01-15 00:10:50 +08:00
parent 90c7f9c27e
commit e504c22d82
3 changed files with 54 additions and 7 deletions
+22 -1
View File
@@ -24,15 +24,36 @@ func Initialize(info *HostInfo) (*InitResult, error) {
// 初始化日志系统
InitLogger()
// 解析和验证参数
// 解析和验证参数(会更新 globalConfig 的凭据信息)
if err := Parse(info); err != nil {
return nil, fmt.Errorf("参数解析失败: %w", err)
}
// 获取 Parse 更新过的凭据信息
parsedCreds := GetGlobalConfig().Credentials
// 从 FlagVars 构建 Config(新架构)
cfg := BuildConfigFromFlags(flagVars)
state := NewState()
// 关键修复:应用 Parse 解析的凭据结果到新 Config
// Parse 会根据 -user/-pwd/-usera/-pwda 等参数更新凭据
if len(parsedCreds.UserPassPairs) > 0 {
cfg.Credentials.UserPassPairs = parsedCreds.UserPassPairs
}
if len(parsedCreds.Userdict) > 0 {
cfg.Credentials.Userdict = parsedCreds.Userdict
}
if len(parsedCreds.Passwords) > 0 {
cfg.Credentials.Passwords = parsedCreds.Passwords
}
if len(parsedCreds.HashValues) > 0 {
cfg.Credentials.HashValues = parsedCreds.HashValues
}
if len(parsedCreds.HashBytes) > 0 {
cfg.Credentials.HashBytes = parsedCreds.HashBytes
}
// 设置全局实例
SetGlobalConfig(cfg)
SetGlobalState(state)
+12
View File
@@ -354,6 +354,18 @@ func (cp *CredentialParser) parseUserPassPairs(input *CredentialInput) ([]config
var errors []error
var warnings []string
// 如果命令行同时指定了单个用户名和单个密码(不是逗号分隔的多个),
// 将其视为精确的用户密码对,而不是做笛卡尔积
if input.Username != "" && input.Password != "" &&
!strings.Contains(input.Username, ",") && !strings.Contains(input.Password, ",") &&
input.UsersFile == "" && input.PasswordsFile == "" && input.UserPassFile == "" {
pairs = append(pairs, config.CredentialPair{
Username: strings.TrimSpace(input.Username),
Password: input.Password, // 密码不trim,可能包含空格
})
return pairs, errors, warnings
}
if input.UserPassFile == "" {
return pairs, errors, warnings
}
+20 -6
View File
@@ -39,12 +39,23 @@ func (p *RDPPlugin) Scan(ctx context.Context, info *common.HostInfo, config *com
login.Socks5Proxy = config.Network.Socks5Proxy
}
// 生成测试凭据(提前生成,用于判断是否为单一凭据测试)
credentials := GenerateCredentials("rdp", config)
// 判断是否为单一凭据测试模式(只有1个凭据时跳过指纹识别)
isSingleCredentialTest := len(credentials) == 1
var osInfo map[string]any
// ============================================
// 第一阶段:系统指纹识别(无需密码)
// 单一凭据测试时跳过此阶段,减少连接次数
// ============================================
osInfo := p.probeOSInfo(target, config, state)
if len(osInfo) > 0 {
p.logOSInfo(target, osInfo)
if !isSingleCredentialTest {
osInfo = p.probeOSInfo(target, config, state)
if len(osInfo) > 0 {
p.logOSInfo(target, osInfo)
}
}
// ============================================
@@ -52,6 +63,12 @@ func (p *RDPPlugin) Scan(ctx context.Context, info *common.HostInfo, config *com
// ============================================
if config.DisableBrute {
// 禁用暴力破解,仅返回服务识别结果
if osInfo == nil {
osInfo = p.probeOSInfo(target, config, state)
if len(osInfo) > 0 {
p.logOSInfo(target, osInfo)
}
}
banner := p.buildBanner(osInfo)
common.LogSuccess(i18n.Tr("rdp_service", target, banner))
return &ScanResult{
@@ -61,9 +78,6 @@ func (p *RDPPlugin) Scan(ctx context.Context, info *common.HostInfo, config *com
Banner: banner,
}
}
// 生成测试凭据
credentials := GenerateCredentials("rdp", config)
if len(credentials) == 0 {
credentials = []Credential{
{Username: "administrator", Password: ""},