Sunteți pe pagina 1din 6

/*

DirectCopy v2.0 - by Napalm @ NetCore2K


------------------------------------
Please try and read and understand this source code. You will learn
something.

Sector = 512 Bytes of disk space


Cluster = A Group of Sectors. This is different depending on your file
system. But normally its 4Kb so thats 8 sectors.
VCN = Virtual Cluster Number. Simply the index of the cluster within
its context.
LCN = Logical Cluster Number. The physical cluster index on containing
media.
Extent = The extent of a Cluster index.

The DirectCopy function invokes a Device Control Code to get the


cluster information about a file.
We then loop though each resulting extent and copy each cluster to a
new file. If the file has no
clusters assigned to it the data is stored in the MFT. This means the
file data itself is in the
MFT since it would be a waste to allocate an entire cluster of sectors
for lets say just 5 bytes.
*/

#define _WIN32_WINNT 0x0500


#include <windows.h>
#include <winioctl.h>
#include <stdio.h>

typedef struct
{
ULONG Type; /* Magic number 'FILE' */
USHORT UsaOffset; /* Offset to the update sequence */
USHORT UsaCount; /* Size in words of Update Sequence Number & Array (S)
*/
ULONGLONG Lsn; /* $LogFile Sequence Number (LSN) */
}
NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER;

typedef struct
{
NTFS_RECORD_HEADER RecHdr;
USHORT SequenceNumber; /* Sequence number */
USHORT LinkCount; /* Hard link count */
USHORT AttributeOffset; /* Offset to the first Attribute */
USHORT Flags; /* Flags */
ULONG BytesInUse; /* Real size of the FILE record */
ULONG BytesAllocated; /* Allocated size of the FILE record */
ULONGLONG BaseFileRecord; /* Reference to the base FILE record */
USHORT NextAttributeNumber; /* Next Attribute Id */
USHORT Pading; /* Align to 4 byte boundary (XP) */
ULONG MFTRecordNumber; /* Number of this MFT Record (XP) */
USHORT UpdateSeqNum;
}
FILE_RECORD_HEADER, *PFILE_RECORD_HEADER;
typedef enum
{
AttributeStandardInformation = 0x10,
AttributeAttributeList = 0x20,
AttributeFileName = 0x30,
AttributeObjectId = 0x40,
AttributeSecurityDescriptor = 0x50,
AttributeVolumeName = 0x60,
AttributeVolumeInformation = 0x70,
AttributeData = 0x80,
AttributeIndexRoot = 0x90,
AttributeIndexAllocation = 0xA0,
AttributeBitmap = 0xB0,
AttributeReparsePoint = 0xC0,
AttributeEAInformation = 0xD0,
AttributeEA = 0xE0,
AttributePropertySet = 0xF0,
AttributeLoggedUtilityStream = 0x100
}
ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE;

typedef struct
{
ATTRIBUTE_TYPE AttributeType;
ULONG Length;
BOOLEAN Nonresident;
UCHAR NameLength;
USHORT NameOffset;
USHORT Flags;
USHORT AttributeNumber;
}
ATTRIBUTE, *PATTRIBUTE;

typedef struct
{
ATTRIBUTE Attribute;
ULONG ValueLength;
USHORT ValueOffset;
UCHAR Flags;
}
RESIDENT_ATTRIBUTE, *PRESIDENT_ATTRIBUTE;

BOOL DirectCopy(LPSTR lpszSrc, LPSTR lpszDest)


