2011년7월6일_구조체의 관점에서 배열을 엑세스와 이 기법을 사용하여 실행파일(PE구조, ELF구조)의 매직코드만 추출해보자. HexaView 프로젝트...

 

★ 함수를 반환하는 함수와 함수를 인자로 받는 함수..그리고 그 함수의 주소를 받을 수 있는 함수포인터와 같이 복잡한 고급문법을 아는 것 보다 저급문법이라도 활용을 잘 하는 것이 중요하다.
★ 잘 하든 못 하든 표현을 잘하면 점점 더 잘하게 된다.
   못 하는 부분이 있으면 회피하지 말고 하는 것이 중요하다.
★ 커뮤니케이션 능력이 떨어지면 사회에서 도태된다.

 

파일을 만들 때 구조 그대로 읽어 들이려면 그 파일의 구조(format)을 알아야 한다.
아래의 링크를 클릭하여 먼저 개념을 익히자.

● 배열을 가리키는 구조체로 일정 양식에 맞춰 엑세스하는 법
    http://sumanaki.tistory.com/106 


오늘 뭐 한거지?  4a46b55d020016m1



PE(Portable Executable) header

 

● 구글 검색

image

 

image

 


● DOS header의 구조 (dos.h파일로 저장)

   1:  typedef unsigned short WORD;
   2:  typedef unsigned int LONG;
   3:   
   4:   
   5:  typedef struct _IMAGE_DOS_HEADER {     
   6:      WORD   e_magic;          // DOS signature : 4D5A ("MZ")
   7:      WORD   e_cblp;                     
   8:      WORD   e_cp;                       
   9:      WORD   e_crlc;                     
  10:      WORD   e_cparhdr;                  
  11:      WORD   e_minalloc;                 
  12:      WORD   e_maxalloc;                 
  13:      WORD   e_ss;                       
  14:      WORD   e_sp;                       
  15:      WORD   e_csum;                     
  16:      WORD   e_ip;                       
  17:      WORD   e_cs;                       
  18:      WORD   e_lfarlc;                   
  19:      WORD   e_ovno;                     
  20:      WORD   e_res[4];                   
  21:      WORD   e_oemid;                    
  22:      WORD   e_oeminfo;                  
  23:      WORD   e_res2[10];                  
  24:      LONG   e_lfanew;         // offset to NT header 
  25:  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;


WORD와 LONG 자료형이 없으므로 typedef으로 각 부호없는 short와 int로 정의하자.

 

● main.c 파일

   1:  #include <stdio.h>
   2:  #include <string.h>
   3:  #include "dos.h"
   4:  //#include <fcntl.h>  //oflag    저수준시 필요한 헤더파일
   5:  //#include <sys/types.h>
   6:  //#include <sys/stat.h>
   7:  #include "HexaView.h"
   8:   
   9:  #define BUFFERSIZE sizeof(IMAGE_DOS_HEADER)        //16 * 16line
  10:   
  11:  int main(int argc, char *argv[])
  12:  {
  13:      FILE *fp;
  14:      int iBytes;
  15:      unsigned int iPage = 0;        //256Bytes단위의 page
  16:      unsigned char ucBuffer[BUFFERSIZE];
  17:      PIMAGE_DOS_HEADER p;
  18:      
  19:      printf("%d\n", sizeof(IMAGE_DOS_HEADER));
  20:      printf("%d\n", sizeof(p));
  21:   
  22:      if(2 != argc)
  23:      {
  24:          fprintf(stderr, "파일이 없삼.\n");
  25:          return -100;        //명령줄 문제
  26:      }
  27:      
  28:      //파일오픈
  29:      fp = fopen(argv[1], "rb");
  30:   
  31:      if(NULL == fp)
  32:      {
  33:          fprintf(stderr, "파일열기 실패!\n");
  34:          fclose(fp);
  35:          return -99;            //파일열기 문제
  36:      }
  37:      
  38:      memset(ucBuffer, 0xFF, BUFFERSIZE);    
  39:   
  40:      iBytes = fread(ucBuffer, 1, BUFFERSIZE, fp);        //64Bytes읽어옴
  41:      p = (IMAGE_DOS_HEADER *)ucBuffer;                    //구조체포인터가 버퍼를 가리킴.
  42:      HexaView(ucBuffer, iBytes);                            //Hexa값 확인
  43:   
  44:      fclose(fp);
  45:   
  46:      printf("매직넘버 %04X\n", p->e_magic); 
  47:      printf("e_cblp? %04X\n", p->e_cblp); 
  48:   
  49:      
  50:      return 0;
  51:  }

 

<실행결과>

image 

매직넘버는 0x5A4D로 Big endian 표시이다. 실제 메모리에는 little endian으로 저장된다.
나머지 변수도 모두 출력해 보는 것이 좋으나 각자 무엇을 의미하는지 몰라 ㅠㅠ





ELF(Executable and Linkable Format) header


● /usr/include/elf.h 파일

   1:  /* The ELF file header.  This appears at the start of every ELF file.  */
   2:   
   3:  #define EI_NIDENT (16)
   4:   
   5:  typedef struct
   6:  {
   7:    unsigned char    e_ident[EI_NIDENT];    /* Magic number and other info */
   8:    Elf32_Half    e_type;            /* Object file type */
   9:    Elf32_Half    e_machine;        /* Architecture */
  10:    Elf32_Word    e_version;        /* Object file version */
  11:    Elf32_Addr    e_entry;        /* Entry point virtual address */
  12:    Elf32_Off    e_phoff;        /* Program header table file offset */
  13:    Elf32_Off    e_shoff;        /* Section header table file offset */
  14:    Elf32_Word    e_flags;        /* Processor-specific flags */
  15:    Elf32_Half    e_ehsize;        /* ELF header size in bytes */
  16:    Elf32_Half    e_phentsize;        /* Program header table entry size */
  17:    Elf32_Half    e_phnum;        /* Program header table entry count */
  18:    Elf32_Half    e_shentsize;        /* Section header table entry size */
  19:    Elf32_Half    e_shnum;        /* Section header table entry count */
  20:    Elf32_Half    e_shstrndx;        /* Section header string table index */
  21:  } Elf32_Ehdr;


32비트와 64비트 두개가 있는데 32비트를 사용하자.

 

● main.c

   1:  #include <stdio.h>
   2:  #include <string.h>
   3:  #include <elf.h>
   4:  #include "HexaView.h"
   5:   
   6:  #define BUFFERSIZE sizeof(Elf32_Ehdr)        //ELF파일 구조체의 크기
   7:   
   8:  int main(int argc, char *argv[])
   9:  {
  10:      FILE *fp;
  11:      int iBytes;
  12:      int iLoop;
  13:      unsigned int iPage = 0;                    //단위 page
  14:      unsigned char ucBuffer[BUFFERSIZE];
  15:      Elf32_Ehdr *p;
  16:      
  17:      printf("%d\n", sizeof(Elf32_Ehdr));
  18:      printf("%d\n", sizeof(p));
  19:   
  20:      if(2 != argc)
  21:      {
  22:          fprintf(stderr, "파일이 없삼.\n");
  23:          return -100;        //명령줄 문제
  24:      }
  25:      
  26:      //파일오픈
  27:      fp = fopen(argv[1], "rb");
  28:   
  29:      if(NULL == fp)
  30:      {
  31:          fprintf(stderr, "파일열기 실패!\n");
  32:          fclose(fp);
  33:          return -99;            //파일열기 문제
  34:      }
  35:      
  36:      memset(ucBuffer, 0xFF, BUFFERSIZE);    
  37:   
  38:      //파일의 내용을 읽어와 버퍼에 저장
  39:      iBytes = fread(ucBuffer, 1, BUFFERSIZE, fp);
  40:      //구조체포인터p가 버퍼를 가리키도록함.
  41:      p = (Elf32_Ehdr *)ucBuffer;
  42:      //page출력
  43:      printf("page.%-100d\n", ++iPage);
  44:      //헥사값을 보기 좋게 출력
  45:      HexaView(ucBuffer, iBytes);
  46:      fclose(fp);
  47:   
  48:      //매직넘버출력 ELF
  49:      printf("매직넘버 : ");
  50:      for(iLoop = 0 ; EI_NIDENT > iLoop ; ++iLoop)
  51:      {
  52:          printf("%02X ", p->e_ident[iLoop]);
  53:      }
  54:   
  55:      putchar('\n');
  56:      
  57:      return 0;
  58:  }


<실행결과>

image


unsigned char    e_ident[EI_NIDENT];    /* Magic number and other info */

매직넘버가 char형이니 big/little endian을 구분할 필요가 없다.
16개의 코드 중 “ELF”를 제외한 나머지 13개의 코드는 무엇을 의미하는지 모르겠당.
아래와 같이 ,

# readelf –h HexaView

image 

실행파일의 header정보를 보기 좋게 표시하는 프로그램을 만들어야 한다.


● log.txt

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x8048490
  Start of program headers:          52 (bytes into file)
  Start of section headers:          12892 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         6
  Size of section headers:           40 (bytes)
  Number of section headers:         29
  Section header string table index: 26







참조(Reference)

 

DSCN3513 DSCN3518 DSCN3519