Member 7766180 wrote:
Is there code to read this "Magic"? I think I know what it is, thanks to your help! But how does one access or read the "Magic"?
Well, it is generally just the start of the file, so read in say the first 8 bytes and check them.
The following is complete code for a C/C++ windows console application that will tell you the file type based on the file. It hasn't been well tested, but you should get the idea.
This is a simple one, that you can hopefully follow easily:
#include <Windows.h>
#include <stdio.h>
typedef struct {
DWORD nLength;
char *pMagic;
} FileMagic;
FileMagic g_fmFileTypes[] = {
{ 4, "RIFF" },
{ 3, "ID3" },
{ 4, "PK\x03\x04" }
};
LPCSTR GetFileExtensions(int nMagicID) {
switch (nMagicID) {
case 0:
return "mp3";
case 1:
return "avi;wav";
case 2:
return "zip";
}
return "";
}
int GetFileType(LPCSTR szFileName) {
BYTE pFileStart[8];
DWORD nBytesRead;
int nFileType;
BYTE *pData = NULL;
int nMagicID = -1;
HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == NULL) {
return -2;
}
if (!ReadFile(hFile, pFileStart, sizeof(pFileStart), &nBytesRead, NULL) || nBytesRead != sizeof(pFileStart)) {
CloseHandle(hFile);
return -2;
}
for (nFileType = 0; nFileType < ARRAYSIZE(g_fmFileTypes); ++nFileType) {
if (memcmp(g_fmFileTypes[nFileType].pMagic, pFileStart, g_fmFileTypes[nFileType].nLength) == 0) {
nMagicID = nFileType;
break;
}
}
CloseHandle(hFile);
return nMagicID;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <file to test>\n", argv[0]);
}
int nMagicID = GetFileType(argv[1]);
if (nMagicID == -2) {
puts("An error occured.");
} else if (nMagicID == -1) {
puts("The type of this file is unknown.");
} else {
printf("The file type(s) are: %s\n", GetFileExtensions(nMagicID));
}
return 0;
}
And a more complex one that works if the magic isn't at the start of the file:
#include <Windows.h>
#include <stdio.h>
typedef enum {
FMID_ERROR,
FMID_UNKNOWN,
FMID_ID3,
FMID_RIFF,
FMID_PK,
} FileMagicID;
typedef struct {
DWORD nOffset;
DWORD nLength;
char *pMagic;
FileMagicID eFileType;
} FileMagic;
FileMagic g_fmFileTypes[] = {
{ 0, 4, "RIFF", FMID_RIFF },
{ 0, 3, "ID3", FMID_ID3 },
{ 0, 4, "PK\x03\x04", FMID_PK }
};
FileMagicID GetFileType(LPCSTR szFileName) {
BYTE pFileStart[8];
DWORD nBytesRead;
DWORD nFileType;
BYTE *pData = NULL;
FileMagicID idMagic = FMID_UNKNOWN;
HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == NULL) {
return FMID_ERROR;
}
if (!ReadFile(hFile, pFileStart, sizeof(pFileStart), &nBytesRead, NULL) || nBytesRead != sizeof(pFileStart)) {
CloseHandle(hFile);
return FMID_ERROR;
}
for (nFileType = 0; nFileType < ARRAYSIZE(g_fmFileTypes); ++nFileType) {
if (g_fmFileTypes[nFileType].nOffset + g_fmFileTypes[nFileType].nLength < sizeof(pFileStart)) {
if (memcmp(g_fmFileTypes[nFileType].pMagic, pFileStart + g_fmFileTypes[nFileType].nOffset, g_fmFileTypes[nFileType].nLength) == 0) {
idMagic = g_fmFileTypes[nFileType].eFileType;
break;
}
} else {
pData = (BYTE *)malloc(g_fmFileTypes[nFileType].nLength);
if (pData == NULL) {
idMagic = FMID_ERROR;
break;
}
nBytesRead = SetFilePointer(hFile, g_fmFileTypes[nFileType].nOffset, NULL, FILE_BEGIN);
if (nBytesRead == g_fmFileTypes[nFileType].nOffset) {
if (ReadFile(hFile, pData, g_fmFileTypes[nFileType].nLength, &nBytesRead, NULL) && nBytesRead == g_fmFileTypes[nFileType].nLength) {
if (memcmp(g_fmFileTypes[nFileType].pMagic, pData, g_fmFileTypes[nFileType].nLength) == 0) {
idMagic = g_fmFileTypes[nFileType].eFileType;
free(pData);
break;
}
}
}
free(pData);
}
}
CloseHandle(hFile);
return idMagic;
}
LPCSTR GetFileExtensions(FileMagicID fmMagic) {
switch (fmMagic) {
case FMID_ID3:
return "mp3";
case FMID_RIFF:
return "avi;wav";
case FMID_PK:
return "zip";
}
return "";
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <file to test>\n", argv[0]);
}
FileMagicID fmMagic = GetFileType(argv[1]);
if (fmMagic == FMID_ERROR) {
puts("An error occured.");
} else if (fmMagic == FMID_UNKNOWN) {
puts("The type of this file is unknown.");
} else {
printf("The file type(s) are: %s\n", GetFileExtensions(fmMagic));
}
return 0;
}
And a sample run of the program:
>Magic.exe test.zip
The file types are: zip
>move test.zip test.mp3
>Magic.exe test.mp3
The file types are: zip
Here I run it on a valid .zip file, then renamed the .zip to a .mp3 and tun it again, and it still detects it as a .zip
I would suggest that you get a hex editor and take a look at the binary data of the files to see what I am talking about. I use
Breakpoint Software's HexWorkshop[
^] its not free but has a trial if u only want to use it for a few days.