PE-sieve
Scans all running processes. Recognizes and dumps a variety of potentially malicious implants (replaced/implanted PEs, shellcodes, hooks, in-memory patches).
Loading...
Searching...
No Matches
syscall_extractor.cpp
Go to the documentation of this file.
1#include "syscall_extractor.h"
2
3#include <windows.h>
4#include <peconv.h> // include libPeConv header
5#include <iostream>
6#include "process_util.h"
7
8namespace pesieve {
9 namespace util {
10
11 bool isSyscallFunc(const std::string& funcName)
12 {
13 std::string prefix("Nt");
14 if (funcName.size() < (prefix.size() + 1)) {
15 return false;
16 }
17 if (funcName.compare(0, prefix.size(), prefix) != 0) {
18 return false;
19 }
20 char afterPrefix = funcName.at(prefix.size());
21 if (afterPrefix >= 'A' && afterPrefix <= 'Z') {
22 // the name of the function after the Nt prefix will start in uppercase,
23 // syscalls are in functions like: NtUserSetWindowLongPtr, but not: NtdllDefWindowProc_A
24 return true;
25 }
26 return false;
27 }
28
29 size_t extract_syscalls(BYTE* pe_buf, size_t pe_size, std::map<DWORD, std::string>& syscallToName, size_t startID = 0)
30 {
31 std::vector<std::string> names_list;
32 if (!peconv::get_exported_names(pe_buf, names_list)) {
33 return 0;
34 }
35
36 std::map<DWORD, std::string> sys_functions;
37 for (auto itr = names_list.begin(); itr != names_list.end(); ++itr) {
38 std::string funcName = *itr;
39 if (isSyscallFunc(funcName)) {
40 ULONG_PTR va = (ULONG_PTR)peconv::get_exported_func(pe_buf, funcName.c_str());
41 if (!va) continue;
42
43 DWORD rva = DWORD(va - (ULONG_PTR)pe_buf);
44 sys_functions[rva] = funcName;
45 }
46 }
47 size_t id = startID;
48 for (auto itr = sys_functions.begin(); itr != sys_functions.end(); ++itr) {
49 std::string funcName = itr->second;
50 syscallToName[id++] = funcName;
51 }
52 return id;
53 }
54
55 size_t extract_from_dll(IN const std::string& path, size_t startSyscallID, OUT std::map<DWORD, std::string>& syscallToName)
56 {
57 size_t bufsize = 0;
58 BYTE* buffer = peconv::load_pe_module(path.c_str(), bufsize, false, false);
59
60 if (!buffer) {
61#ifdef _DEBUG
62 std::cerr << "Failed to load the PE: " << path << "\n";
63#endif
64 return 0;
65 }
66
67 size_t extracted_count = extract_syscalls(buffer, bufsize, syscallToName, startSyscallID);
68 peconv::free_pe_buffer(buffer);
69
70 if (!extracted_count) {
71#ifdef _DEBUG
72 std::cerr << "No syscalls extracted from: " << path << "\n";
73#endif
74 }
75 return extracted_count;
76 }
77
78 }; //namespace util
79
80}; //namespace pesieve
81
82size_t pesieve::util::extract_syscall_table(OUT std::map<DWORD, std::string>& syscallToName)
83{
84 PVOID old_val = NULL;
86
87 std::stringstream outs;
88 size_t extracted_count = 0;
89
90 char ntdll_path[MAX_PATH] = { 0 };
91 ExpandEnvironmentStringsA("%SystemRoot%\\system32\\ntdll.dll", ntdll_path, MAX_PATH);
92 extracted_count += extract_from_dll(ntdll_path, 0, syscallToName);
93
94 char win32u_path[MAX_PATH] = { 0 };
95 ExpandEnvironmentStringsA("%SystemRoot%\\system32\\win32u.dll", win32u_path, MAX_PATH);
96 extracted_count += extract_from_dll(win32u_path, 0x1000, syscallToName);
97
99
100 if (!extracted_count) {
101#ifdef _DEBUG
102 std::cerr << "Failed to extract syscalls.\n";
103#endif
104 return 0;
105 }
106 return syscallToName.size();
107}
bool isSyscallFunc(const std::string &funcName)
BOOL wow64_disable_fs_redirection(OUT PVOID *OldValue)
size_t extract_from_dll(IN const std::string &path, size_t startSyscallID, OUT std::map< DWORD, std::string > &syscallToName)
DWORD(__stdcall *_PssCaptureSnapshot)(HANDLE ProcessHandle
size_t extract_syscall_table(OUT std::map< DWORD, std::string > &syscallToName)
size_t extract_syscalls(BYTE *pe_buf, size_t pe_size, std::map< DWORD, std::string > &syscallToName, size_t startID=0)
BOOL wow64_revert_fs_redirection(IN PVOID OldValue)
int MAX_PATH
Definition pesieve.py:10