Solved

How do I copy an EFS encryted File to a USB drive that I cannot decrypt

Posted on 2010-08-22
5
976 Views
Last Modified: 2012-05-10
I have 3 or 4 users a month that for one reason or another cannot boot their XP OS on their HD and need it to be re-imaged or replaced.  I would like to boot to WINPE, copy the files to USB drive, re-format or replace the HD, then copy the files back.  Some files are EFS Encrypted and the keys can be easily recovered from Active Directory after the HD is reformated and the files copied back to the HD.  I have tried the API's CopyFile and CopyFileEx but neither seem to be able to just copy the file without first decrypting it.  I do not want to decrypt the file while it is stored on the USB drive as the file may contain sensitive information and it is safer just to keep it encrypted while the OS is repaired. ImageX.exe can perform this task and I currently use it for this purpose by copying the files into a WIM file then onto USB.  The problem with imageX.exe is that I would rather just perform the raw copy within my VB6 code and retain a more granular control over which files get copied and which get left behind.
0
Comment
Question by:Cefer
  • 3
  • 2
5 Comments
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 33497147
You have to use the following function to copy/backup encrypted files.

OpenEncryptedFileRaw Function
http://msdn.microsoft.com/en-us/library/aa365429(v=VS.85).aspx
ReadEncryptedFileRaw Function
http://msdn.microsoft.com/en-us/library/aa365466(v=VS.85).aspx

WriteEncryptedFileRaw Function
http://msdn.microsoft.com/en-us/library/aa365746(v=VS.85).aspx
CloseEncryptedFileRaw Function
http://msdn.microsoft.com/en-us/library/aa363839(v=VS.85).aspx

 
0
 

Author Comment

by:Cefer
ID: 33502203
eql1044, you are correct that the above C functions are the basis for copying encrypted files.  I also see that you provided an excelent VB.Net solution here:  http://www.experts-exchange.com/Programming/Languages/Visual_Basic/Q_25235488.html .  My need to use VB6 is related to using this tool in WinPE.  I have the VB6 runtimes working in WinPE but not the VS .Net runtimes.  I have VB6 code to use FindFirstFile and FindNextFile that finds and copies files to the USB drive that match my filter but it fails to copy encrypted files.  To make a tool work in more situations I need to add the copy EncryptedFileRaw functionality.  I have searched the well of Google for any examples of this in VB6 but only found the Declare Function Statements.

Declare Function OpenEncryptedFileRaw Lib "advapi32" Alias "OpenEncryptedFileRawA" (ByVal lpFileName As String, ByVal ulFlags As Long, pvContext As Any) As Long
Declare Function ReadEncryptedFileRaw Lib "advapi32" (ByRef pfExportCallback As PFE_EXPORT_FUNC, pvCallbackContext As Any, pvContext As Any) As Long
Declare Function WriteEncryptedFileRaw Lib "advapi32.dll" (ByRef pfImportCallback As PFE_IMPORT_FUNC, pvCallbackContext As Any, pvContext As Any) As Long
Declare Sub CloseEncryptedFileRaw Lib "advapi32" (pvContext As Any)

My conversion skills from C to VB6 are not strong enough to put the right pieces together.
0
 
LVL 29

Accepted Solution

by:
nffvrxqgrcfqvvc earned 500 total points
ID: 33502389
If your not the owner or on the list for the encrypted files you will have to enable SeBackupPrivilege so you can bypass the security on the file.
I won't go much into that because I explained alot of this in the question you already have found but want to give you a heads up briefly.
I have written a very simple example that would help you use the encrypted API's
(add the code) In a module named : efsbackup.bas
The Backup() method will store the raw content in file. When you need to Restore() the file point it to that raw backup and use the Restore() method.
Usage://
Backup "c:\test\dotnetfx.exe", "c:\test\dotnetfx.exe.efs"
Restore "c:\test\dotnetfx.exe.efs", "c:\test\dotnetfxRestored.exe"

 

Option Explicit



' EFS Backup

' Windows 2000 or later

' egl1044

Public Const ERROR_SUCCESS As Long = 0

Public Const INVALID_HANDLE_VALUE As Long = (-1)

Public Const GENERIC_READ As Long = &H80000000

Public Const GENERIC_WRITE As Long = &H40000000

Public Const OPEN_EXISTING As Long = &H3&

Public Const CREATE_ALWAYS As Long = &H2&



Public Enum EncryptionStatus

  FILE_ENCRYPTABLE = 0            'The file can be encrypted.

  FILE_IS_ENCRYPTED = 1           'The file is encrypted.

  FILE_READ_ONLY = 8              'The file is a read-only file.

  FILE_ROOT_DIR = 3               'The file is a root directory. Root directories cannot be encrypted.

  FILE_SYSTEM_ATTR = 2            'The file is a system file. System files cannot be encrypted.

  FILE_SYSTEM_DIR = 4             'The file is a system directory. System directories cannot be encrypted.

  FILE_SYSTEM_NOT_SUPPORT = 6     'The file system does not support file encryption.

  FILE_UNKNOWN = 5                'The encryption status is unknown. The file may be encrypted.

  FILE_USER_DISALLOWED = 7        'Reserved for future use.

