怎么在linux上查看dll文件,一段linux下分析dll文件格式的程序

/*

下文的代码既可在linux亦可在windows下运行。

为什么要保留这段代码呢?

1.包含了最近一段时间对pe文件格式的分析;

以后如果再需要用pe格式只要看看这段代码就行了,容易上手。

2.pe文件中rva到文件偏移量的转换比较头大;

这段代码中有较好的函数实现。

此程序的功能是判断一个文件是否为.cpl文件。cpl文件其实就是dll,但是包含了一个特殊接口。

*/

#include

#include

#include

#include

#include

using namespace std;

//下面的这些结构都是winnt.h中对pe文件头的定义

typedef struct _IMAGE_DATA_DIRECTORY {

unsigned long   VirtualAddress;

unsigned long   Size;

} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

typedef struct _IMAGE_FILE_HEADER {

unsigned short    Machine;

unsigned short    NumberOfSections;

unsigned long   TimeDateStamp;

unsigned long   PointerToSymbolTable;

unsigned long   NumberOfSymbols;

unsigned short    SizeOfOptionalHeader;

unsigned short    Characteristics;

} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

typedef struct _IMAGE_OPTIONAL_HEADER {

//

// Standard fields.

//

unsigned short    Magic;

char    MajorLinkerVersion;

char    MinorLinkerVersion;

unsigned long   SizeOfCode;

unsigned long   SizeOfInitializedData;

unsigned long   SizeOfUninitializedData;

unsigned long   AddressOfEntryPoint;

unsigned long   BaseOfCode;

unsigned long   BaseOfData;

//

// NT additional fields.

//

unsigned long   ImageBase;

unsigned long   SectionAlignment;

unsigned long   FileAlignment;

unsigned short    MajorOperatingSystemVersion;

unsigned short    MinorOperatingSystemVersion;

unsigned short    MajorImageVersion;

unsigned short    MinorImageVersion;

unsigned short    MajorSubsystemVersion;

unsigned short    MinorSubsystemVersion;

unsigned long   Win32VersionValue;

unsigned long   SizeOfImage;

unsigned long   SizeOfHeaders;

unsigned long   CheckSum;

unsigned short    Subsystem;

unsigned short    DllCharacteristics;

unsigned long   SizeOfStackReserve;

unsigned long   SizeOfStackCommit;

unsigned long   SizeOfHeapReserve;

unsigned long   SizeOfHeapCommit;

unsigned long   LoaderFlags;

unsigned long   NumberOfRvaAndSizes;

IMAGE_DATA_DIRECTORY DataDirectory[16];

} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

typedef struct _IMAGE_NT_HEADERS {

unsigned long Signature;

IMAGE_FILE_HEADER FileHeader;

IMAGE_OPTIONAL_HEADER32 OptionalHeader;

} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

typedef PIMAGE_NT_HEADERS32                 PIMAGE_NT_HEADERS;

typedef struct _IMAGE_SECTION_HEADER {

char    Name[8];

union {

unsigned long   PhysicalAddress;

unsigned long   VirtualSize;

} Misc;

unsigned long   VirtualAddress;

unsigned long   SizeOfRawData;

unsigned long   PointerToRawData;

unsigned long   PointerToRelocations;

unsigned long   PointerToLinenumbers;

unsigned short    NumberOfRelocations;

unsigned short    NumberOfLinenumbers;

unsigned long   Characteristics;

} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

typedef IMAGE_NT_HEADERS32                  IMAGE_NT_HEADERS;

//这段代码判断rva在哪个section中

PIMAGE_SECTION_HEADER imagerva2section(PIMAGE_NT_HEADERS pimage_nt_headers,unsigned long dwRVA)

{

int i;

PIMAGE_SECTION_HEADER pimage_section_header=(PIMAGE_SECTION_HEADER)(((char *)(pimage_nt_headers)) + sizeof(IMAGE_NT_HEADERS));

for(i=0;iFileHeader.NumberOfSections;i++) {

//pimage_section_header->VirtualAddress 是section的首地址

//pimage_section_header->SizeOfRawData 是section的长度

if((pimage_section_header->VirtualAddress) && (dwRVA<=(pimage_section_header->VirtualAddress+pimage_section_header->SizeOfRawData)))

return ((PIMAGE_SECTION_HEADER)pimage_section_header);

pimage_section_header++;

}

return(NULL);

}

