#include <stdio.h> #include <windows.h> #include <stdlib.h>
#define U8 unsigned char #define S8 char #define U16 unsigned short #define U32 unsigned int #define U64 unsigned __int64
#pragma pack (1) typedef struct _FAT16_BPB_struct { U8 JmpBoot[3]; U8 OEMName[8]; U16 BytsPerSec; U8 SecPerClus; U16 RsvdSecCnt; U8 NumFATs; U16 RootEntCnt; U16 TotSec16; U8 Media; U16 FATs16; U16 SecPerTrk; U16 NumHeads; U32 HiddSec; U32 TotSec32; //------------ U8 DriverNumber; U8 Reserved1; U8 BootSignal; U32 VolumID; U8 VolumeLabel[11]; U8 FileSysType[8]; //------------ FAT16 U8 BootCodeArea[448]; U16 Signature; }FAT16_BPB;
typedef struct _DIR_struct { U8 Name[11]; U8 Attr; U8 NTRes; U8 CrtTimeTenth; U16 CrtTime; U16 CrtDate; U16 LstAccDate; U16 FstClusHi; U16 WriteTime; U16 WriteDate; U16 FstClusLow; U32 FileSize; }DirEntry;
typedef struct _LONG_DIR_struct { U8 Order; U8 Name1[10]; U8 Attr; U8 Type; U8 chksum; U8 Name2[12]; U16 FstClusLo; U8 Name3[4]; }LongDirEntry; #pragma pack ()
typedef struct _VOL_struct { U32 Drive; U32 VolBeginSec; U32 FirstDataSec; U32 RootDirSec; U32 RootEntCnt; U32 RootDirSecCnt; U32 FATSize; U32 FATStartSec; U32 TotalClusCnt; U32 TotalSec; U32 DataSecSize; U32 ClusterSize; U32 SecPerClus; }VolStruct;
void print_longName(LongDirEntry *pLongDir, U32 EntryNum); U32 show_dir(DirEntry *pDir); U32 HDD_read(U8 drv, U32 SecAddr, U32 blocks, U8 *buf); U32 Get_BPB_info(FAT16_BPB *BPB, VolStruct *pVol); void HexDump(U8 *addr, U32 len);
VolStruct gVol;
int main(void) { U8 buf[512]; U8 *pRootBuf; U32 MyBr;
gVol.Drive = 0x1; gVol.VolBeginSec = 0x0;
HDD_read(gVol.Drive, gVol.VolBeginSec, 1, buf); // 나의 USB에는 MBR이 있음 MyBr = *((unsigned int *)(buf + 446 + 8)); HDD_read(gVol.Drive, MyBr , 1, buf); // 그래서 BR부분을 한번 더 읽어야 함 if(0 == Get_BPB_info((FAT16_BPB *)buf, &gVol)) // FAT16이 아닐경우 0이 돌아오면서 종료 { printf("It is not FAT16 File System \n");
return 1; } pRootBuf = (U8 *)malloc(gVol.RootDirSecCnt * 512); // 동적할당을 받는다 if(0 == HDD_read(gVol.Drive, MyBr + gVol.RootDirSec, gVol.RootDirSecCnt, pRootBuf)) { printf("Root Dir Read Failed\n"); free(pRootBuf);
return 1; } show_dir((DirEntry *)pRootBuf);
free(pRootBuf);
return 0; }
U32 show_dir(DirEntry *pDir) { U32 i; U32 y; U32 LongEntryEn = 0;
for(i = 0;i <= gVol.RootEntCnt;i++) { switch( (U8)pDir[i].Name[0]) { case 0x00: return 1; case 0xE5: continue; }
if(0x0F == pDir[i].Attr) { LongEntryEn = 1; continue; }
printf("--------Entry Number %d--------\n", i);
if(0x10 == pDir[i].Attr) { printf("Directory Name : "); } else { printf("File Name : "); }
if(1 == LongEntryEn) { print_longName((LongDirEntry *)pDir, i-1); LongEntryEn = 0; } else { for(y = 0;y < 11;y++) { printf("%c", pDir[i].Name[y]); } } printf("\n"); printf("File Size : %d\n", pDir[i].FileSize); printf("Start Cluster : %d\n", (pDir[i].FstClusLow | pDir[i].FstClusHi << 16) ); }
return 1; }
void print_longName(LongDirEntry *pLongDir, U32 EntryNum) { wchar_t filename[512]; char final[512]; U32 nameOffset = 0;
do { memcpy(&filename[nameOffset], pLongDir[EntryNum].Name1, 10); nameOffset = nameOffset + 5; memcpy(&filename[nameOffset], pLongDir[EntryNum].Name2, 12); nameOffset = nameOffset + 6; memcpy(&filename[nameOffset], pLongDir[EntryNum].Name3, 4); nameOffset = nameOffset + 2; }while( 0 == (pLongDir[EntryNum--].Order & 0x40) );
filename[nameOffset] = 0x0000;
wcstombs(final, filename, 512);
printf("%s", final);
return ; }
U32 Get_BPB_info(FAT16_BPB *BPB, VolStruct *pVol) { if( 0 == BPB->RootEntCnt || 0xAA55 != BPB->Signature ) { return 0; }
if( 0 != BPB->TotSec16 ) { pVol->TotalSec = BPB->TotSec16; } else { pVol->TotalSec = BPB->TotSec32; }
pVol->FATSize = BPB->FATs16; // FAT영역의 섹터 수
pVol->FATStartSec = pVol->VolBeginSec + BPB->RsvdSecCnt; // 루트 디렉토리의 Directory Entry 개수
pVol->RootEntCnt = BPB->RootEntCnt; // 루트디렉토리 시작섹터
pVol->RootDirSec = pVol->VolBeginSec + BPB->RsvdSecCnt + (BPB->NumFATs * BPB->FATs16);
pVol->RootDirSecCnt = ((BPB->RootEntCnt * 32) + (BPB->BytsPerSec - 1)) / BPB->BytsPerSec; // 루트디렉토리의 섹터수
pVol->FirstDataSec = pVol->VolBeginSec + BPB->RsvdSecCnt + (BPB->NumFATs * pVol->FATSize) + pVol->RootDirSecCnt; // 첫번째 데이터 섹터를 구하는 코드
pVol->DataSecSize = pVol->TotalSec - (BPB->RsvdSecCnt + (BPB->NumFATs * pVol->FATSize) + pVol->RootDirSecCnt); // 데이터 영역의 섹터 수
pVol->TotalClusCnt = pVol->DataSecSize / BPB->SecPerClus; // 볼륨의 총 클러스터 개수
pVol->ClusterSize = BPB->SecPerClus * BPB->BytsPerSec; // 클러스터의 크기
pVol->SecPerClus = BPB->SecPerClus; // 클러스터가 몇 개의 섹터를 차지하는가
return 1; }
U32 HDD_read(U8 drv, U32 SecAddr, U32 blocks, U8* buf) { U32 ret; U32 ldistanceLow; U32 ldistanceHigh; U32 dwpointer; U32 bytestoread; U32 numread; char cur_drv[100]; HANDLE g_hDevice;
sprintf(cur_drv,"\\\\.\\physicalDrive%d",(U32)drv); g_hDevice = CreateFile(cur_drv, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); // 하드드라이버 연다 if(g_hDevice == INVALID_HANDLE_VALUE) // 에러 체크 { return 0; }
ldistanceLow = SecAddr << 9; ldistanceHigh = SecAddr >> (32 - 9); dwpointer = SetFilePointer(g_hDevice, ldistanceLow, (long *)&ldistanceHigh, FILE_BEGIN); // 파일포인터를 이동시킨다 (제일 처음으로) // FILE_BEGIN 제일 처음으로 이동 (win32표준 :: lseek)
if(0xFFFFFFFF != dwpointer) // -1인지 체크 { bytestoread = blocks * 512; ret = ReadFile(g_hDevice, buf, bytestoread, (unsigned long *)&numread, NULL);
if(ret) { ret = 1; } else { ret = 0; } }
CloseHandle(g_hDevice); return ret; }
void HexDump(U8 *addr, U32 len) { U8 *s = addr; U8 *endPtr = (U8 *)((U32)addr+len); U32 i; U32 remainder = len%16;
printf("\n Offset Hex Value Ascii value\n");
while(s+16 <= endPtr) { printf("0x%08LX ", (long)(s-addr));
for(i = 0;i < 16;i++) { printf("%02X ", s[i]); } printf(" ");
for(i = 0;i < 16;i++) { if(s[i] >= 32 && s[i] <= 125) { printf("%c", s[i]); } else { printf("."); } } s = s + 16; printf("\n"); }
if(remainder) { printf("0x08LX ", (long)(s-addr));
for(i = 0;i < remainder;i++) { printf("%02X ", s[i]); } for(i = 0;i < (16-remainder);i++) { printf(" "); }
printf(" "); for(i = 0;i < remainder;i++) { if(s[i] >= 32 && s[i] <= 125) { printf("%c", s[i]); } else { printf("."); } } for(i = 0;i < (16 - remainder);i++) { printf(" "); } printf("\n"); } return ; }
|