shadow1ng/fscan · error

local_pe_not_found

Error message

local_pe_not_found

What it means

WinRegistryPlugin.Scan stats the path in session.Config.WinPEFile to confirm the local PE file exists before parsing registry autoruns. If os.Stat fails (file missing, bad path, no permission), it returns this localized error with the path interpolated. The plugin does not touch the registry unless the file is present locally.

Source

Thrown at plugins/local/winregistry.go:34

)

type WinRegistryPlugin struct {
	plugins.BasePlugin
}

func NewWinRegistryPlugin() *WinRegistryPlugin {
	return &WinRegistryPlugin{
		BasePlugin: plugins.NewBasePlugin("winregistry"),
	}
}

func (p *WinRegistryPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *plugins.Result {
	pePath := session.Config.WinPEFile
	if pePath == "" {
		return &plugins.Result{Success: false, Error: fmt.Errorf("%s", i18n.GetText("local_pe_not_specified"))}
	}
	if _, err := os.Stat(pePath); err != nil {
		return &plugins.Result{Success: false, Error: fmt.Errorf("%s", i18n.Tr("local_pe_not_found", pePath))}
	}

	absPath, _ := filepath.Abs(pePath)
	baseName := strings.TrimSuffix(filepath.Base(absPath), filepath.Ext(absPath))

	entries := []struct {
		key  string
		name string
		desc string
	}{
		{`HKCU\Software\Microsoft\Windows\CurrentVersion\Run`, fmt.Sprintf("WindowsUpdate_%s", baseName), i18n.GetText("winregistry_current_user_run")},
		{`HKLM\Software\Microsoft\Windows\CurrentVersion\Run`, fmt.Sprintf("SystemUpdate_%s", baseName), i18n.GetText("winregistry_local_machine_run")},
		{`HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce`, fmt.Sprintf("SetupComplete_%s", baseName), i18n.GetText("winregistry_current_user_runonce")},
	}

	var output strings.Builder
	var successCount int

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Verify the file exists at the configured path (ls/Test-Path) and correct Config.WinPEFile.
  2. Use an absolute path so the result does not depend on the process working directory.
  3. Check read permissions on the file and its parent directories.
  4. Re-download or restore the PE sample if it was removed.

Example fix

// before
session.Config.WinPEFile = "samples/implant.dll" // CWD differs -> not found
// after
abs, _ := filepath.Abs("samples/implant.dll")
if _, err := os.Stat(abs); err != nil { log.Fatal(err) }
session.Config.WinPEFile = abs
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(cfg.WinPEFile); err != nil {
    return fmt.Errorf("PE file %q not accessible: %w", cfg.WinPEFile, err)
}

Try / catch

res := plugin.Scan(ctx, host, session)
if !res.Success {
    var peErr *os.PathError
    if errors.As(res.Error, &peErr) { /* handle missing file */ }
}

Prevention

When it happens

Trigger: Config.WinPEFile is non-empty but os.Stat(pePath) returns an error: the file does not exist at that path, the path is misspelled/relative to the wrong working directory, or the stat is blocked by permissions.

Common situations: Typo in the PE file path; running the tool from a different CWD than expected with a relative path; the sample file was deleted/moved after configuration; pointing at a path on a drive that is not mounted.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/d7839ec203200808. Report an issue: GitHub.