본문 바로가기
코스웨어/13년 스마트컨트롤러

131002 수 _ 어셈블리 김성엽

by 알 수 없는 사용자 2013. 10. 2.
728x90
반응형

 Source

#include <stdio.h>

#include <windows.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <WinNT.h>

#define  MAX_PROGRAM_SIZE  0x10000    // 64Kbyte
#define  SECTION_SIZE    512

typedef struct  _CONTEXT1
{
  int  efl;
  int  eip;
  int  edi;
  int  esi;
  int  ebp;
  int  esp;
  int  ebx;
  int  edx;
  int  ecx;
  int  eax;
}CONTEXT1;

void PrintCODE(void);
void PrintDATA(void);
void PrintSTACK(void);
void EXIT(void);
void HELP(void);
void PrintLOAD(void);
void Clear_mem(void);
void GO(void);
void PrintReg(void);

typedef struct _CmdMap
{
  void *vpCmd;
  void (*fp)(void);
}CmdMap;

CmdMap stCmdList[] =  {
      {"CODE" , PrintCODE},
      {"DATA" , PrintDATA},
      {"STACK", PrintSTACK},
      {"LOAD" , PrintLOAD},
      {"HELP" , HELP},  
      {"Q" , EXIT},
      {"MC", Clear_mem},
      {"GO", GO},
      {"R", PrintReg},
      {0,0}      
      };


static unsigned char sucMem[MAX_PROGRAM_SIZE*2];  // 128Kbyte , 동적할당 시작위치
static unsigned char *sucMem_end;      // 동적할당 끝 위치
static unsigned char *sucCODE;        // CODE 의 시작위치
static unsigned char *sucDATA;        // DATA 의 시작위치
static unsigned char *sucSTACK;        // STACK 의 시작위치
static unsigned char Load_Flag;        // 로드유무 표시

static  int  iFd;          // 파일 입출력을 위한 파일디스크립션

void HexaView(unsigned char *, unsigned int);
void STST(CONTEXT1 *);
void LDST(CONTEXT1 *);

unsigned char   MD(void *);    // Momory Display Function By Assembly
void     MM(void *, char);  // Momory Modify Function By Assembly

CONTEXT1  stOldreg;  // 기존의 레지스터값 저장

