해킹, 파괴의 광학에 나오는 소스코드이다.
그냥 코드 보고, PE파일이 어떤식으로 구성되있는지 확인하는 정도로만 보려고 한다.
소스코드는 아래에..
#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, PIMAGE_NT_HEADERS pINH)
{
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pINH);
unsigned i;
DWORD sizee;
for(i=0; i< pINH ->FileHeader.NumberOfSections; i++, section++)
{
sizee = section->Misc.VirtualSize;
if(0 == sizee)
sizee = section->SizeOfRawData;
if( (rva >= section->VirtualAddress) && (rva < (section->VirtualAddress + sizee)))
return section;
}
}
int ParseImports( LPVOID lpBasePointer, PIMAGE_NT_HEADERS pINH)
{
int nDelta = -1;
PIMAGE_SECTION_HEADER pISH;
PIMAGE_IMPORT_DESCRIPTOR pIID;
PIMAGE_THUNK_DATA pITD, pIAT=0;
PIMAGE_IMPORT_BY_NAME pIIBName;
DWORD dwRVAStart;
dwRVAStart = pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
pISH = GetEnclosingSectionHeader(dwRVAStart, pINH);
nDelta = (INT)(pISH->VirtualAddress - pISH->PointerToRawData);
pIID = (PIMAGE_IMPORT_DESCRIPTOR) ((DWORD)lpBasePointer + dwRVAStart - nDelta);
printf("Imports Table:\n");
while(1){
if( (pIID->TimeDateStamp == 0) && (pIID->Name == 0) )
break;
printf(" %s\n", (PBYTE)((DWORD)lpBasePointer + pIID->Name - nDelta));
printf(" Hint/Name Table : %08X\n", pIID->Characteristics);
printf(" TimeDateStamp : %08X\n",pIID->TimeDateStamp);
printf(" ForwarderChain : %08X\n", pIID->ForwarderChain);
printf(" First thunk RVA : %08X\n", pIID->FirstThunk);
pITD = (PIMAGE_THUNK_DATA)pIID->Characteristics;
pIAT = (PIMAGE_THUNK_DATA)pIID->FirstThunk;
pITD = (PIMAGE_THUNK_DATA)( (DWORD)lpBasePointer + (PBYTE)pITD - nDelta);
pIAT = (PIMAGE_THUNK_DATA)( (DWORD)lpBasePointer + (PBYTE)pIAT - nDelta);
printf(" Ordn Name\n");
while(1){
if( pITD->u1.AddressOfData == 0)
break;
if( pITD->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
printf(" %4u", IMAGE_ORDINAL(pITD->u1.Ordinal) );
}
else
{
pIIBName = (PIMAGE_IMPORT_BY_NAME)pITD->u1.AddressOfData;
pIIBName = (PIMAGE_IMPORT_BY_NAME)( (DWORD)lpBasePointer + (PBYTE)pIIBName - nDelta);
printf(" %4u %s", pIIBName->Hint, pIIBName->Name);
}
printf("\n");
pITD++;
}
pIID++;
printf("\n");
}
return TRUE;
}
int ParseExports( LPVOID lpBasePointer, PIMAGE_NT_HEADERS pINH)
{
int i;
DWORD dwDelta, dwRVAExportStart, dwRVAExportEnd;
PDWORD functions;
PWORD ordinals;
PSTR *name;
LPSTR lpFunctionName;
PIMAGE_SECTION_HEADER pISH;
PIMAGE_EXPORT_DIRECTORY pIED;
dwRVAExportStart = pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
dwRVAExportEnd = dwRVAExportStart + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
//익스포트 테이블은 보통IMAGE_SECTION_HEADER중 .edata에 들어있다.
//그러나 반드시 그런것은 아니다. 따라서 이름으로 검사하지 않는다.
pISH = GetEnclosingSectionHeader(dwRVAExportStart, pINH);
if(!pISH)
return FALSE;
dwDelta = (INT)( pISH ->VirtualAddress - pISH->PointerToRawData);
pIED = (PIMAGE_EXPORT_DIRECTORY)( (DWORD)lpBasePointer + dwRVAExportStart - dwDelta);
lpFunctionName = (PSTR)( (DWORD)lpBasePointer + (DWORD)pIED->Name - dwDelta);
printf("%s ", lpFunctionName);
printf("exports table:\n\n");
printf(" Name: %s\n", lpFunctionName);
printf(" Characteristics: %08X\n", pIED->Characteristics);
printf(" TimeDateStamp: %08X\n", pIED->TimeDateStamp);
printf(" Version: %u.%02u\n", pIED->MajorVersion, pIED->MinorVersion);
printf(" Ordinal base: %08X\n", pIED->Base);
printf(" # of functions: %08X\n", pIED->NumberOfFunctions);
printf(" # of Names: %08X\n", pIED->NumberOfNames);
functions = (PDWORD)( (DWORD)pIED->AddressOfFunctions - dwDelta + (DWORD)lpBasePointer);
ordinals = (PWORD)( (DWORD)pIED->AddressOfNameOrdinals - dwDelta + (DWORD)lpBasePointer);
name = (PSTR *)( (DWORD)pIED->AddressOfNames - dwDelta + (DWORD)lpBasePointer);
printf("\n Entry Pt Ordn Name\n");
for(i=0; i<pIED->NumberOfFunctions; i++)
{
DWORD entryPointRVA = functions[i];
DWORD j;
if(entryPointRVA == 0)
continue;
printf(" %08X %4u", entryPointRVA, i+pIED->Base);
for(j=0; j<pIED->NumberOfNames; j++)
if(ordinals[j] == i)
printf(" %s", name[j] - dwDelta + (DWORD)lpBasePointer);
if( (entryPointRVA >= dwRVAExportStart) && (entryPointRVA <= dwRVAExportEnd))
{
printf(" (forwarder -> %s)", entryPointRVA - dwDelta + (DWORD)lpBasePointer);
}
printf("\n");
}
return TRUE;
}
int ParseFileType(PIMAGE_NT_HEADERS pINH)
{
DWORD dwMask;
dwMask = IMAGE_FILE_EXECUTABLE_IMAGE;
if(pINH->FileHeader.Characteristics & dwMask)
printf(" File Executable\n");
dwMask = IMAGE_FILE_SYSTEM;
if(pINH->FileHeader.Characteristics & dwMask)
printf("File Type : System File\n");
dwMask = IMAGE_FILE_DLL;
if(pINH->FileHeader.Characteristics & dwMask)
printf("File Type : DLL\n");
return TRUE;
}
int ParsePE(LPVOID lpBasePointer)
{
PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)lpBasePointer;
PIMAGE_NT_HEADERS pINH = (PIMAGE_NT_HEADERS)( (DWORD)pIDH + pIDH->e_lfanew);
//is it PE File Format?
if( pIDH->e_magic != IMAGE_DOS_SIGNATURE)
{
printf("It has not Pe File Format.");
return FALSE;
}
if( pINH->Signature != IMAGE_NT_SIGNATURE)
{
printf("It has not PE File Format.");
return FALSE;
}
ParseFileType(pINH);
ParseExports(lpBasePointer, pINH);
ParseImports(lpBasePointer, pINH);
return TRUE;
}
int GetPointerOfFile(char* lpFileName, HANDLE* hFile, HANDLE* hFileMap, LPVOID* lpBasePointer)
{
DWORD dwSize;
*hFile = CreateFile( (LPCWSTR)lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == *hFile)
{
printf("File could not opend.");
return FALSE;
}
*hFileMap = CreateFileMapping( *hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if(NULL == *hFileMap)
{
printf("File map could not opend.");
CloseHandle(*hFile);
return FALSE;
}
dwSize = GetFileSize(*hFile, 0);
*lpBasePointer = (char*)MapViewOfFile( *hFileMap, FILE_MAP_READ, 0, 0, dwSize);
if(NULL == lpBasePointer)
{
printf("Could not map view of file.");
CloseHandle(*hFileMap);
CloseHandle(*hFile);
return FALSE;
}
return TRUE;
}
int PEAnalyzer(char *filename)
{
int nResult;
HANDLE hFile;
HANDLE hFileMap;
LPVOID lpBasePointer;
nResult = GetPointerOfFile(filename, &hFile, &hFileMap, &lpBasePointer);
if(FALSE == nResult)
{
return FALSE;
}
nResult = ParsePE(lpBasePointer);
if( FALSE == nResult)
return FALSE;
UnmapViewOfFile(lpBasePointer);
CloseHandle(hFileMap);
CloseHandle(hFile);
return TRUE;
}
int main(int argc, char *argv[])
{
char *filename = NULL;
char fileN[256] = {0,};
printf("Write File Name :: ");
scanf("%s", fileN);
filename = (char*)malloc(strlen(fileN) + 1);
strcpy(filename, fileN);
return PEAnalyzer(filename);
}
일단 가장 첫번째로 매핑된 파일의 베이스 포인터를 얻어오는것이다.
*hFile = CreateFile( (LPCWSTR)lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
요롷게 해주면 lpBasePointer 를 이용해서 마음에 드는데로 요리해 먹을 수 있다.
그리고 PE파일의 구조에 따라 형변환 시켜가면서 각 내용들을 보면 된다.
딱히 복잡한 코드는 아니지만, PE형식에 구조체 및 공용체들이 너무 많아서(이름도 엄청 길고 ㄷㄷ) 이 분야에 뼈를묻을자가 아니라면 파일형식을 알아가는 용도로만 공부해도 될것같다.
PE format은 리버싱분야에서 많이 다루게 되는데,, 리버싱에 관심 많으신 분들은 dakuo.tistory.com 으로 가셔서 관련 글들을 접해보는것도 좋을것같다.
ps. 아 위 코드가, 윈7에서 왜 안되는지 아시는분은,,,, 좀 알려주세요(밑에 main쪽은 제가 막 바꾼거라 거기는 신경쓰지 마시구,,)