CMonitor 소스

C or C++ 2009. 1. 13. 09:22

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <windows.h>

#define  DR_NUM     10   // 출력할 Register 개수
#define  MAX_PROGRAM_SIZE  0x10000   // 적재할 프로그램의 최대 크기
#define SECTION_SIZE  512   

#define  DEFAULT_DISPLAY_LINE 16  // 메모리 출력 시 기본 출력 행 수
#define  ROW_LINE    16  // 메모리 출력 행 수


// 입력할 수 있는 명령 목록
#define  CommandDisplay   0x00 // Command Display when wrong Command
#define  MemoryDisplay    0x01 // Memory Display Command
#define  MemoryModify    0x02 // Memory Modify Command
#define  RegisterDisplay  0x03 // Register Display Command
#define  ProgramLoad   0x04 // Executable Program Load
#define  ProgramRun    0x05 // Loaded Program Execute
#define  MemoryClear   0x06 // Memory Clear Command
#define  CodeDisplay   0x07 // Code Area Display Command
#define  DataDisplay   0x08 // Data Area Display Command
#define  StackDisplay   0x09 // Stack Area Display Command
#define  MemoryStatusDisplay 0xFD // Memory Status Display Command
#define  NoInput    0xFE // 입력이 없을 경우
#define  ExitProgram   0xFF // Exit Command


char *R_NAME[] =      // 레지스터 상태를 출력할 때 사용되는 배열
{
 "EFL", "EIP", "EDI", "ESI", "EBP",
 "ESP", "EBX", "EDX", "ECX", "EAX"
};


typedef struct       // 레지스터 정보가 저장되는 구조체
{
 int  efl;
 int  eip;
 int  edi;
 int  esi;
 int  ebp;
 int  esp;
 int  ebx;
 int  edx;
 int  ecx;
 int  eax;
} context;


struct         // 명령어와 숫자를 대응시키기 위해 사용
{          // 미리 Define된 값과 대응
 unsigned char *name;
 unsigned char f_num;
} GROUP[] =
{
 "Q\n" ,  ExitProgram,
 "QUIT\n",  ExitProgram,
 "MC\n",  MemoryClear,
 "MD\n",  MemoryDisplay,
 "MM\n",  MemoryModify,
 "R\n" ,  RegisterDisplay,
 "P\n" ,  MemoryStatusDisplay,
 "LOAD\n",  ProgramLoad,
 "GO\n",   ProgramRun,
 "\n"  ,  NoInput,
 "CODE\n",  CodeDisplay,
 "DATA\n",  DataDisplay,
 "STACK\n",  StackDisplay,

 "HELP\n",  CommandDisplay,
 0   ,  0,
};

//enum으로 수정할 것!!!
unsigned char  File_Name[255];   // 읽어올 파일 이름의 임시 저장소
static unsigned char  *mem;    // 동적할당의 시작 위치
static unsigned char  *mem_end;   // 동적할당의 끝 위치
static unsigned char  *code;    // 프로그램 저장공간의 시작 위치 -code
static unsigned char  *data;    // 프로그램 저장공간의 시작 위치  -data
unsigned char  Load_Flag;    // 프로그램이 로드 유무 표시
unsigned char  Display_Flag;   // 메모리 값 출력시 계속해서 출력하는
         // 경우를 위해
int    File_DS;     // 저수준 파일의 데스크립터
static context  stat_old;     // 기존의 레지스터 값 저장

// 어셈블리로 구현한 함수
extern
 unsigned char md(int);  // Memory Display Function By Assembly
extern void mm(int, char);    // Memory Modify Function By Assembly
extern void STST(context *);   // STore STatus
extern void LDST(context *);   // LoaD STatus


// C로 구현한 함수
void AddressDisplay();      // 함수, 변수 등의 주소 값 출력
void MDFunction(unsigned int *);   // 주소를 입력 받아 그 곳의 값 출력
void MMFunction(unsigned int *);   // 주소를 입력 받아 그 곳의 값 수정
void RFunction();       // 레지스터 상태 출력
void PRFunction();       // Program Run Function
void CDFunction();       // Command Display Function
void go();         // Program Run Function
void load();        // Program Load Function
void Clear_mem();       // Dynamic Memory Clear Function
unsigned char StringToNum(char *);   // Command String to Number Function
void MSDFunction(unsigned int *, unsigned int); // 주소의 값 출력
void Address_Check(unsigned int *);  // Address Check Function


