fmifs.dll导出函数参数分析和整理

标 题: 【原创】fmifs.dll导出函数参数分析和整理
作 者: raigeki
时 间: 2013-07-18,12:36:28
链 接: http://bbs.pediy.com/showthread.php?t=175653

(大牛飘过吧!~)
    很久以前,发现一本叫逆向工程解密的书,当时,对于只会看MSDN的我和小伙伴们都惊呆了!居然可以通过逆向,分析出未文档化函数的接口参数,加以利用。果断瞧瞧,学习一把。后来我们碰到未文档化的函数时,我们都懂的……
    
    上次发现fmifs.dll以及该动态链接库的导出函数,并且未文档化,我们也来分析一下。(大神曰:此dll功能强大!)转入正题……
    
分析未文档化函数的使用:
一般途径:
    1、能找到一个系统中的调用例子,进行分析,这样可以看到该函数的参数具体形式(如SHFormatDrive中调用了FormatEx);
    2、没有调用例子,通过分析该函数的代码,找出函数各个参数的使用限制,猜测参数的具体形式;
快捷途径:
    1、搜索引擎,瞧瞧,有没有研究过,有直接拿过来就行;
    2、某年某月,windows流出了古老的代码,过去翻翻,看有用得着的东西没有(这个的确快捷好用,别说,以前真不知道,那码怎么用,看哪里……);

走一般途径,各种锻炼;走快捷途径,各种速度;各种通吃也行,看你想要啥?……
    
该DLL共导出17个函数(应该说是16个,有一个初始化的fmifs的是DLLEntryPoint),从函数名可以看出,大致分为三类:查询xxx函数,设置xxx函数,具体操作xxx函数。
    
各种函数传参和返回时:
传入信息时,可以是字符串,或者各种标志信息标志信息中,可能一个DWORD只表示一种状态(如:enum 类型),也可能一个DWORD包含多种信息(如:CreateFile,中各种 标志1|标志2),就看这个DWORD是否涉及位运算;
返回信息时,一般是传入一个地址,然后通过指针往一个地址写东西,通过写的长度,可以判断这个指针所指缓冲区的大小。

分析时碰到的实例:
实例一:
代码:
char __stdcall QueryAvailableFileSystemFormat(unsigned int a1, void *a2, int a3, int a4, int a5)
{
    memcpy(a2, (char *)&dword_696D5008 + 22 * a1, 2 * wcslen((const wchar_t *)&dword_696D5008 + 11 * a1) + 2);
    *(_BYTE *)a3 = byte_696D501A[v6];
    *(_BYTE *)a4 = byte_696D501B[v6];
    *(_BYTE *)a5 = byte_696D501C[v6];
}
(IDA F5 插件,估计又被鄙视了!! )很明显,a3,a4,a5是一个字节的输出缓冲区。a2,从memcpy最后一个参数,2*字符数+2(宽字符是两个字节表示一个字符),表示一个缓冲区。

实例二:
代码:
char __stdcall QueryDeviceInformation(int a1, int a2, unsigned int a3)
{
  ……
  if ( (unsigned __int8)WSTRING__Initialize(&v6, a1, -1)&& ……)
  {
    ……
     *(_DWORD *)a2 = -(v8 != 0) & 0x10 | -(v9 != 0) & 0x41 | -((_BYTE)v10 != 0) & 0x20 | -(BYTE1(v10) != 0) & 0x40;
    
  }
  ……
}
参数a1,和WSTRING_Initialize,a1是宽字串指针;看看a2的赋值,明显PDWORD,而且包含四个标志信息,一个标志信息一个字节。