{

BOOL bResult = FALSE;

HANDLE hSrc = CreateFile(lpszSrc,


FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE
| FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
0,
0);
if(hSrc != INVALID_HANDLE_VALUE)
{

CHAR szDrive[7];
wsprintf(szDrive, "%c:", *lpszSrc);
DWORD dwSectorPerCluster, dwBytesPerSector;
GetDiskFreeSpace(szDrive,
&dwSectorPerCluster,
&dwBytesPerSector,
NULL,
NULL);
DWORD dwClusterSize = (dwBytesPerSector * dwSectorPerCluster);
LARGE_INTEGER liFileSize;
liFileSize.LowPart = GetFileSize(hSrc, (LPDWORD)&liFileSize.HighPart);
//-------???
DWORD dwClusters = (liFileSize.QuadPart / dwClusterSize);

DWORD dwRead,dwWritten;
DWORD dwPointsSize = sizeof(RETRIEVAL_POINTERS_BUFFER) +
(dwClusters * (sizeof(LARGE_INTEGER) * 2));
PRETRIEVAL_POINTERS_BUFFER pPoints = (PRETRIEVAL_POINTERS_BUFFER) new
BYTE[dwPointsSize];
STARTING_VCN_INPUT_BUFFER vcnStart = { 0 };

if(DeviceIoControl(hSrc,
FSCTL_GET_RETRIEVAL_POINTERS,
&vcnStart,
sizeof(vcnStart),
pPoints,
dwPointsSize,
&dwWritten,
NULL))
{
wsprintf(szDrive, "\\\\.\\%c:", *lpszSrc);

HANDLE hDrive = CreateFile(szDrive,


GENERIC_READ,
FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
0);
if(hDrive != INVALID_HANDLE_VALUE)
{

HANDLE hDest = CreateFile(lpszDest,


GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
0,
0);
if(hDest != INVALID_HANDLE_VALUE)
{
SetFilePointer(hDest,
liFileSize.LowPart,
&liFileSize.HighPart,
FILE_BEGIN);

SetEndOfFile(hDest);

LPBYTE lpCluster = new BYTE[dwClusterSize];


LARGE_INTEGER vcnPrev = pPoints->StartingVcn;

for(DWORD dwExtent = 0; dwExtent < pPoints->ExtentCount; dwExtent++)


{
DWORD dwLength = (DWORD)(pPoints->Extents[dwExtent].NextVcn.QuadPart -
vcnPrev.QuadPart);
LARGE_INTEGER liSrcPos = { (pPoints->Extents[dwExtent].Lcn.QuadPart *
dwClusterSize) };
LARGE_INTEGER liDstPos = { (vcnPrev.QuadPart * dwClusterSize) };

for(DWORD dwCluster = 0; dwCluster < dwLength; dwCluster++)


{
SetFilePointer(hDrive,
liSrcPos.LowPart,
&liSrcPos.HighPart,
FILE_BEGIN);

ReadFile(hDrive,
lpCluster,
dwClusterSize,
&dwRead,
NULL);

SetFilePointer(hDest,
liDstPos.LowPart,
&liDstPos.HighPart,
FILE_BEGIN);

WriteFile(hDest,
lpCluster,
dwRead,
&dwWritten,
NULL);

liSrcPos.QuadPart += dwClusterSize;
liDstPos.QuadPart += dwClusterSize;

vcnPrev = pPoints->Extents[dwExtent].NextVcn;
}
delete lpCluster;
CloseHandle(hDest);
bResult = TRUE;
}

CloseHandle(hDrive);
}

else

{
// The file is too small to have a cluster assignment, so we need to
get the MFT record.
if(GetLastError() == ERROR_HANDLE_EOF)
{
CHAR szDrive[7];
wsprintf(szDrive, "\\\\.\\%c:", *lpszSrc);

HANDLE hDrive = CreateFile(szDrive,


GENERIC_READ,
FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
0);
if(hDrive != INVALID_HANDLE_VALUE)
{
NTFS_VOLUME_DATA_BUFFER ntfsVolData;
if(DeviceIoControl(hDrive,
FSCTL_GET_NTFS_VOLUME_DATA,
NULL,
0,
&ntfsVolData,
sizeof(ntfsVolData),
&dwWritten,
NULL))
{
BY_HANDLE_FILE_INFORMATION bhFileInfo;
if(GetFileInformationByHandle(hSrc, &bhFileInfo))
{
DWORD dwOuputSize = (sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER) +
ntfsVolData.BytesPerFileRecordSegment);
NTFS_FILE_RECORD_INPUT_BUFFER mftRecordInput = {

{ bhFileInfo.nFileIndexLow,

bhFileInfo.nFileIndexHigh
}
};
PNTFS_FILE_RECORD_OUTPUT_BUFFER pmftRecordOutput
=(PNTFS_FILE_RECORD_OUTPUT_BUFFER)
new
BYTE[dwOuputSize];

if(DeviceIoControl(hDrive,
FSCTL_GET_NTFS_FILE_RECORD,
&mftRecordInput,
sizeof(mftRecordInput),
pmftRecordOutput,
dwOuputSize,
&dwWritten,
NULL))
{
PFILE_RECORD_HEADER pFileRecord =
(PFILE_RECORD_HEADER)pmftRecordOutput->FileRecordBuffer;
PATTRIBUTE pAttribute = (PATTRIBUTE)((LPBYTE)pFileRecord + pFileRecord-
>AttributeOffset);
LPBYTE lpData = NULL;
DWORD dwSize = 0;

while( (LPBYTE)pAttribute < (LPBYTE)(pFileRecord + pFileRecord-


>BytesInUse))
{

if(pAttribute->AttributeType == AttributeData)
{
PRESIDENT_ATTRIBUTE pResAttrib = (PRESIDENT_ATTRIBUTE)pAttribute;
lpData = ((LPBYTE)pResAttrib + pResAttrib->ValueOffset);
dwSize = pResAttrib->ValueLength;
break;
}
pAttribute = (PATTRIBUTE)((LPBYTE)pAttribute + pAttribute->Length);
}
if(lpData != NULL){
HANDLE hDest = CreateFile(lpszDest, GENERIC_WRITE, 0, NULL, CREATE_NEW,
0, 0);
if(hDest != INVALID_HANDLE_VALUE){
WriteFile(hDest, lpData, dwSize, &dwWritten, NULL);
CloseHandle(hDest);
bResult = TRUE;
}
}
}
delete pmftRecordOutput;
}
}
CloseHandle(hDrive);
}
}
}
delete pPoints;
CloseHandle(hSrc);
}
return bResult;
}

int main(int argc, char *argv[])


{
printf("DirectCopy v2.0 - by Napalm @ NetCore2K\n");
if(argc < 3) return printf("Usage: %s <src> <dest>\n\n", argv[0]);
printf("Copying %s to %s ... ", argv[1], argv[2]);
printf("%s\n\n", (DirectCopy(argv[1], argv[2])?"OK":"Failed!"));
return 0;
}

S-ar putea să vă placă și