April 19, 2024, 06:08:37 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Copying Locked files example

Started by sapero, September 10, 2009, 07:57:07 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

sapero

September 10, 2009, 07:57:07 AM Last Edit: September 14, 2009, 02:04:39 AM by sapero
This example program shows one of thousands ways to open/copy locked files. It requires Windows XP, or other NT based system.
As the source of locked files I have used Youtube flash videos, stored in TEMP directory as fla*.tmp files (if viewed with Internet Explorer)

First, you need a full path to locked file - this program enumerates .tmp files. The full path is converted to \Device\HardDiskVolume1\dir1\dir2\file.ext with QueryDosDevice api, then a list of all open handles is requested with NtQuerySystemInformation api. Each handle is checked for type and name. Type must be "File", and name should be equal to the converted full path to locked file. If you find a match, you need only to call OpenProcess and DuplicateHandle to get the file handle, seek to beginning and copy byte by byte.$include "windowssdk.inc"
$include "ntddk.inc"
$include "undocumented.inc"
$include "stdio.inc"
$use "_crtdll.lib"


'-------------------------- example
$include "shlwapi.inc"
$define REPLACE_ALWAYS
' open youtube in internet explorer, watch any video (should be downloaded in 100%)
' then run this program to copy the locked fla***.tmp file from your TEMP directory
istring tmppath[MAX_PATH]

' 1. enumerate fla*.tmp files in TEMP directory
ExpandEnvironmentStrings("%TEMP%\\", tmppath, MAX_PATH)
int pathlen = len(tmppath)
strcpy(&tmppath[pathlen], "fla*.tmp")
UINT hFind = findopen(tmppath)
int nFilesFound = 0
int nFilesCopied = 0

if (hFind)
istring name[256] = findnext(hFind)
while (name[0] <> 0)

strncpy(&tmppath[pathlen], name, MAX_PATH-pathlen)
' tmppath = local path to flash video

' 2. copy the file with renamed extension (supported by media player classic)
istring newpath[MAX_PATH]
newpath = tmppath
PathRenameExtension(newpath, ".flv")

' check if we can open the file directly
HANDLE hFile = CreateFile(tmppath, GENERIC_READ, FILE_SHARE_READ _
| FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0)

if (hFile <> INVALID_HANDLE_VALUE)
' file opened, so you can copy it with your favorite file manager
CloseHandle(hFile)

else

nFilesFound++
' the file is opened with exclusive access, call the subroutine below to open it
HANDLE hProcess
hFile = OpenFileEx(tmppath, &hProcess)
if (hFile = INVALID_HANDLE_VALUE)
' failed
MessageBox 0, "failed to open " + tmppath, ""
else
' copy it now ...
$ifdef REPLACE_ALWAYS
HANDLE hOutFile = CreateFile(newpath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)
$else
HANDLE hOutFile = CreateFile(newpath, GENERIC_WRITE, 0, 0, CREATE_NEW, 0, 0)
$endif
if (hOutFile = INVALID_HANDLE_VALUE)
' failed ?
MessageBox 0, "failed to create " + newpath, ""
else
' ... but first suspend the owner process (because the handle is duplicated, and
' if the owner process changes file pointer, it will be reflected also in this process)
declare import, NtSuspendProcess(HANDLE hProcess), NTSTATUS
declare import, NtResumeProcess(HANDLE hProcess), NTSTATUS
NtSuspendProcess(hProcess)

' save original file pointer in originalFilePos variable
LARGE_INTEGER originalFilePos
LARGE_INTEGER nullFilePos
nullFilePos.QuadPart = 0q
SetFilePointerEx(hFile, nullFilePos, &originalFilePos, FILE_CURRENT)

' seek to beginning
SetFilePointerEx(hFile, nullFilePos, NULL, FILE_BEGIN)

'  copy, using string name as the buffer
DWORD BytesRead, BytesWriten
while (ReadFile(hFile, &name, 256, &BytesRead, 0) and BytesRead)
WriteFile(hOutFile, name, BytesRead, &BytesWriten, 0)
endwhile
'
nFilesCopied++
' restore file pointer
SetFilePointerEx(hFile, originalFilePos, NULL, FILE_BEGIN)
' cleanup
CloseHandle(hOutFile)
' resume the process
NtResumeProcess(hProcess)
endif
CloseHandle(hFile)
endif
endif
name = findnext(hFind)
endwhile

findclose(hFind)
endif

if (MessageBox(0, using("Copied # from # locked .FLV files. Open Directory ?", nFilesCopied, nFilesFound), "", MB_YESNO) = IDYES)
tmppath[pathlen-1] = 0
system tmppath
endif

'-------------------------- code

type SYSTEM_HANDLE_ENTRY
ULONG OwnerPid
BYTE ObjectType
BYTE HandleFlags
USHORT HandleValue
PVOID ObjectPointer
ACCESS_MASK GrantedAccess
endtype

type SYSTEM_HANDLE_INFORMATION
ULONG HandleCount
SYSTEM_HANDLE_ENTRY Handles[1]
endtype

type MY_OBJECT_TYPE_INFORMATION
OBJECT_TYPE_INFORMATION t
iwstring buffer[64]
endtype

type MY_OBJECT_NAME_INFORMATION
OBJECT_NAME_INFORMATION t
iwstring buffer[280]
endtype

