Code: Select all
procName := "explorer.exe"
DetectHiddenWindows, On
Process, Exist, % procName
if !(PID := ErrorLevel) {
MsgBox, Process not found
ExitApp
}
info := []
OnMessage( 0x4A, Func("WM_COPYDATA_READ").Bind(info) )
files := GetOpenedFiles(PID, info)
MsgBox, % files != "" ? files : "Failed to get opened files"
ExitApp
GetOpenedFiles(PID, info) {
static PROCESS_DUP_HANDLE := 0x0040, inherit := true
hProcess := DllCall("OpenProcess", "UInt", PROCESS_DUP_HANDLE, "UInt", inherit, "UInt", PID)
fail := 0, prev := skip := "", last := -1, arrSkip := {}
Loop {
if !ChildPID {
ChildPID := ExecScript( GetScript(hProcess, PID, skip) )
WinWait, ahk_pid %ChildPID%
try RB := new RemoteBuffer(ChildPID, 4)
catch e {
MsgBox, % e.Message
break
}
SendString( RB.ptr, WinExist() )
}
Sleep, 100
try {
RB.Read(buff, 4)
last := NumGet(buff, "UInt")
}
catch
last := -1
if (last = prev) {
RB := ""
Process, Close, % ChildPID
prev := skip := ChildPID := ""
arrSkip[last] := ""
for k in arrSkip
skip .= (skip = "" ? "" : "|") . k
++fail
continue
}
prev := last
} until fail = 5 || info[1]
DllCall("CloseHandle", "Ptr", hProcess)
Return info[1]
}
ExecScript(script) {
shell := ComObjCreate("WScript.Shell")
exec := shell.Exec("AutoHotkey.exe /ErrorStdOut *")
exec.StdIn.Write(script)
exec.StdIn.Close()
Return exec.ProcessID
}
GetScript(hTargetProc, PID, skip) {
; SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
; https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/handle_ex.htm
; https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/handle_table_entry_ex.htm
script =
(
#NoTrayIcon
SetBatchLines, -1
hParentWnd := %A_ScriptHwnd%
hTargetProc := %hTargetProc%
hCurrProc := DllCall("GetCurrentProcess")
targetPID := %PID%
skip := %skip%
info := []
res := size := 1
structSize := A_PtrSize*3 + 16 ; size of SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
i := 0
arr := {}
OnMessage( 0x4A, Func("WM_COPYDATA_READ").Bind(info) )
while !(pData := info[1]) && A_Index < 10
Sleep, 100
if !pData
ExitApp
while res != 0 {
VarSetCapacity(buff, size, 0)
res := DllCall("ntdll\NtQuerySystemInformation", "Int", SystemExtendedHandleInformation := 0x40
, "Ptr", &buff, "UInt", size, "UIntP", size, "UInt")
}
handleCount := NumGet(buff)
VarSetCapacity(filePath, 1026)
Loop `% handleCount {
processId := NumGet(buff, A_PtrSize*2 + structSize*(A_Index - 1) + A_PtrSize, "UInt")
if (processId = targetPID) {
i++
Loop, parse, skip, |
if (i - 1 = A_LoopField)
continue 2
handle := NumGet(buff, A_PtrSize*2 + structSize*(A_Index - 1) + A_PtrSize*2)
DllCall("DuplicateHandle", "Ptr", hTargetProc, "Ptr", handle, "Ptr", hCurrProc
, "PtrP", lpTargetHandle, "UInt", 0, "UInt", 0, "UInt", DUPLICATE_SAME_ACCESS := 0x2)
if DllCall("GetFinalPathNameByHandle", "Ptr", lpTargetHandle, "Str", filePath, "UInt", 512, "UInt", 0)
arr[ RegExReplace(filePath, "^\\\\\?\\") ] := ""
DllCall("CloseHandle", "Ptr", lpTargetHandle)
NumPut(i, pData + 0, "UInt")
}
}
for file in arr
files .= (files = "" ? "" : "``n") . file
SendString(files, hParentWnd)
ExitApp
WM_COPYDATA_READ(info, wp, lp) {
info[1] := StrGet(NumGet(lp + A_PtrSize*2), "UTF-16")
}
SendString(string, hWnd) {
VarSetCapacity(message, size := StrPut(string, "UTF-16")*2, 0)
StrPut(string, &message, "UTF-16")
VarSetCapacity(COPYDATASTRUCT, A_PtrSize*3)
NumPut(size, COPYDATASTRUCT, A_PtrSize, "UInt")
NumPut(&message, COPYDATASTRUCT, A_PtrSize*2)
DllCall("SendMessage", "Ptr", hWnd, UInt, WM_COPYDATA := 0x4A, "Ptr", 0, "Ptr", ©DATASTRUCT)
}
)
Return script
}
WM_COPYDATA_READ(info, wp, lp) {
info[1] := StrGet(NumGet(lp + A_PtrSize*2), "UTF-16")
}
SendString(string, hWnd) {
VarSetCapacity(message, size := StrPut(string, "UTF-16")*2, 0)
StrPut(string, &message, "UTF-16")
VarSetCapacity(COPYDATASTRUCT, A_PtrSize*3)
NumPut(size, COPYDATASTRUCT, A_PtrSize, "UInt")
NumPut(&message, COPYDATASTRUCT, A_PtrSize*2)
DllCall("SendMessage", "Ptr", hWnd, UInt, WM_COPYDATA := 0x4A, "Ptr", 0, "Ptr", ©DATASTRUCT)
}
class RemoteBuffer
{
__New(PID, size) {
static flags := (PROCESS_VM_OPERATION := 0x8) | (PROCESS_VM_WRITE := 0x20) | (PROCESS_VM_READ := 0x10)
, Params := ["UInt", MEM_COMMIT := 0x1000, "UInt", PAGE_READWRITE := 0x4, "Ptr"]
if !this.hProc := DllCall("OpenProcess", "UInt", flags, "Int", 0, "UInt", PID, "Ptr")
throw Exception("Can't open remote process PID = " . PID . "`nA_LastError: " . A_LastError, "RemoteBuffer.__New")
if !this.ptr := DllCall("VirtualAllocEx", "Ptr", this.hProc, "Ptr", 0, "Ptr", size, Params*) {
DllCall("CloseHandle", "Ptr", this.hProc)
throw Exception("Can't allocate memory in remote process PID = " . PID . "`nA_LastError: " . A_LastError, "RemoteBuffer.__New")
}
}
__Delete() {
DllCall("VirtualFreeEx", "Ptr", this.hProc, "Ptr", this.ptr, "UInt", 0, "UInt", MEM_RELEASE := 0x8000)
DllCall("CloseHandle", "Ptr", this.hProc)
}
Read(ByRef localBuff, size, offset = 0) {
VarSetCapacity(localBuff, size, 0)
if !DllCall("ReadProcessMemory", "Ptr", this.hProc, "Ptr", this.ptr + offset, "Ptr", &localBuff, "Ptr", size, "PtrP", bytesRead)
throw Exception("Can't read data from remote buffer`nA_LastError: " . A_LastError, "RemoteBuffer.Read")
Return bytesRead
}
Write(pData, size, offset = 0) {
if !res := DllCall("WriteProcessMemory", "Ptr", this.hProc, "Ptr", this.ptr + offset, "Ptr", pData, "Ptr", size, "PtrP", bytesWritten)
throw Exception("Can't write data to remote buffer`nA_LastError: " . A_LastError, "RemoteBuffer.Write")
Return bytesWritten
}
}