void main ()
{
 unsigned char  out  = 0;   // 명령의 Define된 변환 값 저장
 unsigned char  Command[255];   // 사용자가 사용하는 명령어를 저장
 unsigned int  addr = 0;   // 메모리 주소값을 입력 받아 저장
 context     stat_new;  // 레지스터 값의 임시 저장

 mem = (unsigned char *)malloc(MAX_PROGRAM_SIZE * 2); // 128Kbyte 동적 할당

 if (NULL == mem)
 {
  printf("메모리 동적 할당에 실패하였습니다.\n");
  printf("모니터 프로그램을 종료합니다.\n");
  return;
 }
 else
 {
  mem_end  = (unsigned char *)(mem + (MAX_PROGRAM_SIZE * 2) - 1);
  code  = (unsigned char *)
   (((unsigned int)mem & 0xFFFF0000) + MAX_PROGRAM_SIZE);
  data  = code + 0x2000;
  Clear_mem();
 }

 STST(&stat_old);     // 초기 레지스터 상태를 저장

 printf("\n\nMonitor Program is Starting....\n");
 AddressDisplay();
 RFunction();
 printf("stat_old's Address = [0x%08X]\n", &stat_old);

 while (1)
 {
  fflush(stdin);
  putchar('>');     // 프롬프트 출력
  putchar(' ');     // 프롬프트 출력

  fgets(Command, 255, stdin);
  out = StringToNum(Command);

  switch (out)
  {
  case MemoryClear:    // 동적 할당 메모리의 초기화
   Clear_mem();
   continue;

  case CommandDisplay:   // 명령 목록을 보여줌
   CDFunction();
   continue;

  case MemoryDisplay:   // Memory Display
   MDFunction(&addr);
   continue;

  case MemoryModify:   // Memory Modify
   MMFunction(&addr);
   continue;

  case RegisterDisplay:  // Register status Display
   RFunction();
   continue;

  case MemoryStatusDisplay:  // 프로그램 주소 정보를 출력
   AddressDisplay();
   continue;

  case ProgramLoad:    // 실행할 프로그램을 적재
   load();
   continue;

  case ProgramRun:    // 적재된 프로그램을 실행
   PRFunction();
   continue;

  case CodeDisplay:    // 코드 영역 출력
   addr = (unsigned int)(code);
   MSDFunction(&addr, DEFAULT_DISPLAY_LINE);
   continue;

  case DataDisplay:    // 데이터 영역 출력
   addr = (unsigned int)(code + 0x2000);
   MSDFunction(&addr, DEFAULT_DISPLAY_LINE);
   continue;

  case StackDisplay:    // 스택 영역 출력
   addr = (unsigned int)(mem_end - 0x00000100 + 0x00000001);
   MSDFunction(&addr, DEFAULT_DISPLAY_LINE);
   Display_Flag = 0;
   continue;


  case NoInput:    // 입력 없이 엔터만 입력할 경우
   if (1 == Display_Flag)
   {
    MSDFunction(&addr, DEFAULT_DISPLAY_LINE);
   }
   else
   {
   }
   continue;

  case ExitProgram:   // 종료 문자를 사용하였을 경우
  default:
   break;
  }
  break;
 }

 free(mem);       // 동적 할당 제거
 mem   = 0;     // 재사용 금지
 mem_end  = 0;     // 재사용 금지
 code   = 0;     // 재사용 금지
 return;
}


void AddressDisplay()      // Address Display Function
/*******************************************************************************
기능  : 현재 프로그램의 주소 정보를 출력
인수  : void
반환값  : void
*******************************************************************************/

{
 Display_Flag = 0;
 printf("\nCode Start Address   : 0x%08X\n", main);
 printf(  "Data Start Address   : 0x%08X\n", R_NAME);
 printf(  "Program Load Address : 0x%08X\n", code);
 printf(  "Dynamic Memory area  : 0x%08X to 0x%08X (%dKBytes)\n"
  , mem, mem_end, (mem_end - mem + 1)/1024);

 return;
}


