반응형
#pragma once

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include <ctype.h>
#include <Windows.h>

extern int offset;

typedef enum
{
    OPERAND_DWORD,
    OPERAND_ULONGLONG,
    OPERAND_NT32,
    OPERAND_NT64,
    OPERAND_NT32_DATADIRECTORY,
    OPERAND_NT64_DATADIRECTORY,
    OPERAND_IID32,
    OPERAND_IID64
} operand;

// 파일 사이즈를 구한다.
int get_file_size(FILE* fp);
// 파일 사이즈를 구한 후 파일의 내용을 동적 메모리에 저장
void* get_file_content(FILE* fp, int *size);
// 파일 오프셋
int set_file_offset(FILE* fp, int offset);
int get_file_offset(FILE* fp, int offset);

ULONGLONG convert_rva_to_raw(const u_char* binary_buf, void* rva_value, operand operand_type);

void print_dos_header(FILE* fp, IMAGE_DOS_HEADER* idh);
void print_nt_header(FILE* fp, unsigned char* buf, operand operand_type);
void print_inh_ioh_datadirectory(FILE* fp, unsigned char* buf, operand operand_type);
void print_section_header(FILE* fp, IMAGE_SECTION_HEADER* ish, WORD section_num);

void print_image_import_descriptor(FILE* fp, u_char* buf, operand operand_type);
int print_image_export_directory(FILE* fp, u_char* buf, IMAGE_EXPORT_DIRECTORY* ied);

 

offset 변수는 분석 대상 파일에 대해서 offset 위치의 값을 저장하고 출력하기 위한 용도이다.

 


파일과 관련된 함수

int get_file_size(FILE* fp); // 파일의 크기 얻어오는 함수

void* get_file_content(FILE* fp, int *size); // 파일의 내용을 얻어오는 함수

int set_file_offset(FILE* fp, int offset); // 얻어온 파일의 데이터의 위치를 가리키는 offset을 설정하는 함수

int get_file_offset(FILE* fp, int offset); // 현재 offset 값을 얻어오는 함수

각 헤더 구조체에 맞게 파일의 데이터를 파싱해 출력하는 함수들

// dos header
void print_dos_header(FILE* fp, IMAGE_DOS_HEADER* idh);

// NT header
void print_nt_header(FILE* fp, unsigned char* buf, operand operand_type);

// NT header의 optional header의 datadirectory
void print_inh_ioh_datadirectory(FILE* fp, unsigned char* buf, operand operand_type);

// Section header
void print_section_header(FILE* fp, IMAGE_SECTION_HEADER* ish, WORD section_num);

// Image Import Descriptor
void print_image_import_descriptor(FILE* fp, u_char* buf, operand operand_type);

// Image Export Directory
int print_image_export_directory(FILE* fp, u_char* buf, IMAGE_EXPORT_DIRECTORY* ied);

rva 값을 raw 값으로 바꿔주는 함수

// 인자 size 값에 따라 처리 후 기본적으로 ULONGLONG 형으로 반환하는 함수
ULONGLONG convert_rva_to_raw(const u_char* binary_buf, void* rva_value, operand operand_type);

get_file_size.c

#include "header.h"

int get_file_size(FILE* fp)
{
	int size = 0;

	// 파일 포인터를 파일의 끝으로 보낸다.
	// 파일 포인터를 파일의 끝으로 보낼 수 없을 때
	if (fseek(fp, 0, SEEK_END) != 0)
	{
		fprintf(stderr, "파일의 끝으로 이동할 수 없습니다. :%s\n", strerror(errno));
		return -1;
	}

	// 파일 포인터를 이동 후 현재 파일 포인터의 위치를 가져올 수 없을 때
	if ((size = ftell(fp)) == -1)
	{
		fprintf(stderr, "파일에서 현재 위치를 알 수 없습니다. :%s\n", strerror(errno));
		return -1;
	}

	// 파일 포인터를 처음 부분으로 위치시킨다.
	rewind(fp);

	/*
	if (fseek(fp, 0, SEEK_SET) != 0)
	{
		fprintf(stderr, "파일의 처음으로 이동할 수 없습니다. :%s\n", strerror(errno));
		return -1;
	}*/

	// 파일 사이즈 구하기 실패 했을 때	
	if (size <= 0)
	{
		printf("파일 사이즈를 구하는 데 실패했습니다.\n");
		return -1;
	}

	return size;
}

 