实例三:
    从上边两个例子的代码可以看出,参数大多是int(可以是指针,标志等),返回值是char(其实是BOOLEAN),而不是我们平时看到的各种HANDLE,XXX_TYPE,ULONG,BOOL,BOOLEAN,PWCHAR等。其实汇编代码里,知道的只是参数的长度(1字节,2字节,4字节等等),究其原因,其实是typedef、enum,#define等关键字,创建了各种各样华丽的包装,使得程序代码看起来生动活泼。汇编语言,因为不生动活泼,所以对其感兴趣的人都是一些寂寞的人。还有一个问题,因为函数传参是,都是push一次,4个字节,而不会出现push 一字节,所以,参数是否是小于四字节的类型,还需要根据代码中对该变量的操作来确定。

下面是一些函数的定义和调用注意事项(windows XP SP3 下的),调用不成功的就不贴了:
代码:
//QueryFileSystemName
typedef BOOLEAN (__stdcall *PQUERYFILESYSTEMNAME)(IN PWCHAR DriveName,
              IN PWCHAR FileSystemName,
              OUT PUCHAR MarjorVersion,//某种特定情况下才会返回版本信息
              OUT PUCHAR MiniVersion,//某种特定情况下才会返回版本信息
              OUT PDWORD Result);

//QueryLatestFileSystemVersion
typedef BOOLEAN (__stdcall *PQUERYLATESTFILESYSTEMVERSION)(IN PWCHAR DriveName,
                 OUT PUCHAR MarjorVersion,//总是返回版本信息
                 OUT PUCHAR MiniVersion);//总是返回版本信息

//QueryAvailableFileSystemFormat
typedef BOOLEAN (__stdcall *PQUERYAVAILABLEFILESYSTEMFORMAT)(IN FILESYS_TYPE FileType,//枚举类型0:FAT,1:FAT32,2:exFAT,3:NTFS4.0,4:NTFS5.0
                   OUT PWCHAR FileSystemName,
                         OUT PUCHAR MajorVersion,//总是返回版本信息
                   OUT PUCHAR MiniVersion,//总是返回版本信息
                   OUT PBOOLEAN Result);

//QueryDeviceInformation
typedef BOOLEAN (__stdcall *PQUERYDEVICEINFORMATION)(IN PWCHAR DriveName,
                 OUT PDWORD DeviceCharacter,//这一组属性解析应该需要很多define值
                 IN size_t nDeviceCharacter);

//QueryDeviceInformationByHandle
typedef BOOLEAN (__stdcall *PQUERYDEVICEINFORMATIONBYHANDLE)(IN HANDLE DriverHandle,
                   OUT PDWORD DeviceCharacter,//这一组属性解析应该需要很多define值
                   IN size_t nDeviceCharacter);

//QuerySupportedMedia
typedef BOOLEAN (__stdcall *PQUERYSUPPORTEDMEDIA)(IN PWCHAR DriveName,
              OUT PDWORD pBuffer,//MEDIA_TYPE类型
              IN size_t nBuffer,
              OUT PDWORD Result);

//SetLabel
typedef BOOLEAN (__stdcall *PSETLABEL)(IN PWCHAR DriveName,
               IN PWCHAR Label);

//EnableVolumeCompression
typedef BOOLEAN (__stdcall *PENABLEVOLUMECOMPRESSION)(IN PWCHAR VolumeDriver,
                  IN BOOLEAN CompressOrNot);
注:压缩功能只针对NTFS文件系统。

//Chkdsk
typedef VOID (__stdcall *PCHKDSK)(IN PWCHAR DriveName,
          IN PWCHAR Format,
          IN BOOLEAN CorrectErrors,
          IN BOOLEAN Verbose,
          IN BOOLEAN CheckOnlyIfDirty,
          IN BOOLEAN Recover,
          IN PWCHAR  PathToCheck,
          IN BOOLEAN Extend,
          IN PFMIFSCALLBACK CallBack);
注:检查功能只针对FAT,FAT32文件系统。

//FormatEx
typedef VOID (__stdcall *PFORMATEX) (IN PWCHAR DriveName,
             IN DWORD MediaFlag,
             IN PWCHAR Format,
             IN  PWCHAR Label,
             IN BOOL QuickFormat,
             IN DWORD ClusterSize,
             IN PFMIFSCALLBACK Callback);

