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

20151022-22번-우대희 LOAD함수 구현

by 알 수 없는 사용자 2015. 10. 23.
728x90
반응형


LOAD함수를 사용하여 실행 파일 동적할당 받은 영역에 올린 후 메모리의 어떻게 적재 되어 있는지 확인해 보자.

 

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

 

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

 

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

http://haerakai.tistory.com/18

 

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

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

 

우선 IMAGE_DOS_HEADER를 살펴보자.

 

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

 

//#include <Windows.h>

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

 

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

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

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

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






/*** 코드 ***/


void Memory_Load() /* 특정값 입력 */
{
int iFd;
char cBuf[CMB_SIZE];
int iRtn;
IMAGE_DOS_HEADER *stpDosH;
IMAGE_NT_HEADERS32 *stPNtH;
IMAGE_SECTION_HEADER *stSH;
IMAGE_FILE_HEADER * stpFH;
IMAGE_SECTION_HEADER * stpSHt;
IMAGE_SECTION_HEADER * stpSHd;
//IMAGE_OPTIONAL_HEADER * stpOH;
unsigned int iAddr;
unsigned int uiNH;
unsigned int uiSizeofOH;
unsigned int uiOHaddr;
unsigned int uiPRDt;
unsigned int uiSRDt;
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;
}

어제 멍때려서 이것도 얻어서 올립니다..

728x90