Chinaunix首页 | 论坛 | 博客
  • 博客访问: 219858
  • 博文数量: 67
  • 博客积分: 3156
  • 博客等级: 中校
  • 技术积分: 650
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-18 17:41
个人简介

软件工程师!

文章分类

全部博文(67)

文章存档

2015年(1)

2014年(1)

2012年(6)

2011年(16)

2010年(31)

2009年(12)

分类: WINDOWS

2009-07-07 16:03:43

   可能很多的人都没有注意到一些事情,就是你的程序是不是合法的可运行的应用程序,例如一个文件只是把后缀改成.exe的形式就显示为应用程序的图标了!你不想写一个根据后缀名就确定应用程序类型的程序吧!这样太哪个了吧!解决方法就是根据PE文件格式来解释.
   关于PE文件格式的资料现在网上汗牛充栋,这里我就不再解释,有兴趣的朋友可以上网查阅PE文件格式资料.我就简单的用代码去演示如何判断PE文件合法, 主要就是两个地方,头为"MZ"签名,跟着DOS头部的就是"PE"签名,任何标准的PE文件都会包含这两个签名.如下这段代码所示,这是一个判断是否为合法PE文件的API.

BOOL IsValidPEFile( CString strPathName )
{
    if ( ! PathFileExists( strPathName ) )
        return FALSE;

    HANDLE hFile = CreateFile( strPathName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
    if ( hFile == INVALID_HANDLE_VALUE ) {
        TRACE1( "Failed To Open File %s !\n", strPathName );
        return FALSE;
    }

    HANDLE hMMFile = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
    if ( hMMFile == INVALID_HANDLE_VALUE ) {
        CloseHandle( hFile );
        return FALSE;
    }

    LPVOID pvMem = MapViewOfFile( hMMFile, FILE_MAP_READ, 0, 0, 0 );
    if ( ! pvMem ) {
        CloseHandle( hMMFile );
        CloseHandle( hFile );
        return FALSE;
    }

    if ( *( USHORT* ) pvMem != IMAGE_DOS_SIGNATURE ) {
        UnmapViewOfFile( pvMem );
        CloseHandle( hMMFile );
        CloseHandle( hFile );
        return FALSE;
    }

    if ( *( ( DWORD* ) ( ( PBYTE ) pvMem + ( ( PIMAGE_DOS_HEADER ) pvMem )->e_lfanew ) ) != IMAGE_NT_SIGNATURE ) {
        UnmapViewOfFile( pvMem );
        CloseHandle( hMMFile );
        CloseHandle( hFile );
        return FALSE;
    }

    UnmapViewOfFile( pvMem );
    CloseHandle( hMMFile );
    CloseHandle( hFile );

    return TRUE;
}


这段代码实现了对PE文件合法性的判断.
但是,我还希望对应用程序的类型作一个更加彻底的判断,如何知道应用程序是基于窗口形式的还是基于命令行形式的程序呢?
其实PE文件中早已经包含了这种程序类型的标志!这个标志包含在PE文件的头部IMAGE_NT_HEADER的结构中的IMAGE_OPTIONAL_HEADER的Sybsystem记录!
看看"winnt.h"中对Sybsystem的宏定义.#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem.
#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character System
#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem.
#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image runs in the Posix character subsystem.
#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 // image is a native Win9x driver.
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 // Image runs in the Windows CE subsystem.
    通过这些定议则可以轻易的判断应用程序是何种形式的,当Subsystem的值为IMAGE_SUBSYSTEM_WINDOWS_GUI的
时候,则可以确定这个程序是基于图形界面的,当它的值为IMAGE_SUBSYSTEM_WINDOWS_CUI的时候可以确定它为命令
行的程序了.

核心的代码如下


LPVOID pvOptionalHeader = ( PBYTE ) pvMem + ( ( PIMAGE_DOS_HEADER ) pvMem )->e_lfanew + sizeof( DWORD ) + sizeof( IMAGE_FILE_HEADER );

    IMAGE_OPTIONAL_HEADER ioh;
    CopyMemory( & ioh, pvOptionalHeader, sizeof( IMAGE_OPTIONAL_HEADER ) );

    if ( ioh.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI ) {
        UnmapViewOfFile( pvMem );
        CloseHandle( hMMFile );
        CloseHandle( hFile );

        return TRUE;
    }


只要找到IMAGE_OPTIONAL_HEADER的结构就可以得出我们想要的结果了!
当然,要有一个Demo证明以上代码完全属实!
文件:Demo.rar
大小:22KB
下载:下载
阅读(1029) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~