Busan IT/Assembly2015. 10. 23. 11:46

==================================Outline====================================

LOAD함수 구현

----------------------------------------------------------------------------

 

LOAD함수를 사용하여 실행 파일을 동적할당 받은 메모리에 올린다. 헥사뷰를 사용하여 메모리의 어떻게 적재 되어 있는지 확인해 본다.

 

LOAD함수가 실행되면 우선 사용자로부터 실행파일명을 입력 받고 파일이 존재하는지 검사 후 파일이 존재하면 파일을 동적 할당 받은 메모리에 적재한다.

 

프로그램 적재 후 코드와 데이터 영역을 따로 메모리에 적재하는데 이 때 각 영역의 주소를 알아내기 위해서 PE 파일 포맷에 대해 알아야 한다.

 

해당 블로그에 자세한 설명이 나와 있음으로 참고한다.

 

http://haerakai.tistory.com/18

 

 

우선 PE 파일 포맷의 전체적인 구조를 살펴보자.

헤더와 섹션으로 구분이 되어 있다. 헤더 부분은 각 섹션에 대한 주요 정보를 담고 있으며 헤더의 정보를 참조하여 각 섹션으로 이동할 수 있다.

 

우선 IMAGE_DOS_HEADER를 살펴보자.

 

//구조체의 원형은 Windows.h에 담겨 있음으로 헤더파일을 추가한다.

 

//#include <Windows.h>

다음 섹션으로 넘어가기 위해 보아야 할 구조체의 멤버는 ‘e_lfanew'이다. 4byte로 되어 있으며 다음 헤더의 주소를 담고 있다.

 

이를 통해 다음 헤더인 IMAGE_INT_HEADER로 이동한다.

Signature4byte임으로 이를 포인터의 주소를 4byte이동 시킨 후 IMAGE_FILE_HEADER를 가리키게 한다.

IMAGE_FILE_HEADER의 멤버인 SizeOfOptionalHeader에 말 그대로 Optional_Header의 크기가 담겨져 있다. 이를 활용하여 Optional_Header의 주소에서 Optional_Header의 크기만큼을 더하면 SECTION_TABLE로 넘어갈 수 있다.

SECTION헤더에서 각 헤더에 대한 크기와 위치가 저장되어 있다. 이것을 활용하여 원하는 섹션의 위치에 데이터를 집어 넣으면 된다.





/*** 코드 ***/


