coff文件简单分析

    最近事情比较多,驱动开发要放点时间在详细研究。说下coff格式的详细内容吧,window下就是编译过程中产生的obj文件,linux下为out文件。首先看下

http://baike.baidu.com/view/1240794.htm的内容吧,其中内容基本正确,这里只做一些补充

  

首先提供各我写的例子,本来就是自己看,所以变量值就用断点看吧。

 

用来生成例子obj的工程

#include
#include

#define PASSWORD_SIZE 100
#define PASSWORD      "myGOODpassword/n"
// The CR above is needed
// so as not to cut off
// the user-entered CR.
#pragma data_seg (".kpnc")
// Note that the period before the name
// isn't mandatory, just customary.
char passwd[ ]=PASSWORD;
#pragma data_seg ()


int main ()
{
// The counter for authentication failures
int count=0;
// The buffer for the user-entered password
char buff [PASSWORD_SIZE];

// The main authentication loop
for (;;)
{
// Prompting the user for a password
// and reading it
printf ("Enter password:");
fgets (&buff [0], PASSWORD_SIZE,stdin);

// Matching the entered password against the reference value
if (strcmp (&buff [0], passwd))
// "Scolding" if the passwords don't match;
printf ("Wrong password/n");
// otherwise (if the passwords are identical),
// getting out of the authentication loop
else break;

// Incrementing the counter of authentication failures
// and terminating the program if 3 attempts have been used
if (++count>3) return -1;
}

// Once we're here, the user has entered the right password.
printf ("Password OK/n");
}

分析coff文件的工程

.h文件

                                                                                                     iCur+=(strlen(str+iCur)+1); // 计算偏移时不要忘了计算‘/0’字符所占的1个字节!
                                                                                                    }
                                                                                                      free(str); // 释放字符串表空间
                                                                                                     直到这里,整个COFF的结构已经全部介绍完了。很多了解PE格式的朋友一定会奇怪,好像少了很多内容!?是的,标准的COFF文件只有这么多的东西。但MS为了和DOS的可执行文件兼容,以及对可执行文件功能的扩展,在COFF格式中加了很多它自己的标准。让我差点就认不出COFF了。但了解了COFF文件以后,再来学习PE文件的格式,那就很简单了。
                                                                                                       想了解PE文件的格式?网上有很多它的资料,我将在本文的基础上再写几篇文章,分别介绍PE,OMF以及ELF的格式。
                                                                                                      现在大家可以自己动手,写一个COFF文件解析器或是一个简单的连接程序了!
*/
#pragma pack(push)
#pragma pack(1)
typedef struct{
 unsigned short usMagic;
 unsigned short usNumSec;
 unsigned long ulTime;
 unsigned long ulSymolOffset;
 unsigned long ulNumSymbol;
 unsigned short usOptHdrSZ;
 unsigned short usFlags;
}COFF_FILE_HEADER;

typedef struct {
    unsigned short usMagic;
 unsigned short usVersion;
 unsigned long ulTextSize;
 unsigned long ulInitDataSZ;
 unsigned long ulUnintiDataSZ;
 unsigned long uEntry;
 unsigned long ulTextBase;
 unsigned long ulDataBase;
}OPTHDR;


typedef struct {
 char cName[8];
 unsigned long ulVSize;
 unsigned long ulVAddr;
 unsigned long ulSize;
 unsigned long ulSecOffset;
 unsigned long ulRelOffset;
 unsigned long ulLNOffset;
 unsigned short ulNumRel;
 unsigned short ulNumLN;
 unsigned long ulFlags;
}SECHDR;

typedef struct {
 unsigned long ulAddr;/* virtual address of reference */
 unsigned long uSymbol;
 unsigned short usType;
} RELOC;

typedef struct {
 unsigned long ulAddrORSymbol;
 unsigned short usLineNq;

} LINENO;

typedef struct {
 union {
  char cName[8];
  struct {
   unsigned long ulZero;
   unsigned long ulOffset;
  }e;
 }e;
 unsigned long ulValue;
 short iSection;
 unsigned short usType;
 unsigned char usClass;
 unsigned char usNumAux;
}SYMENT;
#pragma pack(pop)
.cpp


#include "stdafx.h"
#include "coffHeader.h"
#include "stdlib.h"
#include
#include

using namespace std;
#define MaxMemoryBlock 200
void* pMemBlock[MaxMemoryBlock];