unsigned char StringToNum(char *name)    // String To Number Function
/*******************************************************************************
기능  : 명령을 입력하였을 때 대응하는 Define 숫자로 변환
인수  : 문자열형의 명령어
반환값  : 명령어에 대응하는 hex형 값
*******************************************************************************/

{
 int loop_temp = strlen(name);

 while (1)
 {
  if (0 >= loop_temp)
  {
   break;
  }
  else
  {
   --loop_temp;
   *(name + loop_temp) = toupper(*(name + loop_temp));
  }
 }

 loop_temp = 0;

 while (1) // 구조체의 끝에 도달하면 종료
 {
  if (0 == strcmp(name, (*(GROUP + loop_temp)).name))
   // 일치하는 단어가 검색되었을 경우
  {
   break;
  }
  else if(0 == (*(GROUP + loop_temp)).f_num)
  {
   break;
  }
  else
  {
   ++loop_temp;
  }
 }

 return (*(GROUP + loop_temp)).f_num;
 // 일치하는 단어와 대응되는 숫자를 반환
 // 일치하는 단어가 없으면 0반환
}


void MDFunction(unsigned int *addr)    // Memory Display  Function
/*******************************************************************************
기능  : 주소값을 입력 받아서 그 주소에 있는 값을 출력
인수  : 입력받은 값을 저장할 장소
반환값  : void
*******************************************************************************/

{
 printf("메모리 주소를 입력하세요(0x%08X~0x%08X) : ", mem, mem_end);
 scanf("%x", addr);
 MSDFunction(addr, DEFAULT_DISPLAY_LINE);   // 출력 디폴트 라인 수로 출력
}


void MSDFunction(unsigned int *addr, unsigned int print_line)
// Memory Status Display Function
/*******************************************************************************
기능  : 인수로 넘겨받은 주소로부터 ROW_LINE개 단위를 1줄로 print_line의 숫자 만큼
화면에 출력
인수  : 출력할 대상이 있는 곳의 주소값, 메모리 출력시 출력 라인 수
반환값  : void
*******************************************************************************/

{
 unsigned int  loop_temp  = 0;   // 반복문을 위한 임시 변수 선언
 unsigned char  memory_dump[ROW_LINE];   // 반환된 메모리값을 임시로 저장

 Address_Check(addr);

 if (0 == Display_Flag)
 {
  return;
 }
 else
 {
  printf(" Address   ");     // 화면 상단 자리 표시를 위한 출력
 }

 while (loop_temp < ROW_LINE)    // Hex 부분 출력
 {
  printf("%02X ", loop_temp++);
 }

 putchar(' ');
 loop_temp = 0;

 while (loop_temp < ROW_LINE)    // ASCII 부분 출력
 {
  printf("%X", loop_temp++);
 }

 putchar('\n');

 while (0 < print_line)      // Data 부분 출력 루프 시작
 {
  Address_Check(addr);
  if (0 == Display_Flag)
  {
   return;
  }
  else
  {
   loop_temp = 0;
   printf("0x%08X ", *addr);   // 메모리 주소 출력
  }

  while (1)           // 메모리 읽어 오기 및 hex 출력 시작
  {
   // 메모리 주소에 위치한 값을 배열에 저장
   *(memory_dump + loop_temp) = md(*addr);

   // 배열에 저장된 값 출력
   printf("%02X ", *(memory_dump + loop_temp));

   ++loop_temp;
   ++(*addr);

   if (0 == (loop_temp % ROW_LINE)) // ROW_LINE개를 출력하였으면 loop 종료
   {
    break;
   }
   else
   {
   }
  }          // 메모리 읽어 오기 및 hex 출력 끝

  putchar(' ');
  loop_temp = 0;

  while (1)        // ASCII 부분 출력 루프 시작
  {
   if (0 == *(memory_dump + loop_temp))
   {
    putchar('.');     // 널 문자 대치
   }
   else if (32 > *(memory_dump + loop_temp))
   {
    putchar('*');     // 제어 문자 대치
   }
   else if (127 <= *(memory_dump + loop_temp))
   {
    putchar('*');     // 그래픽 문자 대치
   }
   else
   {
    putchar(*(memory_dump + loop_temp));
   }

   ++loop_temp;

   if (0 == (loop_temp % ROW_LINE)) // ROW_LINE개를 출력하였으면 loop 종료
   {
    break;
   }
   else
   {
   }
  }          // ASCII 부분 출력 루프 끝

  putchar('\n');
  --print_line;
 }           // Data 출력 루프 끝

 putchar('\n');
}