//Format
typedef VOID (__stdcall *PFORMAT)(IN PWCHAR DriveName,
          IN MEDIA_TYPE MediaType,
          IN PWCHAR FileSysName,
          IN PWCHAR Label,
          IN BOOLEAN Quick,
          IN PFMIFSCALLBACK CallBack);

//Extend
typedef BOOL (__stdcall *PEXTEND)(IN PWCHAR DriveName,
          IN BOOLEAN Verify,
          IN PFMIFSCALLBACK CallBack);
注:貌似只针对NTFS文件系统。

//DiskCopy
typedef BOOL (__stdcall *PDISKCOPY)(IN PWCHAR Src_Disk,
            IN PWCHAR Dsk_Disk,
            IN BOOLEAN Verify,
            IN PFMIFSCALLBACK CallBack);

//ComputeFmMediaType
typedef MEDIA_TYPE (__stdcall *PCOMPUTEFMMEDIATYPE)(IN MEDIA_TYPE type);

//Fmifs CallBack
typedef BOOLEAN (__stdcall *PFMIFSCALLBACK)(FMIFS_PACKET_TYPE Command, 
                                               ULONG PackLength, 
                                                                             PVOID PackInfo);
关于MEDIA_TYPE定义,MSDN里面有的。直接拿过来了,发现比之前得到的版本多了好多:
代码:
typedef enum _MEDIA_TYPE { 
  Unknown         = 0x00, //Format is unknown
  F5_1Pt2_512     = 0x01,  //A 5.25" floppy, with 1.2MB and 512 bytes/sector.
  F3_1Pt44_512    = 0x02,  //A 3.5" floppy, with 1.44MB and 512 bytes/sector.
  F3_2Pt88_512    = 0x03,  //A 3.5" floppy, with 2.88MB and 512 bytes/sector.
  F3_20Pt8_512    = 0x04,  //A 3.5" floppy, with 20.8MB and 512 bytes/sector.
  F3_720_512      = 0x05,  //A 3.5" floppy, with 720KB and 512 bytes/sector.
  F5_360_512      = 0x06,  //A 5.25" floppy, with 360KB and 512 bytes/sector.
  F5_320_512      = 0x07,  //A 5.25" floppy, with 320KB and 512 bytes/sector.
  F5_320_1024     = 0x08,  //A 5.25" floppy, with 320KB and 1024 bytes/sector.
  F5_180_512      = 0x09,  //A 5.25" floppy, with 180KB and 512 bytes/sector.
  F5_160_512      = 0x0a,  //A 5.25" floppy, with 160KB and 512 bytes/sector.
  RemovableMedia  = 0x0b,  //Removable media other than floppy.
  FixedMedia      = 0x0c,  //Fixed hard disk media.
  F3_120M_512     = 0x0d,  //A 3.5" floppy, with 120MB and 512 bytes/sector.
  F3_640_512      = 0x0e,  //A 3.5" floppy, with 640KB and 512 bytes/sector.
  F5_640_512      = 0x0f,  //A 5.25" floppy, with 640KB and 512 bytes/sector.
  F5_720_512      = 0x10,  //A 5.25" floppy, with 720KB and 512 bytes/sector.
  F3_1Pt2_512     = 0x11,  //A 3.5" floppy, with 1.2MB and 512 bytes/sector.
  F3_1Pt23_1024   = 0x12,  //A 3.5" floppy, with 1.23MB and 1024 bytes/sector.
  F5_1Pt23_1024   = 0x13,  //A 5.25" floppy, with 1.23MB and 1024 bytes/sector.
  F3_128Mb_512    = 0x14,  //A 3.5" floppy, with 128MB and 512 bytes/sector.
  F3_230Mb_512    = 0x15,  //A 3.5" floppy, with 230MB and 512 bytes/sector.
  F8_256_128      = 0x16,  //An 8" floppy, with 256KB and 128 bytes/sector.
  F3_200Mb_512    = 0x17,  //A 3.5" floppy, with 200MB and 512 bytes/sector. (HiFD).
  F3_240M_512     = 0x18,  //A 3.5" floppy, with 240MB and 512 bytes/sector. (HiFD).
  F3_32M_512      = 0x19  //A 3.5" floppy, with 32MB and 512 bytes/sector.
} MEDIA_TYPE;
关于Fmifs pack type定义和各种包结构定义,参考windows NT4源码,windows兼容性就是好,数据结构扩展性极强,原来的东西都尽量保留 :
代码:
typedef enum _FMIFS_PACKET_TYPE {
  FmIfsPercentCompleted,
  FmIfsFormatReport,
  FmIfsInsertDisk,
  FmIfsIncompatibleFileSystem,
  FmIfsFormattingDestination,
  FmIfsIncompatibleMedia,
  FmIfsAccessDenied,
  FmIfsMediaWriteProtected,
  FmIfsCantLock,
  FmIfsCantQuickFormat,
  FmIfsIoError,
  FmIfsFinished,
  FmIfsBadLabel,
  FmIfsCheckOnReboot,
  FmIfsTextMessage,
  FmIfsHiddenStatus
} FMIFS_PACKET_TYPE, *PFMIFS_PACKET_TYPE;