int main()
{
  int A = 0x12345678;
  static unsigned char ucBuff[255];
  static unsigned char ucCnt = 0;
  int iRet;
  CmdMap *stpCmd;
  sucMem_end  = sucMem + sizeof(sucMem);
  sucCODE    = (unsigned char *)(((unsigned int)sucMem+MAX_PROGRAM_SIZE) & 0xFFFF0000);
  sucDATA    = sucCODE + 0x2000;
  sucSTACK  = (unsigned char *)sucCODE + MAX_PROGRAM_SIZE-1;  

  printf("Memory Start Add : %08x\n", sucMem);
  printf("Memory End Add   : %08x\n", sucMem_end);
  printf("Memory Code Add  : %08x\n", sucCODE);
  printf("Memory DATA Add  : %08x\n", sucDATA);
  printf("Memory Stack Add : %08x\n", sucSTACK);
  
  printf("-------------------- 초기화 상태 --------------------\n");
  PrintReg();
  STST(&stOldreg);
  printf("-------------------- 저장 상태 ----------------------\n");
  PrintReg();

  while(1)
  {
    fflush(stdin);
    putchar('\n');
    putchar('>');
    putchar(' ');
    iRet = read(0,ucBuff,sizeof(ucBuff));

    ucBuff[iRet-1= 0;    

    for(ucCnt=0 ; 0 != ucBuff[ucCnt] ; ++ucCnt) 
    {
      ucBuff[ucCnt] = toupper((int)ucBuff[ucCnt]);
    }
    
    if(0 == strcmp(ucBuff,"Q") )
    {
      break;
    }

    stpCmd = stCmdList;

    while(1)
    {
      if(0 == (stpCmd->fp) ) 
      {
        printf("명령어를 찾을수 없습니다.\n");
        break;
      }
    
      if(0 == strcmp(ucBuff, (stpCmd->vpCmd)) )
      {

        (stpCmd->fp)();
        break;
      }
      ++stpCmd;
    }
    
  }

  //getchar();

  //LDST(&stOldreg);  // STST로 가게해줌. while 문 역할
        // 메모리안에 있는 정보를 CPU 로 옮겨준다.

  return 0;
}

void Clear_mem()
{
  unsigned int uiCnt;

  for(uiCnt=0 ; uiCnt < (int)sucMem_end - (int)sucCODE ; ++uiCnt)
  {
    *(sucCODE+uiCnt) = 0;    
  }

  Load_Flag = 0;

  return;  
}

void PrintLOAD()
{
  
  IMAGE_DOS_HEADER  *stpDOS;// windows.h -> 구조체 IMAGE_DOS_HEADER
  IMAGE_NT_HEADERS  *stpNT;  // NT Header
  IMAGE_FILE_HEADER  *stpFH;  // File Header
  IMAGE_OPTIONAL_HEADER  *stpOH; // Optional Header
  unsigned char    File_Name[255];  // 파일이름 임시저장
  int      Total_Read=0;
  int      Read_Num=0;
  int      Header_Size;
  int      iRet;
  unsigned int    uiCnt;

  Clear_mem();

  printf("\n읽어들일 파일이름을 입력하세요 : ");
  
  iRet = read(0,File_Name,sizeof(File_Name));
  
  for(uiCnt=0 ; uiCnt < iRet-1 ; ++uiCnt) 
  {
    File_Name[uiCnt] = toupper((int)File_Name[uiCnt]);
  }
  
  File_Name[uiCnt]= '\0';

  
  iFd = open( File_Name , O_RDONLY | O_BINARY);

  if0 > iFd )
  {
    printf("File Open Error\n");
    return;
  }

  iRet = read(iFd , sucCODE , SECTION_SIZE);

  if0 > iFd )
  {  
    printf("File was Readed\n");
    close(iFd);
    return;
  }
  else
  {
    stpDOS = (IMAGE_DOS_HEADER *)sucCODE;
    stpNT  = (IMAGE_NT_HEADERS *)(sucCODE + (stpDOS->e_lfanew));
    stpFH  = (IMAGE_FILE_HEADER *)((unsigned char *)stpNT + sizeof(stpNT->Signature));
    stpOH  = (IMAGE_OPTIONAL_HEADER *)((unsigned char *)stpFH + sizeof(IMAGE_FILE_HEADER));
    Header_Size = stpOH->SizeOfHeaders;
    Clear_mem();
  }

  if0 > lseek(iFd, Header_Size, SEEK_SET) )
  {
    printf("파일의 헤더정보 Skip 실패!!\n");
    printf("파일을 적재할 수 없습니다..\n");
    close(iFd);
  }
  else
  {
    Read_Num = read(iFd, sucCODE, SECTION_SIZE);  // Code 영역에 SECTION_SIZE 만큼 읽어들임
  }

  if0 > Read_Num )
  {
    printf("파일이 존재하지만 읽을 수 없습니다.\n");
    close(iFd);
    return;
  }
  else
  {
    Total_Read = Total_Read + Read_Num;
        Read_Num = read(iFd, sucDATA, SECTION_SIZE);  // DATA 영역에 SECTION_SIZE 만큼    
  }              // 읽어 들임

  close(iFd);

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

  return;
}

void GO(void)
{
  CONTEXT1 stNewreg = {0,};  

  if0 == Load_Flag )
  {
    printf("외부 프로그램이 적재되어 있지 않습니다.\n");
    printf("Load 명령을 사용하여 프로그램을 적재하시길 바랍니다.\n");
    return;
  }

  stNewreg.eax = (int)&stOldreg;
  stNewreg.eip = (int)sucCODE;
  stNewreg.esp = (int)(sucSTACK);  // 메모리 끝의 한칸 아래 집어줌
  
  LDST(&stNewreg);
  
  
  printf("Kernel Panic\n");
}

void PrintCODE()
{
  printf("\nCODE Field\n\n");
  HexaView(sucCODE,160);
}

void PrintDATA()
{
  printf("\nDATA Field\n\n");
  HexaView(sucDATA,160);
}

void PrintSTACK()
{  
  printf("\nSTACK Field\n\n");
  HexaView(sucSTACK-159,160);
}

void PrintReg()
{
  printf("EAX VALUE : 0x%08x   ECX VALUE : 0x%08x\n", stOldreg.eax, stOldreg.ecx);
  printf("EDX VALUE : 0x%08x   EBX VALUE : 0x%08x\n", stOldreg.edx, stOldreg.ebx);
  printf("ESP VALUE : 0x%08x   EBP VALUE : 0x%08x\n", stOldreg.esp, stOldreg.ebp);
  printf("ESI VALUE : 0x%08x   EDI VALUE : 0x%08x\n", stOldreg.esi, stOldreg.edi);
  printf("EIP VALUE : 0x%08x   EFL VALUE : 0x%08x\n", stOldreg.eip, stOldreg.efl);
}