void MMFunction(unsigned int *addr)   // Memory Modify Function
/*******************************************************************************
기능  : 수정할 대상이 잇는 곳의 주소를 인수로 받아서 그 곳의 값을 변경하고
변경한 내용을 출력
인수  : 수정할 대상이 있는 곳의 주소값
반환값  : void
*******************************************************************************/

{
 unsigned char out = 0;
 MDFunction(addr);
 *addr = *addr - (DEFAULT_DISPLAY_LINE * ROW_LINE);
 printf("변경하고 싶은 값(16진수)을 입력하세요 : ");
 scanf("%x", &out);
 mm(*addr, out);
 out = md(*addr);
 MSDFunction(addr, 1);

 return;
}


void RFunction()         // Register status display Function
/*******************************************************************************
기능  : 레지스터의 상태를 화면으로 출력
인수  : void
반환값  : void
*******************************************************************************/

{
 unsigned int  i = DR_NUM;
 unsigned int  *temp = (unsigned int *)&stat_old;
 context   stat_new;

 Display_Flag = 0;

 printf("-------------- 프로그램 실행 초기의 레지스터 상태 -------------\n");
 while(1)
 {
  if (i == 0)
  {
   break;
  }
  else
  {
   --i;
   printf("%s ADDRESS VALUE : 0x%08X   ", *(R_NAME + i), *(temp + i));  
  }

  if (0 == i % 2)
  {
   putchar('\n');
  }
  else
  {
  }
 }

 STST(&stat_new);
 temp = (unsigned int *)&stat_new;
 i = DR_NUM;

 printf("-----------------     현재 레지스터 상태    -------------------\n");
 while(1)
 {
  if (i == 0)
  {
   break;
  }
  else
  {
   --i;
   printf("%s ADDRESS VALUE : 0x%08X   ", *(R_NAME + i),*(temp + i));
  }

  if (0 == i % 2)
  {
   putchar('\n');
  }
  else
  {
  }
 }

 printf("---------------------------------------------------------------\n");
 return;
}


void CDFunction()        // Command Display Function
/*******************************************************************************
기능  : 이 프로그램의 사용법을 출력
인수  : void
반환값  : void
*******************************************************************************/

{
 Display_Flag = 0;
 printf("메모리 디버거 명령어\n");
 printf("R         : Register Value Display\n");
 printf("P         : Memory Status Display\n");
 printf("MC        : Memory Clear\n");
 printf("MM        : Memory Modify\n");
 printf("MD        : Memory Display\n");
 printf("LOAD      : Program Load\n");
 printf("GO        : Loaded Program Execute\n");
 printf("CODE      : Code Area Display\n");
 printf("DATA      : Data Area Display\n");
 printf("STACK     : Stack Area Display\n");
 printf("HELP      : Help Message Display\n");
 printf("QUIT(Q)   : Exit Program\n");

 return;
}


void PRFunction()       // Program Run Function
/*******************************************************************************
기능   : 프로그램이 메모리에 적재되었는지 검사하고 적재되어 있으면 실행
인수   : void
반환값   : void
*******************************************************************************/

{
 Display_Flag = 0;
 if (1 == Load_Flag)     // 프로그램 적재 유무 판별
 {
  go();
 }
 else
 {
  printf("외부 프로그램이 적재되어 있지 않습니다.\n");
  printf("load 명령을 사용하여 프로그램을 적재하시길 바랍니다.\n");
 }

 return;
}


void load()        // Program Load Function
/*******************************************************************************
기능   : 프로그램의 이름을 입력받아 그 프로그램을 64K만큼 할당한 임의의 주소
공간에 적재
인수   : void
반환값  : void
*******************************************************************************/

