{"record":{"id":"a50842616e822f11","repo":"shadow1ng/fscan","slug":"local-pe-not-found-a50842","errorCode":null,"errorMessage":"local_pe_not_found","messagePattern":"local_pe_not_found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/local/winlogon.go","lineNumber":32,"sourceCode":"\t\"github.com/shadow1ng/fscan/common/i18n\"\n\t\"github.com/shadow1ng/fscan/plugins\"\n)\n\ntype WinLogonPlugin struct {\n\tplugins.BasePlugin\n}\n\nfunc NewWinLogonPlugin() *WinLogonPlugin {\n\treturn &WinLogonPlugin{BasePlugin: plugins.NewBasePlugin(\"winlogon\")}\n}\n\nfunc (p *WinLogonPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *plugins.Result {\n\tpePath := session.Config.WinPEFile\n\tif pePath == \"\" {\n\t\treturn &plugins.Result{Success: false, Error: fmt.Errorf(\"%s\", i18n.GetText(\"local_pe_not_specified\"))}\n\t}\n\tif _, err := os.Stat(pePath); err != nil {\n\t\treturn &plugins.Result{Success: false, Error: fmt.Errorf(\"%s\", i18n.Tr(\"local_pe_not_found\", pePath))}\n\t}\n\n\tabsPath, _ := filepath.Abs(pePath)\n\tkey := `HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon`\n\n\tentries := []struct {\n\t\tname  string\n\t\tvalue string\n\t\tdesc  string\n\t}{\n\t\t{\"Userinit\", fmt.Sprintf(`C:\\Windows\\system32\\userinit.exe,%s`, absPath), i18n.GetText(\"winlogon_userinit_append\")},\n\t\t{\"Shell\", fmt.Sprintf(`explorer.exe,%s`, absPath), i18n.GetText(\"winlogon_shell_append\")},\n\t}\n\n\tvar output strings.Builder\n\tvar successCount int\n\n\tfor _, e := range entries {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/local/winlogon.go#L14-L50","documentation":"WinLogonPlugin.Scan verifies the configured PE path exists with os.Stat before writing HKLM Winlogon registry entries. If Stat fails, Scan returns a failed Result with the localized \"local_pe_not_found\" message. This guards against configuring a Winlogon hijack to a missing executable.","triggerScenarios":"os.Stat(pePath) returns an error for the non-empty WinPEFile value — path typo, file deleted/quarantined, relative path broken by a different working directory, or inaccessible drive/permissions.","commonSituations":"Path referencing the target host's filesystem instead of the local one, UNC path unreachable, antivirus removing the binary, or a renamed file after the config was written.","solutions":["Verify the file exists locally: Test-Path <pePath>, then correct the WinPEFile value.","Use an absolute path and confirm the drive/share is accessible from the scanning host.","Restore the file from antivirus quarantine or add an exclusion.","Re-check permissions on the file and its directories for the running user."],"exampleFix":"// before\nsession.Config.WinPEFile = \"\\\\\\\\server\\\\share\\\\payload.exe\" // share unreachable -> Stat fails\n// after\np := \"C:\\\\tools\\\\payload.exe\"\nif _, err := os.Stat(p); err != nil {\n    log.Fatalf(\"WinPEFile invalid: %v\", err)\n}\nsession.Config.WinPEFile = p","handlingStrategy":"validation","validationCode":"// Check the Winlogon payload path exists and is a regular file\nfi, err := os.Stat(session.Config.WinPEFile)\nif err != nil {\n    return fmt.Errorf(\"WinPEFile missing: %w\", err)\n}\nif !fi.Mode().IsRegular() {\n    return fmt.Errorf(\"WinPEFile is not a regular file\")","typeGuard":null,"tryCatchPattern":"result := plugin.Scan(ctx, host, session)\nif result != nil && !result.Success && strings.Contains(result.Error.Error(), i18n.GetText(\"local_pe_not_found\")) {\n    // correct the configured path and re-run\n}","preventionTips":["Use absolute, local-disk paths for WinPEFile.","Confirm the file survived between config creation and scan execution.","Verify AV exclusions so the payload isn't removed before the Winlogon write."],"tags":["file","configuration","windows","winlogon"],"backgroundTag":"file-not-found","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}