简单的FAT32 U盘隐写

一、实验预期目的及实验环境

本实验意实现FAT32结构下的U盘隐写不被U盘文件系统读出,主要考察FAT32简单的结构认识和简单的代码能力。

为了方便实现,目标机环境设为Winxp sp2,附带Winhex和VS2010工具包。

二、基础知识

FAT32整体文件结构如下

这里写图片描述

本实验主要需要隐写文件至Upan处,方法采用修改FAT表、0号1号磁盘信息实现隐写。

0号磁盘结构中需要注意如下

偏移0BH:扇区字节数      00 020X0200,512字节
偏移0DH:每簇扇区数      08即每簇包括8个扇区
偏移0EH:保留扇区数      24 00即保留36个扇区
偏移10H:FAT表份数       02即两个FAT表
偏移24H:FAT表占用扇区数  EE 1D  00 00即FAT表占7662个扇区

1号磁盘结构中需要注意如下

偏移0x1E8:空闲簇数        4个字节
偏移0x1Ec:下一可用簇号  4个字节

注意这里存储的都是小端序!

FAT32结构如下
FAT表项每一项占4字节,表项的地址编号对应相应的簇序号。
表项的内容如下:

若为0,该簇未被分配;
若为0xFFFFFF7,坏簇,内有坏扇区;
若为0x0FFFFFF,该簇为文件结束簇;
其它值,为对应文件的下一簇号

我们这里处理用0xFFFFFF7伪造坏簇。一般情况下FAT表会有多个(一般是2个,所以还是需要把每个表都改掉)

注意簇位置对应的公式如下!

保留区*扇区大小+(第一个簇标号-2)*每簇大小*512+FAT表个数*扇区大小*FAT表大小

为什么中间有个减2呢?原因是FAT中的0、1号簇对应的地方用来存放其他的内容了,所以对应的没有0、1号簇,最先的簇从2号开始。’

三、实现思路

这里使用的方法很简单,甚至很幼稚

1.U盘的检测用map数组,最开始标记,动态判定一定数量的的磁盘有无变化来检测

2.U盘中需要存放不连续的簇的位置,我直接写到了U盘的空白区0x800位置,其实如果藏到FAT表中的隐蔽性会更小,受到的大小限制也更小了(因为前面的空白区毕竟有限)

3.只是单纯为了验证效果,写入U盘,和读取U盘文件运行都是用的文件的形式,文件用的固定地址

四、代码

// Upan_killer.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "iostream"
#include "windows.h"
#include "DBT.H"
#include "fstream"
#include "map"
#include "string"
using namespace std;

#define A  TEXT("\\\\.\\A:") 
#define B  TEXT("\\\\.\\B:") 
#define C  TEXT("\\\\.\\C:") 
#define D  TEXT("\\\\.\\D:") 
#define E  TEXT("\\\\.\\E:") 
#define F  TEXT("\\\\.\\F:") 
#define G  TEXT("\\\\.\\G:") 
#define H  TEXT("\\\\.\\H:") 
#define I  TEXT("\\\\.\\I:") 
#define J  TEXT("\\\\.\\J:") 

char U[3]={
  
  0};          //U盘的盘符

int LeftArea,FatSize;   //分别是FAT区的保留区大小和FAT表的大小
int FirstCluster;       //可以利用的第一个簇号码
int SectorLeft;         //剩余可利用的空闲簇
int ClusterSize;        //簇的大小
int ClusterNeed;        //写入的exe文件所需要的簇数
map<string,int>mmp;
//判断文件是否被建立
int FileExits(char *FileName)
{
    fstream _file;
    _file.open(FileName,ios::in);
    if(!_file) return 0;
    else return 1;
}

//参数分别是文件句柄、数据缓冲区、准备文件读取的字节数和读取位置的偏移量
void ReadFileWithSize(HANDLE h,unsigned char* Buffer,DWORD dwBytestoRead,DWORD offset)
{
    DWORD dwBytesRead,dwBytesToRead;
    OVERLAPPED over = { 0 };            //计算读取的偏移量
    over.Offset = offset; 
    dwBytesToRead = dwBytestoRead;      // 要读取的字节数
    dwBytesRead = 0;                    // 实际读取到的字节数
    do{                                       //循环写文件,确保完整的文件被写入  
        ReadFile(h,Buffer,dwBytesToRead,&dwBytesRead,&over);
        dwBytesToRead -= dwBytesRead;
        Buffer += dwBytesRead;
     } while (dwBytesToRead > 0);

}
//参数分别是文件句柄、数据缓冲区、准备文件读取的字节数和读取位置的偏移量
void WriteFileWithSize(HANDLE h,unsigned char* Buffer,DWORD dwBytesToWrite,DWORD offset)
{
    DWORD dwBytesWrite;
    OVERLAPPED over = { 0 };            //计算读取的偏移量
    over.Offset = offset; 
    dwBytesToWrite = dwBytesToWrite;        // 要写入的字节数
    dwBytesWrite = 0;                   // 实际读取到的字节数
    do{                                       //循环写文件,确保完整的文件被写入  
        WriteFile(h,Buffer,dwBytesToWrite,&dwBytesWrite,&over);
        dwBytesToWrite -= dwBytesWrite;
        Buffer += dwBytesWrite;
     } while (dwBytesToWrite > 0);

}

//将一串hex值变成int型
int UcharToInt(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值