{
 int    Read_Num ;
 int   Header_Size;
 IMAGE_DOS_HEADER  *dhp;
 IMAGE_NT_HEADERS32  *php;
 IMAGE_FILE_HEADER  *fhp;
 IMAGE_OPTIONAL_HEADER32 *ohp;
 
 Clear_mem();
 

 printf("\n읽어 들일 파일 이름을 입력하세요 : ");
 scanf("%s", File_Name);
 File_DS = open(File_Name, O_RDONLY | O_BINARY);

 if (0 > File_DS)
 {
  printf("파일을 찾을 수 없거나 읽을 수 없습니다.\n");
  printf("파일이 존재하는지 확인해 주세요.\n");
  printf("(경로명 사이에 '\'를 '\\'로 바꾸어 보십시오)\n");
  return;
 }
 else
 {
  Read_Num = read(File_DS, code, MAX_PROGRAM_SIZE);
 }

 if(0 > Read_Num)
 {
   printf("파일이 존재하지만 읽을 수 없습니다.\n");
  close(File_DS);  
  return;
 }
 else
 {
   dhp = (IMAGE_DOS_HEADER       *) code;
         php = (IMAGE_NT_HEADERS        *) (code+(dhp->e_lfanew));
         fhp = (IMAGE_FILE_HEADER         *) ((char *)php+sizeof(php->Signature));
         ohp = (IMAGE_OPTIONAL_HEADER32  *)((char *)fhp+sizeof(IMAGE_FILE_HEADER));
   
         Header_Size = ohp->SizeOfHeaders;
         Clear_mem();
 }

 
 if (0 > lseek(File_DS, Header_Size, SEEK_SET))
 {
  printf("파일의 헤더정보 Skip 실패!!\n");
  printf("파일을 적재할 수 없습니다..\n");
  close(File_DS);  
  return;
 }
 else
 {
  Read_Num = read(File_DS, code, SECTION_SIZE);
 }

 if(0 > Read_Num)
 {
   printf("파일이 존재하지만 읽을 수 없습니다.\n");
   close(File_DS);  
         return;
 }
 else
 {
  Read_Num = read(File_DS, data, SECTION_SIZE);
 }

 close(File_DS);    

 if(0 > Read_Num)
 {
   printf("파일이 존재하지만 읽을 수 없습니다.\n");
         return;
 }
 else
 {
  File_DS  = 0;
  Load_Flag = 1;
  printf("파일을 성공적으로 메모리에 적재하였습니다.\n");
  printf("읽어 들인 파일의 크기는 [%d]Bytes입니다.\n\n", Read_Num);
 }

 
 return;
}


void go()        // Program Runing Function
/*******************************************************************************
기능  : 동적할당 영역에 저장된 프로그램을 실행
인수  : void
반환값  : void
*******************************************************************************/

{
 context  stat_new;

 stat_new.eax = (int)(&stat_old);
 stat_new.ebx = 0;
 stat_new.ecx = 0;
 stat_new.edx = 0;
 stat_new.esi = 0;
 stat_new.edi = 0;
 stat_new.esp = (int)(mem_end + 1);
 stat_new.ebp = 0;
 stat_new.eip = (int)(code);
 stat_new.efl = 0;

 printf("적재된 프로그램을 실행합니다...\n");
 LDST(&stat_new);
 printf("SYSTEM PANIC!!\n");
}


void Clear_mem()      // Dynamic Memory Clear Function
/*******************************************************************************
기능  : 동적할당 영역에 저장된 값들을 초기화
인수  : void
반환값  : void
*******************************************************************************/

{
 unsigned char  *temp = mem;
 Load_Flag = 0;      // 로드된 프로그램을 제거하므로 0으로 설정
 Display_Flag = 0;

 while (1)
 {
  *temp = 0;
  if (mem_end == temp)
  {
   break;
  }
  else
  {
   ++temp;
  }
 }
}


void Address_Check(unsigned int *addr)    // Address Check Function
/*******************************************************************************
기능  : 파라미터가 출력할 수 있는 범위의 주소 값인지 검사
인수  : 검사할 주소
반환값  : void
*******************************************************************************/

{
 if ((unsigned int)mem > *addr)
 {
  printf("출력할 수 없는 주소 공간입니다.\n");

 }
 else if ((unsigned int)mem_end < *addr)
 {
  printf("출력할 수 없는 주소 공간입니다.\n");
  Display_Flag = 0;
 }
 else
 {
  Display_Flag = 1;
  return;
 }

 Display_Flag = 0;
 return;
}



Posted by 응이

Dream come true.
응이

달력

태그목록