/*

计算偏移量的原理是什么呢?

先判断出rva在哪个section中,然后查section表找到与这个section对应的

文件偏移量,再用以下公式计算文件偏移量:

offset=rva-(section虚拟内存地址-section文件偏移量)

*/

unsigned long rva2offset(char * praw,unsigned long dwRVA)

{

unsigned long _offset;

PIMAGE_SECTION_HEADER section;

PIMAGE_NT_HEADERS pimage_nt_headers;

pimage_nt_headers = (PIMAGE_NT_HEADERS)(praw);

section=imagerva2section(pimage_nt_headers,dwRVA);

if(section==NULL)

return(-1);

//section->VirtualAddress 就是section的虚内存地址

//section->PointerToRawData 就是section的文件偏移量

_offset=dwRVA+section->PointerToRawData-section->VirtualAddress;

return(_offset);

}

// in fact the .cpl file is a .dll file, so we to check if it has "CPlApplet" symbol.

bool _iscpl(FILE * pf)

{

if (NULL==pf)

return false;

char symbolbuff[10];

unsigned long dwOffset = 0;

unsigned short magicnumber = 0;

fseek(pf,0,SEEK_SET);

fread(symbolbuff,1,2,pf);

if (symbolbuff[0]!='M' || symbolbuff[1]!='Z')

return false;

//skip dos stub.

//pe文件头是一个dos stub

fseek(pf,60,SEEK_SET);

//read pe offset.

//然后就是一个偏移量保存了真正的pe文件头

fread(&dwOffset,1,sizeof(dwOffset),pf);

//read nt header.

//在此读文件头并保存到一个结构内

fseek(pf,dwOffset,SEEK_SET);

char ntheader[10240];

fread(ntheader,1,sizeof(ntheader),pf);

fseek(pf,dwOffset,SEEK_SET);

//judge pe signature.

//pe文件头的首部是一个pe signature.

fread(symbolbuff,1,2,pf);

if (symbolbuff[0]!='P' || symbolbuff[1]!='E')

return false;

//read magic number to determine if the file is pe32 or pe32+.

fseek(pf,22,SEEK_CUR);

fread(&magicnumber,1,sizeof(magicnumber),pf);

//get the offset of optional header data directories

dwOffset = 0;

if (0x10b==magicnumber)

dwOffset = 96-2;

else

dwOffset = 112-2;

fseek(pf,dwOffset,SEEK_CUR);

fread(&dwOffset,1,sizeof(dwOffset),pf);

//seek to Optional Header Data Directories

dwOffset = rva2offset(ntheader,dwOffset);

if(dwOffset==-1)

return false;

fseek(pf,dwOffset,SEEK_SET);

int atenum = 0; //The number of entries in the export address table.

int nnpnum = 0; //The number of entries in the name pointer table. This is also the number of entries in the ordinal table.

fseek(pf,dwOffset+20,SEEK_SET);

fread(&atenum,1,sizeof(atenum),pf);

fseek(pf,dwOffset+24,SEEK_SET);

fread(&nnpnum,1,sizeof(nnpnum),pf);

//skip the export address table.

fseek(pf,dwOffset+40+4*atenum,SEEK_SET);

//now process name table.

vector vecstraddr;

for(int i=0;i

int nnpaddr = 0;

fread(&nnpaddr,1,sizeof(nnpaddr),pf);

nnpaddr = rva2offset(ntheader,nnpaddr);

if(nnpaddr==-1)

continue;

vecstraddr.push_back(nnpaddr);

}

//compare name string.

for(i=0;i

char buffstr[128];

int straddr = vecstraddr[i];

fseek(pf,straddr,SEEK_SET);

fread(buffstr,1,sizeof(buffstr),pf);

if(strcmp(buffstr,"CPlApplet")==0)

return true;

}

return false;

}

bool iscpl(const char * inputfile)

{

FILE * pf = fopen(inputfile,"rb");

bool res = _iscpl(pf);

fclose(pf);

return res;

}

int main(int argc, char* argv[])

{

bool res = iscpl("c:\\test.cpl");

return 0;

}

本文转载自:

http://tassardge.blog.163.com/blog/static/1723017082008102185122256/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值