PE-sieve
Scans all running processes. Recognizes and dumps a variety of potentially malicious implants (replaced/implanted PEs, shellcodes, hooks, in-memory patches).
Toggle main menu visibility
Loading...
Searching...
No Matches
utils
path_converter.cpp
Go to the documentation of this file.
1
#include "
path_converter.h
"
2
3
#include <windows.h>
4
5
#include "ntddk.h"
6
#pragma comment(lib, "Ntdll.lib")
7
8
#include <shlwapi.h>
9
#pragma comment (lib, "shlwapi.lib")
10
11
#include <iostream>
12
#include <string>
13
#include <locale>
14
#include <codecvt>
15
16
#include "
path_util.h
"
17
18
#define LONG_PATH_PREFIX "\\\\?\\"
19
#define GLOBALROOT_NAME "GLOBALROOT"
20
21
char
g_System32Path
[MAX_PATH] = { 0 };
//= "C:\\Windows\\system32";
22
char
g_Syswow64Path
[MAX_PATH] = { 0 };
//= "C:\\Windows\\SysWOW64";
23
24
namespace
pesieve
{
25
namespace
util
{
26
27
void
init_syspaths
()
28
{
29
if
(!
g_System32Path
[0]) {
30
memset(
g_System32Path
, 0,
MAX_PATH
);
31
ExpandEnvironmentStringsA(
"%SystemRoot%\\system32"
,
g_System32Path
,
MAX_PATH
);
32
}
33
if
(!
g_Syswow64Path
[0]) {
34
memset(
g_Syswow64Path
, 0,
MAX_PATH
);
35
ExpandEnvironmentStringsA(
"%SystemRoot%\\SysWoW64"
,
g_Syswow64Path
,
MAX_PATH
);
36
}
37
}
38
39
HANDLE
nt_create_file
(PCWSTR filePath)
40
{
41
HANDLE
hFile
;
42
OBJECT_ATTRIBUTES objAttribs = { 0 };
43
44
UNICODE_STRING unicodeString;
45
RtlInitUnicodeString(&unicodeString, filePath);
46
47
InitializeObjectAttributes(&objAttribs, &unicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
48
49
const
int
allocSize = 2048;
50
LARGE_INTEGER largeInteger;
51
largeInteger.QuadPart = allocSize;
52
53
IO_STATUS_BLOCK ioStatusBlock = { 0 };
54
NTSTATUS
status = NtCreateFile(&
hFile
,
55
STANDARD_RIGHTS_READ,
56
&objAttribs,
57
&ioStatusBlock,
58
&largeInteger,
59
FILE_ATTRIBUTE_NORMAL,
60
FILE_SHARE_READ,
61
FILE_OPEN,
62
FILE_NON_DIRECTORY_FILE,
63
NULL,
64
0
65
);
66
if
(status != STATUS_SUCCESS) {
67
std::wcerr <<
"Cannot open file: "
<< filePath <<
". Error: "
<< std::hex << status << std::endl;
68
return
nullptr
;
69
}
70
return
hFile
;
71
}
72
73
std::string
nt_retrieve_file_path
(HANDLE
hFile
)
74
{
75
IO_STATUS_BLOCK status_block = { 0 };
76
77
struct
MY_FILE_NAME_INFORMATION {
78
ULONG FileNameLength;
79
WCHAR FileName[
MAX_PATH
];
80
} name_info;
81
82
memset(&name_info, 0,
sizeof
(MY_FILE_NAME_INFORMATION));
83
84
NTSTATUS
status = ZwQueryInformationFile(
hFile
, &status_block, &name_info,
sizeof
(MY_FILE_NAME_INFORMATION), FileNameInformation);
85
if
(status != STATUS_SUCCESS) {
86
return
""
;
87
}
88
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
89
std::string my_string = converter.to_bytes(name_info.FileName);
90
91
my_string =
get_system_drive
() + my_string;
92
return
my_string;
93
}
94
95
bool
is_relative
(
const
char
*path,
size_t
path_len)
96
{
97
if
(path_len < 2) {
98
return
true
;
99
}
100
// i.e. "c:\"
101
if
(path[1] ==
':'
) {
102
return
false
;
103
}
104
// i.e. "\\path1\" or "\\?\UNC\"
105
if
(path[0] ==
'\\'
&& path[1] ==
'\\'
) {
106
return
false
;
107
}
108
return
true
;
109
}
110
111
bool
is_disk_relative
(
const
char
*path,
size_t
path_len)
112
{
113
if
(path_len < 2) {
114
return
true
;
115
}
116
//check format:
117
if
((path[0] >=
'a'
&& path[0] <=
'z'
)
118
|| (path[0] >=
'A'
&& path[0] <=
'Z'
))
119
{
120
if
(path[1] ==
':'
) {
121
// format i.e: C:\...
122
return
true
;
123
}
124
}
125
return
false
;
126
}
127
128
std::string
remap_to_drive_letter
(
const
std::string &full_path)
129
{
130
size_t
full_path_size = full_path.length();
131
if
(full_path_size == 0) {
132
return
full_path;
133
}
134
135
DWORD
drives_bitmask = GetLogicalDrives();
136
//std::cout << "Drives: " << std::hex << drives_bitmask << std::endl;
137
138
for
(
DWORD
i = 0; i < 32; i += 1, drives_bitmask >>= 1) {
139
if
((drives_bitmask & 1) == 1) {
140
char
letter[] =
"?:"
;
141
letter[0] =
'A'
+ (char)i;
142
//std::cout << "Drive: " << letter << std::endl;
143
char
out_path[
MAX_PATH
] = { 0 };
144
if
(!QueryDosDeviceA(letter, out_path,
MAX_PATH
)) {
145
return
full_path;
146
}
147
//QueryDosDeviceA returns all possible mappings pointing to this drive letter, divided by a delimiter: ";"
148
//sometimes one device letter is mapped to several paths
149
// i.e. "\Device\VBoxMiniRdr\;E:\vboxsrv\vm_shared"
150
const
char
delim[] =
";"
;
151
char
*next_token =
nullptr
;
152
153
char
* pch = strtok_s(out_path, delim, &next_token);
154
while
(pch !=
nullptr
) {
155
// check if the current path starts from any of the mapped paths
156
std::size_t found = full_path.find(pch);
157
if
(found != std::string::npos && found == 0) {
158
size_t
dir_len = strlen(pch);
159
//if so, cut out the mappining path/device path and replace it with a drive letter
160
std::string str2 = full_path.substr(dir_len, full_path_size);
161
if
(str2[0] !=
'/'
&& str2[0] !=
'\\'
) {
162
str2 =
"\\"
+ str2;
163
}
164
return
letter + str2;
165
}
166
pch = strtok_s(
nullptr
, delim, &next_token);
167
}
168
}
169
}
170
return
full_path;
171
}
172
173
std::string
relative_to_absolute_path
(std::string path)
174
{
175
if
(
is_relative
(path.c_str(), path.length())) {
176
char
current_dir[
MAX_PATH
] = { 0 };
177
GetCurrentDirectoryA(
MAX_PATH
, current_dir);
178
path = std::string(current_dir) +
"\\"
+ path;
179
}
180
char
out_path[
MAX_PATH
] = { 0 };
181
PathCanonicalizeA(out_path, path.c_str());
182
return
std::string(out_path);
183
}
184
185
std::string
replace_char
(std::string &str,
char
ch1,
char
ch2) {
186
for
(
size_t
i = 0; i < str.length(); ++i) {
187
if
(str[i] == ch1)
188
str[i] = ch2;
189
}
190
return
str;
191
}
192
};
193
};
194
195
bool
pesieve::util::convert_to_wow64_path
(
char
*szModName)
196
{
197
init_syspaths
();
198
if
(!
get_subpath_ptr
(szModName,
g_System32Path
)) {
199
return
false
;
200
}
201
size_t
sysPathLen = strlen(
g_Syswow64Path
);
202
memcpy(szModName,
g_Syswow64Path
, sysPathLen);
203
return
true
;
204
}
205
206
std::string
pesieve::util::convert_to_win32_path
(
const
std::string &path)
207
{
208
std::string stripped_path =
strip_prefix
(path,
LONG_PATH_PREFIX
);
209
if
(stripped_path.length() < 3) {
210
return
""
;
211
}
212
//check format:
213
if
(
is_disk_relative
(stripped_path.c_str(), stripped_path.length())) {
214
return
stripped_path;
215
}
216
stripped_path =
strip_prefix
(stripped_path,
GLOBALROOT_NAME
);
217
const
char
*szModName = stripped_path.c_str();
218
std::wstring unicode_name(szModName, szModName + strlen(szModName));
219
HANDLE
hFile
=
nt_create_file
(unicode_name.c_str());
220
if
(
hFile
==
nullptr
) {
221
return
""
;
222
}
223
std::string my_path =
nt_retrieve_file_path
(
hFile
);
224
CloseHandle(
hFile
);
225
return
my_path;
226
}
227
228
std::string
pesieve::util::device_path_to_win32_path
(
const
std::string &full_path)
229
{
230
std::string path = full_path;
231
//sometimes mapping can be recursive, so resolve it till the root
232
do
{
233
std::string remapped_path =
remap_to_drive_letter
(path);
234
if
(remapped_path == path)
break
;
235
path = remapped_path;
236
}
while
(
true
);
237
return
path;
238
}
239
240
bool
is_device_path
(
const
std::string &path)
241
{
242
const
std::string device_path =
"\\Device\\"
;
243
if
(path.length() < device_path.length() || path[0] !=
'\\'
) {
244
return
false
;
245
}
246
if
(path.compare(0, device_path.length(), device_path) == 0){
247
return
true
;
248
}
249
return
false
;
250
}
251
252
std::string
pesieve::util::expand_path
(
const
std::string &path)
253
{
254
std::string basic_path =
pesieve::util::device_path_to_win32_path
(path);
255
if
(
is_device_path
(basic_path)) {
256
// Could not normalize it: it is still a device path. Return as is.
257
return
path;
258
}
259
// normalize path sepators: use '/' not '\'
260
replace_char
(basic_path,
'/'
,
'\\'
);
261
262
std::string abs_path =
relative_to_absolute_path
(basic_path);
263
264
char
filename[
MAX_PATH
] = { 0 };
265
if
(GetLongPathNameA(abs_path.c_str(), filename,
MAX_PATH
) == 0) {
266
size_t
len = abs_path.length();
267
if
(len >
MAX_PATH
) len =
MAX_PATH
;
268
//if could not retrieve, process what you have:
269
memcpy(filename, abs_path.c_str(), len);
270
}
271
return
strip_prefix
(filename,
LONG_PATH_PREFIX
);
272
}
pesieve::util
Definition
artefact_scanner.cpp:12
pesieve::util::replace_char
std::string replace_char(std::string &str, char ch1, char ch2)
Definition
path_converter.cpp:185
pesieve::util::nt_retrieve_file_path
std::string nt_retrieve_file_path(HANDLE hFile)
Definition
path_converter.cpp:73
pesieve::util::expand_path
std::string expand_path(const std::string &path)
Definition
path_converter.cpp:252
pesieve::util::get_subpath_ptr
char * get_subpath_ptr(char *modulePath, char *searchedPath)
Definition
path_util.cpp:5
pesieve::util::strip_prefix
std::string strip_prefix(std::string path, std::string prefix)
Definition
path_util.cpp:94
pesieve::util::remap_to_drive_letter
std::string remap_to_drive_letter(const std::string &full_path)
Definition
path_converter.cpp:128
pesieve::util::NTSTATUS
NTSTATUS(NTAPI *_RtlCreateProcessReflection)(HANDLE ProcessHandle
pesieve::util::convert_to_win32_path
std::string convert_to_win32_path(const std::string &path)
Definition
path_converter.cpp:206
pesieve::util::init_syspaths
void init_syspaths()
Definition
path_converter.cpp:27
pesieve::util::device_path_to_win32_path
std::string device_path_to_win32_path(const std::string &full_path)
Definition
path_converter.cpp:228
pesieve::util::is_relative
bool is_relative(const char *path, size_t path_len)
Definition
path_converter.cpp:95
pesieve::util::is_disk_relative
bool is_disk_relative(const char *path, size_t path_len)
Definition
path_converter.cpp:111
pesieve::util::nt_create_file
HANDLE nt_create_file(PCWSTR filePath)
Definition
path_converter.cpp:39
pesieve::util::hFile
DWORD HANDLE hFile
Definition
process_minidump.cpp:11
pesieve::util::get_system_drive
std::string get_system_drive()
Definition
path_util.cpp:46
pesieve::util::DWORD
DWORD(__stdcall *_PssCaptureSnapshot)(HANDLE ProcessHandle
pesieve::util::convert_to_wow64_path
bool convert_to_wow64_path(char *szModName)
Definition
path_converter.cpp:195
pesieve::util::relative_to_absolute_path
std::string relative_to_absolute_path(std::string path)
Definition
path_converter.cpp:173
pesieve
Definition
pesieve.py:1
pesieve.MAX_PATH
int MAX_PATH
Definition
pesieve.py:11
is_device_path
bool is_device_path(const std::string &path)
Definition
path_converter.cpp:240
LONG_PATH_PREFIX
#define LONG_PATH_PREFIX
Definition
path_converter.cpp:18
GLOBALROOT_NAME
#define GLOBALROOT_NAME
Definition
path_converter.cpp:19
g_Syswow64Path
char g_Syswow64Path[MAX_PATH]
Definition
path_converter.cpp:22
g_System32Path
char g_System32Path[MAX_PATH]
Definition
path_converter.cpp:21
path_converter.h
path_util.h
Generated by
1.17.0