declare import, NtQuerySystemInformation(_
int SystemInformationClass,_
PVOID SystemInformation,_
ULONG SystemInformationLength,_
pointer ReturnLength),NTSTATUS

const SystemHandleInformation = 16




sub OpenFileEx(string path, pointer pphProcess),HANDLE
MY_OBJECT_TYPE_INFORMATION htype
MY_OBJECT_NAME_INFORMATION name

*<HANDLE>pphProcess = 0
HANDLE h = INVALID_HANDLE_VALUE

' convert c:\ to \Device\HardDiskVolume...
' 1. extract partition letter
iwstring root[4]
root[0] = path[0], 58, 0
' 2. convert it to \Device\HardDiskVolumeX
iwstring wszNTPath[280]
int cch = QueryDosDeviceW(root, wszNTPath, 280)
if (!cch) then return INVALID_HANDLE_VALUE
' 3. append remaining folders and file name from string path parameter
' so <path> "c:\Program Files" gets converted to <wszNTPath> "\Device\HardDiskVolume1\Program Files"
cch = wcslen(wszNTPath)
_snwprintf(&wszNTPath[cch], 280-cch, L"%S", &path[2])
' now get the list of all handles, and find the handle which name is equal to wszNTPath

ULONG BytesNeeded, BufferSize = 4096
pointer handles = new(char, BufferSize) ' SYSTEM_HANDLE_INFORMATION*

while (handles)

' get the list of all user-mode handles
NTSTATUS status = NtQuerySystemInformation(SystemHandleInformation, handles, BufferSize, &BytesNeeded)
if (status = STATUS_INFO_LENGTH_MISMATCH)

' BytesNeeded is not adjusted, so we need to increase buffer size
delete handles
BufferSize += 32768
handles = new(char, BufferSize)

elseif (!status)

settype handles, SYSTEM_HANDLE_INFORMATION
' sort handles by owning process id
qsort(&*handles.Handles, *handles.HandleCount, len(SYSTEM_HANDLE_ENTRY), &SortHandlesCb)

pointer node = *handles.Handles
settype node, SYSTEM_HANDLE_ENTRY
ULONG OwnerPid = 0
HANDLE hProcess = 0
HANDLE hThisProcess = GetCurrentProcess()
BYTE ObjectTypeFile = 0

while (*handles.HandleCount)

*handles.HandleCount--

if (*node.GrantedAccess & FILE_READ_DATA) ' 13019F

if (OwnerPid <> *node.OwnerPid)

OwnerPid = *node.OwnerPid
if (hProcess) then CloseHandle(hProcess)
hProcess = OpenProcess(PROCESS_DUP_HANDLE|PROCESS_SUSPEND_RESUME, FALSE, OwnerPid)

endif
if (hProcess)

HANDLE hObject
if (DuplicateHandle(hProcess, *node.HandleValue, hThisProcess, &hObject, 0, FALSE, DUPLICATE_SAME_ACCESS))

if (GetFileType(hObject) = FILE_TYPE_DISK)

if (!ObjectTypeFile) ' query object type name as "integer"

if (!NtQueryObject(hObject, ObjectTypeInformation, &htype, len(htype), &BytesNeeded))

if (!_wcsnicmp(htype.t.TypeName.Buffer, L"File", 4))
ObjectTypeFile = *node.ObjectType
endif
endif
endif

' do not query object name with granted access 0x0012019f (deadloock)
if (ObjectTypeFile and (ObjectTypeFile = *node.ObjectType) and (*node.GrantedAccess <> 0x0012019f))

' query file name
if (!NtQueryObject(hObject, ObjectNameInformation, &name, len(name), &BytesNeeded))

if (name.t.Name.Buffer and !wcsicmp(name.t.Name.Buffer, wszNTPath)) ' compare

*<HANDLE>pphProcess = hProcess
delete handles
return hObject
endif
endif
endif
endif
CloseHandle(hObject)
endif
endif
endif
node = &*node[1]
endwhile
if (hProcess) then CloseHandle(hProcess)
delete handles

else
' NtQuerySystemInformation failed
delete handles
endif

endwhile

if (handles) then delete handles
return h
endsub


declare cdecl SortHandlesCb(SYSTEM_HANDLE_ENTRY p1, SYSTEM_HANDLE_ENTRY p2),int

sub SortHandlesCb(SYSTEM_HANDLE_ENTRY p1, SYSTEM_HANDLE_ENTRY p2),int
if (p1.OwnerPid = p2.OwnerPid) then return 0
if (p1.OwnerPid > p2.OwnerPid) then return 1
return -1
endsub

BasBBakker

I am new to IWBasic and would really appreciate some help.

Can someone help me to get this example compiled? Where in particular do these include files come from?

Thanks a million in advance!

$include "windowssdk.inc"
$include "ntddk.inc"
$include "undocumented.inc"
$include "stdio.inc"
$use "_crtdll.lib"

Bill-Bo

August 28, 2013, 05:33:19 PM #2 Last Edit: August 28, 2013, 08:55:28 PM by Bill-Bo
BasBBakker,

Welcome.

You get them at http://www.ionicwind.com/forums/index.php?topic=4983.msg37938#msg37938

In the first item, download the "IWBasic - 05/05/2011" file. I has Sapero's includes and more.

Larry will probably help you more.

Bill

P.S. It is also under "Sapero's Include Files" on the forum main page.