void EXIT()
{  
  exit(0);
}

void HELP()
{
  printf("CODE  : CODE Area Display\n");
  printf("DATA  : DATA Area Display\n");
  printf("STACK : STACK Area Display\n");
  printf("HELP  : Help massage Display\n");
  printf("EXIT  : EXIT Program\n");
  printf("MC    : Memory Clear\n");
  printf("LOAD  : Program Load\n");
  printf("GO    : Loaded Program Excute\n");
  printf("R     : Memory Status\n");
}

void HexaView(unsigned char *ucP, unsigned int isize)
{
  int iCnt;
  int iloop;
  unsigned int iSizeNum;

  iSizeNum = 0;
  
  printf("----------------------------------------"
     "----------------------------------\n");
  printf("Address  \t\t\tHexa\t\t\t      ASCII\n"); 
  printf("\t ");

  
  for(iCnt=0 ; iCnt <= 15 ; iCnt++)
  {
    printf("%02X ", iCnt);
  }

  putchar('\n');

  printf("----------------------------------------"
     "----------------------------------\n");
  
  if0 == isize%16 )
  {
    isize = isize / 16;  
  }
  else
  {
    iSizeNum = isize%16;
    isize = (isize/16);    
  }
  
  for(iloop=0; iloop < isize ; iloop++)
  {
    printf("%08X ", ucP); 
  
    for( iCnt=0 ; iCnt <= 15 ; iCnt++)
    {
      printf("%02X ", MD(ucP+iCnt));
    }
  
    for( iCnt=0 ; iCnt <= 15 ; iCnt++ )
    {
      if(0 == MD(ucP+iCnt))
      {
        printf(".");
      }
      else if32 > MD(ucP+iCnt))
      {
        printf(".");
      }
      else if127 < MD(ucP+iCnt))
      {
        printf(".");      
      }
      else
      {
        printf("%c", MD(ucP+iCnt)); 
      }
    }
  
    putchar('\n');
    ucP = ucP + 16;


  }

  if( iSizeNum != 0 )
  {
    printf("%08X ", ucP); 
  
    for( iCnt=0 ; iCnt <= iSizeNum-1 ; iCnt++)
    {
      printf("%02X ", MD(ucP+iCnt));
    }
    
    for( iCnt=0 ; iCnt <= 15-iSizeNum ; iCnt++ )
    {
      printf("   ");
    }    
    

    for( iCnt=0 ; iCnt <= iSizeNum-1 ; iCnt++ )
    {
      if(0 == MD(ucP+iCnt))
      {
        printf(".");
      }
      else if32 > MD(ucP+iCnt))
      {
        printf(".");
      }
      else if127 < MD(ucP+iCnt))
      {
        printf(".");      
      }
      else
      {
        printf("%c", MD(ucP+iCnt)); 
      }
    }
  
    putchar('\n');

  }  
}



 실행화면


<초기정보>


<적재후 실행 전>


<적재후 함수실행>


<적재되지 않은 상태에서 GO 명령어를 입력 했을시>


<함수 실행>


<HELP 명령어>


<LOAD 명령어>


<R 현재저장상태>




흐름정리

① STST 를 이용해서 CPU 레지스터 정보를 Context 구조체(&stOldReg)에 T1.exe 를 실행하기 위해서 EAX ,EIP, ESP 정보를 담는데,EAX 에는 OldReg의 주소 를 담아주고( t1.exe 를 실행한 후에 LDST를 이용해서 돌아올 주소[레지스터정보]가 필요하기때문에 ),

EIP와 ESP 는 T1.exe에 Test 함수를 실행하기 위해서 EIP 는 T1.exe 의 CODE 영역의 시작주소를 집어넣고, ESP T1.exe의 스택시작주소를 집어넣는다.(컴파일시에 cl /c /GS- t1.c => t1.obj) , ( 링크시에 link /subsystem:console /entry:INIT /nodefaultlib /out:t1.exe /base:0x00410000 init.obj Monitor.obj t1.obj )

② Test 함수를 실행하기 전/후 DATA 영역의 전역변수의 값과 STACK 영역의 값이 바뀌는 것을 확인 할 수 있다. STACK 영역에 변화는  init.asm 에 PUSH EAX(&stOldReg) 와 Return Address 값이 들어가있는 것을 확인 할 수있다. CODE 영역은 기계어를 건드린 부분이 없으므로 변화가 없다.


------------ 파일 -------------

Contextswtiching.zip

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



       

          

          

          

      

         

       


728x90