void ClearMallocBlock()
{
 int iFreeCnt = 0;
 while(iFreeCnt++ {
  free(pMemBlock[iFreeCnt]);
 }
}

int _tmain(int argc, _TCHAR* argv[])
{
 
 int nMemCount = 0;
 FILE *pCoffFile = fopen("F://0501//Debug//erw.obj","rb+");

 int nSectionTotal0ffset = 0;
/*
 char rt[500];
 fread(rt,1,500,pCoffFile);
 int ct = 0;
 while(ct++ < 500)
 {
  if(rt[ct]=='.')
   int er = 0;
 }
*/
 vector vSecHdr;
 vector   vSecData;
 vector  vReloc;
 vector vLineNo;

 unsigned long ulCheckNum = 0;
 
 
 COFF_FILE_HEADER *pCoffHeader = (COFF_FILE_HEADER*)malloc(sizeof(COFF_FILE_HEADER));
 if(pCoffHeader==NULL)
 {
  return -1;
 }
 fread(pCoffHeader,1,sizeof(COFF_FILE_HEADER),pCoffFile);
    nSectionTotal0ffset += sizeof(COFF_FILE_HEADER);

    printf("the magic number is %d/n",pCoffHeader->usMagic);
 printf("the usNumSec is %d/n",pCoffHeader->usNumSec);
 
 if(pCoffHeader->usOptHdrSZ != 0)
 {
  printf("There is a Opt Header!/n");
  OPTHDR *pOptHdr = (OPTHDR*)malloc(sizeof(OPTHDR));
  if(pOptHdr==NULL)
   return -1;
  
  fread(pOptHdr,1,sizeof(OPTHDR),pCoffFile);
  nSectionTotal0ffset+=sizeof(OPTHDR);
 }
 
 int nSectionNum = pCoffHeader->usNumSec;
 int nTempSectionNum = nSectionNum;

 while(nTempSectionNum-->0)
 {
  SECHDR *pSectionHeader = (SECHDR*)malloc(sizeof(SECHDR)); 
  if(pSectionHeader==NULL)
  {
   return -1;
  }
  fseek(pCoffFile,nSectionTotal0ffset,SEEK_SET);
  fread(pSectionHeader,1,sizeof(SECHDR),pCoffFile);
  printf("Section Name is %s/n",pSectionHeader->cName);
  nSectionTotal0ffset+=sizeof(SECHDR);
        vSecHdr.push_back(pSectionHeader);
  
  unsigned long lSectionDataSize = pSectionHeader->ulSize; 

  fseek(pCoffFile,pSectionHeader->ulSecOffset,SEEK_SET);

  void* pSectionData = (void*)malloc(lSectionDataSize);
  if(pSectionData==NULL)
  {
   return -1;
  }
  fread(pSectionData,1,lSectionDataSize,pCoffFile);
  vSecData.push_back(pSectionData);


  // RELOC Content
  if(pSectionHeader->ulSecOffset > 0)
  {
   fseek(pCoffFile,pSectionHeader->ulRelOffset,SEEK_SET);
   
   int nRelocStruct = pSectionHeader->ulNumRel;
   while(nRelocStruct-->0)
   {
    RELOC* pReloc = (RELOC*)malloc(sizeof(RELOC));
    if(pReloc==NULL)
     return -1;
    fread(pReloc,1,sizeof(RELOC),pCoffFile);
                ulCheckNum = pReloc->uSymbol;
    vReloc.push_back(pReloc);
   }
  }

  // LINENUM Content
  if(pSectionHeader->ulLNOffset > 0)
  {
   fseek(pCoffFile,pSectionHeader->ulLNOffset,SEEK_SET);

   int nLineNumStruct = pSectionHeader->ulNumLN;
   while(nLineNumStruct-->0)
   {
    LINENO* pLineNum = (LINENO*)malloc(sizeof(LINENO));
    if(pLineNum==NULL)
     return -1;
    fread(pLineNum,1,sizeof(LINENO),pCoffFile);
    vLineNo.push_back(pLineNum);
   }
  }
 }

 //Symbol table
 FILE *pSymbolFind = pCoffFile;
 fseek(pSymbolFind,pCoffHeader->ulSymolOffset,SEEK_SET);
 unsigned long nSymbolNum = pCoffHeader->ulNumSymbol;
    vector vSymentTotal;
 while(nSymbolNum--)
 {
  SYMENT *pSyment = (SYMENT*)malloc(sizeof(SYMENT));
  fread(pSyment,1,sizeof(SYMENT),pSymbolFind);

  vSymentTotal.push_back(pSyment);

 }

 int iStrlen,iCur=4; // iStrLen是字符串表的长度,iCur是当前字符串偏移
 char *str; // 字符串表
 fread(&iStrlen,1, 4,pSymbolFind); // 得到字符串表长度
  str = (char *)malloc(iStrlen); // 为字符串表分配空间
     // 读字符串表,直到全部读入内存
 fread(str,1,iStrlen,pSymbolFind);

 iCur=4; // 把当前字符串偏移指到每一个字符串
 while (iCur  printf("String offset 0x%04X : %s/n", iCur, str + iCur);
  iCur+=(strlen(str+iCur)+1); // 计算偏移时不要忘了计算‘/0’字符所占的1个字节!
 }
 free(str); // 释放字符串表空间

 fclose(pCoffFile);
 
 return 0;
}

 

设断点就可以看到各项内容,另外在看一下http://osr507doc.sco.com/en/topics/COFF_SymValFld.html的内容,这个比较详细。

 

 

说我补充的几个内容吧,

1.File Header

  Optional Header

  Section Header 1

  ......

  Section Header n

  Section Data 1

  Relocation Directives 1

  Line Numbers 1

 

    Section Data 2

  Relocation Directives 2

      Line Numbers 2

 

  Symbol Table

  String Table

 

每一部分的section data后面是接reloc Directive 和line number的信息的例如

例如:.text 的

ulSize = 162

ulSecOffset = 1328

ulRelOffset = 1490

ulLNOffset = 1600

ulNumRel  = 11

ulNumLN = 11

下一段 dataoffset为 1666

按照这个结果显示

1328 + 162 = 1490

1490 + 11 *10 = 1600

1600 + 11*6 = 1666

可以看出各部分是完全没有空隙的连接的

2.reloc 表的 ulSymbol 这个所谓符号表索引为就是只第一个,比如coff头说有48个符号,那么ulSymbol

的值小于48,就是指第一个,

在我这里lineNum的ulAddrorsymbol的对应项是address ,至于这个需要对照IDA的结果看了,所以vc编译器的断点可以放在大括号上吧。

 

3.IDA把.debug$S .debug$T这个没有地址分配的section没有列出来,不过我看了一下,基本都是说明文件路径,lib名等一些辅助信息的,并没有什么实际意义

 

 

 

你可能感兴趣的:(技术类,authentication,header,passwords,struct,reference,null)