get_file_size 함수는 분석할 파일의 크기를 알아오기 위함이다.

 

파일의 크기를 구했으면 파일의 포인터를 다시 처음으로 이동시키고, 파일의 크기를 반환한다.

 

1. 파일 포인터를 끝을 이동할 수 없을 때

2. 파일 포인터를 이동 후 현재 파일 포인터의 위치 값을 가져올 수 없을 때

3. 구한 파일 사이즈 값이 0 이하일 때

 

위 3가지 경우에 있어서 return -1;을 하겠끔 했다.


get_file_content.c

#include "header.h"

// 파일 사이즈를 구한 후 파일의 내용을 동적 메모리에 저장
void* get_file_content(FILE* fp, int *size)
{
	void* buf = NULL;

	// 파일 사이즈 구해오기
	if ((*size = get_file_size(fp)) < 0)
	{
		printf("get_file_size() error\n");
		return NULL;
	}
	
	// 파일 사이즈만큼 메모리 동적 할당
	if ((buf = malloc(*size)) == NULL)
	{
		printf("malloc() error\n");
		return NULL;
	}

	// 동적 할당한 heap 메모리 공간을 0으로 초기화
	if (memset(buf, 0x00, *size) == NULL)
	{
		printf("memset() error\n");
		return NULL;
	}

	// 동적 할당한 메모리에 file 내용 전체 읽기
	if (fread(buf, 1, *size, fp) != *size)
	{
		printf("fread() error\n");
		return NULL;
	}

	// 파일 사이즈를 구해왔고, 내용을 읽었다면 다시 파일 포인터를 처음으로 위치
	rewind(fp);

	return buf;
}

 

get_file_content 함수는 분석할 대상 프로그램의 사이즈만큼 동적으로 공간을 생성하고, 생성한 동적 공간에 파일의 내용을 담기 위한 용도이다.

 

동적 할당한 공간에 파일의 내용을 담았으면 해당 공간의 주소를 반환한다.

 

1. 파일의 크기가 0보다 작을 때

2. 동적 메모리 할당에 실패했을 때

3. 동적 공간을 0으로 초기화하지 못했을 때

4. 파일의 내용을 제대로 동적 공간에 담지 못했을 때

 

위 4가지 경우에 있어서 return NULL;을 반환한다.


set_file_offset.c

#include "header.h"

// 파일 포인터의 현재 위치를 인자로 넘어온 값으로 맞추고, 현재 파일 포인터의 위치를 반환한다.
int set_file_offset(FILE* fp, int offset)
{
	if (fseek(fp, offset, SEEK_SET) != 0)
	{
		perror("fseek()");
		return -1;
	}
	else
		return ftell(fp);
}

 

set_file_offset 함수는 파일포인터의 현재 위치를 인자로 넘어온 값으로 설정하고, 설정된 현재 파일 포인터의 위치를 반환한다.

 

파일의 첫 위치로부터 인자로 넘어온 값만큼 이동하지 못했을 때

 

위의 경우에 있어서 return -1를 반환한다.


get_file_offset.c

#include "header.h"

// size 인자 만큼 파일 포인터를 이동하여 해당 위치의 offset 값을 반환한다.
int get_file_offset(FILE* fp, int offset)
{
	fseek(fp, offset, SEEK_CUR);
	return ftell(fp);
}

 

get_file_offset 함수는 현재 파일 포인터의 위치로부터 인자로 넘어온 값만큼 이동시키는 후 이동된 위치의 값을 반환하는 함수이다.

 

반응형

+ Recent posts