typedef struct _FMIFS_PERCENT_COMPLETE_INFORMATION {
  ULONG   PercentCompleted;
} FMIFS_PERCENT_COMPLETE_INFORMATION, *PFMIFS_PERCENT_COMPLETE_INFORMATION;

typedef struct _FMIFS_FORMAT_REPORT_INFORMATION {
  ULONG   KiloBytesTotalDiskSpace;
  ULONG   KiloBytesAvailable;
} FMIFS_FORMAT_REPORT_INFORMATION, *PFMIFS_FORMAT_REPORT_INFORMATION;

typedef struct _FMIFS_INSERT_DISK_INFORMATION{
  ULONG   DiskType;
} FMIFS_INSERT_DISK_INFORMATION, *PFMIFS_INSERT_DISK_INFORMATION;

typedef struct _FMIFS_IO_ERROR_INFORMATION {
  ULONG   DiskType;
  ULONG   Head;
  ULONG   Track;
} FMIFS_IO_ERROR_INFORMATION, *PFMIFS_IO_ERROR_INFORMATION;

typedef struct _FMIFS_FINISHED_INFORMATION {
  BOOLEAN Success;
} FMIFS_FINISHED_INFORMATION, *PFMIFS_FINISHED_INFORMATION;

typedef struct _FMIFS_CHECKONREBOOT_INFORMATION {
  OUT BOOLEAN QueryResult; // TRUE for "yes", FALSE for "no"
} FMIFS_CHECKONREBOOT_INFORMATION, *PFMIFS_CHECKONREBOOT_INFORMATION;

typedef enum _TEXT_MESSAGE_TYPE {
  MESSAGE_TYPE_PROGRESS,
  MESSAGE_TYPE_RESULTS,
  MESSAGE_TYPE_FINAL
} TEXT_MESSAGE_TYPE, *PTEXT_MESSAGE_TYPE;

typedef struct _FMIFS_TEXT_MESSAGE {
  IN TEXT_MESSAGE_TYPE    MessageType;
  IN PSTR                 Message;
} FMIFS_TEXT_MESSAGE, *PFMIFS_TEXT_MESSAGE;
PS:差不多了,上面的说的和写的肯定有很多不足,欢迎拍砖!~,上面这些够用了,调用的代码我就不贴了。上次V大说的内个ChkdskEx,倒数第二个参数整不明白……没调用成功,貌似是一个结构体。

你可能感兴趣的:(看雪转载笔记,逆向)