void load()
{
  int iFd;
  char cBuf[CMD_SIZE];
  int iRtn;
  IMAGE_DOS_HEADER *stpDosH;
  IMAGE_NT_HEADERS32 *stPNtH;
  IMAGE_SECTION_HEADER *stSH;
  unsigned int iAddr;
  unsigned int uiNH;
  IMAGE_FILE_HEADER * stpFH;
  unsigned int uiSizeofOH;
  //IMAGE_OPTIONAL_HEADER * stpOH;
  unsigned int uiOHaddr;
  IMAGE_SECTION_HEADER * stpSHt;  
  unsigned int uiPRDt;
  unsigned int uiSRDt;
  IMAGE_SECTION_HEADER * stpSHd;
  unsigned int uiPRDd;
  unsigned int uiSRDd;  
  
  printf("읽어 들일 파일명을 입력하세요.\n");
  iRtn = read(0, cBuf, CMD_SIZE);
  if(iRtn < 2)
  {
    return;  
  }  
  cBuf[iRtn-1= 0;
  
  iFd = open(cBuf, O_RDONLY|O_BINARY, 666);
  if(iFd== 0)
  {
    printf("[%s]을 사용할 수 없습니다.\n", cBuf);
    return;
  }
  
  iRtn = read(iFd, vpMem_start, MAX_PRG_SIZE);
  if(iRtn== 0)
  {
    printf("파일을 불러올 수 없습니다..\n");
    return;
  }
  printf("------------------ LOAD PROCEDURE ------------------\n"); 
  printf("vpMem_start         [%08X]\n", vpMem_start);

  
  stpDosH = (IMAGE_DOS_HEADER *)vpMem_start;

  uiNH = stpDosH->e_lfanew;
  printf("IMAGE_HEADER->e_lfanew      [%08X]\n", uiNH);

  stPNtH = (IMAGE_NT_HEADERS32 *)( ( (int)vpMem_start) + uiNH );
  printf("IMAGE_NT_HEADERS32       [%08X]\n", stPNtH);

  stpFH = (IMAGE_FILE_HEADER * )( (int)stPNtH + sizeof(stPNtH->Signature) );
  printf("IMAGE_NT_HEADERS32->IMAGE FILE HEADER  [%08X]\n", stpFH);

  uiSizeofOH = stpFH->SizeOfOptionalHeader;
  printf("Size of Optional Header     [%08X]\n", uiSizeofOH);

  uiOHaddr = (unsigned int) ( &(stPNtH->OptionalHeader) );
  printf("addr. of OH         [%08X]\n", uiOHaddr);

  stpSHt = (IMAGE_SECTION_HEADER*) ((int)uiOHaddr + uiSizeofOH);
  printf("addr. of SH. txt       [%08X]\n", stpSHt);

  uiPRDt = stpSHt->PointerToRawData;
  uiSRDt = stpSHt->SizeOfRawData;
  uiPRDd = uiSRDt + uiPRDt;
  
  printf("size of raw data. txt       [%08X]\n", uiSRDt);
  printf("pointer to raw data. txt    [%08X]\n", uiPRDt);
  printf("pointer to raw data. data     [%08X]\n", uiPRDd);  
  printf("------------------ LOAD PROCEDURE ------------------\n");  

  iRtn = lseek(iFd, uiPRDt, SEEK_SET);
  if(0 > iRtn)
  {
    memory_clear();
    close(iFd);
    printf("프로그램 적재 실패\n");
    return;
  }

  iRtn = read(iFd, vpCode, SECTION_SIZE);
  if(0 > iRtn)
  {
    memory_clear();
    close(iFd);
    printf("프로그램 적재 실패\n");
    return;
  }
  printf("코드영역 적재 완료\n");

  iRtn = lseek(iFd, uiPRDd, SEEK_SET);
  if(0 > iRtn)
  {
    memory_clear();
    close(iFd);
    printf("프로그램 적재 실패\n");
    return;
  }

  iRtn = read(iFd, vpData, SECTION_SIZE);
  if(0 > iRtn)
  {
    memory_clear();
    close(iFd);
    printf("프로그램 적재 실패\n");
    return;
  }
  else if(0 == iRtn)
  {
    memory_clear();
    close(iFd);
    printf("데이터 영역이 존재하지 않습니다.\n");  
    return;
  }    
  printf("데이터영역 적재 완료\n");    
  
  return;
}


반응형
Posted by newind2000
Busan IT/Assembly2015. 10. 22. 08:45

==================================Outline====================================

PE구조체

----------------------------------------------------------------------------

load함수를 구현해보자.

 

프로그램을 메모리에 입력시키기 위해서는 실행 파일이 메모리에 어떻게 적재 되는지 알아야 한다.




 

lseek을 사용하여 “.text"가 있는 곳까지 이동시켜야 한다.

 

도스헤더의 주소를 받은 후 '1D8'만큼 떨어진 Section header(".text")에서 Section(".text")의 주소를 찾아야 한다.

 

http://haerakai.tistory.com/18

 

위에 블로그에 접속하여 정독한다.

 

 

 

 

 

 

 

 

반응형
Posted by newind2000
Busan IT/Assembly2015. 10. 20. 17:34

==================================Outline====================================

memory_modify함수

----------------------------------------------------------------------------

메모리의 값을 수정해주는 함수를 만들자.

 

함수의 이름은 'memory_modify'이다. 이 함수는 원하는 메모리 주소에 찾아가서 1byte의 값을 바꾸는 역할을 한다.

 

void memory_modify()
{
  unsigned int uiAddr;
  unsigned int uiVal;  
  while(1)
  {
    printf("수정할 메모리 주소를 입력하세요 [%08X - %08X]  :  ", vpMem_start, vpMem_end);
    scanf("%x"&uiAddr);
    fflush(0);
    if(uiAddr < (unsigned int)vpMem_start || uiAddr > (unsigned int)vpMem_end)
    {
      printf("잘못입력하셨습니다. \n");
      continue;
    }
    break;    
  }
  hexaview((void *)uiAddr, 16);
  printf("수정할 값을 입력하세요 : ");
  scanf("%x"&uiVal);  
  
  fflush(0);  

  *((unsigned int *)uiAddr) = uiVal;
  hexaview((void *)uiAddr, 16);  
  return;
}

 

내일은 load함수를 하겠다.


 /*** 코드 ***/

#include <stdio.h>

/*  사용자 정의  */
#define CMD_SIZE   20
#define  MAX_PRG_SIZE  (64*1024)
#define  MEM_SIZE   (MAX_PRG_SIZE*2)
#define  MASK_CODE  0xFFFF0000
typedef struct
{
  unsigned int efl;
  unsigned int eip;
  unsigned int edi;
  unsigned int esi;
  unsigned int ebp;
  unsigned int esp;
  unsigned int ebx;
  unsigned int edx;
  unsigned int ecx;
  unsigned int eax;
  
}context;

typedef struct
{
  char * cpCmd;
  void (*fp)();  
}comm;

/*   전역 변수  */
static context stOld_state;
extern void stst(context *);
extern void ldst(context *);
void * vpMem_start;
void * vpMem_end;
void print_addr();
void * vpCode;
void * vpData;
void * vpStack;

/*  함수 원형  */
void print_r();
void print_help();
void memory_clear();
void quit();
void view_code();
void view_data();
void view_stack();
void load();
void memory_modify();


void hexaview(void *, unsigned int);

comm stCmd_Map[] ={  //메세지 맵 기법
         {
        "R", print_r
         },
      {
        "H", print_help
      },
      {  
        "MC", memory_clear      
      },
      {  
        "Q", quit
      },
      {
        "QUIT", quit 
      },
      {
        "P", print_addr
      },        
      {
        "CODE", view_code
      },
      {
        "DATA", view_data
      },
      {
        "STACK", view_stack
      },
      {
        "LOAD", load
      },
      {
        "MM", memory_modify
      },
         {
        00
         }        
      };
int main(void)
{
  char cInput[CMD_SIZE];
  comm * stpCmd;
  int iRet;  
  
  vpMem_start = (void *)malloc(MEM_SIZE);
  if(0==vpMem_start)
  {
    return -1;
  }
  vpCode = (void *)( ( ((int)vpMem_start) & (MASK_CODE) )+MAX_PRG_SIZE);
  vpData = (void *)((int)vpCode + 0x2000);   
  vpMem_end = (void *)( (int)vpMem_start + MEM_SIZE - 1 );    
  vpStack = (void *)( (int)vpMem_end - (16 * 16)+1);
  
  stst(&stOld_state);  
  printf("Moniter Program Start\n");
  while(1)
  {
    putchar('>');    
    iRet = read(0, cInput, CMD_SIZE);
    if(iRet < 2)
    {
      continue;  
    }    
    cInput[iRet-1= 0;    
    strupr(cInput);
    
    stpCmd = stCmd_Map;
    while(0 != (stpCmd->fp))
    {
      if(0 == strcmp(strupr(cInput), stpCmd->cpCmd))
      {
        break;
      }      
      ++stpCmd;
    }
    if(0!= (stpCmd->fp))
    {
      ((stpCmd->fp)());      
      
    }
    else
    {
      print_help();
    }    
  }
  return 0;
}
void print_r()
{
  printf("main    : %08X\n", main);
  printf("stOld_state  : %08X\n\n"&stOld_state);
  printf("EAX = %08X  EBX = %08X\nECX = %08X  EDX = %08X\nESI = %08X  EDI = %08X\nEBP = %08X  ESP = %08X\nEIP = %08X  EFL = %08X\n\n",stOld_state.eax, stOld_state.ebx, stOld_state.ecx, stOld_state.edx, stOld_state.esi, stOld_state.edi, stOld_state.ebp, stOld_state.esp, stOld_state.eip, stOld_state.efl);

}
void print_help()
{
  printf("Memory Debugging Prompt\n\n");
  printf("R: Print Register Info.\n");
  printf("H: Print Command List\n");    
  printf("H: Clear Momory\n");    
  printf("P: Print Memory\n");
}
void memory_clear()
{  
  memset(vpMem_start, 0, MEM_SIZE);  
}
void print_addr()
{
  printf("Code Start Address    : 0x%08X\n", vpCode);  
  printf("Dynamic Memory Area    : 0x%08X - 0x%08X [128Byte]\n", vpMem_start, vpMem_end);
}
void quit()
{
  free(vpMem_start);
  exit(0);
}
void view_code()
{
  hexaview(vpCode, 16*16);

  return;
}

void view_data()
{
  hexaview(vpData, 16*16);

  return;
}
void view_stack()
{
  hexaview(vpStack, 16*16);

  return;
}
void load()
{
  memset(vpCode, 0xFF, 16*16);
  memset(vpData, 0xEE, 16*16);
  memset(vpStack, 0xDD, 16*16);

  return;
}
void memory_modify()
{
  unsigned int uiAddr;
  unsigned int uiVal;  
  while(1)
  {
    printf("수정할 메모리 주소를 입력하세요 [%08X - %08X]  :  ", vpMem_start, vpMem_end);
    scanf("%x"&uiAddr);
    fflush(0);
    if(uiAddr < (unsigned int)vpMem_start || uiAddr > (unsigned int)vpMem_end)
    {
      printf("잘못입력하셨습니다. \n");
      continue;
    }
    break;    
  }
  hexaview((void *)uiAddr, 16);
  printf("수정할 값을 입력하세요 : ");
  scanf("%x"&uiVal);  
  
  fflush(0);  

  *((unsigned int *)uiAddr) = uiVal;
  hexaview((void *)uiAddr, 16);  
  return;
}


void hexaview(void * vP, unsigned int uiLen)
{
  unsigned int uiCnt;
  unsigned int uiLine;

  printf("===============================================================================\n");
  printf("  Address      Hexa           ASCII       \n"); 
  printf("-------------------------------------------------------------------------------\n");
  for (uiLine = 0; uiLine <  uiLen; uiLine += 16)
  {
    printf(" %08X  ", vP);
  
    for(uiCnt=0; uiCnt<16; ++uiCnt)
    {
      printf("%02X ", *((unsigned char *)vP));
      vP = (char *)vP + 1;
    }
    vP = (char *)vP - 16;
    putchar(' ');

    for(uiCnt=0; uiCnt<16; ++uiCnt)
    {
      if (32 > *((unsigned char *)vP))
      {
        putchar('.');
      }    
      else if(127 < *((unsigned char *)vP))
      {
        putchar('.');
      }
      else
      {        
        printf("%1c", *((unsigned char *)vP));
      }

      vP = (char *)vP + 1;
    }
    putchar('\n');
  }
  return;
}


 

반응형

'Busan IT > Assembly' 카테고리의 다른 글

LOAD함수 구현  (0) 2015.10.23
PE구조체  (0) 2015.10.22
코드/데이터/스택 영역 설정, load, clear  (0) 2015.10.20
메모리 출력 프로그램 #1  (0) 2015.10.15
stst(store state), ldst(load state)  (0) 2015.10.15
Posted by newind2000