shadow1ng/fscan · error

%s: %v (LastError: %d) [minidump_open_process_failed]

Error message

%s: %v (LastError: %d) [minidump_open_process_failed]

What it means

OpenProcess(PROCESS_ALL_ACCESS) returned a zero handle, so the plugin could not open the target process to build a minidump. The syscall's returned error and the captured windows.GetLastError() value are reported. This library throws it because the Windows API refused access to the PID before MiniDumpWriteDump could run.

Source

Thrown at plugins/local/minidump.go:501

			return fmt.Errorf(i18n.GetText("minidump_write_dump_failed")+" (LastError: %d)", windows.GetLastError())
		}
	}

	return nil
}

// openProcess 打开进程
func (pm *ProcessManager) openProcess(pid uint32) (uintptr, error) {
	proc, err := pm.kernel32.FindProc("OpenProcess")
	if err != nil {
		return 0, fmt.Errorf("%s: %w", i18n.Tr("minidump_find_proc_failed", "OpenProcess"), err)
	}

	handle, _, callErr := proc.Call(uintptr(PROCESS_ALL_ACCESS), 0, uintptr(pid))
	if handle == 0 {
		lastError := windows.GetLastError()
		//nolint:errorlint // Windows LastError不应该wrapped
		return 0, fmt.Errorf(i18n.GetText("minidump_open_process_failed")+": %v (LastError: %d)", callErr, lastError)
	}
	return handle, nil
}

// createDumpFile 创建转储文件
func (pm *ProcessManager) createDumpFile(path string) (uintptr, error) {
	pathPtr, err := syscall.UTF16PtrFromString(path)
	if err != nil {
		return 0, err
	}

	createFile, err := pm.kernel32.FindProc("CreateFileW")
	if err != nil {
		return 0, fmt.Errorf("%s: %w", i18n.Tr("minidump_find_proc_failed", "CreateFileW"), err)
	}

	handle, _, callErr := createFile.Call(
		uintptr(unsafe.Pointer(pathPtr)),

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Re-run the scan/plugin from an elevated (Administrator) process so OpenProcess can obtain PROCESS_ALL_ACCESS.
  2. Verify the PID still exists (Task Manager / tasklist) before dumping; retry with a fresh enumeration.
  3. Retry with a reduced access mask (e.g. PROCESS_QUERY_INFORMATION|PROCESS_VM_READ) if full access is blocked by policy/AV.
  4. Enable SeDebugPrivilege in the calling process before opening system processes.

Example fix

// before
handle, _, callErr := proc.Call(uintptr(PROCESS_ALL_ACCESS), 0, uintptr(pid))
// after — request only the access MiniDumpWriteDump needs
const desiredAccess = windows.PROCESS_QUERY_INFORMATION | windows.PROCESS_VM_READ
handle, _, callErr := proc.Call(uintptr(desiredAccess), 0, uintptr(pid))
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: pre-check the PID is alive and that we run elevated before attempting the dump
func canAttemptDump(pid uint32) bool {
	if p, err := os.FindProcess(int(pid)); err != nil || p == nil {
		return false
	}
	admin, _ := isElevated() // token elevation check
	return admin
}

Type guard

func isOpenProcessSuccess(handle uintptr) bool { return handle != 0 }

Try / catch

handle, err := pm.openProcess(pid)
if err != nil {
	var winErr errno-like
	if windows.GetLastError() == windows.ERROR_ACCESS_DENIED {
		// fall back to reduced access mask or skip target
	}
	session.LogWarning("skip %d: %v", pid, err)
}

Prevention

When it happens

Trigger: proc.Call on kernel32!OpenProcess with PROCESS_ALL_ACCESS returns handle==0 for the given PID; typically the PID is protected, elevated, a system process, the plugin is not elevated, or the process has exited between enumeration and open.

Common situations: Dumping an LSASS/AV process from a non-admin shell; targeting a PID that terminated; running a 32-bit build against a 64-bit process; security software blocking handle creation.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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