End Enum



Public Enum EncryptedFileFlags

  CREATE_FOR_EXPORT = 0           'Open the file for export (backup).

  CREATE_FOR_IMPORT = 1           'The file is being opened for import (restore).

  CREATE_FOR_DIR = 2              'Import (restore) a directory containing encrypted files. This must be combined with one of the previous two flags to indicate the operation.

  OVERWRITE_HIDDEN = 4            'Overwrite a hidden file on import.

End Enum



Public Declare Function CreateFileW Lib "Kernel32.dll" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long



Public Declare Function ReadFile Lib "Kernel32.dll" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToRead As Long, ByRef lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long



Public Declare Function WriteFile Lib "Kernel32.dll" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToWrite As Long, ByRef lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long



Public Declare Function CloseHandle Lib "Kernel32.dll" (ByVal hObject As Long) As Long



Public Declare Function FileEncryptionStatusW Lib "Advapi32.dll" (ByVal lpFileName As Long, ByRef lpStatus As Long) As Long

  

Public Declare Function OpenEncryptedFileRawW Lib "Advapi32.dll" (ByVal lpFileName As Long, ByVal ulFlags As EncryptedFileFlags, ByRef pvContext As Long) As Long



Public Declare Function ReadEncryptedFileRaw Lib "Advapi32.dll" (ByVal pfExportCallback As Long, ByVal pvCallbackContext As Long, ByVal pvContext As Long) As Long

  

Public Declare Function WriteEncryptedFileRaw Lib "Advapi32.dll" (ByVal pfImportCallback As Long, ByVal pvCallbackContext As Long, ByVal pvContext As Long) As Long



Public Declare Function CloseEncryptedFileRaw Lib "Advapi32.dll" (ByVal pvContext As Long) As Long



    

Public Sub Backup(ByVal sourceFile As String, ByVal targetFile As String)

  

  Dim hFileSource     As Long

  Dim ctx             As Long

  

  ' Create new file that will store the raw encrypted backup data.

  hFileSource = CreateFileW(StrPtr("\\?\" & targetFile), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)

  If hFileSource = INVALID_HANDLE_VALUE Then

    Debug.Print "CreateFile failed."; Err.LastDllError

    Exit Sub

  End If

  ' Open the source file and write the raw encrypted data into the backup file.

  If OpenEncryptedFileRawW(StrPtr(sourceFile), CREATE_FOR_EXPORT, ctx) = ERROR_SUCCESS Then

    ReadEncryptedFileRaw AddressOf ExportCallback, hFileSource, ctx

    CloseEncryptedFileRaw ctx

  Else

    Debug.Print "OpenEncryptedFileRaw failed."; Err.LastDllError

  End If

  ' cleanUp

  CloseHandle hFileSource

  

End Sub



Public Sub Restore(ByVal sourceFile As String, ByVal targetFile As String)



  Dim hFileSource     As Long

  Dim hFileTarget     As Long

  Dim ctx             As Long

  

  ' Create new file that will restore the raw encrypted backup data.

  hFileTarget = CreateFileW(StrPtr("\\?\" & targetFile), 0, 0, 0, CREATE_ALWAYS, 0, 0)

  If hFileTarget = INVALID_HANDLE_VALUE Then

    Debug.Print "CreateFile failed."; Err.LastDllError

    Exit Sub

  End If

  ' cleanUp

  CloseHandle hFileTarget

  

  ' Open the raw encrypted backup file.

  hFileSource = CreateFileW(StrPtr("\\?\" & sourceFile), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0)

  If hFileSource = INVALID_HANDLE_VALUE Then

    Debug.Print "CreateFile failed."; Err.LastDllError

    Exit Sub

  End If

  

  ' Open the raw backup file and restore the raw backup data.

  If OpenEncryptedFileRawW(StrPtr(targetFile), CREATE_FOR_IMPORT, ctx) = ERROR_SUCCESS Then

    WriteEncryptedFileRaw AddressOf ImportCallback, hFileSource, ctx

    CloseEncryptedFileRaw ctx

  Else

    Debug.Print "OpenEncryptedFileRaw failed."; Err.LastDllError

  End If

  ' cleanUp

  CloseHandle hFileSource



End Sub



Public Function ImportCallback( _

  ByVal pbData As Long, _

  ByVal pvCallbackContext As Long, _

  ByRef ulLength As Long) As Long

  ' Restore Callback

  Dim dwReadBytes As Long

  ReadFile pvCallbackContext, pbData, ulLength, dwReadBytes, 0

  ulLength = dwReadBytes

  ImportCallback = ERROR_SUCCESS

End Function



Public Function ExportCallback( _

  ByVal pbData As Long, _

  ByVal pvCallbackContext As Long, _

  ByVal ulLength As Long) As Long

  'Backup Callback

  Dim dwWrittenBytes As Long

  WriteFile pvCallbackContext, pbData, ulLength, dwWrittenBytes, 0

End Function

Open in new window

0
 

Author Closing Comment

by:Cefer
ID: 33503713
Thank you for the example code.  I am very grateful.
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 33505428
Your welcome buddy, Everything working as expected?
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now