libPeConv
A library to load, manipulate, dump PE files.
Loading...
Searching...
No Matches
file_util.cpp
Go to the documentation of this file.
1#include "peconv/file_util.h"
3#include "peconv/util.h"
4
5#include <fstream>
6#include "peconv/logger.h"
7
8//load file content using MapViewOfFile
9peconv::UNALIGNED_BUF peconv::load_file(IN LPCTSTR filename, OUT size_t &read_size)
10{
11 HANDLE file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
12 if(file == INVALID_HANDLE_VALUE) {
13 LOG_ERROR("Could not open file.");
14 return nullptr;
15 }
16 HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, 0, 0);
17 if (!mapping) {
18 LOG_ERROR("Could not create file mapping.");
19 CloseHandle(file);
20 return nullptr;
21 }
22 BYTE *dllRawData = (BYTE*) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
23 if (!dllRawData) {
24 LOG_ERROR("Could not map view of file.");
25 CloseHandle(mapping);
26 CloseHandle(file);
27 return nullptr;
28 }
29 size_t r_size = GetFileSize(file, 0);
30 if (r_size == INVALID_FILE_SIZE) {
31 LOG_ERROR("Cannot retrieve file size.");
32 UnmapViewOfFile(dllRawData);
33 CloseHandle(mapping);
34 CloseHandle(file);
35 return nullptr;
36 }
37 if (read_size != 0 && read_size <= r_size) {
38 r_size = read_size;
39 }
40 if (peconv::is_bad_read_ptr(dllRawData, r_size)) {
41 LOG_ERROR("Mapping is invalid.");
42 UnmapViewOfFile(dllRawData);
43 CloseHandle(mapping);
44 CloseHandle(file);
45 return nullptr;
46 }
47 peconv::UNALIGNED_BUF localCopyAddress = peconv::alloc_unaligned(r_size);
48 if (localCopyAddress != nullptr) {
49 memcpy(localCopyAddress, dllRawData, r_size);
50 read_size = r_size;
51 } else {
52 read_size = 0;
53 LOG_ERROR("Could not allocate memory in the current process.");
54 }
55 UnmapViewOfFile(dllRawData);
56 CloseHandle(mapping);
57 CloseHandle(file);
58 return localCopyAddress;
59}
60
61//load file content using ReadFile
62peconv::UNALIGNED_BUF peconv::read_from_file(IN LPCTSTR in_path, IN OUT size_t &read_size)
63{
64 HANDLE file = CreateFile(in_path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
65 if (file == INVALID_HANDLE_VALUE) {
66 LOG_ERROR("Cannot open the file for reading.");
67 return nullptr;
68 }
69 DWORD r_size = GetFileSize(file, 0);
70 if (r_size == INVALID_FILE_SIZE) {
71 LOG_ERROR("Cannot retrieve file size.");
72 CloseHandle(file);
73 return nullptr;
74 }
75 if (read_size != 0 && read_size <= r_size) {
76 r_size = MASK_TO_DWORD(read_size);
77 }
79 if (!buffer) {
80 CloseHandle(file);
81 LOG_ERROR("Buffer allocation failed.");
82 return nullptr;
83 }
84 DWORD out_size = 0;
85 if (!ReadFile(file, buffer, r_size, &out_size, nullptr)) {
86 LOG_ERROR("ReadFile failed.");
87 peconv::free_file(buffer);
88 buffer = nullptr;
89 read_size = 0;
90 } else {
91 read_size = out_size;
92 }
93 CloseHandle(file);
94 return buffer;
95}
96
97bool peconv::dump_to_file(IN LPCTSTR out_path, IN PBYTE dump_data, IN size_t dump_size)
98{
99 if (!out_path || !dump_data || !dump_size) return false;
100
101 HANDLE file = CreateFile(out_path, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
102 if (file == INVALID_HANDLE_VALUE) {
103 LOG_ERROR("Cannot open the file for writing.");
104 return false;
105 }
106 if (dump_size > MAX_DWORD) {
107 LOG_WARNING("Dump size exceeds DWORD range and will be truncated.");
108 }
109 DWORD written_size = 0;
110 bool is_dumped = false;
111 if (WriteFile(file, dump_data, (DWORD) dump_size, &written_size, nullptr)) {
112 if (written_size != dump_size) {
113 LOG_WARNING("The written size %llu is different than the requested size: %llu.", (unsigned long long)written_size, (unsigned long long)dump_size);
114 }
115 if (written_size) {
116 is_dumped = true;
117 }
118 }
119 else {
120 LOG_ERROR("Failed to write to the file.");
121 }
122 CloseHandle(file);
123 return is_dumped;
124}
125
126//free the buffer allocated by load_file/read_from_file
128{
130}
131
132std::string peconv::get_file_name(IN const std::string str)
133{
134 size_t found = str.find_last_of("/\\");
135 if (found == std::string::npos) {
136 return str;
137 }
138 return str.substr(found + 1);
139}
140
141std::string peconv::get_directory_name(IN const std::string str)
142{
143 size_t found = str.find_last_of("/\\");
144 if (found == std::string::npos) {
145 return "";
146 }
147 return str.substr(0, found);
148}
149
150size_t peconv::find_extension_pos(IN const std::string str)
151{
152 size_t len = str.length();
153 size_t ext_pos = len;
154 for (size_t k = len; k != 0; k--) {
155 size_t i = k - 1;
156 char c = str[i];
157 if (c == '.') {
158 ext_pos = i;
159 break;
160 }
161 }
162 return ext_pos;
163}
Definitions of the used buffer types. Functions for their allocation and deallocation.
#define MAX_DWORD
Definition: buffer_util.h:10
#define MASK_TO_DWORD(val)
Definition: buffer_util.h:12
Functions related to operations on files. Wrappers for read/write.
Compile-time configurable logging macros for peconv.
#define LOG_ERROR(fmt,...)
Definition: logger.h:60
#define LOG_WARNING(fmt,...)
Definition: logger.h:68
bool dump_to_file(IN LPCTSTR path, IN PBYTE dump_data, IN size_t dump_size)
Definition: file_util.cpp:97
UNALIGNED_BUF alloc_unaligned(size_t buf_size)
Definition: buffer_util.cpp:37
peconv::UNALIGNED_BUF load_file(IN LPCTSTR filename, OUT size_t &r_size)
Definition: file_util.cpp:9
std::string get_directory_name(IN const std::string full_path)
Definition: file_util.cpp:141
bool is_bad_read_ptr(LPCVOID areaStart, SIZE_T areaSize)
Definition: util.cpp:156
void free_file(IN peconv::UNALIGNED_BUF buffer)
Definition: file_util.cpp:127
PBYTE UNALIGNED_BUF
Definition: buffer_util.h:41
size_t find_extension_pos(IN const std::string str)
Definition: file_util.cpp:150
peconv::UNALIGNED_BUF read_from_file(IN LPCTSTR path, IN OUT size_t &read_size)
Definition: file_util.cpp:62
std::string get_file_name(IN const std::string full_path)
Definition: file_util.cpp:132
void free_unaligned(UNALIGNED_BUF section_buffer)
Definition: buffer_util.cpp:45
Miscellaneous utility functions.