├── defender
├── MpAsBase.vdm
├── MpAsDlta.vdm
├── MpAvBase.vdm
└── MpAvDlta.vdm
├── assets
└── image-20220630172140496.png
├── .gitignore
├── README.md
├── LICENSE
├── rsignal.h
└── mptest.cc
/defender/MpAsBase.vdm:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/defender/MpAsDlta.vdm:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/defender/MpAvBase.vdm:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/defender/MpAvDlta.vdm:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/image-20220630172140496.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/h0li3/mpengine_diskus/HEAD/assets/image-20220630172140496.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 | *.lib
28 |
29 | # Executables
30 | *.exe
31 | *.out
32 | *.app
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mpengine_diskus
2 | **参考自[taviso的项目代码](https://github.com/taviso/loadlibrary),稍微逆向mpengine.dll练习逆向基础。**
3 |
4 | #### 编译运行
5 |
6 | *原作者的项目是用到Linux中的,我这里为了方便直接在windows里面运行,运行时在Windows中搜索defender目录中对应的文件的名称,并复制到defender目录中。其中一部分枚举、结构体定义直接照搬的大哥原项目的定义,大哥太厉害了。*
7 |
8 | ```powershell
9 | cl.exe /DEBUG /Zi mptest.cc
10 | .\mptest.exe sample.exe virus.exe ...
11 | ```
12 |
13 |
14 |
15 | #### 问题
16 |
17 | 1. 运行结束时MpEngine.dll释放资源时,会出现非法内存访问;
18 | 2. 简陋。
19 |
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 h0li3
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/rsignal.h:
--------------------------------------------------------------------------------
1 | #ifndef __RSIGNAL_H
2 | #define __RSIGNAL_H
3 |
4 | enum class rsignal_code
5 | {
6 | RSIG_BASE = 0x4000,
7 | RSIG_RESERVED1 = 0x4003,
8 | RSIG_GETEINFO = 0x4004,
9 | RSIG_VIRINFO = 0x4005,
10 | RSIG_UNLOADENGINE = 0x4006,
11 | RSIG_RESERVED2 = 0x4007,
12 | RSIG_SCANFILE_TS_W = 0x4014,
13 | RSIG_SCANPATH_TS_W = 0x4015,
14 | RSIG_RESERVED3 = 0x4019,
15 | RSIG_CONFIGURE_NEW_W = 0x401A,
16 | RSIG_RESERVED4 = 0x401C,
17 | RSIG_FIW32_CONFIG = 0x401D,
18 | RSIG_SPLIT_VIRNAME = 0x401E,
19 | RSIG_HOOK_API = 0x401F,
20 | RSIG_INIT_ENGINE_CONTEXT = 0x4020,
21 | RSIG_CLEANUP_ENGINE_CONTEXT = 0x4021,
22 | RSIG_SCANFILE_TS_WCONTEXT = 0x4023,
23 | RSIG_SCANPATH_TS_WCONTEXT = 0x4024,
24 | RSIG_VIRINFO_FILTERED = 0x4025,
25 | RSIG_SCAN_OPEN = 0x4026,
26 | RSIG_SCAN_GETEVENT = 0x4027,
27 | RSIG_SCAN_CLOSE = 0x4028,
28 | RSIG_GET_THREAT_INFO = 0x4030,
29 | RSIG_SCANSTREAMW = 0x4031,
30 | RSIG_SCANSTREAMW_WCONTEXT = 0x4032,
31 | RSIG_CHECK_PRIVILEGES = 0x4033,
32 | RSIG_ADJUST_PRIVILEGES = 0x4034,
33 | RSIG_SET_FILECHANGEQUERY = 0x4035,
34 | RSIG_BOOTENGINE = 0x4036,
35 | RSIG_RTP_GETINITDATA = 0x4037,
36 | RSIG_RTP_SETEVENTCALLBACK = 0x4038,
37 | RSIG_RTP_NOTIFYCHANGE = 0x4039,
38 | RSIG_RTP_GETBEHAVIORCONTEXT = 0x403A,
39 | RSIG_RTP_SETBEHAVIORCONTEXT = 0x403B,
40 | RSIG_RTP_FREEBEHAVIORCONTEXT = 0x403C,
41 | RSIG_SCAN_STREAMBUFFER = 0x403D,
42 | RSIG_RTP_STARTBEHAVIORMONITOR = 0x403E,
43 | RSIG_RTP_STOPBEHAVIORMONITOR = 0x403F,
44 | RSIG_GET_SIG_DATA = 0x4041,
45 | RSIG_VALIDATE_FEATURE = 0x4042,
46 | RSIG_SET_CALLBACK = 0x4043,
47 | RSIG_OBFUSCATE_DATA = 0x4044,
48 | RSIG_DROP_BMDATA = 0x4045,
49 | RSIG_SCANEXTRACT = 0x4046,
50 | RSIG_CHANGE_SETTINGS = 0x4047,
51 | RSIG_RTSIG_DATA = 0x4048,
52 | RSIG_SYSTEM_REBOOT = 0x4049,
53 | RSIG_REVOKE_QUERY = 0x4050,
54 | RSIG_CHECK_EXCLUSIONS = 0x4051,
55 | RSIG_COMPLETE_INITIALIZATION = 0x4052,
56 | RSIG_STATE_CHANGE = 0x4053,
57 | RSIG_SEND_CALLISTO_TELEMETRY = 0x4054,
58 | RSIG_DYNAMIC_CONFIG = 0x4055,
59 | RSIG_SEND_EARLY_BOOT_DATA = 0x4056,
60 | RSIG_SCAN_TCG_LOG = 0x4057,
61 | RSIG_CANCEL_ENGINE_LOAD = 0x4058,
62 | RSIG_SQM_CONFIG = 0x4059,
63 | RSIG_SERVICE_NOTIFICATION = 0x405B,
64 | RSIG_SCAN_TCG_LOG_EX = 0x405B,
65 | RSIG_FREE_TCG_EXTENDED_DATA = 0x405C,
66 | RSIG_NOTIFY_MAINTENANCE_WINDOW_STATE = 0x405D,
67 | RSIG_SEND_REMOTE_ATTESTATION_DATA = 0x405E,
68 | RSIG_ON_CLOUD_COMPLETION = 0x4060,
69 | RSIG_CONTROL_SPLI = 0x4061,
70 | RSIG_THREAT_UPDATE_STATUS = 0x4062,
71 | RSIG_VERIFY_MACHINE_GUID = 0x4063,
72 | RSIG_NRI_UPDATE_STATE = 0x4064,
73 | RSIG_TPM_CONFIG = 0x4065,
74 | RSIG_GET_RESOURCE_INFO = 0x4066,
75 | RSIG_GET_ASYNC_QUEUE_LENGTH = 0x4067,
76 | RSIG_RTP_IMAGENAME_CONFIG = 0x4068,
77 | RSIG_SET_CUSTOM_SET_ID = 0x4069,
78 | RSIG_CONFIGURE_ROLES = 0x4070,
79 | RSIG_HOOK_WOW = 0x4071,
80 | RSIG_AMSI_SESSION_END = 0x4072,
81 | RSIG_RESOURCE_CONTEXT_CONSOLIDATION = 0x4073,
82 | RSIG_ADD_IDEBUG_IFACE = 0x4074,
83 | RSIG_REMOVE_IDEBUG_IFACE = 0x4075,
84 | RSIG_SAMPLE_SUBMISSION_CONSENT = 0x4076,
85 | RSIG_ENGINE_PRE_SHUTDOWN = 0x4077,
86 | RSIG_ENGINE_SAMPLE_CHUNK = 0x4078,
87 | RSIG_ENGINE_SAMPLE_SUBMISSION_COMPLETE = 0x4079,
88 | RSIG_GENERATE_SIGNATURE = 0x407A,
89 | RSIG_GET_WMI_SENSOR_CONFIG = 0x407B,
90 | RSIG_RTP_IMAGENAME_CONFIG_EX = 0x407C,
91 | RSIG_SET_AC_SIGNING_SEED = 0x407D,
92 | RSIG_ON_CLOUD_COMPLETION_EX = 0x407F,
93 | RSIG_GENERATE_SUPPORT_LOG = 0x4080,
94 | RSIG_GET_FOLDERGUARD_DATA = 0x4081,
95 | RSIG_SET_PROCESS_EXCLUSIONS = 0x4082,
96 | RSIG_FLUSH_LOWFI_CACHE = 0x4083,
97 | RSIG_SYNC_NOTIFICATION = 0x4084,
98 | RSIG_NETWORK_HIPS_CONNECTION_METADATA = 0x4085,
99 | RSIG_ASR_DATA = 0x4086,
100 | RSIG_DETECTION_INFO = 0x4087,
101 | RSIG_SCAN_STREAMBUFFER_EX = 0x4088,
102 | RSIG_GET_DETECTION_CLASSIFICATION = 0x4089,
103 | RSIG_DLP_SET_RULE = 0x408A,
104 | RSIG_GET_DLP_DATA = 0x408B,
105 | RSIG_URL_DETERMINATION = 0x408C,
106 | RSIG_DECODE_SCHEMA_DATA = 0x408D,
107 | RSIG_RELEASE_SCHEMA_DATA = 0x408E,
108 | RSIG_ADD_CUSTOM_VDM = 0x408F,
109 | RSIG_DLP_QUERY_BLANKET_POLICY = 0x4090,
110 | RSIG_ALLOW_THREAT = 0x4091,
111 | RSIG_XPLAT_COLLECT_HEARTBEAT_REPORT = 0x4092,
112 | RSIG_XPLAT_GET_HEARTBEAT_REPORT = 0x4093,
113 | RSIG_XPLAT_PARSE_HEARTBEAT_RESPONSE = 0x4094,
114 | RSIG_CHECK_THREAT_ID = 0x4095,
115 | RSIG_DLP_QUERY_PRINT_FILE_HEURISTIC_POLICY = 0x4096,
116 | RSIG_HIPS_USER_EXCLUSION = 0x4097,
117 | RSIG_DLP_IS_PROCESS_EXCLUDED = 0x4098,
118 | RSIG_DLP_QUERY_DETOURS_INJECTION_PROCESS_POLICY = 0x4099,
119 | RSIG_FLUSH_VOLUME_GUID_CACHE = 0x409A,
120 | RSIG_DLP_QUERY_CLIPBOARD_APPLICATION_SETTINGS = 0x409B,
121 |
122 | RSIG_ENGINE_WAITFORIDLE = 0x454C4449,
123 | };
124 |
125 | #endif
126 |
--------------------------------------------------------------------------------
/mptest.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "rsignal.h"
4 |
5 | enum class MP_ERROR
6 | {
7 | InvalidParameter = 0x800C,
8 | };
9 |
10 | struct engine_configw_t
11 | {
12 | char _Blank[0x100];
13 | };
14 |
15 | struct UnknownStruct
16 | {
17 | DWORD data[4];
18 | };
19 |
20 | struct engine_boot_t
21 | {
22 | DWORD ClientMajorVersion;
23 | DWORD Reserved0;
24 | const wchar_t* String1;
25 | size_t Reserved3;
26 | engine_configw_t* EngineConfig;
27 | UnknownStruct* UnknownData;
28 | char Reserved1[0x20];
29 | char ProductId_0[0x10];
30 | char Reserved2[0x1C];
31 | char ProductId_1[0x10];
32 | char Reserved4[0x2C];
33 | void* DynamicConfig;
34 | char _Blank[0x100];
35 | };
36 |
37 | struct StreamBufferDescriptor
38 | {
39 | void* UserData;
40 | size_t (__fastcall *Read_cb)(StreamBufferDescriptor*, size_t, BYTE*, size_t, size_t *);
41 | size_t (__fastcall *Write_cb)(StreamBufferDescriptor*, size_t, void*, size_t, size_t *);
42 | size_t (__fastcall *GetSize_cb)(StreamBufferDescriptor*, size_t*);
43 | size_t (__fastcall *SetSize_cb)(StreamBufferDescriptor*, size_t);
44 | const wchar_t* (__fastcall *GetName_cb)(StreamBufferDescriptor*);
45 | size_t (__fastcall *GetAttribute_cb)(StreamBufferDescriptor*, size_t, size_t, size_t, size_t*);
46 | size_t (__fastcall *SetAttribute_cb)(StreamBufferDescriptor*);
47 |
48 | const char* filename;
49 | wchar_t* filename_w;
50 | FILE* fp;
51 | size_t file_size;
52 |
53 | StreamBufferDescriptor(const char* filename) :
54 | UserData(this),
55 | Read_cb(&StreamBufferDescriptor::Read),
56 | Write_cb(nullptr),
57 | GetSize_cb(&StreamBufferDescriptor::GetSize),
58 | SetSize_cb(nullptr),
59 | GetName_cb(&StreamBufferDescriptor::GetName),
60 | GetAttribute_cb(nullptr),
61 | SetAttribute_cb(nullptr),
62 | filename(filename),
63 | filename_w(new wchar_t[strlen(filename) + 1]),
64 | fp(nullptr),
65 | file_size(0)
66 | {
67 | fp = fopen(filename, "rb");
68 | if (!fp)
69 | {
70 | printf("[-] Could not open the sample file virus.exe!\n");
71 | return;
72 | }
73 | fseek(fp, 0, SEEK_END);
74 | file_size = ftell(fp);
75 | }
76 |
77 | ~StreamBufferDescriptor()
78 | {
79 | if (fp)
80 | fclose(fp);
81 | if (filename_w)
82 | delete[] filename_w;
83 | }
84 |
85 | private:
86 | static size_t Read(StreamBufferDescriptor* self, size_t offset, BYTE* buffer, size_t size, size_t* nsize)
87 | {
88 | fseek(self->fp, offset, SEEK_SET);
89 | *nsize = fread(buffer, 1, size, self->fp);
90 | //printf("offset => %llu, %llu bytes has read (%llu bytes wanted).\n", offset, *nsize, size);
91 | if (*nsize != size)
92 | return 6;
93 | return 0;
94 | }
95 |
96 | static size_t GetSize(StreamBufferDescriptor* self, size_t* size)
97 | {
98 | *size = self->file_size;
99 | return 0;
100 | }
101 |
102 | static const wchar_t* GetName(StreamBufferDescriptor* self)
103 | {
104 | mbstowcs(self->filename_w, self->filename, strlen(self->filename));
105 | self->filename_w[strlen(self->filename)] = 0;
106 | return self->filename_w;
107 | }
108 | };
109 |
110 | struct SCANSTRUCT
111 | {
112 | DWORD Field_0x00;
113 | DWORD Flags;
114 | const char* FileName;
115 | char VirusName[0x20];
116 | size_t Reversed[0x58];
117 | const char* FileName2;
118 | const wchar_t* FileName_WSTR;
119 | const wchar_t* FileName_WSTR2;
120 | };
121 |
122 | enum {
123 | SCAN_FILENAME = 1 << 8,
124 | SCAN_ENCRYPTED = 1 << 6,
125 | SCAN_MEMBERNAME = 1 << 7,
126 | SCAN_FILETYPE = 1 << 9,
127 | SCAN_TOPLEVEL = 1 << 18,
128 | SCAN_PACKERSTART = 1 << 19,
129 | SCAN_PACKEREND = 1 << 12,
130 | SCAN_ISARCHIVE = 1 << 16,
131 | SCAN_VIRUSFOUND = 1 << 27,
132 | SCAN_CORRUPT = 1 << 13,
133 | SCAN_UNKNOWN = 1 << 15, // I dunno what this means
134 | };
135 |
136 | struct ScanReply
137 | {
138 | DWORD (*ScanCallback_ptr)(SCANSTRUCT*);
139 | size_t R[2];
140 | DWORD Flags = 0x7fffffff; // no idea for this.
141 |
142 | ScanReply() : ScanCallback_ptr(&ScanCallback), R{0}
143 | {}
144 |
145 | static DWORD ScanCallback(SCANSTRUCT* data)
146 | {
147 | if ((data->Flags & SCAN_VIRUSFOUND) || data->VirusName[0] != 0)
148 | {
149 | printf(" [!][%s] Flags=%lx, Virus found: %s\n", data->FileName, data->Flags, data->VirusName);
150 | }
151 | return 0;
152 | }
153 | };
154 |
155 | /* Placeholder */
156 | struct UfsClientRequest
157 | {
158 | };
159 |
160 | /*
161 | struct UfsScanBufferCmd
162 | {
163 | UfsClientRequest* ufs_client_request;
164 |
165 | virtual void Execute() {}
166 | virtual void OnComplete(UfsClientRequest&) {}
167 | };
168 | */
169 |
170 | /*
171 | Size of StreamBufferDescriptor must be 32 bytes.
172 | */
173 | struct StreamBufferScanData
174 | {
175 | StreamBufferDescriptor* buffer;
176 | ScanReply* reply;
177 | size_t Field_0x16;
178 | UfsClientRequest* ufs_client_request;
179 |
180 | explicit StreamBufferScanData(const char* filename):
181 | Field_0x16(0),
182 | ufs_client_request(nullptr)
183 | {
184 | buffer = new StreamBufferDescriptor(filename);
185 | reply = new ScanReply{};
186 | }
187 |
188 | ~StreamBufferScanData()
189 | {
190 | delete buffer;
191 | delete reply;
192 | }
193 | };
194 |
195 | class MpEngine
196 | {
197 | static constexpr DWORD MAJOR_VERSION = 0x8E00;
198 |
199 | using rsignal_func_t = unsigned int (*)(rsignal_code, void*, DWORD);
200 |
201 | public:
202 | MpEngine()
203 | {
204 | engine_handle_ = LoadLibraryA("defender\\MpEngine.dll");
205 | if (!engine_handle_)
206 | {
207 | printf("[-] Failed to load MpEngine.dll: 0x%lx\n", GetLastError());
208 | return;
209 | }
210 |
211 | rsignal_ = reinterpret_cast(GetProcAddress(engine_handle_, "rsignal"));
212 | if (!rsignal_)
213 | {
214 | printf("[-] Failed to get address of function rsignal!\n");
215 | return;
216 | }
217 | }
218 |
219 | bool boot()
220 | {
221 | engine_boot_t boot_params{};
222 | engine_configw_t config{};
223 | UnknownStruct unk1{};
224 | boot_params.ClientMajorVersion = MAJOR_VERSION;
225 | boot_params.String1 = L"defender";
226 | boot_params.EngineConfig = &config;
227 | boot_params.UnknownData = &unk1;
228 |
229 | auto result = rsignal_(rsignal_code::RSIG_BOOTENGINE,
230 | reinterpret_cast(&boot_params), 0xE8);
231 | if (result)
232 | {
233 | printf("Failed to start mpengine: 0x%lx\n", result);
234 | return false;
235 | }
236 | return true;
237 | }
238 |
239 | bool scan(const char* filename)
240 | {
241 | StreamBufferScanData scan_data(filename);
242 |
243 | auto result = rsignal_(rsignal_code::RSIG_SCAN_STREAMBUFFER, &scan_data, sizeof(scan_data));
244 | if (result)
245 | {
246 | printf("[-] Failed to perform scanning: 0x%lx\n", result);
247 | return false;
248 | }
249 | return true;
250 | }
251 |
252 | bool is_ready() const noexcept { return rsignal_ != nullptr; }
253 |
254 | private:
255 | HMODULE engine_handle_;
256 | rsignal_func_t rsignal_;
257 | };
258 |
259 | int main(int argc, char** argv)
260 | {
261 | MpEngine engine;
262 |
263 | if (argc < 2)
264 | {
265 | printf("Usage: %s [file 2] [file 3] [...]\n", argv[0]);
266 | return 1;
267 | }
268 |
269 | __try
270 | {
271 | printf("Preparing defender engine...\n");
272 | if (engine.is_ready() && engine.boot())
273 | {
274 | for (int i = 1; i < argc; ++i)
275 | {
276 | printf("Scanning %s...\n", argv[i]);
277 | engine.scan(argv[i]);
278 | }
279 | printf("Completed.\n");
280 | return 0;
281 | }
282 | }
283 | __except(1)
284 | {
285 | printf("Exception: %lx\n", GetExceptionCode());
286 | return 5;
287 | }
288 |
289 | return 5;
290 | }
291 |
--------------------------------------------------------------------------------