├── .hgignore
├── LICENSE.txt
├── README.txt
├── ROADMAP.txt
├── TODO.txt
├── doc
├── protocol.rst
└── readme.rst
├── misc
└── download.rb
├── samples
├── setenv.sh
└── virtdbg-ui.rb
└── src
├── amd64
└── amd64.asm
├── dirs
├── loader
├── Makefile
├── loader.c
└── sources
├── make.bat
├── metasm
├── factorize-headers.rb
├── inc
│ ├── forensic1394.h
│ ├── ntkrnlmp.pdb_30092be745b24fe2a311a936e7b7486f2.h
│ ├── ntoskrnl.exe_F8E2A8B5C9B74BF4A6E4A48F18009994.h
│ ├── virtdbg.h
│ └── wdbgexts.h
├── virtdbg.rb
└── virtdbg
│ ├── forensic1394.rb
│ ├── main.rb
│ ├── system.rb
│ ├── util.rb
│ └── virtdbg.rb
└── virtdbg
├── Makefile
├── amd64.h
├── debug.c
├── debug.h
├── driver.c
├── driver.h
├── log.c
├── log.h
├── mem.c
├── mem.h
├── misc.h
├── protocol.c
├── protocol.h
├── snprintf.c
├── snprintf.h
├── sources
├── virtdbg.c
├── virtdbg.h
├── vmx.c
└── vmx.h
/.hgignore:
--------------------------------------------------------------------------------
1 | syntax: glob
2 | *.pyc
3 | *.pdb
4 |
5 | syntax: regexp
6 | ^src/.*/objchk_.*$
7 | ^src/.*/objfre_.*$
8 | ^src/buildchk.*$
9 | ^build/.*$
10 | ^ext/.*$
11 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | README
2 | ======
3 |
4 | Virtdbg is a POC of a kernel debugger taking advantage of hardware virtualization technology.
5 |
6 | See ./doc directory.
7 |
8 |
--------------------------------------------------------------------------------
/ROADMAP.txt:
--------------------------------------------------------------------------------
1 | ROADMAP
2 | =======
3 |
4 | - loader.py script (./loader.py [vmx.sys])
5 | - find a location for CONTROL_AREA
6 |
7 | - VMCS reconfiguration (pour catcher les exceptions)
8 | - handle processor exceptions (div by 0, etc)
9 | - cpu emulation for memory breakpoints ?
10 | - memory virtualization or buffer relocation (ptes direct manipulation)
11 | - virtualization of dr registers and debug msrs
12 | - ida debug stub ?
13 |
14 |
15 | 0.1
16 | ---
17 |
18 | - initial release
19 |
20 |
21 | 0.2
22 | ---
23 |
24 | - x86 support
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/TODO.txt:
--------------------------------------------------------------------------------
1 | TODO
2 | ====
3 |
4 | - handle firewire write in metasm client
5 | - add support for symbols
6 | - how to load kernel symbols ? a .map extension ?
7 | - need a version packet
8 | - remove ack and reset packet
9 | - need a FORWARD event for exception
10 | - need a EVENT struct inside EXCEPTION
11 | - changing on the fly VMCS configuration
12 | - include "config.h" in hypervisor
13 |
14 |
--------------------------------------------------------------------------------
/doc/protocol.rst:
--------------------------------------------------------------------------------
1 | Protocol
2 | ========
3 |
4 |
--------------------------------------------------------------------------------
/doc/readme.rst:
--------------------------------------------------------------------------------
1 | README
2 | ======
3 |
4 | The purpose of Virtdbg is to implement a kernel debugger
5 | using the hardware virtualization technology provided by Intel (VT-x).
6 | This project is born because when it comes to Windows 7 x64, the available
7 | kernel debuggers tend to be very limited.
8 |
9 | We have WinDbg which is very good but need cooperation of the OS. We can't use
10 | it in order to debugging protected parts of the operating system like PatchGuard
11 | for example. Microsoft doesn't allow it.
12 |
13 | The other kernel debuggers are local debuggers like SoftICE, Syser or HyperDbg
14 | (which uses the same approach). I made the choice of not using a local debugger
15 | because I find that they are difficult to extend and to script.
16 |
17 | Disclaimer
18 | ----------
19 |
20 | VirtDbg is in very alpha state. So I decline all responsabilities if your
21 | computer bluescreened ;) However I will be happy if you give it a try.
22 | It is under heavy development so expect a lot of changes quickly.
23 |
24 | Features
25 | --------
26 |
27 | TBW
28 |
29 | Dependencies
30 | ------------
31 |
32 | - Microsoft WDK for compiling virtdbg driver.
33 | - metasm (http://metasm.cr0.org) for the client side (gui and heavy treatments).
34 | - libforensic1394 (https://freddie.witherden.org/tools/libforensic1394/) for handling DMA communications
35 | - FireWire cable for communication between target and client.
36 |
37 |
38 | Limitations
39 | -----------
40 |
41 | - The hypervisor is not currently signed so you need to boot in testsigning mode
42 | to load it or wait for the "dma loader".
43 | - The "dma loader" is not present in the repository for the moment because
44 | I need to port some code in ruby. For the interested persons it allows to load
45 | the virtdbg driver directly with DMA access (no need to reboot and no need for
46 | a signed driver).
47 | - Only support VT-x extension. For the persons using VT-d you need to disable it
48 | in the BIOS or the hypervisor won't load.
49 | - You will need to run Linux or MacOSX to be able to control the hypervisor
50 | because of libforensic1394.
51 |
52 |
53 | Known bugs
54 | ----------
55 |
56 | - Sometimes a bluescreen happens when queuing DPCS. The bugcheck says
57 | "CLOCK_WATCHDOG_TIMEOUT (101)". I need to debug this...
58 |
59 |
60 | Quickstart
61 | ----------
62 |
63 | Building
64 | ~~~~~~~~
65 |
66 | $ cd src/virtdbg
67 | $ make
68 |
69 |
70 | Usage
71 | ~~~~~
72 |
73 | First you must load the driver into the targeted system. To do that you can use
74 | the loader available in the src/loader directory. It is very basic but it gets
75 | the job done.
76 |
77 | $ loader.exe [path to virtdbg.sys]
78 |
79 | Then you need to connect a FireWire cable between the machines.
80 |
81 | Last you launch the client gui (which uses the metasm framework).
82 |
83 | $ cd samples/
84 | $ ruby virtdbg-ui.rb
85 |
86 | The gui is very "softice"-like so it will be really familiar to some persons.
87 |
88 |
--------------------------------------------------------------------------------
/misc/download.rb:
--------------------------------------------------------------------------------
1 | require 'net/http'
2 |
3 | server = "msdl.microsoft.com"
4 | pdb = "ntkrnlmp"
5 | guid = "30092be745b24fe2a311a936e7b7486f2"
6 | uri = "/download/symbols/#{pdb}.pdb/#{guid}/#{pdb}.pd_"
7 | dest = "#{pdb}.pd_"
8 |
9 | puts uri
10 |
11 | Net::HTTP.start(server) { |http|
12 | headers = {"User-Agent" => "Microsoft-Symbol-Server/6.6.0007.5"}
13 | resp = http.get(uri, headers)
14 | open(dest, "wb") { |file|
15 | file.write(resp.body)
16 | }
17 | }
18 | puts "Yay!!"
19 |
20 |
--------------------------------------------------------------------------------
/samples/setenv.sh:
--------------------------------------------------------------------------------
1 | export RUBYLIB=../ext/metasm:../src/metasm/
2 | export LD_LIBRARY_PATH=/usr/local/lib
3 |
4 |
--------------------------------------------------------------------------------
/samples/virtdbg-ui.rb:
--------------------------------------------------------------------------------
1 | # This file is part of Virtdbg
2 | # Copyright (C) 2010-2011 Damien AUMAITRE
3 | #
4 | # Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | require 'metasm'
8 | require 'virtdbg'
9 | require 'optparse'
10 |
11 | $VERBOSE = false
12 |
13 | # parse arguments
14 | opts = { :device => 0 }
15 |
16 | OptionParser.new { |opt|
17 | opt.banner = 'Usage: virtdbg.rb [options]'
18 | opt.on('--list-devices', 'list FireWire devices') { opts[:list] = true }
19 | opt.on('--device [device]', 'select FireWire device') { |h| opts[:device] = h.to_i }
20 | opt.on('-v', '--verbose') { $VERBOSE = true } # default
21 | opt.on('--debug') { $DEBUG = $VERBOSE = true }
22 | }.parse!(ARGV)
23 |
24 | def init_1394(device)
25 | bus = VirtDbg::Bus.new()
26 | bus.enable_sbp2
27 | puts "waiting for dma access..."
28 | sleep 5
29 | devices = bus.devices
30 | dev = devices[device]
31 | if not dev
32 | puts "error: requested device not found"
33 | return nil
34 | end
35 | dev.open
36 | mem = VirtDbg::FireWireMem.new(dev)
37 | puts "testing physical memory access..."
38 | puts mem.hexdump(0x8000, 0X100)
39 | mem
40 | end
41 |
42 | mem = init_1394(opts[:device])
43 | impl = VirtDbg::VirtDbgImpl.new(mem)
44 | impl.setup
45 | dbg = VirtDbg::VirtDbg.new(impl)
46 | w = Metasm::Gui::DbgWindow.new(dbg, 'virtdbg')
47 | Metasm::Gui.main
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/amd64/amd64.asm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/upring/virtdbg/38d6e354c3a295f6b5070ccd3d996eae6aa476e1/src/amd64/amd64.asm
--------------------------------------------------------------------------------
/src/dirs:
--------------------------------------------------------------------------------
1 | DIRS = amd64 \
2 | virtdbg \
3 | loader
4 |
5 |
--------------------------------------------------------------------------------
/src/loader/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
3 | # file to this component. This file merely indirects to the real make file
4 | # that is shared by all the components of NT OS/2
5 | #
6 | ! INCLUDE $(NTMAKEENV)\makefile.def
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/loader/loader.c:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 |
6 |
7 | void PrintError()
8 | {
9 | DWORD dw;
10 | LPVOID lpMsg;
11 | dw = GetLastError();
12 |
13 | FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
14 | NULL,
15 | dw,
16 | MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
17 | (char *) &lpMsg,
18 | 0,
19 | NULL);
20 |
21 | printf("error 0x%08x:%s\n", dw, (char*)lpMsg);
22 | }
23 |
24 |
25 | int _cdecl main(int argc, char **argv)
26 | {
27 | HANDLE hSCManager;
28 | HANDLE hService;
29 | SERVICE_STATUS ss;
30 | BOOL bStatus;
31 | char buffer[4096];
32 |
33 | if (argc != 2)
34 | {
35 | printf("Usage: %s \n", argv[0]);
36 | return 0;
37 | }
38 |
39 | bStatus = GetFullPathNameA(argv[1], 4096, buffer, NULL);
40 |
41 | if (bStatus == 0)
42 | {
43 | PrintError();
44 | return -1;
45 | }
46 |
47 | hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
48 |
49 | if (hSCManager == NULL)
50 | {
51 | printf("Can't open SCManager\n");
52 | PrintError();
53 | return -1;
54 | }
55 |
56 | printf("Loading driver ...\n");
57 |
58 | printf("Creating service ...\n");
59 |
60 | hService = CreateServiceA(hSCManager, "Virtdbg",
61 | "VirtDbg driver",
62 | SERVICE_START | DELETE | SERVICE_STOP,
63 | SERVICE_KERNEL_DRIVER,
64 | SERVICE_DEMAND_START,
65 | SERVICE_ERROR_NORMAL,
66 | buffer,
67 | NULL, NULL, NULL, NULL, NULL);
68 |
69 | if (hService == NULL)
70 | {
71 | printf("Can't create service, maybe service already created\n");
72 | PrintError();
73 | printf("Opening service...\n");
74 |
75 | hService = OpenServiceA(hSCManager, "Virtdbg",
76 | SERVICE_START | DELETE | SERVICE_STOP);
77 | if (hService == NULL)
78 | {
79 | printf("Can't open service\n");
80 | PrintError();
81 | goto err;
82 | }
83 | }
84 |
85 | printf("Starting service\n");
86 |
87 | bStatus = StartService(hService, 0, NULL);
88 |
89 | if (bStatus == 0)
90 | {
91 | printf("Can't start service\n");
92 | PrintError();
93 | goto err;
94 | }
95 |
96 | printf("Press a key to close service\n");
97 | getchar();
98 |
99 | bStatus = ControlService(hService, SERVICE_CONTROL_STOP, &ss);
100 |
101 | if (bStatus == 0)
102 | {
103 | printf("Can't stop service\n");
104 | PrintError();
105 | goto err;
106 | }
107 |
108 | err:
109 | DeleteService(hService);
110 | CloseServiceHandle(hService);
111 | CloseServiceHandle(hSCManager);
112 |
113 | return 0;
114 | }
115 |
--------------------------------------------------------------------------------
/src/loader/sources:
--------------------------------------------------------------------------------
1 | TARGETNAME=loader
2 | TARGETPATH=..\..\build\loader
3 | TARGETTYPE=PROGRAM
4 | UMTYPE=console
5 | USE_LIBCMT=1
6 |
7 | SOURCES=loader.c
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/make.bat:
--------------------------------------------------------------------------------
1 | build -czgw
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/metasm/factorize-headers.rb:
--------------------------------------------------------------------------------
1 | # This file is part of Metasm, the Ruby assembly manipulation suite
2 | # Copyright (C) 2006-2009 Yoann GUILLOT
3 | #
4 | # Licence is LGPL, see LICENCE in the top-level directory
5 |
6 | #
7 | # this exemple illustrates the use of the cparser/preprocessor #factorize functionnality:
8 | # we write some code using standard headers, and the factorize call on CParser
9 | # gives us back the macro/C definitions that we use in our code, so that we can
10 | # get rid of the header
11 | # Argument: C file to factorize, [path to visual studio installation]
12 | # with a single argument, uses GCC standard headers
13 | #
14 |
15 | require 'metasm'
16 | include Metasm
17 |
18 | abort 'target needed' if not file = ARGV.shift
19 |
20 | visualstudiopath = ARGV.shift
21 | if visualstudiopath
22 | stub = <
4 |
5 | libforensic1394 is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Lesser General Public License as
7 | published by the Free Software Foundation, either version 3 of the
8 | License, or (at your option) any later version.
9 |
10 | libforensic1394 is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with libforensic1394. If not, see
17 | .
18 | */
19 |
20 | /**
21 | * \file forensic1394.h
22 | *
23 | * \brief Main header file for libforensic1394.
24 | */
25 |
26 | /**
27 | * \mainpage libforensic1394
28 | *
29 | * The latest version of libforensic1394 can be found at:
30 | * https://freddie.witherden.org/tools/libforensic1394/
31 | *
32 | * This API gives you access to the FireWire bus of contemporary operating
33 | * systems in order to facilitate digital forensics on an attached device.
34 | * Unlike existing APIs Forensic1394 is:
35 | * - Modern; unlike existing FireWire libraries Forensic1394 supports the
36 | * new `Juju' stack introduced in Linux 2.6.22.
37 | * - Portable; with platform drivers existing for both Linux (Juju stack
38 | * only) and Mac OS X (via I/O Kit).
39 | * - Minimal; only functions required for performing digital forensics are
40 | * provided.
41 | *
42 | * By omitting features not required in forensic applications (such as
43 | * isochronous transfers) the API is both simple to use and port. For example
44 | * the memory of an attached device can be read using the following code:
45 | *
46 | * \code
47 | * forensic1394_bus *bus;
48 | * forensic1394_dev **dev;
49 | * char data[512];
50 | *
51 | * // Allocate a bus handle
52 | * bus = forensic1394_alloc();
53 | * assert(bus);
54 | *
55 | * // Enabls SBP-2; required for memory access to some systems
56 | * forensic1394_enable_sbp2(bus);
57 | *
58 | * // Give the bus time to reinitialise
59 | * sleep(2);
60 | *
61 | * // Get the devices attached to the systen
62 | * dev = forensic1394_get_devices(bus, NULL, NULL);
63 | * assert(dev);
64 | *
65 | * // Open the first device
66 | * forensic1394_open_device(dev[0]);
67 | *
68 | * // Read some memory from the device
69 | * forensic1394_read_device(dev[0], 50 * 1024 * 1024, 512, data);
70 | *
71 | * // Data now contains 512 bytes of memory starting at an offset of 50MiB
72 | *
73 | * // Close the device and destroy the bus
74 | * forensic1394_close_device(dev[0]);
75 | * forensic1394_destroy(bus);
76 | * \endcode
77 | *
78 | * \section sbp2 Enabling SBP-2
79 | * In order to gain direct memory access to certain systems, namely Windows and
80 | * GNU/Linux, it is necessary to present the target system with an SBP-2 unit
81 | * directory. This can be done by calling ::forensic1394_enable_sbp2. It is
82 | * usual for devices on the bus to take a couple of seconds to react to this
83 | * change. Therefore, client applications should ideally wait for ~2 seconds
84 | * before attempting to read or write to a device. Although there are
85 | * provisions in the SBP-2 specification to determine when a target system has
86 | * enabled the DMA filter, client-side API limitations currently prevent
87 | * libforensic1394 from leveraging this.
88 | *
89 | * \section reset Handling Bus Resets
90 | * Bus resets occur when devices are added/removed from the system or when the
91 | * configuration ROM of a device is updated. The following methods are
92 | * affected by bus resets:
93 | * - ::forensic1394_open_device
94 | * - ::forensic1394_read_device
95 | * - ::forensic1394_read_device_v
96 | * - ::forensic1394_write_device
97 | * - ::forensic1394_write_device_v
98 | *
99 | * After a bus reset calls to all of these methods will result in
100 | * #FORENSIC1394_RESULT_BUS_RESET being returned. Applications should
101 | * handle this by saving the GUIDs of any devices being accessed and then call
102 | * ::forensic1394_get_devices. Calling this will void all device handles.
103 | * The new list of devices can then be iterated through and their GUIDs
104 | * compared against saved GUIDs. The GUID of a device can be obtained by
105 | * calling ::forensic1394_get_device_guid.
106 | *
107 | * \section thread Thread Safety
108 | * libforensic1394 is thread safe at the device level with the restriction
109 | * that devices can only be accessed by the thread that opened them. This is
110 | * because some backends, namely Mac OS X/IOKit, install thread-specific
111 | * callback dispatchers upon opening a device. When using multiple threads of
112 | * execution care must be taken when calling ::forensic1394_get_devices (which
113 | * closes and destroys any open device handles). It is the responsibility of
114 | * the caller to ensure that this is safe. The process can be simplified
115 | * through the use of an \a ondestroy callback handler.
116 | *
117 | * \author Freddie Witherden
118 | */
119 |
120 | #ifndef _FORENSIC_1394_H
121 | #define _FORENSIC_1394_H
122 |
123 | #ifdef __cplusplus
124 | extern "C"
125 | {
126 | #endif
127 |
128 | #if defined(FORENSIC1394_DECL)
129 | // No op
130 | #elif defined(_MSC_VER)
131 | # define FORENSIC1394_DECL __declspec(dllexport)
132 | #elif (__GNUC__ >= 3)
133 | # define FORENSIC1394_DECL __attribute__((visibility("default")))
134 | #else
135 | # define FORENSIC1394_DECL
136 | #endif
137 |
138 | typedef long int64_t;
139 | typedef unsigned long size_t;
140 | typedef unsigned short uint16_t;
141 | typedef unsigned int uint32_t;
142 | typedef unsigned long uint64_t;
143 |
144 |
145 | /// An opaque bus handle
146 | typedef struct _forensic1394_bus forensic1394_bus;
147 |
148 | /// An opaque device handle
149 | typedef struct _forensic1394_dev forensic1394_dev;
150 |
151 | /**
152 | * \brief A request structure used for making batch read/write requests.
153 | *
154 | * For use with the batch APIs (suffixed by _v) requests allow
155 | * forensic1394 to take advantage of the asynchronous capabilities of
156 | * FireWire stacks in order to improve performance.
157 | *
158 | * \sa forensic1394_read_device_v
159 | * \sa forensic1394_write_device_v
160 | */
161 | typedef struct _forensic1394_req
162 | {
163 | /// The address to read/write
164 | uint64_t addr;
165 |
166 | /// Length of the buffer in bytes
167 | size_t len;
168 |
169 | /// Data buffer
170 | void *buf;
171 | } forensic1394_req;
172 |
173 | /**
174 | * \brief Number of uint32 elements required to store a device ROM.
175 | *
176 | * A FireWire configuration status ROM (CSR) is made up of unsigned 32-bit
177 | * integers. The maximum size of a ROM is 1024 bytes, giving 256 elements.
178 | */
179 | #define FORENSIC1394_CSR_SZ 256
180 |
181 | /**
182 | * A function to be called when a ::forensic1394_dev is about to be destroyed.
183 | * This should be passed to ::forensic1394_get_devices and will be associated
184 | * with all devices returned by the method. The callback will fire either when
185 | * the bus is destroyed via ::forensic1394_destroy or the next time that
186 | * ::forensic1394_get_devices is called (which has the implicit effect of
187 | * destroying all existing devices first).
188 | *
189 | * If user data is required it can be attached on either a per-bus or per-device
190 | * level.
191 | *
192 | * \param bus The bus owning the device.
193 | * \param dev The device being destroyed.
194 | *
195 | * \sa forensic1394_set_bus_user_data
196 | * \sa forensic1394_set_device_user_data
197 | */
198 | typedef void (*forensic1394_device_callback) (forensic1394_bus *bus,
199 | forensic1394_dev *dev);
200 |
201 | /**
202 | * \brief Possible return status codes.
203 | *
204 | * In general methods return 0 on success and a negative integer on failure.
205 | * These codes may be used to ascertain precisely why a method failed. It is
206 | * worth noting that invalid input parameters are handled with assertions as
207 | * opposed to status codes.
208 | *
209 | * \sa forensic1394_get_result_str
210 | */
211 | typedef enum
212 | {
213 | /// No errors encountered
214 | FORENSIC1394_RESULT_SUCCESS = 0,
215 | /// General, unspecified, error
216 | FORENSIC1394_RESULT_OTHER_ERROR = -1,
217 | /// A bus reset has occured
218 | FORENSIC1394_RESULT_BUS_RESET = -2,
219 | /// Permissions related error
220 | FORENSIC1394_RESULT_NO_PERM = -3,
221 | /// Device is busy
222 | FORENSIC1394_RESULT_BUSY = -4,
223 | /// General I/O error
224 | FORENSIC1394_RESULT_IO_ERROR = -5,
225 | /// Bad transfer size (normally too large)
226 | FORENSIC1394_RESULT_IO_SIZE = -6,
227 | /// I/O Timeout
228 | FORENSIC1394_RESULT_IO_TIMEOUT = -7,
229 | /// Sentinel; internal use only
230 | FORENSIC1394_RESULT_END = -8
231 | } forensic1394_result;
232 |
233 | /**
234 | * \brief Allocates a new forensic1394 handle.
235 | *
236 | * This handle can then be used to query the devices attached to the bus and to
237 | * update the configuration status ROM (CSR) of the bus.
238 | *
239 | * \return A handle to a forensic1394_bus on success, NULL otherwise.
240 | */
241 | FORENSIC1394_DECL forensic1394_bus *forensic1394_alloc(void);
242 |
243 | /**
244 | * \brief Provides an SBP-2 unit directory; required for DMA to Windows systems.
245 | *
246 | * Updates the configuration status ROM of the bus to contain an SBP-2
247 | * unit directory. This is required in order for some connected
248 | * devices to allow for direct memory access (`DMA').
249 | *
250 | * Note that this is usually a global change, affecting all FireWire
251 | * ports on the system.
252 | *
253 | * As calling this method usually results in a bus reset it is advisable to
254 | * call it as soon as a bus is available.
255 | *
256 | * \param bus The 1394 bus to add the SBP-2 unit directory to.
257 | * \return A result status code.
258 | */
259 | FORENSIC1394_DECL forensic1394_result
260 | forensic1394_enable_sbp2(forensic1394_bus *bus);
261 |
262 | /**
263 | * \brief Gets the devices attached to the FireWire bus.
264 | *
265 | * This method scans the (foreign) devices attached to \a bus and returns a
266 | * NULL-terminated list of them.
267 | *
268 | * The out-parameter \a ndev, if not NULL, serves a dual purpose. After a call
269 | * to the function if \a *ndev is:
270 | *
271 | * - >= 0 then the call was successful and it contains the number of devices
272 | * attached to the system, which may be 0 if no devices are attached.
273 | * - < 0 then the call was not successful and it contains the appropriate
274 | * ::forensic1394_result error code.
275 | *
276 | * Getting the attached devices is a destructive process; voiding any existing
277 | * device handles. To compensate for this the \a ondestroy callback is
278 | * provided. This argument, if not NULL, will be called when the new device
279 | * list is destroyed, usually as a result of a subsequent call to
280 | * ::forensic1394_get_devices or a call to ::forensic1394_destroy. The
281 | * function is called for each device in the list.
282 | *
283 | * \warning Calling this method will invalidate all active device handles.
284 | *
285 | * \param bus The bus to get the devices for.
286 | * \param[out] ndev The number of devices found; NULL is acceptable.
287 | * \param[in] ondestroy Function to be called when the returned device list is
288 | * destroyed; NULL for no callback.
289 | * \return A NULL-terminated list of devices.
290 | *
291 | * \sa forensic1394_device_callback
292 | * \sa forensic1394_result
293 | */
294 | FORENSIC1394_DECL forensic1394_dev **
295 | forensic1394_get_devices(forensic1394_bus *bus,
296 | int *ndev,
297 | forensic1394_device_callback ondestroy);
298 |
299 | /**
300 | * \brief Destroys a bus handle.
301 | *
302 | * Releases all of the memory associated with the handle, closing any open
303 | * devices. After a call to this method all forensic1394 device handles are
304 | * invalidated.
305 | *
306 | * \param bus The forensic1394_bus to destroy.
307 | */
308 | FORENSIC1394_DECL void
309 | forensic1394_destroy(forensic1394_bus *bus);
310 |
311 | /**
312 | * \brief Fetches the user data for \a bus.
313 | *
314 | * Returns the user data for \a bus. If ::forensic1394_set_bus_user_data is
315 | * yet to be called on the bus the result is undefined.
316 | *
317 | * \param bus The bus.
318 | * \return The user data associated with the bus.
319 | *
320 | * \sa forensic1394_set_bus_user_data
321 | */
322 | FORENSIC1394_DECL void *
323 | forensic1394_get_bus_user_data(forensic1394_bus *bus);
324 |
325 | /**
326 | * \brief Sets the user data for the bus.
327 | *
328 | * \param bus The bus.
329 | * \param[in] u The user data to set.
330 | *
331 | * \sa forensic1394_get_bus_user_data
332 | */
333 | FORENSIC1394_DECL void
334 | forensic1394_set_bus_user_data(forensic1394_bus *bus, void *u);
335 |
336 | /**
337 | * \brief Opens the device \a dev for reading/writing.
338 | *
339 | * It is necessary to open a device before attempting to read/write from it.
340 | *
341 | * \param dev The device to open.
342 | * \return A result status code.
343 | *
344 | * \sa forensic1394_close_device
345 | */
346 | FORENSIC1394_DECL forensic1394_result
347 | forensic1394_open_device(forensic1394_dev *dev);
348 |
349 | /**
350 | * \brief Closes the device \a dev.
351 | *
352 | * This can only be called on an open device.
353 | *
354 | * \param dev The device to close.
355 | */
356 | FORENSIC1394_DECL void
357 | forensic1394_close_device(forensic1394_dev *dev);
358 |
359 | /**
360 | * \brief Checks if a device is open or not.
361 | *
362 | * \param dev The FireWire device.
363 | * \return Non-zero if the device is open; 0 if it is closed.
364 | */
365 | FORENSIC1394_DECL int
366 | forensic1394_is_device_open(forensic1394_dev *dev);
367 |
368 | /**
369 | * \brief Reads \a len bytes from \a dev starting at \a addr into \a buf.
370 | *
371 | * Performs a blocking (synchronous) read on the device \a dev, starting at the
372 | * address \a addr and attempting to read \a len bytes. The resulting bytes
373 | * are copied into \a buf.
374 | *
375 | * It is worth noting that many devices impose a limit on the maximum transfer
376 | * size. This limit can be obtained by calling
377 | * ::forensic1394_get_device_request_size and is usually 2048 bytes in size.
378 | *
379 | * This method is a convenience wrapper around ::forensic1394_read_device_v.
380 | *
381 | * \param dev The device to read from.
382 | * \param addr The memory address to start reading from.
383 | * \param len The number of bytes to read.
384 | * \param[out] buf The buffer to copy the read bytes into; must be at least
385 | * \a len bytes in size.
386 | * \return A result status code.
387 | *
388 | * \sa forensic1394_get_device_request_size
389 | * \sa forensic1394_read_device_v
390 | */
391 | FORENSIC1394_DECL forensic1394_result
392 | forensic1394_read_device(forensic1394_dev *dev,
393 | uint64_t addr,
394 | size_t len,
395 | void *buf);
396 |
397 | /**
398 | * \brief Reads each request specified in \a req from \a dev asynchronously.
399 | *
400 | * Vectorised, scatter input, read method. By issuing requests asynchronously
401 | * this function is often able to offer better performance than a series of
402 | * ::forensic1394_read_device calls. The performance gains, if any, depend
403 | * heavily on the capabilities of the backend.
404 | *
405 | * Each request must be no larger than ::forensic1394_get_device_request_size
406 | * bytes. If any of the data buffers in \a req overlap then the behaviour
407 | * is undefined.
408 | *
409 | * The method will return early should one of the requests fail. It is not
410 | * currently possible to determine which request caused the error.
411 | *
412 | * \param dev The device to read from.
413 | * \param req The read requests to service.
414 | * \param nreq The number of requests in \a req.
415 | * \return A result status code.
416 | */
417 | FORENSIC1394_DECL forensic1394_result
418 | forensic1394_read_device_v(forensic1394_dev *dev,
419 | forensic1394_req *req,
420 | size_t nreq);
421 |
422 | /**
423 | * \brief Writes \a len bytes from \a buf to \a dev starting at \a addr.
424 | *
425 | * Performs a blocking (synchronous) write on the device \a dev attempting to
426 | * copy \a len bytes from \a buf to the device address \a addr. See
427 | * the documentation for ::forensic1394_read_device for a discussion on the
428 | * maximum transfer size.
429 | *
430 | * This method is a convenience wrapper around ::forensic1394_write_device_v.
431 | *
432 | * \param dev The device to write to.
433 | * \param addr The memory address to start writing to.
434 | * \param len The number of bytes to write.
435 | * \param[in] buf The buffer to write.
436 | * \return A result status code.
437 | *
438 | * \a forensic1394_read_device
439 | */
440 | FORENSIC1394_DECL forensic1394_result
441 | forensic1394_write_device(forensic1394_dev *dev,
442 | uint64_t addr,
443 | size_t len,
444 | void *buf);
445 |
446 | /**
447 | * \brief Writes each request specified in \a req to \a dev asynchronously.
448 | *
449 | * The vectorised, gather output, write method. Depending on the backend this
450 | * method may issue the requests in \a req asynchronously in order to improve
451 | * performance. See ::forensic1394_read_device_v for further discussion.
452 | *
453 | * \param dev The device to write to.
454 | * \param[in] req The write requests to service.
455 | * \param nreq The number of requests in \a req.
456 | * \return A result status code.
457 | */
458 | FORENSIC1394_DECL forensic1394_result
459 | forensic1394_write_device_v(forensic1394_dev *dev,
460 | const forensic1394_req *req,
461 | size_t nreq);
462 |
463 | /**
464 | * \brief Copies the configuration ROM for the device \a dev into \a rom.
465 | *
466 | * Fetches the configuration status ROM (CSR) for the device and copies it
467 | * into \a rom. This is assumed to be of at least #FORENSIC1394_CSR_SZ
468 | * elements in size. Any unused space will be filled with zeros.
469 | *
470 | * \param dev The device.
471 | * \param rom The array to copy the CSR into.
472 | */
473 | FORENSIC1394_DECL void
474 | forensic1394_get_device_csr(forensic1394_dev *dev,
475 | uint32_t *rom);
476 |
477 | /**
478 | * \brief Returns the node ID of the device.
479 | *
480 | * It is important to note that this value does not remain constant across bus
481 | * resets and is hence unsuitable for device identification.
482 | *
483 | * \param dev The device.
484 | * \return The node ID of the device.
485 | */
486 | FORENSIC1394_DECL uint16_t
487 | forensic1394_get_device_nodeid(forensic1394_dev *dev);
488 |
489 | /**
490 | * \brief Returns the GUID of the device.
491 | *
492 | * This is a 48-bit value, similar to a MAC address, that uniquely identifies
493 | * a FireWire device.
494 | *
495 | * \param dev The device.
496 | * \return The GUID of the device.
497 | */
498 | FORENSIC1394_DECL int64_t
499 | forensic1394_get_device_guid(forensic1394_dev *dev);
500 |
501 | /**
502 | * \brief Returns the product name of the device, if any.
503 | *
504 | * Should the property not exist for the device an empty string ("") is
505 | * returned. The string is guaranteed to remain valid for the lifetime of the
506 | * device.
507 | *
508 | * \param dev The device.
509 | * \return The product name of the device, if any.
510 | */
511 | FORENSIC1394_DECL const char *
512 | forensic1394_get_device_product_name(forensic1394_dev *dev);
513 |
514 | /**
515 | * \brief Returns the product ID of the device, if any.
516 | *
517 | * Should the property not exist then 0 is returned.
518 | *
519 | * \param dev The device.
520 | * \return The product ID of the device, or 0 if it is not defined.
521 | */
522 | FORENSIC1394_DECL int
523 | forensic1394_get_device_product_id(forensic1394_dev *dev);
524 |
525 | /**
526 | * \brief Returns the vendor name of the device, if any.
527 | *
528 | * Should the property not exist for the device an empty string ("") is
529 | * returned. The string is guaranteed to remain valid for the lifetime of the
530 | * device.
531 | *
532 | * \param dev The device.
533 | * \return The vendor name of the device, if any.
534 | */
535 | FORENSIC1394_DECL const char *
536 | forensic1394_get_device_vendor_name(forensic1394_dev *dev);
537 |
538 | /**
539 | * \brief Returns the vendor ID of the device, if any.
540 | *
541 | * Should the property not exist then 0 is returned.
542 | *
543 | * \param dev The device.
544 | * \return The vendor ID of the device, or 0 if it is not defined.
545 | */
546 | FORENSIC1394_DECL int
547 | forensic1394_get_device_vendor_id(forensic1394_dev *dev);
548 |
549 | /**
550 | * \brief Returns the maximum request size supported by the device.
551 | *
552 | * Parses the configuration status ROM for the device and extracts the maximum
553 | * supported request size (usually 2048 bytes). This value should be taken as
554 | * an upper-bound for the length of read/write calls. If a size can not be
555 | * found in the CSR then 512 bytes will be returned.
556 | *
557 | * The returned size is guaranteed to be a positive power of two.
558 | *
559 | * \param dev The device.
560 | * \return The maximum request size in bytes.
561 | */
562 | FORENSIC1394_DECL int
563 | forensic1394_get_device_request_size(forensic1394_dev *dev);
564 |
565 | /**
566 | * \brief Fetches the user data for the device \a dev.
567 | *
568 | * If ::forensic1394_set_device_user_data is yet to be called on the device the
569 | * result is undefined.
570 | *
571 | * \param dev The device.
572 | * \return The user data associated with the device.
573 | *
574 | * \sa forensic1394_set_device_user_data
575 | */
576 | FORENSIC1394_DECL void *
577 | forensic1394_get_device_user_data(forensic1394_dev *dev);
578 |
579 | /**
580 | * \brief Sets the user data for the device \a dev to \a u.
581 | *
582 | * \param dev The device.
583 | * \param[in] u The user data to set.
584 | *
585 | * \sa forensic1394_get_device_user_data
586 | */
587 | FORENSIC1394_DECL void
588 | forensic1394_set_device_user_data(forensic1394_dev *dev, void *u);
589 |
590 | /**
591 | * \brief Converts a return status code to a string.
592 | *
593 | * Returns a textual representation of the return status code \a result. The
594 | * string returned is guaranteed to be valid for the lifetime of the program.
595 | *
596 | * In the event of an invalid code NULL is returned.
597 | *
598 | * \param r The return status code.
599 | * \return A description of the error code on success; NULL otherwise.
600 | */
601 | FORENSIC1394_DECL const char *
602 | forensic1394_get_result_str(forensic1394_result r);
603 |
604 | #ifdef __cplusplus
605 | }
606 | #endif
607 |
608 | #endif // _FORENSIC_1394_H
609 |
610 |
611 |
612 |
--------------------------------------------------------------------------------
/src/metasm/inc/virtdbg.h:
--------------------------------------------------------------------------------
1 |
2 | typedef unsigned long ULONG;
3 | typedef ULONG *PULONG;
4 | typedef unsigned short USHORT;
5 | typedef USHORT *PUSHORT;
6 | typedef unsigned char UCHAR;
7 | typedef UCHAR *PUCHAR;
8 | typedef char *PSZ;
9 |
10 | typedef char CHAR;
11 | typedef short SHORT;
12 | typedef long LONG;
13 | typedef int INT;
14 | typedef SHORT *PSHORT; // winnt
15 | typedef LONG *PLONG; // winnt
16 |
17 | typedef __int64 LONGLONG;
18 | typedef unsigned __int64 ULONGLONG;
19 | typedef void *PVOID;
20 |
21 | typedef signed char INT8, *PINT8;
22 | typedef signed short INT16, *PINT16;
23 | typedef signed int INT32, *PINT32;
24 | typedef signed __int64 INT64, *PINT64;
25 | typedef unsigned char UINT8, *PUINT8;
26 | typedef unsigned short UINT16, *PUINT16;
27 | typedef unsigned int UINT32, *PUINT32;
28 | typedef unsigned __int64 UINT64, *PUINT64;
29 |
30 | typedef signed int LONG32, *PLONG32;
31 | typedef unsigned int ULONG32, *PULONG32;
32 |
33 | typedef __int64 LONG64, *PLONG64;
34 | typedef unsigned __int64 ULONG64, *PULONG64;
35 | typedef unsigned __int64 DWORD64, *PDWORD64;
36 |
37 | typedef struct _LARGE_INTEGER_unnamed1 {
38 | ULONG32 LowPart;
39 | LONG32 HighPart;
40 | } LARGE_INTEGER_unnamed1;
41 |
42 | typedef union _LARGE_INTEGER {
43 | LARGE_INTEGER_unnamed1 u;
44 | LONG64 QuadPart;
45 | } LARGE_INTEGER;
46 |
47 | typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
48 |
49 | typedef struct _VIRTDBG_CONTROL_AREA
50 | {
51 | ULONG32 Magic1;
52 | ULONG32 Magic2;
53 | PHYSICAL_ADDRESS SendArea;
54 | PHYSICAL_ADDRESS RecvArea;
55 | PVOID KernelBase;
56 | PVOID DebuggerData;
57 | PHYSICAL_ADDRESS LogBuffer;
58 | ULONG32 ClientId;
59 | ULONG32 ServerId;
60 | ULONG32 LastClientId;
61 | ULONG32 LastServerId;
62 | LONG State;
63 | } VIRTDBG_CONTROL_AREA, *PVIRTDBG_CONTROL_AREA;
64 |
65 | #define CONTROL_AREA_SIZE 0x1000
66 | #define CONTROL_AREA_MAGIC1 0xbabebabe
67 | #define CONTROL_AREA_MAGIC2 0xcafecafe
68 |
69 | typedef struct _PACKET_HEADER {
70 | ULONG32 Magic;
71 | ULONG32 Type;
72 | ULONG32 Size;
73 | ULONG32 Id;
74 | ULONG32 ClientId;
75 | ULONG32 Checksum;
76 | } PACKET_HEADER, *PPACKET_HEADER;
77 |
78 | typedef struct _BREAKIN_PACKET {
79 | ULONG64 Cr3;
80 | } BREAKIN_PACKET, *PBREAKIN_PACKET;
81 |
82 | #define CONTINUE_STATUS_SINGLE_STEP 0x1
83 | #define CONTINUE_STATUS_UNLOAD 0x2
84 | #define CONTINUE_STATUS_CONTINUE 0x3
85 |
86 | typedef struct _CONTINUE_PACKET {
87 | ULONG32 Status;
88 | } CONTINUE_PACKET, *PCONTINUE_PACKET;
89 |
90 | typedef struct _SOFTWARE_BREAKPOINT_PACKET {
91 | ULONG64 Address;
92 | } SOFTWARE_BREAKPOINT_PACKET, *PSOFTWARE_BREAKPOINT_PACKET;
93 |
94 | typedef struct _HARDWARE_BREAKPOINT_PACKET {
95 | ULONG64 Address;
96 | } HARDWARE_BREAKPOINT_PACKET, *PHARDWARE_BREAKPOINT_PACKET;
97 |
98 | typedef struct _MEMORY_BREAKPOINT_PACKET {
99 | ULONG64 Address;
100 | } MEMORY_BREAKPOINT_PACKET, *PMEMORY_BREAKPOINT_PACKET;
101 |
102 | typedef struct _STATE_CHANGE_PACKET {
103 | ULONG32 Exception;
104 | ULONG64 Address;
105 | } STATE_CHANGE_PACKET, *PSTATE_CHANGE_PACKET;
106 |
107 | typedef struct _READ_VIRTUAL_MEMORY_PACKET {
108 | ULONG64 Address;
109 | ULONG32 Size;
110 | } READ_VIRTUAL_MEMORY_PACKET, *PREAD_VIRTUAL_MEMORY_PACKET;
111 |
112 | typedef struct _WRITE_VIRTUAL_MEMORY_PACKET {
113 | ULONG64 Address;
114 | ULONG32 Size;
115 | } WRITE_VIRTUAL_MEMORY_PACKET, *PWRITE_VIRTUAL_MEMORY_PACKET;
116 |
117 | typedef struct _READ_PHYSICAL_MEMORY_PACKET {
118 | ULONG64 Address;
119 | ULONG32 Size;
120 | } READ_PHYSICAL_MEMORY_PACKET, *PREAD_PHYSICAL_MEMORY_PACKET;
121 |
122 | typedef struct _WRITE_PHYSICAL_MEMORY_PACKET {
123 | ULONG64 Address;
124 | ULONG32 Size;
125 | } WRITE_PHYSICAL_MEMORY_PACKET, *PWRITE_PHYSICAL_MEMORY_PACKET;
126 |
127 | typedef struct _DEBUG_CONTEXT {
128 | ULONG64 rax;
129 | ULONG64 rbx;
130 | ULONG64 rcx;
131 | ULONG64 rdx;
132 | ULONG64 rsi;
133 | ULONG64 rdi;
134 | ULONG64 rbp;
135 | ULONG64 rsp;
136 | ULONG64 r8;
137 | ULONG64 r9;
138 | ULONG64 r10;
139 | ULONG64 r11;
140 | ULONG64 r12;
141 | ULONG64 r13;
142 | ULONG64 r14;
143 | ULONG64 r15;
144 | ULONG64 rip;
145 | ULONG64 rflags;
146 | ULONG64 cr0;
147 | ULONG64 cr3;
148 | ULONG64 cr4;
149 | ULONG64 cr8;
150 | ULONG64 dr0;
151 | ULONG64 dr1;
152 | ULONG64 dr2;
153 | ULONG64 dr3;
154 | ULONG64 dr6;
155 | ULONG64 dr7;
156 | USHORT cs;
157 | USHORT ds;
158 | USHORT es;
159 | USHORT fs;
160 | USHORT ss;
161 | USHORT gs;
162 | } DEBUG_CONTEXT, *PDEBUG_CONTEXT;
163 |
164 | typedef struct _GET_CONTEXT_PACKET {
165 | ULONG32 Flags;
166 | } GET_CONTEXT_PACKET, *PGET_CONTEXT_PACKET;
167 |
168 | typedef struct _SET_CONTEXT_PACKET {
169 | ULONG32 Flags;
170 | } SET_CONTEXT_PACKET, *PSET_CONTEXT_PACKET;
171 |
172 | typedef struct _MANIPULATE_STATE_PACKET {
173 | ULONG32 ApiNumber;
174 | ULONG32 Error;
175 | union {
176 | READ_VIRTUAL_MEMORY_PACKET ReadVirtualMemory;
177 | WRITE_VIRTUAL_MEMORY_PACKET WriteVirtualMemory;
178 | READ_PHYSICAL_MEMORY_PACKET ReadPhysicalMemory;
179 | WRITE_PHYSICAL_MEMORY_PACKET WritePhysicalMemory;
180 | GET_CONTEXT_PACKET GetContext;
181 | SET_CONTEXT_PACKET SetContext;
182 | } u;
183 | } MANIPULATE_STATE_PACKET, *PMANIPULATE_STATE_PACKET;
184 |
185 | #define PACKET_TYPE_RESET 1
186 | #define PACKET_TYPE_BREAKIN 2
187 | #define PACKET_TYPE_ACK 3
188 | #define PACKET_TYPE_RESEND 4
189 | #define PACKET_TYPE_STATE_CHANGE 5
190 | #define PACKET_TYPE_MANIPULATE_STATE 6
191 | #define PACKET_TYPE_CONTINUE 7
192 |
193 | #define READ_VIRTUAL_MEMORY_API 0x41
194 | #define WRITE_VIRTUAL_MEMORY_API 0x42
195 | #define GET_CONTEXT_API 0x43
196 | #define SET_CONTEXT_API 0x44
197 |
198 | #define INITIAL_ID 0x41424344
199 | #define PACKET_MAGIC 0xdeadbabe
200 |
201 | #define MAX_PACKET_SIZE 0x800
202 |
203 | #define MAX_RETRIES 0x1000000
204 | #define HEADER_SIZE sizeof(PACKET_HEADER)
205 |
206 |
207 |
--------------------------------------------------------------------------------
/src/metasm/inc/wdbgexts.h:
--------------------------------------------------------------------------------
1 | /*++
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Module Name:
6 |
7 | wdbgexts.h
8 |
9 | Abstract:
10 |
11 | This file contains the necessary prototypes and data types for a user
12 | to write a debugger extension DLL. This header file is also included
13 | by the NT debuggers (WINDBG & KD).
14 |
15 | This header file must be included after "windows.h" and "dbghelp.h".
16 |
17 | Please see the NT DDK documentation for specific information about
18 | how to write your own debugger extension DLL.
19 |
20 | Environment:
21 |
22 | Win32 only.
23 |
24 | Revision History:
25 |
26 | --*/
27 | #ifdef __cplusplus
28 | extern "C" {
29 | #endif
30 |
31 |
32 | #define VOID void
33 | #define STDCALL __stdcall
34 | #define FASTCALL __fastcall
35 | #define CDECL __cdecl
36 | #define THISCALL __thiscall
37 | #define NEAR
38 | #define FAR
39 |
40 | typedef signed char INT8;
41 | typedef signed char CHAR;
42 | typedef unsigned char UCHAR;
43 | typedef signed short INT16;
44 | typedef signed int INT32;
45 | typedef signed int BOOL;
46 | typedef signed __int64 INT64;
47 | typedef signed __int64 LONG64;
48 | typedef signed long LONG32;
49 | typedef unsigned char UINT8;
50 | typedef unsigned char BYTE;
51 | typedef unsigned short UINT16;
52 | typedef unsigned short WCHAR;
53 | typedef unsigned int UINT32;
54 | typedef unsigned __int64 UINT64;
55 | typedef unsigned __int64 ULONG64;
56 | typedef unsigned long ULONG32;
57 | typedef float FLOAT32;
58 | typedef double FLOAT64;
59 | typedef struct {unsigned short W[5];} FLOAT80;
60 | typedef struct { __int64 LowPart;__int64 HighPart;} FLOAT128;
61 | typedef double DATE;
62 | typedef signed long HRESULT;
63 | typedef union { struct {unsigned long Lo; long Hi;}; __int64 int64;} CURRENCY;
64 |
65 |
66 | typedef struct _LIST_ENTRY64 // 2 elements, 0x10 bytes (sizeof)
67 | {
68 | /*0x000*/ UINT64 Flink;
69 | /*0x008*/ UINT64 Blink;
70 | }LIST_ENTRY64, *PLIST_ENTRY64;
71 |
72 | typedef struct _DBGKD_GET_VERSION64 {
73 | UINT16 MajorVersion;
74 | UINT16 MinorVersion;
75 | UCHAR ProtocolVersion;
76 | UCHAR KdSecondaryVersion; // Cannot be 'A' for compat with dump header
77 | UINT16 Flags;
78 | UINT16 MachineType;
79 |
80 | //
81 | // Protocol command support descriptions.
82 | // These allow the debugger to automatically
83 | // adapt to different levels of command support
84 | // in different kernels.
85 | //
86 |
87 | // One beyond highest packet type understood, zero based.
88 | UCHAR MaxPacketType;
89 | // One beyond highest state change understood, zero based.
90 | UCHAR MaxStateChange;
91 | // One beyond highest state manipulate message understood, zero based.
92 | UCHAR MaxManipulate;
93 |
94 | // Kind of execution environment the kernel is running in,
95 | // such as a real machine or a simulator. Written back
96 | // by the simulation if one exists.
97 | UCHAR Simulation;
98 |
99 | UINT16 Unused[1];
100 |
101 | ULONG64 KernBase;
102 | ULONG64 PsLoadedModuleList;
103 |
104 | //
105 | // Components may register a debug data block for use by
106 | // debugger extensions. This is the address of the list head.
107 | //
108 | // There will always be an entry for the debugger.
109 | //
110 |
111 | ULONG64 DebuggerDataList;
112 |
113 | } DBGKD_GET_VERSION64, *PDBGKD_GET_VERSION64;
114 |
115 |
116 | //
117 | // This structure is used by the debugger for all targets
118 | // It is the same size as DBGKD_DATA_HEADER on all systems
119 | //
120 | typedef struct _DBGKD_DEBUG_DATA_HEADER64 {
121 |
122 | //
123 | // Link to other blocks
124 | //
125 |
126 | struct _LIST_ENTRY64 List;
127 |
128 | //
129 | // This is a unique tag to identify the owner of the block.
130 | // If your component only uses one pool tag, use it for this, too.
131 | //
132 |
133 | ULONG32 OwnerTag;
134 |
135 | //
136 | // This must be initialized to the size of the data block,
137 | // including this structure.
138 | //
139 |
140 | ULONG32 Size;
141 |
142 | } DBGKD_DEBUG_DATA_HEADER64, *PDBGKD_DEBUG_DATA_HEADER64;
143 |
144 |
145 | //
146 | // This structure is the same size on all systems. The only field
147 | // which must be translated by the debugger is Header.List.
148 | //
149 |
150 | //
151 | // DO NOT ADD OR REMOVE FIELDS FROM THE MIDDLE OF THIS STRUCTURE!!!
152 | //
153 | // If you remove a field, replace it with an "unused" placeholder.
154 | // Do not reuse fields until there has been enough time for old debuggers
155 | // and extensions to age out.
156 | //
157 | typedef struct _KDDEBUGGER_DATA64 {
158 |
159 | struct _DBGKD_DEBUG_DATA_HEADER64 Header;
160 |
161 | //
162 | // Base address of kernel image
163 | //
164 |
165 | ULONG64 KernBase;
166 |
167 | //
168 | // DbgBreakPointWithStatus is a function which takes an argument
169 | // and hits a breakpoint. This field contains the address of the
170 | // breakpoint instruction. When the debugger sees a breakpoint
171 | // at this address, it may retrieve the argument from the first
172 | // argument register, or on x86 the eax register.
173 | //
174 |
175 | ULONG64 BreakpointWithStatus; // address of breakpoint
176 |
177 | //
178 | // Address of the saved context record during a bugcheck
179 | //
180 | // N.B. This is an automatic in KeBugcheckEx's frame, and
181 | // is only valid after a bugcheck.
182 | //
183 |
184 | ULONG64 SavedContext;
185 |
186 | //
187 | // help for walking stacks with user callbacks:
188 | //
189 |
190 | //
191 | // The address of the thread structure is provided in the
192 | // WAIT_STATE_CHANGE packet. This is the offset from the base of
193 | // the thread structure to the pointer to the kernel stack frame
194 | // for the currently active usermode callback.
195 | //
196 |
197 | UINT16 ThCallbackStack; // offset in thread data
198 |
199 | //
200 | // these values are offsets into that frame:
201 | //
202 |
203 | UINT16 NextCallback; // saved pointer to next callback frame
204 | UINT16 FramePointer; // saved frame pointer
205 |
206 | //
207 | // pad to a quad boundary
208 | //
209 | UINT16 PaeEnabled;
210 |
211 | //
212 | // Address of the kernel callout routine.
213 | //
214 |
215 | ULONG64 KiCallUserMode; // kernel routine
216 |
217 | //
218 | // Address of the usermode entry point for callbacks.
219 | //
220 |
221 | ULONG64 KeUserCallbackDispatcher; // address in ntdll
222 |
223 |
224 | //
225 | // Addresses of various kernel data structures and lists
226 | // that are of interest to the kernel debugger.
227 | //
228 |
229 | ULONG64 PsLoadedModuleList;
230 | ULONG64 PsActiveProcessHead;
231 | ULONG64 PspCidTable;
232 |
233 | ULONG64 ExpSystemResourcesList;
234 | ULONG64 ExpPagedPoolDescriptor;
235 | ULONG64 ExpNumberOfPagedPools;
236 |
237 | ULONG64 KeTimeIncrement;
238 | ULONG64 KeBugCheckCallbackListHead;
239 | ULONG64 KiBugcheckData;
240 |
241 | ULONG64 IopErrorLogListHead;
242 |
243 | ULONG64 ObpRootDirectoryObject;
244 | ULONG64 ObpTypeObjectType;
245 |
246 | ULONG64 MmSystemCacheStart;
247 | ULONG64 MmSystemCacheEnd;
248 | ULONG64 MmSystemCacheWs;
249 |
250 | ULONG64 MmPfnDatabase;
251 | ULONG64 MmSystemPtesStart;
252 | ULONG64 MmSystemPtesEnd;
253 | ULONG64 MmSubsectionBase;
254 | ULONG64 MmNumberOfPagingFiles;
255 |
256 | ULONG64 MmLowestPhysicalPage;
257 | ULONG64 MmHighestPhysicalPage;
258 | ULONG64 MmNumberOfPhysicalPages;
259 |
260 | ULONG64 MmMaximumNonPagedPoolInBytes;
261 | ULONG64 MmNonPagedSystemStart;
262 | ULONG64 MmNonPagedPoolStart;
263 | ULONG64 MmNonPagedPoolEnd;
264 |
265 | ULONG64 MmPagedPoolStart;
266 | ULONG64 MmPagedPoolEnd;
267 | ULONG64 MmPagedPoolInformation;
268 | ULONG64 MmPageSize;
269 |
270 | ULONG64 MmSizeOfPagedPoolInBytes;
271 |
272 | ULONG64 MmTotalCommitLimit;
273 | ULONG64 MmTotalCommittedPages;
274 | ULONG64 MmSharedCommit;
275 | ULONG64 MmDriverCommit;
276 | ULONG64 MmProcessCommit;
277 | ULONG64 MmPagedPoolCommit;
278 | ULONG64 MmExtendedCommit;
279 |
280 | ULONG64 MmZeroedPageListHead;
281 | ULONG64 MmFreePageListHead;
282 | ULONG64 MmStandbyPageListHead;
283 | ULONG64 MmModifiedPageListHead;
284 | ULONG64 MmModifiedNoWritePageListHead;
285 | ULONG64 MmAvailablePages;
286 | ULONG64 MmResidentAvailablePages;
287 |
288 | ULONG64 PoolTrackTable;
289 | ULONG64 NonPagedPoolDescriptor;
290 |
291 | ULONG64 MmHighestUserAddress;
292 | ULONG64 MmSystemRangeStart;
293 | ULONG64 MmUserProbeAddress;
294 |
295 | ULONG64 KdPrintCircularBuffer;
296 | ULONG64 KdPrintCircularBufferEnd;
297 | ULONG64 KdPrintWritePointer;
298 | ULONG64 KdPrintRolloverCount;
299 |
300 | ULONG64 MmLoadedUserImageList;
301 |
302 | // NT 5.1 Addition
303 |
304 | ULONG64 NtBuildLab;
305 | ULONG64 KiNormalSystemCall;
306 |
307 | // NT 5.0 hotfix addition
308 |
309 | ULONG64 KiProcessorBlock;
310 | ULONG64 MmUnloadedDrivers;
311 | ULONG64 MmLastUnloadedDriver;
312 | ULONG64 MmTriageActionTaken;
313 | ULONG64 MmSpecialPoolTag;
314 | ULONG64 KernelVerifier;
315 | ULONG64 MmVerifierData;
316 | ULONG64 MmAllocatedNonPagedPool;
317 | ULONG64 MmPeakCommitment;
318 | ULONG64 MmTotalCommitLimitMaximum;
319 | ULONG64 CmNtCSDVersion;
320 |
321 | // NT 5.1 Addition
322 |
323 | ULONG64 MmPhysicalMemoryBlock;
324 | ULONG64 MmSessionBase;
325 | ULONG64 MmSessionSize;
326 | ULONG64 MmSystemParentTablePage;
327 |
328 | // Server 2003 addition
329 |
330 | ULONG64 MmVirtualTranslationBase;
331 |
332 | UINT16 OffsetKThreadNextProcessor;
333 | UINT16 OffsetKThreadTeb;
334 | UINT16 OffsetKThreadKernelStack;
335 | UINT16 OffsetKThreadInitialStack;
336 |
337 | UINT16 OffsetKThreadApcProcess;
338 | UINT16 OffsetKThreadState;
339 | UINT16 OffsetKThreadBStore;
340 | UINT16 OffsetKThreadBStoreLimit;
341 |
342 | UINT16 SizeEProcess;
343 | UINT16 OffsetEprocessPeb;
344 | UINT16 OffsetEprocessParentCID;
345 | UINT16 OffsetEprocessDirectoryTableBase;
346 |
347 | UINT16 SizePrcb;
348 | UINT16 OffsetPrcbDpcRoutine;
349 | UINT16 OffsetPrcbCurrentThread;
350 | UINT16 OffsetPrcbMhz;
351 |
352 | UINT16 OffsetPrcbCpuType;
353 | UINT16 OffsetPrcbVendorString;
354 | UINT16 OffsetPrcbProcStateContext;
355 | UINT16 OffsetPrcbNumber;
356 |
357 | UINT16 SizeEThread;
358 |
359 | ULONG64 KdPrintCircularBufferPtr;
360 | ULONG64 KdPrintBufferSize;
361 |
362 | ULONG64 KeLoaderBlock;
363 |
364 | UINT16 SizePcr;
365 | UINT16 OffsetPcrSelfPcr;
366 | UINT16 OffsetPcrCurrentPrcb;
367 | UINT16 OffsetPcrContainedPrcb;
368 |
369 | UINT16 OffsetPcrInitialBStore;
370 | UINT16 OffsetPcrBStoreLimit;
371 | UINT16 OffsetPcrInitialStack;
372 | UINT16 OffsetPcrStackLimit;
373 |
374 | UINT16 OffsetPrcbPcrPage;
375 | UINT16 OffsetPrcbProcStateSpecialReg;
376 | UINT16 GdtR0Code;
377 | UINT16 GdtR0Data;
378 |
379 | UINT16 GdtR0Pcr;
380 | UINT16 GdtR3Code;
381 | UINT16 GdtR3Data;
382 | UINT16 GdtR3Teb;
383 |
384 | UINT16 GdtLdt;
385 | UINT16 GdtTss;
386 | UINT16 Gdt64R3CmCode;
387 | UINT16 Gdt64R3CmTeb;
388 |
389 | ULONG64 IopNumTriageDumpDataBlocks;
390 | ULONG64 IopTriageDumpDataBlocks;
391 |
392 | // Longhorn addition
393 |
394 | ULONG64 VfCrashDataBlock;
395 | ULONG64 MmBadPagesDetected;
396 | ULONG64 MmZeroedPageSingleBitErrorsDetected;
397 |
398 |
399 | } KDDEBUGGER_DATA64, *PKDDEBUGGER_DATA64;
400 |
401 |
402 |
--------------------------------------------------------------------------------
/src/metasm/virtdbg.rb:
--------------------------------------------------------------------------------
1 | # This file is part of Virtdbg
2 | # Copyright (C) 2010-2011 Damien AUMAITRE
3 | #
4 | # Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 | module VirtDbg
7 | VIRTDBGDIR = File.dirname(__FILE__)
8 | # add it to the ruby library path
9 | $: << VIRTDBGDIR
10 | end
11 |
12 | %w[forensic1394 virtdbg util main system].each { |f|
13 | require File.join('virtdbg', f)
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/src/metasm/virtdbg/forensic1394.rb:
--------------------------------------------------------------------------------
1 | # This file is part of Virtdbg
2 | # Copyright (C) 2010-2011 Damien AUMAITRE
3 | #
4 | # Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | require 'metasm'
8 | require 'metasm/dynldr'
9 |
10 | include Metasm
11 |
12 | module VirtDbg
13 |
14 | class Forensic1394 < Metasm::DynLdr
15 | new_api_c File.read(File.join(VIRTDBGDIR, "inc", "forensic1394.h")),
16 | "libforensic1394.so"
17 | end
18 |
19 | # FIXME : need to handle 32 bits ruby
20 |
21 | class Bus
22 | def initialize
23 | @bus_ptr = Forensic1394.forensic1394_alloc()
24 | # ObjectSpace.define_finalizer(self, self.class.finalize(@bus_ptr))
25 | end
26 |
27 | def self.finalize(bus_ptr)
28 | proc {Forensic1394.forensic1394_destroy(bus_ptr)}
29 | end
30 |
31 | def enable_sbp2
32 | Forensic1394.forensic1394_enable_sbp2(@bus_ptr)
33 | end
34 |
35 | def devices
36 | # Query the list of devices attached to the system
37 | ndev_ptr = (0.chr)*8
38 | devlist = Forensic1394.forensic1394_get_devices(@bus_ptr, ndev_ptr, 0)
39 | ndev_value = ndev_ptr.unpack('Q').first
40 | if ndev_value < 0
41 | puts "error: can't get devices"
42 | return nil
43 | end
44 | devices = []
45 | ndev_value.times {|i|
46 | dev_ptr = Forensic1394.memory_read_int(devlist+i*8)
47 | devices << Device.new(self, dev_ptr)
48 | }
49 | devices
50 | end
51 | end
52 |
53 | class Device
54 |
55 | attr_accessor :nodeid, :guid, :product_name, :product_id, :vendor_name, :vendor_id, :request_size, :csr
56 |
57 | def initialize(bus, dev_ptr)
58 | @bus = bus
59 | @dev_ptr = dev_ptr
60 |
61 | @nodeid = Forensic1394.forensic1394_get_device_nodeid(@dev_ptr)
62 | @guid = Forensic1394.forensic1394_get_device_guid(@dev_ptr)
63 | @product_name = Forensic1394.forensic1394_get_device_product_name(@dev_ptr)
64 | @product_name = Forensic1394.memory_read_strz(@product_name)
65 | @product_id = Forensic1394.forensic1394_get_device_product_id(@dev_ptr)
66 | @vendor_name = Forensic1394.forensic1394_get_device_vendor_name(@dev_ptr)
67 | @vendor_name = Forensic1394.memory_read_strz(@vendor_name)
68 | @vendor_id = Forensic1394.forensic1394_get_device_vendor_id(@dev_ptr)
69 | @request_size = Forensic1394.forensic1394_get_device_request_size(@dev_ptr)
70 |
71 | @csr = (0.chr)*1024
72 | Forensic1394.forensic1394_get_device_csr(@dev_ptr, @csr)
73 | # ObjectSpace.define_finalizer(self, self.class.finalize(@dev_ptr))
74 | end
75 |
76 | def open
77 | Forensic1394.forensic1394_open_device(@dev_ptr)
78 | end
79 |
80 | def close
81 | Forensic1394.forensic1394_close_device(@dev_ptr)
82 | end
83 |
84 | def internal_read(address, size)
85 | buf = (0.chr)*size
86 | Forensic1394.forensic1394_read_device(@dev_ptr, address, size, buf)
87 | buf
88 | end
89 |
90 | def internal_read_v(req)
91 | buffers = []
92 | creq_size = Forensic1394.alloc_c_struct("forensic1394_req").length
93 |
94 | creq = req.map {|addr, size|
95 | creq = Forensic1394.alloc_c_struct("forensic1394_req")
96 | creq.addr = addr
97 | creq.len = size
98 | buf = (0.chr)*size
99 | buffers << buf
100 | creq.buf = buf
101 | creq
102 | }
103 |
104 | ptr = tmp = Forensic1394.memory_alloc(req.size*creq_size)
105 | creq.each { |s| Forensic1394.memory_write(tmp, s.str) ; tmp += s.length }
106 | Forensic1394.forensic1394_read_device_v(@dev_ptr, ptr, req.size)
107 | buffers
108 | end
109 |
110 | def read(address, size)
111 | #FIXME handle read requests > request_size
112 | end
113 |
114 |
115 | def internal_write(address, data)
116 | Forensic1394.forensic1394_write_device(@dev_ptr, address, data.size, data)
117 | end
118 |
119 | def internal_write_v(req)
120 | creq_size = Forensic1394.alloc_c_struct("forensic1394_req").length
121 | creq = req.map {|addr, data|
122 | creq = Forensic1394.alloc_c_struct("forensic1394_req")
123 | creq.addr = addr
124 | creq.buf = data
125 | creq.len = data.size
126 | creq
127 | }
128 | ptr = tmp = Forensic1394.memory_alloc(req.size*creq_size)
129 | creq.each { |s| Forensic1394.memory_write(tmp, s.str) ; tmp += s.length }
130 | Forensic1394.forensic1394_write_device_v(@dev_ptr, ptr, req.size)
131 | end
132 |
133 | def write(address, data)
134 | #FIXME handle write requests > request_size
135 | end
136 |
137 | def self.finalize(dev_ptr)
138 | proc {Forensic1394.forensic1394_destroy(dev_ptr)}
139 | end
140 | end
141 |
142 | class FireWireMem < VirtualString
143 | def initialize(device, addr=0, length=nil)
144 | @device = device
145 | length ||= 1<<32
146 | super(addr, length)
147 | @pagecache_len = 128
148 | @pagelength = @device.request_size
149 | end
150 |
151 | def dup(addr=@addr_start, len=@length)
152 | self.class.new(@device, addr, len)
153 | end
154 |
155 | def rewrite_at(addr, data)
156 | # puts "1394: rewrite @ #{addr.to_s(16)} #{data.length.to_s(16)} bytes"
157 | @device.internal_write(addr, data)
158 | end
159 |
160 | def get_page(addr, len=@pagelength)
161 | # puts "1394: get page @ #{addr.to_s(16)}, #{len} bytes"
162 | buf = @device.internal_read(addr, len)
163 | buf
164 | end
165 |
166 | def close
167 | @dev.close
168 | end
169 |
170 | def hexdump(addr, size)
171 | @device.internal_read(addr, size).hexdump(:fmt => ['c','a'], :noend => true)
172 | end
173 | end
174 |
175 | end
176 |
--------------------------------------------------------------------------------
/src/metasm/virtdbg/main.rb:
--------------------------------------------------------------------------------
1 | # This file is part of Virtdbg
2 | # Copyright (C) 2010-2011 Damien AUMAITRE
3 | #
4 | # Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 | require 'metasm'
7 | require 'metasm/dynldr'
8 |
9 | include Metasm
10 |
11 | module VirtDbg
12 |
13 | class VirtDbgMem < VirtualString
14 | def initialize(impl, addr=0, length=nil)
15 | @impl = impl
16 | length ||= 1<<64
17 | super(addr, length)
18 | @pagecache_len = 128
19 | @pagelength = 0x400
20 | end
21 |
22 | def dup(addr=@addr_start, len=@length)
23 | self.class.new(@impl, addr, len)
24 | end
25 |
26 | def rewrite_at(addr, data)
27 | # puts "virtdbgmem: rewrite @ #{addr.to_s(16)} #{data.length.to_s(16)} bytes"
28 | @impl.write_virtual_memory(addr, data)
29 | end
30 |
31 | def get_page(addr, len=@pagelength)
32 | # puts "virtdbgmem: get page @ #{addr.to_s(16)}, #{len} bytes"
33 | buf = @impl.read_virtual_memory(addr, len)
34 | buf
35 | end
36 |
37 | def hexdump(addr, size)
38 | get_page(addr, size).hexdump(:fmt => ['c','a'], :noend => true)
39 | end
40 | end
41 |
42 | class VirtDbg < Debugger
43 | def initialize(impl)
44 | @impl = impl
45 | @cpu = X86_64.new
46 | @memory = VirtDbgMem.new(impl)
47 | @context = {}
48 | @system = nil
49 | super()
50 | @info = nil
51 | end
52 |
53 | def state
54 | @impl.state
55 | end
56 |
57 | def state=(state)
58 | @impl.state = state
59 | end
60 |
61 | def get_reg_value(reg)
62 | if @context.empty?
63 | context = @impl.get_context
64 | return 0 if not context
65 | @context = context
66 | end
67 |
68 | @context[reg]
69 | end
70 |
71 | def set_reg_value(reg, val)
72 | @context[reg] = val
73 | end
74 |
75 | def invalidate
76 | if not @context.empty?
77 | @impl.set_context @context
78 | end
79 | @memory.invalidate
80 | @context.clear
81 | super()
82 | end
83 |
84 | def do_continue(*a)
85 | invalidate
86 | @impl.continue
87 | @info = nil
88 | end
89 |
90 | def do_singlestep(*a)
91 | invalidate
92 | @impl.singlestep
93 | @info = "singlestep"
94 | end
95 |
96 | def break
97 | @impl.breakin
98 | end
99 |
100 | # non blocking
101 | def do_check_target
102 | invalidate
103 | packet = @impl.recv_packet
104 | if packet and packet.kind_of? StateChangePacket
105 | @impl.state = :stopped
106 | @info = "got exception #{packet.exception}"
107 | else
108 | puts "do check, got #{packet.inspect}" if packet
109 | end
110 | end
111 |
112 | # blocking
113 | def do_wait_target
114 | loop do
115 | do_check_target
116 | break if @impl.state == :stopped
117 | end
118 | end
119 |
120 | def bpx(addr, *a)
121 | hwbp(addr, :x, 1, *a)
122 | end
123 |
124 | def need_stepover(di)
125 | di and ((di.instruction.prefix and di.instruction.prefix[:rep]) or di.opcode.props[:saveip])
126 | end
127 |
128 | def enable_bp(addr)
129 | return if not b = @breakpoint[addr]
130 | case b.type
131 | when :hw
132 | @cpu.dbg_enable_bp(self, addr, b)
133 | end
134 | b.state = :active
135 | end
136 |
137 | def disable_bp(addr)
138 | return if not b = @breakpoint[addr]
139 | @cpu.dbg_disable_bp(self, addr, b)
140 | b.state = :inactive
141 | end
142 |
143 | def dumplog(arg=nil)
144 | puts @impl.dumplog
145 | end
146 |
147 | def handshake(arg=nil)
148 | puts @impl.handshake
149 | end
150 |
151 | def loadsyms(addr, name="%08x"%addr.to_i)
152 | return if not peek = @memory.get_page(addr, 4)
153 | if peek[0, 2] == "MZ" and @memory[addr+@memory[addr+0x3c,4].unpack('V').first, 4] == "PE\0\0"
154 | cls = LoadedPE
155 | else return
156 | end
157 |
158 | @loadedsyms ||= {}
159 | return if @loadedsyms[name]
160 | @loadedsyms[name] = true
161 |
162 | begin
163 | e = cls.load @memory[addr, 0x1000_0000]
164 | e.load_address = addr
165 | e.decode_header
166 | e.decode_exports
167 | rescue
168 | @modulemap[addr.to_s(16)] = [addr, addr+0x1000]
169 | return
170 | end
171 |
172 | if n = e.module_name and n != name
173 | name = n
174 | return if @loadedsyms[name]
175 | @loadedsyms[name] = true
176 | end
177 |
178 | @modulemap[name] = [addr, addr+e.module_size]
179 |
180 | sl = @symbols.length
181 | e.module_symbols.each { |n_, a, l|
182 | a += addr
183 | @disassembler.set_label_at(a, n_, false)
184 | @symbols[a] = n_
185 | if l and l > 1; @symbols_len[a] = l
186 | else @symbols_len.delete a # we may overwrite an existing symbol, keep len in sync
187 | end
188 | }
189 | puts "loaded #{@symbols.length - sl} symbols from #{name}"
190 | true
191 | end
192 |
193 | def loadkernel(arg=nil)
194 | kernelbase = @impl.area.KernelBase
195 | gui.parent_widget.mem.focus_addr kernelbase
196 | loadsyms kernelbase
197 | end
198 |
199 | def info(arg=nil)
200 | # dumping various info
201 | end
202 |
203 | def system(arg=nil)
204 | puts "getting operating system..."
205 | kernelbase = @impl.area.KernelBase
206 | @system = System.new(@memory, kernelbase)
207 | puts "done"
208 | end
209 |
210 | def idt(arg=nil)
211 | puts "dumping idt ! na kidding !"
212 | end
213 |
214 | def processes(arg=nil)
215 | # @statusline = "listing processes, please wait"
216 | # redraw
217 | # Gui.main_iter
218 | if not @system
219 | # @statusline = "getting system"
220 | # redraw
221 | # Gui.main_iter
222 | system
223 | end
224 | @system.processes {|p| puts "#{p.name} (#{p.pid})"}
225 | end
226 |
227 | def modules(arg=nil)
228 | if not @system
229 | system
230 | end
231 | @system.modules {|m| puts "#{m.name} 0x#{m.base.to_s(16)} 0x#{m.size.to_s(16)} 0x#{m.entrypoint.to_s(16)}"}
232 | end
233 |
234 | def ui_command_setup(ui)
235 | ui.new_command('idt', 'dump idt') { |arg| idt arg }
236 | ui.new_command('dumplog', 'dump log') { |arg| dumplog arg }
237 | ui.new_command('handshake', 'get a new client id') { |arg| handshake arg }
238 | ui.new_command('loadkernel', 'load kernel symbols') { |arg| loadkernel arg }
239 | ui.new_command('processes', 'list processes') { |arg| processes arg }
240 | ui.new_command('modules', 'list modules') { |arg| modules arg }
241 | end
242 |
243 | end
244 |
245 | end
246 |
--------------------------------------------------------------------------------
/src/metasm/virtdbg/system.rb:
--------------------------------------------------------------------------------
1 | # This file is part of Virtdbg
2 | # Copyright (C) 2010-2011 Damien AUMAITRE
3 | #
4 | # Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 | require 'metasm'
7 | require 'metasm/dynldr'
8 | require 'iconv'
9 |
10 | class String
11 | def utf16_to_iso
12 | converter = Iconv.new('ISO-8859-1//IGNORE//TRANSLIT', 'UTF-16')
13 | converter.iconv(self)
14 | end
15 | end
16 |
17 | include Metasm
18 |
19 |
20 | module VirtDbg
21 |
22 | # class WindowsAPI < DynLdr
23 | # new_api_c File.read(File.join(VIRTDBGDIR, "inc", "ntoskrnl.exe_F8E2A8B5C9B74BF4A6E4A48F18009994.h"))
24 | # end
25 |
26 | # class WinDbgAPI < DynLdr
27 | # new_api_c File.read(File.join(VIRTDBGDIR, "inc", "wdbgexts.h"))
28 | # end
29 |
30 | class System
31 |
32 | attr_accessor :mem, :ctypes
33 | def initialize(mem, addr)
34 | @mem = mem
35 | @kernelbase = addr
36 |
37 | puts "kernel @ 0x%x" % addr
38 |
39 | pe = LoadedPE.load @mem[addr, 0x1000_0000]
40 | pe.load_address = addr
41 | pe.decode_header
42 | pe.decode_debug
43 | @kernel = pe
44 |
45 | filename = pe.debug[0].data.pdbfilename
46 | guid = pe.debug[0].data.guid
47 | guid = '%x%x%x%x%x' % guid.unpack('VvvNN')
48 | age = pe.debug[0].data.age
49 | path = "#{filename}_#{guid}#{age}.h"
50 | @wdbgexts = Class.new(DynLdr)
51 | @wdbgexts.cp.llp64
52 | puts "loading wdbgexts header..."
53 | @wdbgexts.new_api_c File.read(File.join(VIRTDBGDIR, "inc", "wdbgexts.h"))
54 | @ctypes = Class.new(DynLdr)
55 | @ctypes.cp.llp64
56 | puts "loading #{path} header..."
57 | @ctypes.new_api_c File.read(File.join(VIRTDBGDIR, "inc", path))
58 | offset = 0x1e9070 # FIXME export this in hypervisor find KDBG sig
59 | @debugdata = @wdbgexts.decode_c_struct("KDDEBUGGER_DATA64", @mem, addr+offset)
60 | end
61 |
62 | def offsetof(structname, fieldname)
63 | st = @ctypes.cp.find_c_struct(structname)
64 | st.offsetof(nil, fieldname)
65 | end
66 |
67 | def decode_c_ptr(addr)
68 | @ctypes.decode_c_ary('void*', 1, @mem, addr)
69 | end
70 |
71 | def processes
72 | addr = decode_c_ptr(@debugdata.PsActiveProcessHead)[0]
73 | offset = offsetof("EPROCESS", "ActiveProcessLinks")
74 | first = Process.new(self, addr-offset)
75 | current = first
76 | while 42
77 | n = current.next
78 | break if n.address == first.address
79 | yield current
80 | current = n
81 | end
82 | end
83 |
84 | def modules
85 | addr = decode_c_ptr(@debugdata.PsLoadedModuleList)[0]
86 | first = Module.new(self, addr)
87 | current = first
88 | while 42
89 | n = current.next
90 | break if n.address == first.address
91 | yield current
92 | current = n
93 | end
94 | end
95 |
96 | end
97 |
98 | class Process
99 |
100 | attr_accessor :address
101 |
102 | def initialize(system, address)
103 | @system = system
104 | @address = address
105 | @offset = system.offsetof("EPROCESS", "ActiveProcessLinks")
106 | @eproc = system.ctypes.decode_c_struct("EPROCESS", system.mem, address)
107 | puts @eproc.to_s
108 | end
109 |
110 | def cr3
111 | @eproc.Pcb.DirectoryTableBase
112 | end
113 |
114 | def pid
115 | @eproc.UniqueProcessId
116 | end
117 |
118 | def name
119 | @eproc.ImageFileName.to_array.pack('C*').strip
120 | end
121 |
122 | def processlinks
123 | @eproc.ActiveProcessLinks
124 | end
125 |
126 | def next
127 | address = @eproc.ActiveProcessLinks.Flink
128 | puts "address=%x" % address
129 | puts "offset=%x" % @offset
130 | self.class.new(@system, address-@offset)
131 | end
132 |
133 | end
134 |
135 | class Module
136 |
137 | attr_accessor :address
138 |
139 | def initialize(system, address)
140 | @system = system
141 | @address = address
142 | @entry = system.ctypes.decode_c_struct("LDR_DATA_TABLE_ENTRY", system.mem, address)
143 | puts @entry.to_s
144 | end
145 |
146 | def next
147 | addr = @entry.InLoadOrderLinks.Flink
148 | self.class.new(@system, addr)
149 | end
150 |
151 | def fullname
152 | ptr = @entry.FullDllName.Buffer
153 | len = @entry.FullDllName.Length
154 | fullname = @system.mem[ptr,len]
155 | fullname.utf16_to_iso
156 | end
157 |
158 | def name
159 | ptr = @entry.BaseDllName.Buffer
160 | len = @entry.BaseDllName.Length
161 | name = @system.mem[ptr,len]
162 | name.utf16_to_iso
163 | end
164 |
165 | def base
166 | base = @entry.DllBase
167 | base
168 | end
169 |
170 | def size
171 | size = @entry.SizeOfImage
172 | size
173 | end
174 |
175 | def entrypoint
176 | entrypoint = @entry.EntryPoint
177 | entrypoint
178 | end
179 |
180 | end
181 |
182 | end
183 |
184 |
--------------------------------------------------------------------------------
/src/metasm/virtdbg/util.rb:
--------------------------------------------------------------------------------
1 | # ripped from metasm/misc
2 | class IO
3 | def hexdump(ctx={})
4 | ctx[:noend] = true
5 | while buf = read(512) and not buf.empty?
6 | buf.hexdump(ctx)
7 | end
8 | ctx.delete :noend
9 | ''.hexdump(ctx)
10 | end
11 | end
12 |
13 | class String
14 | def hexdump(ctx={})
15 | fmt = ctx[:fmt] ||= ['c', 'd', 'a']
16 | ctx[:pos] ||= 0
17 | ctx[:linelen] ||= 16
18 | scan(/.{1,#{ctx[:linelen]}}/m) { |s|
19 | if s != ctx[:lastline]
20 | ctx[:lastdup] = false
21 | print '%04x ' % ctx[:pos]
22 | print s.unpack('C*').map { |b| '%02x' % b }.join(' ').ljust(3*16-1) + ' ' if fmt.include? 'c'
23 | print s.unpack('v*').map { |b| '%04x' % b }.join(' ').ljust(5*8-1) + ' ' if fmt.include? 'w'
24 | print s.unpack('L*').map { |b| '%08x' % b }.join(' ').ljust(9*4-1) + ' ' if fmt.include? 'd'
25 | print s.tr("\0-\x1f\x7f-\xff", '.') if fmt.include? 'a'
26 | puts
27 | elsif not ctx[:lastdup]
28 | ctx[:lastdup] = true
29 | puts '*'
30 | end
31 | ctx[:lastline] = s
32 | ctx[:pos] += s.length
33 | }
34 | puts '%04x' % ctx[:pos] if not ctx[:noend]
35 | end
36 | end
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/metasm/virtdbg/virtdbg.rb:
--------------------------------------------------------------------------------
1 | # This file is part of Virtdbg
2 | # Copyright (C) 2010-2011 Damien AUMAITRE
3 | #
4 | # Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 | require 'metasm'
7 | require 'metasm/dynldr'
8 |
9 | include Metasm
10 |
11 | def calc_checksum(data)
12 | data.unpack('C*').inject(0) { |sum, byte| sum+byte }
13 | end
14 |
15 | module VirtDbg
16 |
17 | class VirtDbgAPI < DynLdr
18 | new_api_c File.read(File.join(VIRTDBGDIR, "inc", "virtdbg.h"))
19 | end
20 |
21 | class VirtDbgPacket
22 | attr_accessor :header, :data1, :data2
23 | def initialize
24 | @header = VirtDbgAPI.alloc_c_struct("PACKET_HEADER")
25 | @header.Magic = VirtDbgAPI::PACKET_MAGIC
26 | @data1 = nil
27 | @data2 = nil
28 | end
29 |
30 | def data
31 | data = @data1 ? @data1.str[@data1.stroff, @data1.length] : ""
32 | if @data2.kind_of? String
33 | data << @data2
34 | elsif @data2
35 | data << @data2.str[@data2.stroff, @data2.length]
36 | end
37 | data
38 | end
39 |
40 | def encode
41 | fixup
42 | raw = @header.str[@header.stroff, @header.length]
43 | raw << data
44 | raw
45 | end
46 |
47 | def to_s
48 | puts @header.to_s
49 | puts @data1.to_s if @data1
50 | puts @data2.to_s if @data2 and not @data2.kind_of? String
51 | end
52 |
53 | def fixup
54 | @header.Checksum = calc_checksum(data)
55 | @header.Size = (@data1 ? @data1.length : 0) + (@data2 ? @data2.length : 0)
56 | end
57 | end
58 |
59 | class BreakinPacket < VirtDbgPacket
60 | def initialize(cr3=0)
61 | super()
62 | @header.Type = VirtDbgAPI::PACKET_TYPE_BREAKIN
63 | @data1 = VirtDbgAPI.alloc_c_struct("BREAKIN_PACKET")
64 | @data1.Cr3 = cr3
65 | end
66 | end
67 |
68 | class ResetPacket < VirtDbgPacket
69 | def initialize
70 | super()
71 | @header.Type = VirtDbgAPI::PACKET_TYPE_RESET
72 | end
73 | end
74 |
75 | class AckPacket < VirtDbgPacket
76 | def initialize
77 | super()
78 | @header.Type = VirtDbgAPI::PACKET_TYPE_ACK
79 | end
80 | end
81 |
82 | class ContinuePacket < VirtDbgPacket
83 | def initialize(status=0)
84 | super()
85 | @header.Type = VirtDbgAPI::PACKET_TYPE_CONTINUE
86 | @data1 = VirtDbgAPI.alloc_c_struct("CONTINUE_PACKET")
87 | @data1.Status = status
88 | end
89 | end
90 |
91 | class ManipulateStatePacket < VirtDbgPacket
92 | def initialize
93 | super()
94 | @header.Type = VirtDbgAPI::PACKET_TYPE_MANIPULATE_STATE
95 | @data1 = VirtDbgAPI.alloc_c_struct("MANIPULATE_STATE_PACKET")
96 | end
97 |
98 | def error
99 | @data1.Error
100 | end
101 | end
102 |
103 | class ReadVirtualMemoryPacket < ManipulateStatePacket
104 | def initialize(address=0, size=0)
105 | super()
106 | @data1.ApiNumber = VirtDbgAPI::READ_VIRTUAL_MEMORY_API
107 | @data1.ReadVirtualMemory.Address = address
108 | @data1.ReadVirtualMemory.Size = size
109 | end
110 | end
111 |
112 | class WriteVirtualMemoryPacket < ManipulateStatePacket
113 | def initialize(address=0, data="")
114 | super()
115 | @data1.ApiNumber = VirtDbgAPI::WRITE_VIRTUAL_MEMORY_API
116 | @data1.WriteVirtualMemory.Address = address
117 | @data1.WriteVirtualMemory.Size = data.size
118 | @data2 = data
119 | end
120 | end
121 |
122 | class GetContextPacket < ManipulateStatePacket
123 | def initialize
124 | super()
125 | @data1.ApiNumber = VirtDbgAPI::GET_CONTEXT_API
126 | @data2 = VirtDbgAPI.alloc_c_struct("DEBUG_CONTEXT")
127 | end
128 | end
129 |
130 | class SetContextPacket < ManipulateStatePacket
131 | def initialize
132 | super()
133 | @data1.ApiNumber = VirtDbgAPI::SET_CONTEXT_API
134 | @data2 = VirtDbgAPI.alloc_c_struct("DEBUG_CONTEXT")
135 | end
136 | end
137 |
138 | class StateChangePacket < VirtDbgPacket
139 | def initialize
140 | super()
141 | @header.Type = VirtDbgAPI::PACKET_TYPE_STATE_CHANGE
142 | @data1 = VirtDbgAPI.alloc_c_struct("STATE_CHANGE_PACKET")
143 | end
144 |
145 | def exception
146 | @data1.Exception
147 | end
148 | end
149 |
150 | PAGE_SIZE = 0x1000
151 | MAX_PFN = 0x80000
152 | # 7c000
153 | MIN_PFN = 0
154 |
155 | class VirtDbgImpl
156 | attr_accessor :mem, :area, :state, :clientid
157 | def initialize(mem, max_pfn=MAX_PFN)
158 | @mem = mem
159 | @area = nil
160 | @lastid = 0
161 | @clientid = 0
162 | @id = VirtDbgAPI::INITIAL_ID
163 | @attached = false
164 | @unexpected_packets = []
165 | @state = :running
166 | @max_pfn = max_pfn
167 | end
168 |
169 | def new_clientid
170 | rand(0x100000)
171 | end
172 |
173 | def setup
174 | result = find_control_area
175 | if result
176 | handshake
177 | return true
178 | else
179 | return false
180 | end
181 | end
182 |
183 | def send_area
184 | @area.RecvArea.QuadPart if @area
185 | end
186 |
187 | def recv_area
188 | @area.SendArea.QuadPart if @area
189 | end
190 |
191 | def find_control_area
192 | puts "searching control area..."
193 | magic = [VirtDbgAPI::CONTROL_AREA_MAGIC1,
194 | VirtDbgAPI::CONTROL_AREA_MAGIC2].pack("LL")
195 |
196 | pfn = @max_pfn.downto(0).find {|i|
197 | header = @mem[i*0x1000, 8]
198 | header == magic }
199 |
200 | if not pfn
201 | puts "can't find control area, aborting"
202 | return false
203 | end
204 |
205 | control_area_paddr = pfn*PAGE_SIZE
206 | puts "found control area @ #{control_area_paddr.to_s(16)}"
207 | @area = VirtDbgAPI.decode_c_struct('VIRTDBG_CONTROL_AREA',
208 | @mem, control_area_paddr)
209 |
210 | # @send_area = @area.recvarea.quadpart
211 | # @recv_area = @area.sendarea.quadpart
212 | puts "send_area @ #{self.send_area.to_s(16)}"
213 | puts "recv_area @ #{self.recv_area.to_s(16)}"
214 | true
215 | end
216 |
217 | def handshake
218 | @clientid = new_clientid
219 | @lastid = 0
220 | @area.ClientId = @clientid
221 | start = Time.now
222 | while @area.ServerId != @clientid
223 | @mem.invalidate
224 | if Time.now-start > 10.0
225 | puts "can't make handshake in 10s, aborting"
226 | return false
227 | end
228 | end
229 | @attached = true
230 | puts "handshake done (client id 0x#{@clientid.to_s(16)})"
231 | return true
232 | end
233 |
234 | def dumplog
235 | @mem.invalidate
236 | @mem[@area.LogBuffer.QuadPart,2048]+@mem[@area.LogBuffer.QuadPart+2048,2048]
237 | end
238 |
239 | def send_packet_internal(packet)
240 | packet.header.ClientId = @clientid
241 | packet.header.Id = @id
242 | packet.fixup
243 | data = packet.encode
244 | @mem[self.send_area, data.length] = data
245 | @id += 1
246 | data.length
247 | end
248 |
249 | def send_packet(packet)
250 | return false if not @attached
251 | start = Time.now
252 | length = send_packet_internal(packet)
253 | while @area.LastClientId != packet.header.Id
254 | @mem.invalidate
255 | return false if Time.now-start > 2.0
256 | end
257 | true
258 | end
259 |
260 | def dispatch_packet(packet)
261 | @unexpected_packets << packet if packet
262 | puts "got an unexpected packet #{packet.inspect}" if packet
263 | end
264 |
265 | def recv_packet_with_type(type)
266 | packet = nil
267 | start = Time.now
268 | loop do
269 | packet = recv_packet
270 | break if packet.kind_of? type
271 | break if Time.now-start > 2.0
272 | dispatch_packet packet
273 | end
274 | packet
275 | end
276 |
277 | def recv_packet
278 | return if not @attached
279 | packet = nil
280 | @mem.invalidate
281 | packet = recv_packet_internal
282 | packet
283 | end
284 |
285 | def recv_packet_internal
286 | data = @mem[self.recv_area, VirtDbgAPI::HEADER_SIZE]
287 | header = VirtDbgAPI.decode_c_struct('PACKET_HEADER', data, 0)
288 |
289 | if header.Magic != VirtDbgAPI::PACKET_MAGIC
290 | # puts "no magic number in header"
291 | return
292 | end
293 |
294 | if not (0..VirtDbgAPI::MAX_PACKET_SIZE).cover? header.Size
295 | # puts "packet too big"
296 | return
297 | end
298 |
299 | if header.Id <= @lastid
300 | # puts "not a new packet"
301 | return
302 | end
303 |
304 | packet_size = VirtDbgAPI::HEADER_SIZE+header.Size
305 |
306 | if header.Size > 0
307 | body = @mem[self.recv_area+VirtDbgAPI::HEADER_SIZE, header.Size]
308 | data << body
309 |
310 | sum = calc_checksum(body)
311 | if sum != header.Checksum
312 | puts "bad checksum, expected #{sum.to_s(16)}, got #{header.Checksum.to_s(16)}"
313 | return
314 | end
315 | end
316 |
317 | case header.Type
318 | when VirtDbgAPI::PACKET_TYPE_RESET
319 | packet = ResetPacket.new
320 | when VirtDbgAPI::PACKET_TYPE_MANIPULATE_STATE
321 | data1 = VirtDbgAPI.decode_c_struct('MANIPULATE_STATE_PACKET',
322 | data, VirtDbgAPI::HEADER_SIZE)
323 | case data1.ApiNumber
324 | when VirtDbgAPI::READ_VIRTUAL_MEMORY_API
325 | packet = ReadVirtualMemoryPacket.new
326 | offset = header.length+data1.length
327 | size = header.Size-data1.length
328 | # puts "offset=0x#{offset.to_s(16)}, size=0x#{size.to_s(16)}"
329 | data2 = data[offset, size]
330 | packet.data2 = data2
331 |
332 | when VirtDbgAPI::WRITE_VIRTUAL_MEMORY_API
333 | packet = WriteVirtualMemoryPacket.new
334 | when VirtDbgAPI::GET_CONTEXT_API
335 | packet = GetContextPacket.new
336 | offset = header.length+data1.length
337 | data2 = VirtDbgAPI.decode_c_struct("DEBUG_CONTEXT",
338 | data, offset)
339 | packet.data2 = data2
340 |
341 | when VirtDbgAPI::SET_CONTEXT_API
342 | packet = SetContextPacket.new
343 | else
344 | puts "invalid api number"
345 | return
346 | end
347 |
348 | packet.data1 = data1
349 |
350 | when VirtDbgAPI::PACKET_TYPE_STATE_CHANGE
351 | data1 = VirtDbgAPI.decode_c_struct('STATE_CHANGE_PACKET',
352 | data,
353 | VirtDbgAPI::HEADER_SIZE)
354 | packet = StateChangePacket.new
355 | packet.data1 = data1
356 |
357 | when VirtDbgAPI::PACKET_TYPE_CONTINUE
358 | data1 = VirtDbgAPI.decode_c_struct('CONTINUE_PACKET',
359 | data,
360 | VirtDbgAPI::HEADER_SIZE)
361 | packet = ContinuePacket.new
362 | packet.data1 = data1
363 |
364 | else
365 | puts "invalid header type"
366 | return
367 | end
368 |
369 | packet.header = header
370 | @lastid = header.Id
371 | # puts packet.to_s
372 | # puts data.hexdump
373 |
374 | @area.LastServerId = header.Id
375 | packet
376 | end
377 |
378 | def breakin
379 | request = BreakinPacket.new
380 | send_packet request
381 | packet = recv_packet
382 | if packet and packet.kind_of? StateChangePacket
383 | @state = :stopped
384 | end
385 | # FIXME need to handle this better
386 | # puts "breakin, got #{packet.inspect}"
387 | packet
388 | end
389 |
390 | def continue
391 | request = ContinuePacket.new(VirtDbgAPI::CONTINUE_STATUS_CONTINUE)
392 | send_packet request
393 | @state = :running
394 | end
395 |
396 | def singlestep
397 | request = ContinuePacket.new(VirtDbgAPI::CONTINUE_STATUS_SINGLE_STEP)
398 | send_packet request
399 | packet = recv_packet
400 | if packet and packet.kind_of? StateChangePacket
401 | @state = :stopped
402 | end
403 | packet
404 | end
405 |
406 | def extract_context(response)
407 | context = {}
408 | context[:rax] = response.data2.rax
409 | context[:rbx] = response.data2.rbx
410 | context[:rcx] = response.data2.rcx
411 | context[:rdx] = response.data2.rdx
412 | context[:rsi] = response.data2.rsi
413 | context[:rdi] = response.data2.rdi
414 | context[:rbp] = response.data2.rbp
415 | context[:rsp] = response.data2.rsp
416 | context[:r8] = response.data2.r8
417 | context[:r9] = response.data2.r9
418 | context[:r10] = response.data2.r10
419 | context[:r11] = response.data2.r11
420 | context[:r12] = response.data2.r12
421 | context[:r13] = response.data2.r13
422 | context[:r14] = response.data2.r14
423 | context[:r15] = response.data2.r15
424 | context[:rip] = response.data2.rip
425 | context[:rflags] = response.data2.rflags
426 | context[:cr0] = response.data2.cr0
427 | context[:cr3] = response.data2.cr3
428 | context[:cr4] = response.data2.cr4
429 | context[:cr8] = response.data2.cr8
430 | context[:dr0] = response.data2.dr0
431 | context[:dr1] = response.data2.dr1
432 | context[:dr2] = response.data2.dr2
433 | context[:dr3] = response.data2.dr3
434 | context[:dr6] = response.data2.dr6
435 | context[:dr7] = response.data2.dr7
436 | context
437 | end
438 |
439 | def fill_context(request, context)
440 | request.data2.rax = context[:rax] if context[:rax]
441 | request.data2.rbx = context[:rbx] if context[:rbx]
442 | request.data2.rcx = context[:rcx] if context[:rcx]
443 | request.data2.rdx = context[:rdx] if context[:rdx]
444 | request.data2.rsi = context[:rsi] if context[:rsi]
445 | request.data2.rdi = context[:rdi] if context[:rdi]
446 | request.data2.rbp = context[:rbp] if context[:rbp]
447 | request.data2.rsp = context[:rsp] if context[:rsp]
448 | request.data2.r8 = context[:r8] if context[:r8]
449 | request.data2.r9 = context[:r9] if context[:r9]
450 | request.data2.r10 = context[:r10] if context[:r10]
451 | request.data2.r11 = context[:r11] if context[:r11]
452 | request.data2.r12 = context[:r12] if context[:r12]
453 | request.data2.r13 = context[:r13] if context[:r13]
454 | request.data2.r14 = context[:r14] if context[:r14]
455 | request.data2.r15 = context[:r15] if context[:r15]
456 | request.data2.rip = context[:rip] if context[:rip]
457 | request.data2.rflags = context[:rflags] if context[:rflags]
458 | request.data2.cr0 = context[:cr0] if context[:cr0]
459 | request.data2.cr3 = context[:cr3] if context[:cr3]
460 | request.data2.cr4 = context[:cr4] if context[:cr4]
461 | request.data2.cr8 = context[:cr8] if context[:cr8]
462 | request.data2.dr0 = context[:dr0] if context[:dr0]
463 | request.data2.dr1 = context[:dr1] if context[:dr1]
464 | request.data2.dr2 = context[:dr2] if context[:dr2]
465 | request.data2.dr3 = context[:dr3] if context[:dr3]
466 | request.data2.dr6 = context[:dr6] if context[:dr6]
467 | request.data2.dr7 = context[:dr7] if context[:dr7]
468 | request
469 | end
470 |
471 | def get_context
472 | return if @state == :running
473 | request = GetContextPacket.new
474 | send_packet request
475 | response = recv_packet_with_type GetContextPacket
476 | if response and response.error == 0
477 | return extract_context(response)
478 | else
479 | return nil
480 | end
481 | end
482 |
483 | def set_context(context)
484 | return if @state == :running
485 | request = SetContextPacket.new
486 | fill_context request, context
487 | send_packet request
488 | response = recv_packet_with_type SetContextPacket
489 | end
490 |
491 | def read_virtual_memory(address, size)
492 | return if @state == :running
493 | request = ReadVirtualMemoryPacket.new(address, size)
494 | send_packet request
495 | response = recv_packet_with_type ReadVirtualMemoryPacket
496 | if response and response.error == 0
497 | return response.data2
498 | else
499 | return nil
500 | end
501 | end
502 |
503 | def write_virtual_memory(address, data)
504 | return if @state == :running
505 | request = WriteVirtualMemoryPacket.new(address, data)
506 | send_packet request
507 | response = recv_packet_with_type WriteVirtualMemoryPacket
508 | end
509 |
510 | end
511 |
512 | end
513 |
--------------------------------------------------------------------------------
/src/virtdbg/Makefile:
--------------------------------------------------------------------------------
1 | !INCLUDE $(NTMAKEENV)\makefile.def
2 |
3 |
--------------------------------------------------------------------------------
/src/virtdbg/amd64.h:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #ifndef AMD64_H
8 | #define AMD64_H
9 |
10 | #include
11 |
12 | #define KGDT64_NULL (0 * 16) // NULL descriptor
13 | #define KGDT64_R0_CODE (1 * 16) // kernel mode 64-bit code
14 | #define KGDT64_R0_DATA (1 * 16) + 8 // kernel mode 64-bit data (stack)
15 | #define KGDT64_R3_CMCODE (2 * 16) // user mode 32-bit code
16 | #define KGDT64_R3_DATA (2 * 16) + 8 // user mode 32-bit data
17 | #define KGDT64_R3_CODE (3 * 16) // user mode 64-bit code
18 | #define KGDT64_SYS_TSS (4 * 16) // kernel mode system task state
19 | #define KGDT64_R3_CMTEB (5 * 16) // user mode 32-bit TEB
20 | #define KGDT64_R0_CMCODE (6 * 16) // kernel mode 32-bit code
21 |
22 | #pragma pack (push, 1)
23 |
24 | /*
25 | * Attribute for segment selector. This is a copy of bit 40:47 & 52:55 of the
26 | * segment descriptor.
27 | */
28 | typedef union
29 | {
30 | USHORT UCHARs;
31 | struct
32 | {
33 | USHORT type:4; /* 0; Bit 40-43 */
34 | USHORT s:1; /* 4; Bit 44 */
35 | USHORT dpl:2; /* 5; Bit 45-46 */
36 | USHORT p:1; /* 7; Bit 47 */
37 | // gap!
38 | USHORT avl:1; /* 8; Bit 52 */
39 | USHORT l:1; /* 9; Bit 53 */
40 | USHORT db:1; /* 10; Bit 54 */
41 | USHORT g:1; /* 11; Bit 55 */
42 | USHORT Gap:4;
43 | } fields;
44 | } SEGMENT_ATTRIBUTES;
45 |
46 | typedef struct _TSS64
47 | {
48 | ULONG Reserved0;
49 | PVOID RSP0;
50 | PVOID RSP1;
51 | PVOID RSP2;
52 | ULONG64 Reserved1;
53 | PVOID IST1;
54 | PVOID IST2;
55 | PVOID IST3;
56 | PVOID IST4;
57 | PVOID IST5;
58 | PVOID IST6;
59 | PVOID IST7;
60 | ULONG64 Reserved2;
61 | USHORT Reserved3;
62 | USHORT IOMapBaseAddress;
63 | } TSS64, *PTSS64;
64 |
65 | typedef struct _SEGMENT_SELECTOR
66 | {
67 | USHORT sel;
68 | SEGMENT_ATTRIBUTES attributes;
69 | ULONG32 limit;
70 | ULONG64 base;
71 | } SEGMENT_SELECTOR, *PSEGMENT_SELECTOR;
72 |
73 | typedef struct _SEGMENT_DESCRIPTOR
74 | {
75 | USHORT limit0;
76 | USHORT base0;
77 | UCHAR base1;
78 | UCHAR attr0;
79 | UCHAR limit1attr1;
80 | UCHAR base2;
81 | } SEGMENT_DESCRIPTOR, *PSEGMENT_DESCRIPTOR;
82 |
83 | typedef struct _INTERRUPT_GATE_DESCRIPTOR
84 | {
85 | USHORT TargetOffset1500;
86 | USHORT TargetSelector;
87 | UCHAR InterruptStackTable;
88 | UCHAR Attributes;
89 | USHORT TargetOffset3116;
90 | ULONG32 TargetOffset6332;
91 | ULONG32 Reserved;
92 | } INTERRUPT_GATE_DESCRIPTOR,
93 | *PINTERRUPT_GATE_DESCRIPTOR;
94 |
95 | #pragma pack (pop)
96 |
97 | #define LA_ACCESSED 0x01
98 | #define LA_READABLE 0x02 // for code segments
99 | #define LA_WRITABLE 0x02 // for data segments
100 | #define LA_CONFORMING 0x04 // for code segments
101 | #define LA_EXPANDDOWN 0x04 // for data segments
102 | #define LA_CODE 0x08
103 | #define LA_STANDARD 0x10
104 | #define LA_DPL_0 0x00
105 | #define LA_DPL_1 0x20
106 | #define LA_DPL_2 0x40
107 | #define LA_DPL_3 0x60
108 | #define LA_PRESENT 0x80
109 |
110 | #define LA_LDT64 0x02
111 | #define LA_ATSS64 0x09
112 | #define LA_BTSS64 0x0b
113 | #define LA_CALLGATE64 0x0c
114 | #define LA_INTGATE64 0x0e
115 | #define LA_TRAPGATE64 0x0f
116 |
117 | #define HA_AVAILABLE 0x01
118 | #define HA_LONG 0x02
119 | #define HA_DB 0x04
120 | #define HA_GRANULARITY 0x08
121 |
122 | typedef enum SEGREGS
123 | {
124 | ES = 0,
125 | CS,
126 | SS,
127 | DS,
128 | FS,
129 | GS,
130 | LDTR,
131 | TR
132 | };
133 |
134 | #define DIVIDE_ERROR_EXCEPTION 0
135 | #define DEBUG_EXCEPTION 1
136 | #define NMI_INTERRUPT 2
137 | #define BREAKPOINT_EXCEPTION 3
138 | #define OVERFLOW_EXCEPTION 4
139 | #define BOUND_EXCEPTION 5
140 | #define INVALID_OPCODE_EXCEPTION 6
141 | #define DEVICE_NOT_AVAILABLE_EXCEPTION 7
142 | #define DOUBLE_FAULT_EXCEPTION 8
143 | #define COPROCESSOR_SEGMENT_OVERRUN 9
144 | #define INVALID_TSS_EXCEPTION 10
145 | #define SEGMENT_NOT_PRESENT 11
146 | #define STACK_FAULT_EXCEPTION 12
147 | #define GENERAL_PROTECTION_EXCEPTION 13
148 | #define PAGE_FAULT_EXCEPTION 14
149 | #define X87_FLOATING_POINT_ERROR 16
150 | #define ALIGNMENT_CHECK_EXCEPTION 17
151 | //#define MACHINE_CHECK_EXCEPTION 18
152 | #define SIMD_FLOATING_POINT_EXCEPTION 19
153 |
154 | #define EXTERNAL_INTERRUPT 0
155 | #define HARDWARE_EXCEPTION 3
156 | #define SOFTWARE_INTERRUPT 4
157 | #define PRIVILEGED_SOFTWARE_EXCEPTION 5
158 | #define SOFTWARE_EXCEPTION 6
159 | #define OTHER_EVENT 7
160 |
161 | #define EFER_LME (1<<8)
162 | #define EFER_LMA (1<<10)
163 |
164 | /*
165 | * Intel CPU flags in CR0
166 | */
167 | #define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */
168 | #define X86_CR0_MP 0x00000002 /* Monitor Coprocessor (RW) */
169 | #define X86_CR0_EM 0x00000004 /* Require FPU Emulation (RO) */
170 | #define X86_CR0_TS 0x00000008 /* Task Switched (RW) */
171 | #define X86_CR0_ET 0x00000010 /* Extension type (RO) */
172 | #define X86_CR0_NE 0x00000020 /* Numeric Error Reporting (RW) */
173 | #define X86_CR0_WP 0x00010000 /* Supervisor Write Protect (RW) */
174 | #define X86_CR0_AM 0x00040000 /* Alignment Checking (RW) */
175 | #define X86_CR0_NW 0x20000000 /* Not Write-Through (RW) */
176 | #define X86_CR0_CD 0x40000000 /* Cache Disable (RW) */
177 | #define X86_CR0_PG 0x80000000 /* Paging (RW) */
178 |
179 | /*
180 | * Intel CPU features in CR4
181 | */
182 | #define X86_CR4_VME 0x0001 /* enable vm86 extensions */
183 | #define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */
184 | #define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */
185 | #define X86_CR4_DE 0x0008 /* enable debugging extensions */
186 | #define X86_CR4_PSE 0x0010 /* enable page size extensions */
187 | #define X86_CR4_PAE 0x0020 /* enable physical address extensions */
188 | #define X86_CR4_MCE 0x0040 /* Machine check enable */
189 | #define X86_CR4_PGE 0x0080 /* enable global pages */
190 | #define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */
191 | #define X86_CR4_OSFXSR 0x0200 /* enable fast FPU save and restore */
192 | #define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */
193 | #define X86_CR4_VMXE 0x2000 /* enable VMX */
194 |
195 | /*
196 | * Intel CPU MSR
197 | */
198 |
199 | /* MSRs & bits used for VMX enabling */
200 |
201 | #define MSR_IA32_VMX_BASIC 0x480
202 | #define MSR_IA32_FEATURE_CONTROL 0x03a
203 | #define MSR_IA32_VMX_PINBASED_CTLS 0x481
204 | #define MSR_IA32_VMX_PROCBASED_CTLS 0x482
205 | #define MSR_IA32_VMX_EXIT_CTLS 0x483
206 | #define MSR_IA32_VMX_ENTRY_CTLS 0x484
207 |
208 | #define MSR_IA32_SYSENTER_CS 0x174
209 | #define MSR_IA32_SYSENTER_ESP 0x175
210 | #define MSR_IA32_SYSENTER_EIP 0x176
211 | #define MSR_IA32_DEBUGCTL 0x1d9
212 |
213 | /* x86-64 MSR */
214 |
215 | #define MSR_EFER 0xc0000080 /* extended feature register */
216 | #define MSR_STAR 0xc0000081 /* legacy mode SYSCALL target */
217 | #define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target */
218 | #define MSR_CSTAR 0xc0000083 /* compatibility mode SYSCALL target */
219 | #define MSR_SYSCALL_MASK 0xc0000084 /* EFLAGS mask for syscall */
220 | #define MSR_FS_BASE 0xc0000100 /* 64bit FS base */
221 | #define MSR_GS_BASE 0xc0000101 /* 64bit GS base */
222 | #define MSR_SHADOW_GS_BASE 0xc0000102 /* SwapGS GS shadow */
223 |
224 | #define CR0 0
225 | #define CR3 3
226 | #define CR4 4
227 | #define CR8 8
228 |
229 | #define RAX 0
230 | #define RCX 1
231 | #define RDX 2
232 | #define RBX 3
233 | #define RSP 4
234 | #define RBP 5
235 | #define RSI 6
236 | #define RDI 7
237 | #define R8 8
238 | #define R9 9
239 | #define R10 10
240 | #define R11 11
241 | #define R12 12
242 | #define R13 13
243 | #define R14 14
244 | #define R15 15
245 |
246 | //
247 | // Used by the cpuid instruction when eax=1
248 | //
249 |
250 | typedef struct _VMX_FEATURES {
251 | unsigned SSE3 :1; // SSE3 Extensions
252 | unsigned RES1 :2;
253 | unsigned MONITOR :1; // MONITOR/WAIT
254 | unsigned DS_CPL :1; // CPL qualified Debug Store
255 | unsigned VMX :1; // Virtual Machine Technology
256 | unsigned RES2 :1;
257 | unsigned EST :1; // Enhanced Intel© Speedstep Technology
258 | unsigned TM2 :1; // Thermal monitor 2
259 | unsigned SSSE3 :1; // SSSE3 extensions
260 | unsigned CID :1; // L1 context ID
261 | unsigned RES3 :2;
262 | unsigned CX16 :1; // CMPXCHG16B
263 | unsigned xTPR :1; // Update control
264 | unsigned PDCM :1; // Performance/Debug capability MSR
265 | unsigned RES4 :2;
266 | unsigned DCA :1;
267 | unsigned RES5 :13;
268 | } VMX_FEATURES;
269 |
270 | typedef struct _IA32_FEATURE_CONTROL_MSR {
271 | unsigned Lock :1; // Bit 0 is the lock bit - cannot be
272 | // modified once lock is set, controled by BIOS
273 | unsigned VmxonInSmx :1;
274 | unsigned VmxonOutSmx :1;
275 | unsigned Reserved2 :29;
276 | unsigned Reserved3 :32;
277 | } IA32_FEATURE_CONTROL_MSR;
278 |
279 | typedef struct _CR4_REG {
280 | unsigned VME :1; // Virtual Mode Extensions
281 | unsigned PVI :1; // Protected-Mode Virtual Interrupts
282 | unsigned TSD :1; // Time Stamp Disable
283 | unsigned DE :1; // Debugging Extensions
284 | unsigned PSE :1; // Page Size Extensions
285 | unsigned PAE :1; // Physical Address Extension
286 | unsigned MCE :1; // Machine-Check Enable
287 | unsigned PGE :1; // Page Global Enable
288 | unsigned PCE :1; // Performance-Monitoring Counter Enable
289 | unsigned OSFXSR :1; // OS Support for FXSAVE/FXRSTOR
290 | unsigned OSXMMEXCPT :1; // OS Support for Unmasked SIMD Floating-Point Exceptions
291 | unsigned Reserved1 :2; //
292 | unsigned VMXE :1; // Virtual Machine Extensions Enabled
293 | unsigned Reserved2 :18; //
294 | } CR4_REG, *PCR4_REG;
295 |
296 |
297 | typedef struct _RFLAGS {
298 | unsigned CF:1;
299 | unsigned Reserved1:1;
300 | unsigned PF:1;
301 | unsigned Reserved2:1;
302 | unsigned AF:1;
303 | unsigned Reserved3:1;
304 | unsigned ZF:1;
305 | unsigned SF:1;
306 | unsigned TF:1;
307 | unsigned IF:1;
308 | unsigned DF:1;
309 | unsigned OF:1;
310 | unsigned IOPL:2;
311 | unsigned NT:1;
312 | unsigned Reserved4:1;
313 | unsigned RF:1;
314 | unsigned VM:1;
315 | unsigned AC:1;
316 | unsigned VIF:1;
317 | unsigned VIP:1;
318 | unsigned ID:1;
319 | unsigned Reserved5:10;
320 | } RFLAGS, *PRFLAGS;
321 |
322 | #define TF 0x100
323 |
324 | typedef union _DR6 {
325 | ULONG Value;
326 | struct {
327 | unsigned B0:1;
328 | unsigned B1:1;
329 | unsigned B2:1;
330 | unsigned B3:1;
331 | unsigned Reserved1:10;
332 | unsigned BD:1;
333 | unsigned BS:1;
334 | unsigned BT:1;
335 | unsigned Reserved2:16;
336 | };
337 | } DR6, *PDR6;
338 |
339 | typedef union _DR7 {
340 | ULONG Value;
341 | struct {
342 | unsigned L0:1;
343 | unsigned G0:1;
344 | unsigned L1:1;
345 | unsigned G1:1;
346 | unsigned L2:1;
347 | unsigned G2:1;
348 | unsigned L3:1;
349 | unsigned G3:1;
350 | unsigned LE:1;
351 | unsigned GE:1;
352 | unsigned Reserved1:3;
353 | unsigned GD:1;
354 | unsigned Reserved2:2;
355 | unsigned RW0:2;
356 | unsigned LEN0:2;
357 | unsigned RW1:2;
358 | unsigned LEN1:2;
359 | unsigned RW2:2;
360 | unsigned LEN2:2;
361 | unsigned RW3:2;
362 | unsigned LEN3:2;
363 | };
364 | } DR7, *PDR7;
365 |
366 | typedef union _IA32_DEBUGCTL_MSR
367 | {
368 | ULONG Value;
369 | struct {
370 | unsigned LBR:1;
371 | unsigned BTF:1;
372 | unsigned Reserved1:4;
373 | unsigned TR:1;
374 | unsigned BTS:1;
375 | unsigned BTINT:1;
376 | unsigned BTS_OFF_OS:1;
377 | unsigned BTS_OFF_USR:1;
378 | unsigned FREEZE_LBRS_ON_PMI:1;
379 | unsigned FREEZE_PERFMON_ON_PMI:1;
380 | unsigned Reserved2:1;
381 | unsigned FREEZE_WHILE_SMM_EN:1;
382 | };
383 | } IA32_DEBUGCTL_MSR, *PIA32_DEBUGCTL_MSR;
384 |
385 | typedef struct _MSR {
386 | ULONG Lo;
387 | ULONG Hi;
388 | } MSR, *PMSR;
389 |
390 | typedef struct _VMX_BASIC_MSR {
391 | unsigned RevId:32;
392 | unsigned szVmxOnRegion:12;
393 | unsigned ClearBit:1;
394 | unsigned Reserved:3;
395 | unsigned PhysicalWidth:1;
396 | unsigned DualMonitor:1;
397 | unsigned MemoryType:4;
398 | unsigned VmExitInformation:1;
399 | unsigned Reserved2:9;
400 | } VMX_BASIC_MSR, *PVMX_BASIC_MSR;
401 |
402 | typedef struct _GUEST_REGS
403 | {
404 | ULONG64 rax;
405 | ULONG64 rcx;
406 | ULONG64 rdx;
407 | ULONG64 rbx;
408 | ULONG64 rsp;
409 | ULONG64 rbp;
410 | ULONG64 rsi;
411 | ULONG64 rdi;
412 | ULONG64 r8;
413 | ULONG64 r9;
414 | ULONG64 r10;
415 | ULONG64 r11;
416 | ULONG64 r12;
417 | ULONG64 r13;
418 | ULONG64 r14;
419 | ULONG64 r15;
420 | } GUEST_REGS, *PGUEST_REGS;
421 |
422 | USHORT _Cs();
423 | USHORT _Ds();
424 | USHORT _Es();
425 | USHORT _Ss();
426 | USHORT _Fs();
427 | USHORT _Gs();
428 | ULONG64 _Cr0();
429 | ULONG64 _Cr2();
430 | VOID _SetCr2(ULONG64 NewCr2);
431 | ULONG64 _Cr3();
432 | ULONG64 _Cr4();
433 | VOID _SetCr4(ULONG32 mask);
434 |
435 | ULONG64 _Cr8();
436 | ULONG64 _Rflags();
437 | ULONG64 _Rsp();
438 |
439 | ULONG64 _IdtBase();
440 | USHORT _IdtLimit();
441 | ULONG64 _GdtBase();
442 | USHORT _GdtLimit();
443 | USHORT _Ldtr();
444 |
445 | USHORT _TrSelector();
446 |
447 | ULONG64 _Rbx();
448 | ULONG64 _Rax();
449 |
450 | ULONG64 _TSC();
451 |
452 | ULONG64 _Dr0();
453 | ULONG64 _Dr1();
454 | ULONG64 _Dr2();
455 | ULONG64 _Dr3();
456 | ULONG64 _Dr6();
457 | ULONG64 _SetDr0();
458 | ULONG64 _SetDr1();
459 | ULONG64 _SetDr2();
460 | ULONG64 _SetDr3();
461 |
462 | ULONG64 _SetCr3(PVOID NewCr3);
463 | ULONG64 _SetCr8(ULONG64 NewCr8);
464 |
465 | VOID _CpuId(ULONG32 fn, OUT PULONG32 ret_eax, OUT PULONG32 ret_ebx, OUT
466 | PULONG32 ret_ecx, OUT PULONG32 ret_edx);
467 |
468 | ULONG64 _ReadMsr(ULONG32 reg);
469 | VOID _WriteMsr(ULONG32 reg, ULONG64 MsrValue);
470 |
471 | VOID _VmxOn(PHYSICAL_ADDRESS PA);
472 | VOID _VmxOff(ULONG64 Rip, ULONG64 Rsp);
473 | ULONG64 _ReadVMCS(ULONG32 Encoding);
474 | VOID _WriteVMCS(ULONG32 Encoding, ULONG64 Value);
475 | VOID _VmPtrLd(PHYSICAL_ADDRESS PA);
476 | VOID _VmClear(PHYSICAL_ADDRESS PA);
477 | ULONG _VmLaunch();
478 | VOID _VmResume();
479 |
480 | ULONG32 _VmFailValid();
481 | ULONG32 _VmFailInvalid();
482 |
483 | VOID _GuestEntryPoint();
484 | VOID _ExitHandler();
485 | NTSTATUS _StartVirtualization();
486 |
487 | VOID _StopVirtualization();
488 | VOID _GuestExit();
489 |
490 | VOID _Int3();
491 | VOID _Invd();
492 |
493 | VOID _InvalidatePage(ULONG64 Page);
494 | VOID _SetInterrupts();
495 | VOID _ClearInterrupts();
496 |
497 | VOID _InitSpinLock(PULONG32 Lock);
498 | VOID _AcquireSpinLock(PULONG32 Lock);
499 | VOID _ReleaseSpinLock(PULONG32 Lock);
500 |
501 |
502 | #endif
503 |
--------------------------------------------------------------------------------
/src/virtdbg/debug.h:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #ifndef _VIRTDBG_DEBUG_H
8 | #define _VIRTDBG_DEBUG_H
9 |
10 | #include
11 | #include "amd64.h"
12 | #include "vmx.h"
13 | #include "mem.h"
14 | #include "protocol.h"
15 |
16 | NTSTATUS InitDebugLayer();
17 |
18 | static BOOLEAN HandleVmInstruction(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs);
19 | static BOOLEAN HandleUnimplemented(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs, ULONG64 ExitCode);
20 | static BOOLEAN HandleCpuid(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs);
21 | static BOOLEAN HandleMsrRead(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs);
22 | static BOOLEAN HandleMsrWrite(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs);
23 | static BOOLEAN HandleDrAccess(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs);
24 | static BOOLEAN HandleCrAccess(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs);
25 | static BOOLEAN HandleException(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs);
26 | static BOOLEAN HandleNmi(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs);
27 | static BOOLEAN HandleInvd(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs);
28 |
29 | VOID HandleVmExit(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs);
30 |
31 | static VOID EnableTF();
32 | static VOID DisableTF();
33 |
34 | static VOID ReportException(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs, ULONG Exception, ULONG64 Address);
35 | static BOOLEAN EnterDebugger(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs, ULONG64 Cr3);
36 | static VOID FreezeExecution(PVIRT_CPU pCpu);
37 | static VOID ResumeCpus(ULONG32 RunningProcessor);
38 | static VOID FreezeCpus(ULONG32 RunningProcessor);
39 |
40 | static BOOLEAN HandleClientRequest(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs, ULONG64 Cr3);
41 |
42 | static BOOLEAN HandleContinuePacket(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs, PVOID pPacket);
43 |
44 | static BOOLEAN HandleBreakinPacket(PVIRT_CPU pCpu, PGUEST_REGS pGuestRegs, PVOID pPacket, ULONG64 Cr3);
45 |
46 | #endif
47 |
--------------------------------------------------------------------------------
/src/virtdbg/driver.c:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #include "driver.h"
8 |
9 | NTSTATUS DriverUnload(PDRIVER_OBJECT DriverObject)
10 | {
11 | CCHAR i;
12 | KIRQL OldIrql;
13 | KAFFINITY OldAffinity;
14 |
15 | for (i=0; iDriverUnload = DriverUnload;*/
33 |
34 | Status = PsCreateSystemThread(&hThread,
35 | THREAD_ALL_ACCESS,
36 | NULL,
37 | NULL,
38 | NULL,
39 | VirtDbgStart, NULL);
40 | if (!NT_SUCCESS(Status))
41 | {
42 | return Status;
43 | }
44 |
45 | return STATUS_SUCCESS;
46 | }
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/virtdbg/driver.h:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #ifndef _VIRTDBG_DRIVER_H
8 | #define _VIRTDBG_DRIVER_H
9 |
10 | #include
11 | #include "virtdbg.h"
12 |
13 | #endif
14 |
15 |
--------------------------------------------------------------------------------
/src/virtdbg/log.c:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #include "log.h"
8 |
9 | PVOID g_LogBuffer = NULL;
10 | static LONG g_LogIndex = 0;
11 | static PKSPIN_LOCK g_LogLock;
12 |
13 | PVOID InitLog()
14 | {
15 | g_LogBuffer = AllocateMemory(LOGBUFFER_SIZE);
16 |
17 | if (g_LogBuffer == NULL)
18 | return NULL;
19 |
20 | g_LogLock = AllocateMemory(sizeof(KSPIN_LOCK));
21 |
22 | if (g_LogLock == NULL)
23 | return NULL;
24 |
25 | KeInitializeSpinLock(g_LogLock);
26 |
27 | return g_LogBuffer;
28 | }
29 |
30 | static BOOLEAN InsertLogEntry(char *buffer, unsigned short size)
31 | {
32 | if (g_LogBuffer == NULL)
33 | return FALSE;
34 |
35 | if (g_LogIndex+size > LOGBUFFER_SIZE)
36 | {
37 | RtlZeroMemory(g_LogBuffer, LOGBUFFER_SIZE);
38 | g_LogIndex = 0;
39 | }
40 |
41 | RtlCopyMemory((PUCHAR)g_LogBuffer+g_LogIndex, buffer, size);
42 | InterlockedExchangeAdd(&g_LogIndex, size);
43 | return TRUE;
44 | }
45 |
46 | VOID Log(char *format, ...)
47 | {
48 | KIRQL CurrentIrql;
49 |
50 | unsigned short size;
51 | va_list args;
52 | UCHAR buffer[1024] = {0};
53 |
54 | va_start(args, format);
55 |
56 | CurrentIrql = KeGetCurrentIrql();
57 | if (CurrentIrql < DISPATCH_LEVEL)
58 | {
59 | KeRaiseIrqlToDpcLevel();
60 | }
61 |
62 | KeAcquireSpinLockAtDpcLevel(g_LogLock);
63 |
64 | /* RtlZeroMemory(&buffer, sizeof(buffer));*/
65 | /* vsnprintf((PUCHAR)&buffer, sizeof(buffer), "%d:", g_LogIndex);*/
66 | /* buffer[1023] = '\0';*/
67 | /* size = strlen(buffer);*/
68 |
69 | /* InsertLogEntry(buffer, size);*/
70 | /* */
71 |
72 | RtlZeroMemory(&buffer, sizeof(buffer));
73 | vsnprintf((PUCHAR)&buffer, sizeof(buffer), (PUCHAR)format, args);
74 | buffer[1023] = '\0';
75 | size = strlen(buffer);
76 |
77 | InsertLogEntry(buffer, size);
78 |
79 | KeReleaseSpinLockFromDpcLevel(g_LogLock);
80 |
81 | if (CurrentIrql < DISPATCH_LEVEL)
82 | {
83 | KeLowerIrql(CurrentIrql);
84 | }
85 | }
86 |
87 |
88 |
--------------------------------------------------------------------------------
/src/virtdbg/log.h:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #ifndef VIRTDBG_LOG_H
8 | #define VIRTDBG_LOG_H
9 |
10 | #include
11 | #include "snprintf.h"
12 | #include "mem.h"
13 | #include
14 |
15 | #define LOGBUFFER_SIZE 0x1000
16 |
17 |
18 | PVOID InitLog();
19 | VOID Log(char *format, ...);
20 |
21 |
22 | #endif
23 |
--------------------------------------------------------------------------------
/src/virtdbg/mem.c:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #include "mem.h"
8 |
9 | PVOID AllocateMemory(ULONG32 Size)
10 | {
11 | PVOID pMem = NULL;
12 | pMem = ExAllocatePoolWithTag(NonPagedPool, Size, VIRTDBG_POOLTAG);
13 | if (pMem == NULL)
14 | return NULL;
15 |
16 | RtlZeroMemory(pMem, Size);
17 | return pMem;
18 | }
19 |
20 | VOID UnAllocateMemory(PVOID pMem)
21 | {
22 | ExFreePoolWithTag(pMem, VIRTDBG_POOLTAG);
23 | }
24 |
25 | PVOID AllocateContiguousMemory(ULONG size)
26 | {
27 | PVOID Address;
28 | PHYSICAL_ADDRESS l1, l2, l3;
29 |
30 | l1.QuadPart = 0;
31 | l2.QuadPart = -1;
32 | l3.QuadPart = 0x200000;
33 |
34 | Address = MmAllocateContiguousMemorySpecifyCache(size, l1, l2, l3, MmCached);
35 |
36 | if (Address == NULL)
37 | {
38 | return NULL;
39 | }
40 |
41 | RtlZeroMemory(Address, size);
42 | return Address;
43 | }
44 |
45 | NTSTATUS IsPagePresent(ULONG64 PageVA)
46 | {
47 | ULONG64 Pml4e, Pdpe, Pde, Pte;
48 |
49 | Pml4e = *(PULONG64)(((PageVA >> 36) & 0xff8) + PML4_BASE);
50 |
51 | if (!(Pml4e & P_PRESENT))
52 | return STATUS_NO_MEMORY;
53 |
54 | Pdpe = *(PULONG64)(((PageVA >> 27) & 0x1ffff8) + PDP_BASE);
55 |
56 | if (!(Pdpe & P_PRESENT))
57 | return STATUS_NO_MEMORY;
58 |
59 | Pde = *(PULONG64)(((PageVA >> 18) & 0x3ffffff8) + PD_BASE);
60 |
61 | if (!(Pde & P_PRESENT))
62 | return STATUS_NO_MEMORY;
63 |
64 | if ((Pde & P_LARGE) == P_LARGE)
65 | return STATUS_SUCCESS;
66 |
67 | Pte = *(PULONG64)(((PageVA >> 9) & 0x7ffffffff8) + PT_BASE);
68 |
69 | if (!(Pte & P_PRESENT))
70 | return STATUS_NO_MEMORY;
71 |
72 | return STATUS_SUCCESS;
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/virtdbg/mem.h:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #ifndef _MEM_H
8 | #define _MEM_H
9 |
10 | #include
11 |
12 | #define P_PRESENT 0x01
13 | #define P_WRITABLE 0x02
14 | #define P_USERMODE 0x04
15 | #define P_WRITETHROUGH 0x08
16 | #define P_CACHE_DISABLED 0x10
17 | #define P_ACCESSED 0x20
18 | #define P_DIRTY 0x40
19 | #define P_LARGE 0x80
20 | #define P_GLOBAL 0x100
21 |
22 | #define PML4_BASE 0xfffff6fb7dbed000ULL
23 | #define PDP_BASE 0xfffff6fb7da00000ULL
24 | #define PD_BASE 0xfffff6fb40000000ULL
25 | #define PT_BASE 0xfffff68000000000ULL
26 |
27 | #define VIRTDBG_POOLTAG 0xbad0bad0
28 |
29 | PVOID AllocateMemory(ULONG32 Size);
30 | VOID UnAllocateMemory(PVOID pMem);
31 | PVOID AllocateContiguousMemory(ULONG size);
32 | NTSTATUS IsPagePresent(ULONG64 PageVA);
33 |
34 | #endif
35 |
--------------------------------------------------------------------------------
/src/virtdbg/misc.h:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #ifndef _VIRTDBG_MISC_H
8 | #define _VIRTDBG_MISC_H
9 |
10 | #include
11 | #include "log.h"
12 |
13 | //#define DbgLog(_args_) { DbgPrint("virtdbg[#%d][IRQL=0x%x](%s): ", KeGetCurrentProcessorNumber(), KeGetCurrentIrql(), __FUNCTION__); DbgPrint _args_; }
14 | #define DbgLog(_args_) { Log("vmx[#%d][IRQL=0x%x](%s): ", KeGetCurrentProcessorNumber(), KeGetCurrentIrql(), __FUNCTION__); Log _args_; }
15 |
16 |
17 | #endif
18 |
19 |
--------------------------------------------------------------------------------
/src/virtdbg/protocol.c:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #include "protocol.h"
8 |
9 | static LONG g_Id = 0;
10 | static ULONG32 g_LastId = 0;
11 | static ULONG32 g_ClientId = 0;
12 | static PVOID g_SendArea = NULL;
13 | static PVOID g_RecvArea = NULL;
14 |
15 | extern PVIRTDBG_CONTROL_AREA g_ControlArea;
16 |
17 | NTSTATUS InitProtocolLayer(PVOID SendArea, PVOID RecvArea)
18 | {
19 | g_SendArea = SendArea;
20 | g_RecvArea = RecvArea;
21 | g_Id = INITIAL_ID;
22 | return STATUS_SUCCESS;
23 | }
24 |
25 |
26 | static ULONG32 CalcChecksum(PVOID Src, ULONG32 Size)
27 | {
28 | ULONG32 Checksum;
29 | ULONG32 i;
30 |
31 | Checksum = 0;
32 | for (i=0;iId = g_Id;
45 | pHeader->ClientId = g_ClientId;
46 | pHeader->Checksum = CalcChecksum((PUCHAR)pPacket+sizeof(PACKET_HEADER),
47 | pHeader->Size);
48 | }
49 |
50 |
51 | BOOLEAN SendPacket(PVOID pPacket, ULONG32 MaxRetries)
52 | {
53 | PPACKET_HEADER pHeader;
54 | ULONG32 Size, retries;
55 |
56 | retries = 0;
57 | pHeader = (PPACKET_HEADER)pPacket;
58 |
59 | FixUpPacket(pPacket);
60 | Size = pHeader->Size+sizeof(PACKET_HEADER);
61 |
62 | if (g_SendArea == NULL)
63 | {
64 | DbgLog(("not initialized ?\n"));
65 | return FALSE;
66 | }
67 |
68 | if (Size > MAX_PACKET_SIZE)
69 | {
70 | DbgLog(("packet too big\n"));
71 | return FALSE;
72 | }
73 |
74 | RtlCopyMemory(g_SendArea, pPacket, Size);
75 | DestroyPacket(pPacket);
76 |
77 | while (retries < MaxRetries)
78 | {
79 | retries++;
80 | if (g_ControlArea->LastServerId == pHeader->Id)
81 | {
82 | InterlockedIncrement(&g_Id);
83 | DbgLog(("packet successfully sent\n"));
84 | return TRUE;
85 | }
86 | }
87 | DbgLog(("no ack after %d retries\n", retries));
88 | return FALSE;
89 | }
90 |
91 | VOID CheckNewClientId()
92 | {
93 | if (g_ControlArea == NULL)
94 | return;
95 |
96 | g_ControlArea->ServerId = g_ControlArea->ClientId;
97 | if (g_ControlArea->ClientId != g_ClientId)
98 | {
99 | DbgLog(("new client : 0x%x\n", g_ControlArea->ClientId));
100 | g_ClientId = g_ControlArea->ClientId;
101 | g_Id = INITIAL_ID;
102 | g_LastId = 0;
103 | DbgLog(("send @ 0x%llx (0x%llx) recv @ 0x%llx (0x%llx)\n", g_SendArea, g_ControlArea->RecvArea, g_RecvArea, g_ControlArea->SendArea));
104 | DbgLog(("sizeof(MANIPULATE_STATE_PACKET)=0x%x\n",
105 | sizeof(MANIPULATE_STATE_PACKET)));
106 | DbgLog(("sizeof(PACKET_HEADER)=0x%x\n",
107 | sizeof(PACKET_HEADER)));
108 |
109 | }
110 |
111 | }
112 |
113 | PVOID ReceivePacket()
114 | {
115 | PVOID pPacket;
116 | PPACKET_HEADER pHeader;
117 | ULONG32 Size, Checksum;
118 |
119 | CheckNewClientId();
120 |
121 | if (g_RecvArea == NULL)
122 | {
123 | DbgLog(("not initialized ?\n"));
124 | return NULL;
125 | }
126 |
127 | pHeader = (PPACKET_HEADER)(g_RecvArea);
128 | if (pHeader->Magic != PACKET_MAGIC)
129 | return NULL;
130 |
131 | if (pHeader->Size > MAX_PACKET_SIZE)
132 | return NULL;
133 |
134 | if (pHeader->Id <= g_LastId)
135 | return NULL;
136 |
137 | Size = sizeof(PACKET_HEADER) + pHeader->Size;
138 | pPacket = AllocateMemory(Size);
139 | if (pPacket == NULL)
140 | {
141 | return NULL;
142 | }
143 |
144 | RtlCopyMemory(pPacket, g_RecvArea, Size);
145 |
146 | if (pHeader->Size > 0)
147 | {
148 | Checksum = CalcChecksum((PUCHAR)pPacket+sizeof(PACKET_HEADER),
149 | pHeader->Size);
150 | if (Checksum != pHeader->Checksum)
151 | {
152 | UnAllocateMemory(pPacket);
153 | return NULL;
154 | }
155 | }
156 |
157 | g_LastId = pHeader->Id;
158 | g_ControlArea->LastClientId = g_LastId;
159 | DbgLog(("Received packet (id=0x%x)\n", g_LastId));
160 | return pPacket;
161 |
162 | }
163 |
164 |
165 | static PVOID CreateBreakinPacket()
166 | {
167 | PVOID pPacket;
168 | PPACKET_HEADER pHeader;
169 | ULONG32 Size;
170 |
171 | Size = sizeof(PACKET_HEADER)+sizeof(BREAKIN_PACKET);
172 |
173 | pPacket = AllocateMemory(Size);
174 | if (pPacket == NULL)
175 | return NULL;
176 |
177 | pHeader = (PPACKET_HEADER)pPacket;
178 | pHeader->Magic = PACKET_MAGIC;
179 | pHeader->Type = PACKET_TYPE_BREAKIN;
180 | pHeader->Size = sizeof(BREAKIN_PACKET);
181 |
182 | return pPacket;
183 |
184 | }
185 |
186 | PVOID CreateManipulateStatePacket(ULONG32 ApiNumber, ULONG32 Data2Size)
187 | {
188 | PVOID pPacket;
189 | PPACKET_HEADER pHeader;
190 | PMANIPULATE_STATE_PACKET pData1;
191 | ULONG32 Size;
192 |
193 | Size = sizeof(PACKET_HEADER)+sizeof(MANIPULATE_STATE_PACKET)+Data2Size;
194 |
195 | pPacket = AllocateMemory(Size);
196 | if (pPacket == NULL)
197 | return NULL;
198 |
199 | pHeader = (PPACKET_HEADER)pPacket;
200 | pHeader->Magic = PACKET_MAGIC;
201 | pHeader->Type = PACKET_TYPE_MANIPULATE_STATE;
202 | pHeader->Size = sizeof(MANIPULATE_STATE_PACKET)+Data2Size;
203 |
204 | pData1 = (PMANIPULATE_STATE_PACKET)((PUCHAR)pPacket+sizeof(PACKET_HEADER));
205 | pData1->ApiNumber = ApiNumber;
206 | return pPacket;
207 | }
208 |
209 | PVOID CreateStateChangePacket(ULONG32 Exception, ULONG64 Address)
210 | {
211 | PVOID pPacket;
212 | PPACKET_HEADER pHeader;
213 |
214 | PSTATE_CHANGE_PACKET pData1;
215 | ULONG32 Size;
216 |
217 | Size = sizeof(PACKET_HEADER)+sizeof(STATE_CHANGE_PACKET);
218 | pPacket = AllocateMemory(Size);
219 | if (pPacket == NULL)
220 | return NULL;
221 |
222 | pHeader = (PPACKET_HEADER)pPacket;
223 | pHeader->Magic = PACKET_MAGIC;
224 | pHeader->Type = PACKET_TYPE_STATE_CHANGE;
225 | pHeader->Size = sizeof(STATE_CHANGE_PACKET);
226 |
227 | pData1 = (PSTATE_CHANGE_PACKET)((PUCHAR)pPacket+sizeof(PACKET_HEADER));
228 | pData1->Exception = Exception;
229 | pData1->Address = Address;
230 | return pPacket;
231 | }
232 |
233 |
234 | VOID DestroyPacket(PVOID pPacket)
235 | {
236 | UnAllocateMemory(pPacket);
237 | }
238 |
239 |
240 |
--------------------------------------------------------------------------------
/src/virtdbg/protocol.h:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #ifndef _VIRTDBG_PROTOCOL_H
8 | #define _VIRTDBG_PROTOCOL_H
9 |
10 | #include
11 | #include "misc.h"
12 | #include "mem.h"
13 |
14 | typedef struct _VIRTDBG_CONTROL_AREA
15 | {
16 | ULONG32 Magic1;
17 | ULONG32 Magic2;
18 | PHYSICAL_ADDRESS SendArea;
19 | PHYSICAL_ADDRESS RecvArea;
20 | PVOID KernelBase;
21 | PVOID DebuggerData;
22 | PHYSICAL_ADDRESS LogBuffer;
23 | ULONG32 ClientId;
24 | ULONG32 ServerId;
25 | ULONG32 LastClientId;
26 | ULONG32 LastServerId;
27 | LONG State;
28 | } VIRTDBG_CONTROL_AREA, *PVIRTDBG_CONTROL_AREA;
29 |
30 | #define CONTROL_AREA_SIZE 0x1000
31 | #define CONTROL_AREA_MAGIC1 0xbabebabe
32 | #define CONTROL_AREA_MAGIC2 0xcafecafe
33 |
34 | typedef struct _PACKET_HEADER {
35 | ULONG32 Magic;
36 | ULONG32 Type;
37 | ULONG32 Size;
38 | ULONG32 Id;
39 | ULONG32 ClientId;
40 | ULONG32 Checksum;
41 | } PACKET_HEADER, *PPACKET_HEADER;
42 |
43 | typedef struct _BREAKIN_PACKET {
44 | ULONG64 Cr3;
45 | } BREAKIN_PACKET, *PBREAKIN_PACKET;
46 |
47 | #define CONTINUE_STATUS_SINGLE_STEP 0x1
48 | #define CONTINUE_STATUS_UNLOAD 0x2
49 | #define CONTINUE_STATUS_CONTINUE 0x3
50 |
51 | typedef struct _CONTINUE_PACKET {
52 | ULONG32 Status;
53 | } CONTINUE_PACKET, *PCONTINUE_PACKET;
54 |
55 | typedef struct _SOFTWARE_BREAKPOINT_PACKET {
56 | ULONG64 Address;
57 | } SOFTWARE_BREAKPOINT_PACKET, *PSOFTWARE_BREAKPOINT_PACKET;
58 |
59 | typedef struct _HARDWARE_BREAKPOINT_PACKET {
60 | ULONG64 Address;
61 | } HARDWARE_BREAKPOINT_PACKET, *PHARDWARE_BREAKPOINT_PACKET;
62 |
63 | typedef struct _MEMORY_BREAKPOINT_PACKET {
64 | ULONG64 Address;
65 | } MEMORY_BREAKPOINT_PACKET, *PMEMORY_BREAKPOINT_PACKET;
66 |
67 | typedef struct _STATE_CHANGE_PACKET {
68 | ULONG32 Exception;
69 | ULONG64 Address;
70 | } STATE_CHANGE_PACKET, *PSTATE_CHANGE_PACKET;
71 |
72 | typedef struct _READ_VIRTUAL_MEMORY_PACKET {
73 | ULONG64 Address;
74 | ULONG32 Size;
75 | } READ_VIRTUAL_MEMORY_PACKET, *PREAD_VIRTUAL_MEMORY_PACKET;
76 |
77 | typedef struct _WRITE_VIRTUAL_MEMORY_PACKET {
78 | ULONG64 Address;
79 | ULONG32 Size;
80 | } WRITE_VIRTUAL_MEMORY_PACKET, *PWRITE_VIRTUAL_MEMORY_PACKET;
81 |
82 | typedef struct _READ_PHYSICAL_MEMORY_PACKET {
83 | ULONG64 Address;
84 | ULONG32 Size;
85 | } READ_PHYSICAL_MEMORY_PACKET, *PREAD_PHYSICAL_MEMORY_PACKET;
86 |
87 | typedef struct _WRITE_PHYSICAL_MEMORY_PACKET {
88 | ULONG64 Address;
89 | ULONG32 Size;
90 | } WRITE_PHYSICAL_MEMORY_PACKET, *PWRITE_PHYSICAL_MEMORY_PACKET;
91 |
92 | typedef struct _DEBUG_CONTEXT {
93 | ULONG64 rax;
94 | ULONG64 rbx;
95 | ULONG64 rcx;
96 | ULONG64 rdx;
97 | ULONG64 rsi;
98 | ULONG64 rdi;
99 | ULONG64 rbp;
100 | ULONG64 rsp;
101 | ULONG64 r8;
102 | ULONG64 r9;
103 | ULONG64 r10;
104 | ULONG64 r11;
105 | ULONG64 r12;
106 | ULONG64 r13;
107 | ULONG64 r14;
108 | ULONG64 r15;
109 | ULONG64 rip;
110 | ULONG64 rflags;
111 | ULONG64 cr0;
112 | ULONG64 cr3;
113 | ULONG64 cr4;
114 | ULONG64 cr8;
115 | ULONG64 dr0;
116 | ULONG64 dr1;
117 | ULONG64 dr2;
118 | ULONG64 dr3;
119 | ULONG64 dr6;
120 | ULONG64 dr7;
121 | USHORT cs;
122 | USHORT ds;
123 | USHORT es;
124 | USHORT fs;
125 | USHORT ss;
126 | USHORT gs;
127 | } DEBUG_CONTEXT, *PDEBUG_CONTEXT;
128 |
129 | typedef struct _GET_CONTEXT_PACKET {
130 | ULONG32 Flags;
131 | } GET_CONTEXT_PACKET, *PGET_CONTEXT_PACKET;
132 |
133 | typedef struct _SET_CONTEXT_PACKET {
134 | ULONG32 Flags;
135 | } SET_CONTEXT_PACKET, *PSET_CONTEXT_PACKET;
136 |
137 | typedef struct _MANIPULATE_STATE_PACKET {
138 | ULONG32 ApiNumber;
139 | ULONG32 Error;
140 | union {
141 | READ_VIRTUAL_MEMORY_PACKET ReadVirtualMemory;
142 | WRITE_VIRTUAL_MEMORY_PACKET WriteVirtualMemory;
143 | READ_PHYSICAL_MEMORY_PACKET ReadPhysicalMemory;
144 | WRITE_PHYSICAL_MEMORY_PACKET WritePhysicalMemory;
145 | GET_CONTEXT_PACKET GetContext;
146 | SET_CONTEXT_PACKET SetContext;
147 | } u;
148 | } MANIPULATE_STATE_PACKET, *PMANIPULATE_STATE_PACKET;
149 |
150 | #define PACKET_TYPE_RESET 1
151 | #define PACKET_TYPE_BREAKIN 2
152 | #define PACKET_TYPE_ACK 3
153 | #define PACKET_TYPE_RESEND 4
154 | #define PACKET_TYPE_STATE_CHANGE 5
155 | #define PACKET_TYPE_MANIPULATE_STATE 6
156 | #define PACKET_TYPE_CONTINUE 7
157 |
158 | #define READ_VIRTUAL_MEMORY_API 0x41
159 | #define WRITE_VIRTUAL_MEMORY_API 0x42
160 | #define GET_CONTEXT_API 0x43
161 | #define SET_CONTEXT_API 0x44
162 |
163 | #define INITIAL_ID 0x41424344
164 | #define PACKET_MAGIC 0xdeadbabe
165 |
166 | #define MAX_PACKET_SIZE 0x800
167 |
168 | #define MAX_RETRIES 0x10000000
169 |
170 | NTSTATUS InitProtocolLayer(PVOID SendArea, PVOID RecvArea);
171 | PVOID ReceivePacket();
172 | BOOLEAN SendPacket(PVOID pPacket, ULONG32 Retries);
173 | VOID DestroyPacket(PVOID pPacket);
174 |
175 | static PVOID CreateBreakinPacket();
176 | PVOID CreateManipulateStatePacket(ULONG32 ApiNumber, ULONG32 Data2Size);
177 | PVOID CreateStateChangePacket(ULONG32 Exception, ULONG64 Address);
178 | static ULONG32 CalcChecksum(PVOID Src, ULONG32 Size);
179 |
180 | #endif
181 |
--------------------------------------------------------------------------------
/src/virtdbg/snprintf.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Patrick Powell 1995
3 | * This code is based on code written by Patrick Powell (papowell@astart.com)
4 | * It may be used for any purpose as long as this notice remains intact
5 | * on all source code distributions
6 | */
7 |
8 | /**************************************************************
9 | * Original:
10 | * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
11 | * A bombproof version of doprnt (dopr) included.
12 | * Sigh. This sort of thing is always nasty do deal with. Note that
13 | * the version here does not include floating point...
14 | *
15 | * snprintf() is used instead of sprintf() as it does limit checks
16 | * for string length. This covers a nasty loophole.
17 | *
18 | * The other functions are there to prevent NULL pointers from
19 | * causing nast effects.
20 | *
21 | * More Recently:
22 | * Brandon Long 9/15/96 for mutt 0.43
23 | * This was ugly. It is still ugly. I opted out of floating point
24 | * numbers, but the formatter understands just about everything
25 | * from the normal C string format, at least as far as I can tell from
26 | * the Solaris 2.5 printf(3S) man page.
27 | *
28 | * Brandon Long 10/22/97 for mutt 0.87.1
29 | * Ok, added some minimal floating point support, which means this
30 | * probably requires libm on most operating systems. Don't yet
31 | * support the exponent (e,E) and sigfig (g,G). Also, fmtint()
32 | * was pretty badly broken, it just wasn't being exercised in ways
33 | * which showed it, so that's been fixed. Also, formated the code
34 | * to mutt conventions, and removed dead code left over from the
35 | * original. Also, there is now a builtin-test, just compile with:
36 | * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
37 | * and run snprintf for results.
38 | *
39 | * Thomas Roessler 01/27/98 for mutt 0.89i
40 | * The PGP code was using unsigned hexadecimal formats.
41 | * Unfortunately, unsigned formats simply didn't work.
42 | *
43 | * Michael Elkins 03/05/98 for mutt 0.90.8
44 | * The original code assumed that both snprintf() and vsnprintf() were
45 | * missing. Some systems only have snprintf() but not vsnprintf(), so
46 | * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
47 | *
48 | * Andrew Tridgell (tridge@samba.org) Oct 1998
49 | * fixed handling of %.0f
50 | * added test for HAVE_LONG_DOUBLE
51 | *
52 | * tridge@samba.org, idra@samba.org, April 2001
53 | * got rid of fcvt code (twas buggy and made testing harder)
54 | * added C99 semantics
55 | *
56 | **************************************************************/
57 |
58 | #define HAVE_STRING_H
59 | #define HAVE_CTYPE_H
60 | #define HAVE_STDLIB_H
61 | #define HAVE_LONG_LONG
62 |
63 | #ifdef HAVE_STRING_H
64 | # include
65 | #endif
66 |
67 | #ifdef HAVE_STRINGS_H
68 | # include
69 | #endif
70 | #ifdef HAVE_CTYPE_H
71 | # include
72 | #endif
73 | #include
74 | #include
75 | #ifdef HAVE_STDLIB_H
76 | # include
77 | #endif
78 |
79 | #if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF)
80 | /* only include stdio.h if we are not re-defining snprintf or vsnprintf */
81 | # include
82 | /* make the compiler happy with an empty file */
83 | void dummy_snprintf (
84 | void
85 | )
86 | {
87 | }
88 | #else
89 |
90 | # ifdef HAVE_LONG_LONG
91 | # define LLONG long long
92 | # else
93 | # define LLONG long
94 | # endif
95 |
96 | # ifdef isdigit
97 | # undef isdigit
98 | # endif
99 | # define isdigit(c) ((c) >= '0' && (c) <= '9')
100 |
101 | static size_t dopr (
102 | char *buffer,
103 | size_t maxlen,
104 | const char *format,
105 | va_list args
106 | );
107 | static void fmtstr (
108 | char *buffer,
109 | size_t * currlen,
110 | size_t maxlen,
111 | char *value,
112 | int flags,
113 | int min,
114 | int max
115 | );
116 | static void fmtint (
117 | char *buffer,
118 | size_t * currlen,
119 | size_t maxlen,
120 | long long value,
121 | int base,
122 | int min,
123 | int max,
124 | int flags
125 | );
126 | static void dopr_outch (
127 | char *buffer,
128 | size_t * currlen,
129 | size_t maxlen,
130 | char c
131 | );
132 |
133 | /*
134 | * dopr(): poor man's version of doprintf
135 | */
136 |
137 | /* format read states */
138 | # define DP_S_DEFAULT 0
139 | # define DP_S_FLAGS 1
140 | # define DP_S_MIN 2
141 | # define DP_S_DOT 3
142 | # define DP_S_MAX 4
143 | # define DP_S_MOD 5
144 | # define DP_S_CONV 6
145 | # define DP_S_DONE 7
146 |
147 | /* format flags - Bits */
148 | # define DP_F_MINUS (1 << 0)
149 | # define DP_F_PLUS (1 << 1)
150 | # define DP_F_SPACE (1 << 2)
151 | # define DP_F_NUM (1 << 3)
152 | # define DP_F_ZERO (1 << 4)
153 | # define DP_F_UP (1 << 5)
154 | # define DP_F_UNSIGNED (1 << 6)
155 |
156 | /* Conversion Flags */
157 | # define DP_C_SHORT 1
158 | # define DP_C_LONG 2
159 | # define DP_C_LDOUBLE 3
160 | # define DP_C_LLONG 4
161 |
162 | # define char_to_int(p) ((p)- '0')
163 | # ifndef MAX
164 | # define MAX(p,q) (((p) >= (q)) ? (p) : (q))
165 | # endif
166 |
167 | static size_t dopr (
168 | char *buffer,
169 | size_t maxlen,
170 | const char *format,
171 | va_list args
172 | )
173 | {
174 | char ch;
175 | LLONG value;
176 | char *strvalue;
177 | int min;
178 | int max;
179 | int state;
180 | int flags;
181 | int cflags;
182 | size_t currlen;
183 |
184 | state = DP_S_DEFAULT;
185 | currlen = flags = cflags = min = 0;
186 | max = -1;
187 | ch = *format++;
188 |
189 | while (state != DP_S_DONE) {
190 | if (ch == '\0')
191 | state = DP_S_DONE;
192 |
193 | switch (state) {
194 | case DP_S_DEFAULT:
195 | if (ch == '%')
196 | state = DP_S_FLAGS;
197 | else
198 | dopr_outch (buffer, &currlen, maxlen, ch);
199 | ch = *format++;
200 | break;
201 | case DP_S_FLAGS:
202 | switch (ch) {
203 | case '-':
204 | flags |= DP_F_MINUS;
205 | ch = *format++;
206 | break;
207 | case '+':
208 | flags |= DP_F_PLUS;
209 | ch = *format++;
210 | break;
211 | case ' ':
212 | flags |= DP_F_SPACE;
213 | ch = *format++;
214 | break;
215 | case '#':
216 | flags |= DP_F_NUM;
217 | ch = *format++;
218 | break;
219 | case '0':
220 | flags |= DP_F_ZERO;
221 | ch = *format++;
222 | break;
223 | default:
224 | state = DP_S_MIN;
225 | break;
226 | }
227 | break;
228 | case DP_S_MIN:
229 | if (isdigit ((unsigned char) ch)) {
230 | min = 10 * min + char_to_int (ch);
231 | ch = *format++;
232 | } else if (ch == '*') {
233 | min = va_arg (args, int
234 | );
235 | ch = *format++;
236 | state = DP_S_DOT;
237 | } else {
238 | state = DP_S_DOT;
239 | }
240 | break;
241 | case DP_S_DOT:
242 | if (ch == '.') {
243 | state = DP_S_MAX;
244 | ch = *format++;
245 | } else {
246 | state = DP_S_MOD;
247 | }
248 | break;
249 | case DP_S_MAX:
250 | if (isdigit ((unsigned char) ch)) {
251 | if (max < 0)
252 | max = 0;
253 | max = 10 * max + char_to_int (ch);
254 | ch = *format++;
255 | } else if (ch == '*') {
256 | max = va_arg (args, int
257 | );
258 | ch = *format++;
259 | state = DP_S_MOD;
260 | } else {
261 | state = DP_S_MOD;
262 | }
263 | break;
264 | case DP_S_MOD:
265 | switch (ch) {
266 | case 'h':
267 | cflags = DP_C_SHORT;
268 | ch = *format++;
269 | break;
270 | case 'l':
271 | cflags = DP_C_LONG;
272 | ch = *format++;
273 | if (ch == 'l') { /* It's a long long */
274 | cflags = DP_C_LLONG;
275 | ch = *format++;
276 | }
277 | break;
278 | case 'L':
279 | cflags = DP_C_LDOUBLE;
280 | ch = *format++;
281 | break;
282 | default:
283 | break;
284 | }
285 | state = DP_S_CONV;
286 | break;
287 | case DP_S_CONV:
288 | switch (ch) {
289 | case 'd':
290 | case 'i':
291 | if (cflags == DP_C_SHORT)
292 | value = va_arg (args, int
293 | );
294 | else if (cflags == DP_C_LONG)
295 | value = va_arg (args, long int
296 | );
297 | else if (cflags == DP_C_LLONG)
298 | value = va_arg (args, LLONG);
299 | else
300 | value = va_arg (args, int
301 | );
302 | fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
303 | break;
304 | case 'o':
305 | flags |= DP_F_UNSIGNED;
306 | if (cflags == DP_C_SHORT)
307 | value = va_arg (args, unsigned int
308 | );
309 | else if (cflags == DP_C_LONG)
310 | value = (long) va_arg (args, unsigned long int
311 | );
312 | else if (cflags == DP_C_LLONG)
313 | value = (long) va_arg (args, unsigned LLONG
314 | );
315 | else
316 | value = (long) va_arg (args, unsigned int
317 | );
318 | fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
319 | break;
320 | case 'u':
321 | flags |= DP_F_UNSIGNED;
322 | if (cflags == DP_C_SHORT)
323 | value = va_arg (args, unsigned int
324 | );
325 | else if (cflags == DP_C_LONG)
326 | value = (long) va_arg (args, unsigned long int
327 | );
328 | else if (cflags == DP_C_LLONG)
329 | value = (LLONG) va_arg (args, unsigned LLONG
330 | );
331 | else
332 | value = (long) va_arg (args, unsigned int
333 | );
334 | fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
335 | break;
336 | case 'X':
337 | flags |= DP_F_UP;
338 | case 'x':
339 | flags |= DP_F_UNSIGNED;
340 | if (cflags == DP_C_SHORT)
341 | value = va_arg (args, unsigned int
342 | );
343 | else if (cflags == DP_C_LONG)
344 | value = (long) va_arg (args, unsigned long int
345 | );
346 | else if (cflags == DP_C_LLONG)
347 | value = (LLONG) va_arg (args, unsigned LLONG
348 | );
349 | else
350 | value = (long) va_arg (args, unsigned int
351 | );
352 | fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
353 | break;
354 | case 'f':
355 | break;
356 | case 'E':
357 | flags |= DP_F_UP;
358 | case 'e':
359 | break;
360 | case 'G':
361 | flags |= DP_F_UP;
362 | case 'g':
363 | break;
364 | case 'c':
365 | dopr_outch (buffer, &currlen, maxlen, va_arg (args, char)
366 | );
367 | break;
368 | case 's':
369 | strvalue = va_arg (args, char *
370 | );
371 | if (max == -1) {
372 | max = (int)strlen (strvalue);
373 | }
374 | if (min > 0 && max >= 0 && min > max)
375 | max = min;
376 | fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
377 | break;
378 | case 'p':
379 | flags |= DP_F_UNSIGNED | DP_F_UP;
380 | strvalue = va_arg (args, void *
381 | );
382 | fmtint (buffer, &currlen, maxlen, (long long) strvalue, 16, min, max, flags);
383 | break;
384 | case 'n':
385 | if (cflags == DP_C_SHORT) {
386 | short int *num;
387 | num = va_arg (args, short int *
388 | );
389 | *num = (short int) currlen;
390 | } else if (cflags == DP_C_LONG) {
391 | long int *num;
392 | num = va_arg (args, long int *
393 | );
394 | *num = (long int) currlen;
395 | } else if (cflags == DP_C_LLONG) {
396 | LLONG *num;
397 | num = va_arg (args, LLONG *);
398 | *num = (LLONG) currlen;
399 | } else {
400 | int *num;
401 | num = va_arg (args, int *
402 | );
403 | *num = (int)currlen;
404 | }
405 | break;
406 | case '%':
407 | dopr_outch (buffer, &currlen, maxlen, ch);
408 | break;
409 | case 'w':
410 | /* not supported yet, treat as next char */
411 | ch = *format++;
412 | break;
413 | default:
414 | /* Unknown, skip */
415 | break;
416 | }
417 | ch = *format++;
418 | state = DP_S_DEFAULT;
419 | flags = cflags = min = 0;
420 | max = -1;
421 | break;
422 | case DP_S_DONE:
423 | break;
424 | default:
425 | /* hmm? */
426 | break; /* some picky compilers need this */
427 | }
428 | }
429 | if (maxlen != 0) {
430 | if (currlen < maxlen - 1)
431 | buffer[currlen] = '\0';
432 | else if (maxlen > 0)
433 | buffer[maxlen - 1] = '\0';
434 | }
435 |
436 | return currlen;
437 | }
438 |
439 | static void fmtstr (
440 | char *buffer,
441 | size_t * currlen,
442 | size_t maxlen,
443 | char *value,
444 | int flags,
445 | int min,
446 | int max
447 | )
448 | {
449 | int padlen, strln; /* amount to pad */
450 | int cnt = 0;
451 |
452 | # ifdef DEBUG_SNPRINTF
453 | printf ("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
454 | # endif
455 | if (value == 0) {
456 | value = "";
457 | }
458 |
459 | for (strln = 0; value[strln]; ++strln); /* strlen */
460 | padlen = min - strln;
461 | if (padlen < 0)
462 | padlen = 0;
463 | if (flags & DP_F_MINUS)
464 | padlen = -padlen; /* Left Justify */
465 |
466 | while ((padlen > 0) && (cnt < max)) {
467 | dopr_outch (buffer, currlen, maxlen, ' ');
468 | --padlen;
469 | ++cnt;
470 | }
471 | while (*value && (cnt < max)) {
472 | dopr_outch (buffer, currlen, maxlen, *value++);
473 | ++cnt;
474 | }
475 | while ((padlen < 0) && (cnt < max)) {
476 | dopr_outch (buffer, currlen, maxlen, ' ');
477 | ++padlen;
478 | ++cnt;
479 | }
480 | }
481 |
482 | /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
483 |
484 | static void fmtint (
485 | char *buffer,
486 | size_t * currlen,
487 | size_t maxlen,
488 | long long value,
489 | int base,
490 | int min,
491 | int max,
492 | int flags
493 | )
494 | {
495 | int signvalue = 0;
496 | unsigned long long uvalue;
497 | char convert[20];
498 | int place = 0;
499 | int spadlen = 0; /* amount to space pad */
500 | int zpadlen = 0; /* amount to zero pad */
501 | int caps = 0;
502 |
503 | if (max < 0)
504 | max = 0;
505 |
506 | uvalue = (unsigned long long) value;
507 |
508 | if (!(flags & DP_F_UNSIGNED)) {
509 | if (value < 0) {
510 | signvalue = '-';
511 | uvalue = (unsigned long long) -value;
512 | } else {
513 | if (flags & DP_F_PLUS) /* Do a sign (+/i) */
514 | signvalue = '+';
515 | else if (flags & DP_F_SPACE)
516 | signvalue = ' ';
517 | }
518 | }
519 |
520 | if (flags & DP_F_UP)
521 | caps = 1; /* Should characters be upper case? */
522 |
523 | do {
524 | convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
525 | [uvalue % (unsigned) base];
526 | uvalue = (uvalue / (unsigned) base);
527 | } while (uvalue && (place < 20));
528 | if (place == 20)
529 | place--;
530 | convert[place] = 0;
531 |
532 | zpadlen = max - place;
533 | spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
534 | if (zpadlen < 0)
535 | zpadlen = 0;
536 | if (spadlen < 0)
537 | spadlen = 0;
538 | if (flags & DP_F_ZERO) {
539 | zpadlen = MAX (zpadlen, spadlen);
540 | spadlen = 0;
541 | }
542 | if (flags & DP_F_MINUS)
543 | spadlen = -spadlen; /* Left Justifty */
544 |
545 | # ifdef DEBUG_SNPRINTF
546 | printf ("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", zpadlen, spadlen, min, max, place);
547 | # endif
548 |
549 | /* Spaces */
550 | while (spadlen > 0) {
551 | dopr_outch (buffer, currlen, maxlen, ' ');
552 | --spadlen;
553 | }
554 |
555 | /* Sign */
556 | if (signvalue)
557 | dopr_outch (buffer, currlen, maxlen, (char) signvalue);
558 |
559 | /* Zeros */
560 | if (zpadlen > 0) {
561 | while (zpadlen > 0) {
562 | dopr_outch (buffer, currlen, maxlen, '0');
563 | --zpadlen;
564 | }
565 | }
566 |
567 | /* Digits */
568 | while (place > 0)
569 | dopr_outch (buffer, currlen, maxlen, convert[--place]);
570 |
571 | /* Left Justified spaces */
572 | while (spadlen < 0) {
573 | dopr_outch (buffer, currlen, maxlen, ' ');
574 | ++spadlen;
575 | }
576 | }
577 |
578 | static void dopr_outch (
579 | char *buffer,
580 | size_t * currlen,
581 | size_t maxlen,
582 | char c
583 | )
584 | {
585 | if (*currlen < maxlen) {
586 | buffer[(*currlen)] = c;
587 | }
588 | (*currlen)++;
589 | }
590 |
591 | # if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
592 | int vsnprintf (
593 | char *str,
594 | size_t count,
595 | const char *fmt,
596 | va_list args
597 | )
598 | {
599 | return (int)dopr (str, count, fmt, args);
600 | }
601 | # endif
602 |
603 | # if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
604 | int snprintf (
605 | char *str,
606 | size_t count,
607 | const char *fmt,
608 | ...
609 | )
610 | {
611 | size_t ret;
612 | va_list ap;
613 |
614 | va_start (ap, fmt);
615 | ret = vsnprintf (str, count, fmt, ap);
616 | va_end (ap);
617 | return (int)ret;
618 | }
619 | # endif
620 |
621 | #endif
622 |
--------------------------------------------------------------------------------
/src/virtdbg/snprintf.h:
--------------------------------------------------------------------------------
1 | #ifndef _PORTABLE_SNPRINTF_H_
2 | # define _PORTABLE_SNPRINTF_H_
3 |
4 | extern int snprintf (
5 | char *,
6 | size_t,
7 | const char *, /*args */
8 | ...
9 | );
10 | extern int vsnprintf (
11 | char *,
12 | size_t,
13 | const char *,
14 | va_list
15 | );
16 |
17 | #endif
18 |
--------------------------------------------------------------------------------
/src/virtdbg/sources:
--------------------------------------------------------------------------------
1 | TARGETNAME=virtdbg
2 | TARGETTYPE=DRIVER
3 | TARGETPATH=..\..\build\virtdbg
4 |
5 | INCLUDES=.
6 |
7 | MSC_WARNING_LEVEL=/W4 /wd4201 /wd4214 /wd4100
8 |
9 | SOURCES=\
10 | snprintf.c \
11 | log.c \
12 | mem.c \
13 | debug.c \
14 | protocol.c \
15 | vmx.c \
16 | virtdbg.c \
17 | driver.c
18 |
19 | AMD64_SOURCES=\
20 | amd64.asm
21 |
22 |
--------------------------------------------------------------------------------
/src/virtdbg/virtdbg.c:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #include "virtdbg.h"
8 |
9 | static KMUTEX g_mutex;
10 | static LONG g_processors = 0;
11 |
12 | PVIRT_CPU *g_cpus = NULL;
13 | PVIRTDBG_CONTROL_AREA g_ControlArea = NULL;
14 | LONG g_Initialized = 0;
15 |
16 | static PVOID g_SendArea = NULL;
17 | static PVOID g_RecvArea = NULL;
18 |
19 | extern PVOID g_LogBuffer;
20 |
21 | NTSTATUS VirtDbgStart(PVOID StartContext)
22 | {
23 | NTSTATUS Status;
24 | CCHAR i;
25 | KIRQL OldIrql;
26 | KAFFINITY OldAffinity;
27 |
28 | InitLog();
29 |
30 | Status = CheckForVirtualizationSupport();
31 | if (Status == STATUS_UNSUCCESSFUL)
32 | {
33 | DbgLog(("aborting, no virtualisation support\n"));
34 | return STATUS_UNSUCCESSFUL;
35 | }
36 |
37 | KeInitializeMutex(&g_mutex, 0);
38 | KeWaitForSingleObject(&g_mutex, Executive, KernelMode, FALSE, NULL);
39 | DbgLog(("virtualizing %d processors ...\n", KeNumberProcessors));
40 |
41 | g_cpus = ExAllocatePoolWithTag(NonPagedPool, KeNumberProcessors*sizeof(PVIRT_CPU), 0x42424242);
42 |
43 | if (!g_cpus)
44 | {
45 | DbgLog(("can't allocate cpus array\n"));
46 | return STATUS_INSUFFICIENT_RESOURCES;
47 | }
48 |
49 | DbgLog(("Allocated g_cpus array @ 0x%llx, size=0x%x\n", g_cpus, KeNumberProcessors*sizeof(PVIRT_CPU)));
50 | RtlZeroMemory(g_cpus, KeNumberProcessors*sizeof(PVIRT_CPU));
51 |
52 | InitControlArea();
53 | InitDebugLayer();
54 | InitProtocolLayer(g_SendArea, g_RecvArea);
55 |
56 | for (i = 0; i < KeNumberProcessors; i++)
57 | {
58 | OldAffinity = KeSetSystemAffinityThreadEx((KAFFINITY) (1 << i));
59 | OldIrql = KeRaiseIrqlToDpcLevel();
60 | _StartVirtualization();
61 | KeLowerIrql(OldIrql);
62 | KeRevertToUserAffinityThreadEx(OldAffinity);
63 | }
64 |
65 | DbgLog(("all done...\n"));
66 |
67 | KeReleaseMutex (&g_mutex, FALSE);
68 |
69 | if (KeNumberProcessors != g_processors)
70 | {
71 | DbgLog(("aborting, not all processors are virtualized\n"));
72 | return STATUS_UNSUCCESSFUL;
73 | }
74 |
75 | InterlockedIncrement(&g_Initialized);
76 |
77 | /* for (i = 0; i < KeNumberProcessors; i++)*/
78 | /* {*/
79 | /* DumpVirtCpu(g_cpus[i]);*/
80 | /* }*/
81 |
82 | return STATUS_SUCCESS;
83 |
84 | }
85 |
86 | NTSTATUS InitControlArea()
87 | {
88 | PHYSICAL_ADDRESS l1, l2, l3;
89 |
90 | l1.QuadPart = 0;
91 | l2.QuadPart = -1;
92 | l3.QuadPart = 0x200000;
93 |
94 | g_ControlArea = (PVIRTDBG_CONTROL_AREA)MmAllocateContiguousMemorySpecifyCache(CONTROL_AREA_SIZE,
95 | l1, l2, l3, MmCached);
96 |
97 | if (g_ControlArea == NULL)
98 | return STATUS_NO_MEMORY;
99 |
100 | DbgLog(("Allocated CONTROL_AREA structure @ 0x%llx\n", g_ControlArea));
101 | l1 = MmGetPhysicalAddress(g_ControlArea);
102 | DbgLog(("CONTROL_AREA phys @ 0x%llx\n", l1.QuadPart));
103 |
104 | RtlZeroMemory(g_ControlArea, CONTROL_AREA_SIZE);
105 |
106 | g_ControlArea->Magic1 = CONTROL_AREA_MAGIC1;
107 | g_ControlArea->Magic2 = CONTROL_AREA_MAGIC2;
108 |
109 | g_SendArea = AllocateMemory(0x1000);
110 |
111 | if (g_SendArea == NULL)
112 | return STATUS_NO_MEMORY;
113 |
114 | g_ControlArea->SendArea = MmGetPhysicalAddress(g_SendArea);
115 |
116 | g_RecvArea = AllocateMemory(0x1000);
117 |
118 | if (g_RecvArea == NULL)
119 | return STATUS_NO_MEMORY;
120 |
121 | g_ControlArea->RecvArea = MmGetPhysicalAddress(g_RecvArea);
122 |
123 | g_ControlArea->KernelBase = FindNtoskrnlBase(ZwClose);
124 | g_ControlArea->DebuggerData = 0;
125 | g_ControlArea->LogBuffer = MmGetPhysicalAddress(g_LogBuffer);
126 |
127 | return STATUS_SUCCESS;
128 | }
129 |
130 | #define IMAGE_DOS_SIGNATURE 0x5a4d
131 |
132 | static PVOID FindNtoskrnlBase(PVOID Addr)
133 | {
134 | /// Scandown from a given symbol’s address.
135 | Addr = (PVOID)((ULONG_PTR)Addr & ~0xfff);
136 | __try {
137 | while ((*(PUSHORT)Addr != IMAGE_DOS_SIGNATURE)) {
138 | Addr = (PVOID) ((ULONG_PTR)Addr - PAGE_SIZE);
139 | }
140 | return Addr;
141 | }
142 | __except(1) { }
143 | return NULL;
144 | }
145 |
146 | NTSTATUS StartVirtualization(PVOID GuestRsp)
147 | {
148 | NTSTATUS Status;
149 | PVOID HostKernelStackBase;
150 | PVIRT_CPU pCpu;
151 |
152 | Status = CheckIfVMXIsEnabled();
153 |
154 | if (Status == STATUS_UNSUCCESSFUL)
155 | {
156 | return STATUS_UNSUCCESSFUL;
157 | }
158 |
159 | HostKernelStackBase = ExAllocatePoolWithTag(NonPagedPool, 16*0x1000, 0x42424242);
160 | RtlZeroMemory(HostKernelStackBase, 16*0x1000);
161 | if (!HostKernelStackBase)
162 | {
163 | DbgLog(("can't allocate host kernel stack\n"));
164 | return STATUS_INSUFFICIENT_RESOURCES;
165 | }
166 |
167 | pCpu = (PVIRT_CPU)((PCHAR)HostKernelStackBase+16*0x1000-8-sizeof(VIRT_CPU));
168 | pCpu->HostKernelStackBase = HostKernelStackBase;
169 | pCpu->Self = pCpu;
170 | pCpu->State = STATE_RUNNING;
171 | pCpu->Mailbox = IPI_RUNNING;
172 |
173 | Status = SetupVMX(pCpu);
174 |
175 | g_cpus[pCpu->ProcessorNumber] = pCpu;
176 |
177 | if (Status == STATUS_UNSUCCESSFUL)
178 | {
179 | return STATUS_UNSUCCESSFUL;
180 | }
181 |
182 | Status = SetupVMCS(pCpu, GuestRsp);
183 |
184 | if (Status == STATUS_UNSUCCESSFUL)
185 | {
186 | return STATUS_UNSUCCESSFUL;
187 | }
188 |
189 | InterlockedIncrement(&g_processors);
190 |
191 | Status = Virtualize(pCpu);
192 |
193 | if (Status == STATUS_UNSUCCESSFUL)
194 | {
195 | return STATUS_UNSUCCESSFUL;
196 | }
197 |
198 | return STATUS_SUCCESS;
199 | }
200 |
201 |
--------------------------------------------------------------------------------
/src/virtdbg/virtdbg.h:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #ifndef _VIRTDBG_MAIN_H
8 | #define _VIRTDBG_MAIN_H
9 |
10 | #include
11 | #include "amd64.h"
12 | #include "vmx.h"
13 | #include "mem.h"
14 | #include "debug.h"
15 | #include "misc.h"
16 | #include "protocol.h"
17 |
18 | NTSTATUS VirtDbgStart(PVOID StartContext);
19 | NTSTATUS InitControlArea();
20 | NTSTATUS StartVirtualization(PVOID GuestRsp);
21 | static PVOID FindNtoskrnlBase(PVOID Addr);
22 |
23 | #endif
24 |
25 |
--------------------------------------------------------------------------------
/src/virtdbg/vmx.c:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #include "vmx.h"
8 |
9 |
10 | VOID DumpVirtCpu(PVIRT_CPU pCpu)
11 | {
12 | DbgLog(("pCpu @ %p\n", pCpu));
13 | DbgLog(("pCpu->Self=0x%llx\n", pCpu->Self));
14 | DbgLog(("pCpu->ProcessorNumber=0x%lx\n", pCpu->ProcessorNumber));
15 | DbgLog(("pCpu->State=0x%lx\n", pCpu->State));
16 | DbgLog(("pCpu->Mailbox=0x%lx\n", pCpu->Mailbox));
17 | }
18 |
19 | BOOLEAN IsBitSet(ULONG64 v, UCHAR bitNo)
20 | {
21 | ULONG64 mask = (ULONG64) 1 << bitNo;
22 | return (BOOLEAN) ((v & mask) != 0);
23 | }
24 |
25 |
26 | VOID DumpGuestRegs(PGUEST_REGS pGuestRegs)
27 | {
28 | DbgPrint("rax=0x%llx\n", pGuestRegs->rax);
29 | DbgPrint("rbx=0x%llx\n", pGuestRegs->rbx);
30 | DbgPrint("rcx=0x%llx\n", pGuestRegs->rcx);
31 | DbgPrint("rdx=0x%llx\n", pGuestRegs->rdx);
32 | DbgPrint("rbp=0x%llx\n", pGuestRegs->rbp);
33 | DbgPrint("rsp=0x%llx\n", pGuestRegs->rsp);
34 | DbgPrint("rdi=0x%llx\n", pGuestRegs->rdi);
35 | DbgPrint("rsi=0x%llx\n", pGuestRegs->rsi);
36 | DbgPrint("r8=0x%llx\n", pGuestRegs->r8);
37 | DbgPrint("r9=0x%llx\n", pGuestRegs->r9);
38 | DbgPrint("r10=0x%llx\n", pGuestRegs->r10);
39 | DbgPrint("r11=0x%llx\n", pGuestRegs->r11);
40 | DbgPrint("r12=0x%llx\n", pGuestRegs->r12);
41 | DbgPrint("r13=0x%llx\n", pGuestRegs->r13);
42 | DbgPrint("r14=0x%llx\n", pGuestRegs->r14);
43 | DbgPrint("r15=0x%llx\n", pGuestRegs->r15);
44 | }
45 |
46 | NTSTATUS InitializeSegmentSelector(PSEGMENT_SELECTOR SegmentSelector,
47 | USHORT Selector, PUCHAR GdtBase)
48 | {
49 | PSEGMENT_DESCRIPTOR SegDesc;
50 | ULONG64 tmp;
51 |
52 | if (!SegmentSelector)
53 | return STATUS_INVALID_PARAMETER;
54 |
55 | if (Selector & 0x4) {
56 | DbgPrint("InitializeSegmentSelector(): Given selector (0x%X) points to LDT\n", Selector);
57 | return STATUS_INVALID_PARAMETER;
58 | }
59 |
60 | SegDesc = (PSEGMENT_DESCRIPTOR) ((PUCHAR) GdtBase + (Selector & ~0x7));
61 |
62 | SegmentSelector->sel = Selector;
63 | SegmentSelector->base = SegDesc->base0 | SegDesc->base1 << 16 | SegDesc->base2 << 24;
64 | SegmentSelector->limit = SegDesc->limit0 | (SegDesc->limit1attr1 & 0xf) << 16;
65 | SegmentSelector->attributes.UCHARs = SegDesc->attr0 | (SegDesc->limit1attr1 & 0xf0) << 4;
66 |
67 | if (!(SegDesc->attr0 & LA_STANDARD)) {
68 | // this is a TSS or callgate etc, save the base high part
69 | tmp = (*(PULONG64) ((PUCHAR) SegDesc + 8));
70 | SegmentSelector->base = (SegmentSelector->base & 0xffffffff) | (tmp << 32);
71 | }
72 |
73 | if (SegmentSelector->attributes.fields.g) {
74 | // 4096-bit granularity is enabled for this segment, scale the limit
75 | SegmentSelector->limit = (SegmentSelector->limit << 12) + 0xfff;
76 | }
77 |
78 | return STATUS_SUCCESS;
79 | }
80 |
81 | ULONG32 AdjustControls(ULONG32 Ctl, ULONG32 Msr)
82 | {
83 | LARGE_INTEGER MsrValue;
84 | MsrValue.QuadPart = _ReadMsr(Msr);
85 | DbgLog(("Adjusting control for msr 0x%x\n", Msr));
86 | DbgLog(("Adjusting controls (low): 0x%08x\n", MsrValue.LowPart));
87 | DbgLog(("Adjusting controls (high): 0x%08x\n", MsrValue.HighPart));
88 | Ctl &= MsrValue.HighPart;
89 | Ctl |= MsrValue.LowPart;
90 | return Ctl;
91 | }
92 |
93 |
94 | NTSTATUS CheckForVirtualizationSupport()
95 | {
96 | ULONG32 eax, ebx, ecx, edx;
97 | /* vmx supported by cpu ? */
98 | _CpuId(0, &eax, &ebx, &ecx, &edx);
99 | if (eax < 1)
100 | {
101 | DbgLog(("error: extended CPUID functions not implemented\n"));
102 | return STATUS_UNSUCCESSFUL;
103 | }
104 |
105 | /* Intel Genuine */
106 | if (!(ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69))
107 | {
108 | DbgLog(("error: not an INTEL processor\n"));
109 | return STATUS_UNSUCCESSFUL;
110 | }
111 |
112 | _CpuId(0x1, &eax, &ebx, &ecx, &edx);
113 | if (!IsBitSet(ecx, 5))
114 | {
115 | DbgLog(("error: VMX not supported\n"));
116 | return STATUS_UNSUCCESSFUL;
117 | }
118 |
119 | return STATUS_SUCCESS;
120 | }
121 |
122 | NTSTATUS ResumeGuest()
123 | {
124 | DbgLog(("Resuming guest...\n"));
125 | return STATUS_SUCCESS;
126 | }
127 |
128 | NTSTATUS FillGuestSelectorData(PVOID GdtBase, ULONG Segreg, USHORT
129 | Selector)
130 | {
131 | SEGMENT_SELECTOR SegmentSelector = { 0 };
132 | ULONG uAccessRights;
133 |
134 | InitializeSegmentSelector(&SegmentSelector, Selector, GdtBase);
135 | uAccessRights = ((PUCHAR) & SegmentSelector.attributes)[0] + (((PUCHAR) &
136 | SegmentSelector.attributes)[1] << 12);
137 |
138 | if (!Selector)
139 | uAccessRights |= 0x10000;
140 |
141 | _WriteVMCS(GUEST_ES_SELECTOR + Segreg * 2, Selector);
142 | _WriteVMCS(GUEST_ES_LIMIT + Segreg * 2, SegmentSelector.limit);
143 | _WriteVMCS(GUEST_ES_AR_BYTES + Segreg * 2, uAccessRights);
144 |
145 | if ((Segreg == LDTR) || (Segreg == TR))
146 | // don't setup for FS/GS - their bases are stored in MSR values
147 | _WriteVMCS(GUEST_ES_BASE + Segreg * 2, SegmentSelector.base);
148 |
149 | return STATUS_SUCCESS;
150 | }
151 |
152 | NTSTATUS SetupVMCS(PVIRT_CPU pCpu, PVOID GuestRsp)
153 | {
154 | ULONG32 Interceptions, ExceptionBitmap;
155 | PVOID GdtBase;
156 | SEGMENT_SELECTOR SegmentSelector;
157 | ULONG32 i;
158 | PHYSICAL_ADDRESS pa;
159 |
160 | i = KeGetCurrentProcessorNumber();
161 | DbgLog(("GuestRsp=%p\n", GuestRsp));
162 |
163 | pa = pCpu->VMCS_pa;
164 | DbgLog(("VMCS PHYSICAL_ADDRESS %llx\n", pa));
165 | _VmClear(pa);
166 | _VmPtrLd(pa);
167 |
168 | _WriteVMCS(GUEST_CR0, _Cr0());
169 | _WriteVMCS(GUEST_CR3, _Cr3());
170 | _WriteVMCS(GUEST_CR4, _Cr4());
171 | _WriteVMCS(GUEST_DR7, 0x400);
172 | _WriteVMCS(GUEST_RSP, (ULONG64)GuestRsp);
173 | _WriteVMCS(GUEST_RIP, (ULONG64)_GuestEntryPoint);
174 | _WriteVMCS(GUEST_RFLAGS, _Rflags());
175 |
176 | GdtBase = (PVOID) _GdtBase();
177 | FillGuestSelectorData(GdtBase, ES, _Es());
178 | FillGuestSelectorData(GdtBase, CS, _Cs());
179 | FillGuestSelectorData(GdtBase, SS, _Ss());
180 | FillGuestSelectorData(GdtBase, DS, _Ds());
181 | FillGuestSelectorData(GdtBase, FS, _Fs());
182 | FillGuestSelectorData(GdtBase, GS, _Gs());
183 | FillGuestSelectorData(GdtBase, LDTR, _Ldtr());
184 | FillGuestSelectorData(GdtBase, TR, _TrSelector());
185 | _WriteVMCS(GUEST_ES_BASE, 0);
186 | _WriteVMCS(GUEST_CS_BASE, 0);
187 | _WriteVMCS(GUEST_SS_BASE, 0);
188 | _WriteVMCS(GUEST_DS_BASE, 0);
189 | _WriteVMCS(GUEST_FS_BASE, _ReadMsr(MSR_FS_BASE));
190 | _WriteVMCS(GUEST_GS_BASE, _ReadMsr(MSR_GS_BASE));
191 | _WriteVMCS(GUEST_GDTR_BASE, (ULONG64) GdtBase);
192 | _WriteVMCS(GUEST_IDTR_BASE, _IdtBase());
193 | _WriteVMCS(GUEST_GDTR_LIMIT, _GdtLimit());
194 | _WriteVMCS(GUEST_IDTR_LIMIT, _IdtLimit());
195 |
196 | _WriteVMCS(GUEST_IA32_DEBUGCTL, _ReadMsr(MSR_IA32_DEBUGCTL) & 0xffffffff);
197 | _WriteVMCS(GUEST_IA32_DEBUGCTL_HIGH, _ReadMsr(MSR_IA32_DEBUGCTL) >> 32);
198 | _WriteVMCS(GUEST_SYSENTER_CS, _ReadMsr(MSR_IA32_SYSENTER_CS));
199 | _WriteVMCS(GUEST_SYSENTER_ESP, _ReadMsr(MSR_IA32_SYSENTER_ESP));
200 | _WriteVMCS(GUEST_SYSENTER_EIP, _ReadMsr(MSR_IA32_SYSENTER_EIP));
201 |
202 | /* guest non register state */
203 | _WriteVMCS(GUEST_INTERRUPTIBILITY_INFO, 0);
204 | _WriteVMCS(GUEST_ACTIVITY_STATE, 0);
205 | _WriteVMCS(VMCS_LINK_POINTER, 0xffffffff);
206 | _WriteVMCS(VMCS_LINK_POINTER_HIGH, 0xffffffff);
207 |
208 | /* host state area */
209 | _WriteVMCS(HOST_CR0, _Cr0());
210 | _WriteVMCS(HOST_CR3, _Cr3());
211 | _WriteVMCS(HOST_CR4, _Cr4());
212 | _WriteVMCS(HOST_RSP, (ULONG64) pCpu);
213 | _WriteVMCS(HOST_RIP, (ULONG64) _ExitHandler);
214 |
215 | _WriteVMCS(HOST_ES_SELECTOR, KGDT64_R0_DATA);
216 | _WriteVMCS(HOST_CS_SELECTOR, KGDT64_R0_CODE);
217 | _WriteVMCS(HOST_SS_SELECTOR, KGDT64_R0_DATA);
218 | _WriteVMCS(HOST_DS_SELECTOR, KGDT64_R0_DATA);
219 | _WriteVMCS(HOST_FS_SELECTOR, (_Fs() & 0xf8));
220 | _WriteVMCS(HOST_GS_SELECTOR, (_Gs() & 0xf8));
221 | _WriteVMCS(HOST_TR_SELECTOR, (_TrSelector() & 0xf8));
222 | _WriteVMCS(HOST_FS_BASE, _ReadMsr(MSR_FS_BASE));
223 | _WriteVMCS(HOST_GS_BASE, _ReadMsr(MSR_GS_BASE));
224 |
225 | InitializeSegmentSelector(&SegmentSelector, _TrSelector(), (PVOID)
226 | _GdtBase());
227 |
228 | _WriteVMCS(HOST_TR_BASE, SegmentSelector.base);
229 |
230 | _WriteVMCS(HOST_GDTR_BASE, _GdtBase());
231 | _WriteVMCS(HOST_IDTR_BASE, _IdtBase());
232 |
233 | _WriteVMCS(HOST_IA32_SYSENTER_ESP, _ReadMsr(MSR_IA32_SYSENTER_ESP));
234 | _WriteVMCS(HOST_IA32_SYSENTER_EIP, _ReadMsr(MSR_IA32_SYSENTER_EIP));
235 | _WriteVMCS(HOST_IA32_SYSENTER_CS, _ReadMsr(MSR_IA32_SYSENTER_CS));
236 |
237 | /* VM Execution Control Fields */
238 | _WriteVMCS(PIN_BASED_VM_EXEC_CONTROL, AdjustControls(0,
239 | MSR_IA32_VMX_PINBASED_CTLS));
240 |
241 | Interceptions = 0;
242 | Interceptions |= CPU_BASED_ACTIVATE_MSR_BITMAP;
243 | _WriteVMCS(CPU_BASED_VM_EXEC_CONTROL, AdjustControls(Interceptions,
244 | MSR_IA32_VMX_PROCBASED_CTLS));
245 |
246 | ExceptionBitmap = 0;
247 | ExceptionBitmap |= 1<MSR_bitmap_pa.LowPart);
261 | _WriteVMCS(MSR_BITMAP_HIGH, pCpu->MSR_bitmap_pa.HighPart);
262 |
263 | /* VM Exit Control */
264 | _WriteVMCS(VM_EXIT_CONTROLS, AdjustControls(VM_EXIT_IA32E_MODE |
265 | VM_EXIT_ACK_INTR_ON_EXIT, MSR_IA32_VMX_EXIT_CTLS));
266 |
267 | _WriteVMCS(VM_EXIT_MSR_STORE_COUNT, 0);
268 | _WriteVMCS(VM_EXIT_MSR_LOAD_COUNT, 0);
269 | _WriteVMCS(VM_ENTRY_CONTROLS, AdjustControls(VM_ENTRY_IA32E_MODE,
270 | MSR_IA32_VMX_ENTRY_CTLS));
271 |
272 | _WriteVMCS(VM_ENTRY_MSR_LOAD_COUNT, 0);
273 | _WriteVMCS(VM_ENTRY_INTR_INFO_FIELD, 0);
274 |
275 | _WriteVMCS(CR0_GUEST_HOST_MASK, X86_CR0_PG);
276 | _WriteVMCS(CR0_READ_SHADOW, (_Cr0() & X86_CR0_PG) | X86_CR0_PG);
277 |
278 | _WriteVMCS(CR4_GUEST_HOST_MASK, X86_CR4_VMXE);
279 | _WriteVMCS(CR4_READ_SHADOW, 0);
280 |
281 | _WriteVMCS(CR3_TARGET_COUNT, 0);
282 | _WriteVMCS(CR3_TARGET_VALUE0, 0); //no use
283 | _WriteVMCS(CR3_TARGET_VALUE1, 0); //no use
284 | _WriteVMCS(CR3_TARGET_VALUE2, 0); //no use
285 | _WriteVMCS(CR3_TARGET_VALUE3, 0); //no use
286 |
287 | return STATUS_SUCCESS;
288 | }
289 |
290 | NTSTATUS SetupVMX(PVIRT_CPU pCpu)
291 | {
292 | PHYSICAL_ADDRESS pa;
293 | ULONG64 msr;
294 | PVMX_BASIC_MSR pvmx;
295 | ULONG32 i;
296 | PVOID va;
297 | ULONG size;
298 |
299 | i = KeGetCurrentProcessorNumber();
300 |
301 | pCpu->ProcessorNumber = i;
302 | msr = _ReadMsr(MSR_IA32_VMX_BASIC);
303 | pvmx = (PVMX_BASIC_MSR)&msr;
304 |
305 | size = pvmx->szVmxOnRegion;
306 |
307 | DbgLog(("VMXON region size: 0x%x\n", size));
308 | DbgLog(("VMX revision ID: 0x%x\n", pvmx->RevId));
309 |
310 | va = AllocateContiguousMemory(size);
311 |
312 | if (va == NULL)
313 | {
314 | DbgLog(("error: can't allocate vmxon region\n"));
315 | return STATUS_INSUFFICIENT_RESOURCES;
316 | }
317 |
318 | *(ULONG32 *)va = pvmx->RevId;
319 | pa = MmGetPhysicalAddress(va);
320 |
321 | _VmxOn(pa);
322 |
323 | if (_VmFailInvalid())
324 | {
325 | DbgLog(("_VmxOn failed\n"));
326 | return STATUS_UNSUCCESSFUL;
327 | }
328 |
329 | pCpu->VMXON_va = va;
330 | pCpu->VMXON_pa = pa;
331 |
332 | va = AllocateContiguousMemory(size);
333 |
334 | if (va == NULL)
335 | {
336 | DbgLog(("error: can't allocate vmcs region\n"));
337 | return STATUS_INSUFFICIENT_RESOURCES;
338 | }
339 |
340 | *(ULONG32 *)va = pvmx->RevId;
341 | pa = MmGetPhysicalAddress(va);
342 |
343 | pCpu->VMCS_va = va;
344 | pCpu->VMCS_pa = pa;
345 |
346 | va = AllocateContiguousMemory(0x1000);
347 | pa = MmGetPhysicalAddress(va);
348 |
349 | if (va == NULL)
350 | {
351 | DbgLog(("error: can't allocate msr bitmap\n"));
352 | return STATUS_INSUFFICIENT_RESOURCES;
353 | }
354 |
355 | pCpu->MSR_bitmap_va = va;
356 | pCpu->MSR_bitmap_pa = pa;
357 |
358 | return STATUS_SUCCESS;
359 | }
360 |
361 | NTSTATUS CheckIfVMXIsEnabled()
362 | {
363 | ULONG64 cr4, msr;
364 |
365 | /* vmxon supported ? */
366 | _SetCr4(X86_CR4_VMXE);
367 | cr4 = _Cr4();
368 |
369 | if (!(cr4 & X86_CR4_VMXE))
370 | {
371 | DbgLog(("error: VMXON not supported\n"));
372 | return STATUS_UNSUCCESSFUL;
373 | }
374 |
375 | /* vmx desactived by bios ? */
376 | msr = _ReadMsr(MSR_IA32_FEATURE_CONTROL);
377 | if (!(msr & 4))
378 | {
379 | DbgLog(("vmx is disabled in bios: MSR_IA32_FEATURE_CONTROL is 0x%llx\n", msr));
380 | return STATUS_UNSUCCESSFUL;
381 | }
382 |
383 | return STATUS_SUCCESS;
384 | }
385 |
386 |
387 | NTSTATUS Virtualize(PVIRT_CPU pCpu)
388 | {
389 | /* ULONG64 rsp;*/
390 | ULONG32 i;
391 |
392 | i = KeGetCurrentProcessorNumber();
393 | DbgLog(("CPU: 0x%p \n", pCpu));
394 | DbgLog(("rsp: 0x%llx \n", _Rsp()));
395 |
396 | _VmLaunch();
397 | /* never returns if successful */
398 | DbgLog(("rflags after _VmLaunch: 0x%x\n", _Rflags()));
399 | if (_VmFailInvalid())
400 | {
401 | DbgLog(("no current VMCS\n"));
402 | return STATUS_UNSUCCESSFUL;
403 | }
404 |
405 | if (_VmFailValid())
406 | {
407 | DbgLog(("vmlaunch failed\n"));
408 | DbgLog(("_ReadVMCS: 0x%llx\n", _ReadVMCS(VM_INSTRUCTION_ERROR)));
409 | return STATUS_UNSUCCESSFUL;
410 | }
411 |
412 | return STATUS_UNSUCCESSFUL;
413 | }
414 |
415 |
416 |
417 |
418 |
419 |
--------------------------------------------------------------------------------
/src/virtdbg/vmx.h:
--------------------------------------------------------------------------------
1 | // This file is part of Virtdbg
2 | // Copyright (C) 2010-2011 Damien AUMAITRE
3 |
4 | // Licence is GPLv3, see LICENCE.txt in the top-level directory
5 |
6 |
7 | #ifndef _VIRTDBG_VMX_H
8 | #define _VIRTDBG_VMX_H
9 |
10 | #include
11 | #include "amd64.h"
12 | #include "misc.h"
13 | #include "mem.h"
14 |
15 | typedef struct _VIRT_CPU {
16 | PVOID Self;
17 | ULONG32 ProcessorNumber;
18 | PVOID VMXON_va;
19 | PHYSICAL_ADDRESS VMXON_pa;
20 | PVOID VMCS_va;
21 | PHYSICAL_ADDRESS VMCS_pa;
22 | PVOID HostKernelStackBase;
23 | PVOID MSR_bitmap_va;
24 | PHYSICAL_ADDRESS MSR_bitmap_pa;
25 | ULONG32 State;
26 | ULONG32 Mailbox;
27 | } VIRT_CPU, *PVIRT_CPU;
28 |
29 | #define STATE_RUNNING 1
30 | #define STATE_FROZEN 2
31 | #define STATE_BREAKIN 3
32 | #define STATE_DEBUGGED 4
33 |
34 | #define IPI_FREEZE 1
35 | #define IPI_FROZEN 2
36 | #define IPI_RESUME 3
37 | #define IPI_RUNNING 4
38 |
39 | /*
40 | * VMX Exit Reasons
41 | */
42 |
43 | #define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
44 |
45 | #define EXIT_REASON_EXCEPTION_NMI 0
46 | #define EXIT_REASON_EXTERNAL_INTERRUPT 1
47 | #define EXIT_REASON_TRIPLE_FAULT 2
48 | #define EXIT_REASON_INIT 3
49 | #define EXIT_REASON_SIPI 4
50 | #define EXIT_REASON_IO_SMI 5
51 | #define EXIT_REASON_OTHER_SMI 6
52 | #define EXIT_REASON_PENDING_INTERRUPT 7
53 |
54 | #define EXIT_REASON_TASK_SWITCH 9
55 | #define EXIT_REASON_CPUID 10
56 | #define EXIT_REASON_HLT 12
57 | #define EXIT_REASON_INVD 13
58 | #define EXIT_REASON_INVLPG 14
59 | #define EXIT_REASON_RDPMC 15
60 | #define EXIT_REASON_RDTSC 16
61 | #define EXIT_REASON_RSM 17
62 | #define EXIT_REASON_VMCALL 18
63 | #define EXIT_REASON_VMCLEAR 19
64 | #define EXIT_REASON_VMLAUNCH 20
65 | #define EXIT_REASON_VMPTRLD 21
66 | #define EXIT_REASON_VMPTRST 22
67 | #define EXIT_REASON_VMREAD 23
68 | #define EXIT_REASON_VMRESUME 24
69 | #define EXIT_REASON_VMWRITE 25
70 | #define EXIT_REASON_VMXOFF 26
71 | #define EXIT_REASON_VMXON 27
72 | #define EXIT_REASON_CR_ACCESS 28
73 | #define EXIT_REASON_DR_ACCESS 29
74 | #define EXIT_REASON_IO_INSTRUCTION 30
75 | #define EXIT_REASON_MSR_READ 31
76 | #define EXIT_REASON_MSR_WRITE 32
77 |
78 | #define EXIT_REASON_INVALID_GUEST_STATE 33
79 | #define EXIT_REASON_MSR_LOADING 34
80 |
81 | #define EXIT_REASON_MWAIT_INSTRUCTION 36
82 | #define EXIT_REASON_MONITOR_INSTRUCTION 39
83 | #define EXIT_REASON_PAUSE_INSTRUCTION 40
84 |
85 | #define EXIT_REASON_MACHINE_CHECK 41
86 |
87 | #define EXIT_REASON_TPR_BELOW_THRESHOLD 43
88 |
89 | #define VMX_MAX_GUEST_VMEXIT EXIT_REASON_TPR_BELOW_THRESHOLD
90 |
91 | typedef struct _MOV_CR_QUALIFICATION {
92 | unsigned ControlRegister:4;
93 | unsigned AccessType:2;
94 | unsigned LMSWOperandType:1;
95 | unsigned Reserved1:1;
96 | unsigned Register:4;
97 | unsigned Reserved2:4;
98 | unsigned LMSWSourceData:16;
99 | unsigned Reserved3:32;
100 | } MOV_CR_QUALIFICATION, *PMOV_CR_QUALIFICATION;
101 |
102 | typedef struct _INTERRUPT_INFO_FIELD {
103 | unsigned Vector:8;
104 | unsigned InterruptionType:3;
105 | unsigned ErrorCodeValid:1;
106 | unsigned NMIUnblocking:1;
107 | unsigned Reserved:18;
108 | unsigned Valid:1;
109 | } INTERRUPT_INFO_FIELD, *PINTERRUPT_INFO_FIELD;
110 |
111 | typedef struct _INTERRUPT_INJECT_INFO_FIELD{
112 | unsigned Vector:8;
113 | unsigned InterruptionType:3;
114 | unsigned DeliverErrorCode:1;
115 | unsigned Reserved:19;
116 | unsigned Valid:1;
117 | } INTERRUPT_INJECT_INFO_FIELD, *PINTERRUPT_INJECT_INFO_FIELD;
118 |
119 | typedef struct _DEBUG_EXIT_QUALIFICATION {
120 | unsigned B0:1;
121 | unsigned B1:1;
122 | unsigned B2:1;
123 | unsigned B3:1;
124 | unsigned Reserved:9;
125 | unsigned BD:1;
126 | unsigned BS:1;
127 | unsigned Reserved2:17;
128 | unsigned Reserved3:32;
129 | } DEBUG_EXIT_QUALIFICATION, *PDEBUG_EXIT_QUALIFICATION;
130 |
131 |
132 | #define MOV_TO_CR 0
133 | #define MOV_FROM_CR 1
134 | #define CLTS 2
135 | #define LMSW 3
136 |
137 | #define CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004
138 | #define CPU_BASED_USE_TSC_OFFSETING 0x00000008
139 | #define CPU_BASED_HLT_EXITING 0x00000080
140 | #define CPU_BASED_INVDPG_EXITING 0x00000200
141 | #define CPU_BASED_MWAIT_EXITING 0x00000400
142 | #define CPU_BASED_RDPMC_EXITING 0x00000800
143 | #define CPU_BASED_RDTSC_EXITING 0x00001000
144 | #define CPU_BASED_CR8_LOAD_EXITING 0x00080000
145 | #define CPU_BASED_CR8_STORE_EXITING 0x00100000
146 | #define CPU_BASED_TPR_SHADOW 0x00200000
147 | #define CPU_BASED_MOV_DR_EXITING 0x00800000
148 | #define CPU_BASED_UNCOND_IO_EXITING 0x01000000
149 | #define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000
150 | #define CPU_BASED_ACTIVATE_MSR_BITMAP 0x10000000
151 | #define CPU_BASED_MONITOR_EXITING 0x20000000
152 | #define CPU_BASED_PAUSE_EXITING 0x40000000
153 |
154 | #define PIN_BASED_EXT_INTR_MASK 0x00000001
155 | #define PIN_BASED_NMI_EXITING 0x00000008
156 |
157 | #define VM_EXIT_IA32E_MODE 0x00000200
158 | #define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000
159 |
160 | #define VM_ENTRY_IA32E_MODE 0x00000200
161 | #define VM_ENTRY_SMM 0x00000400
162 | #define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800
163 |
164 | /* VMCS Encodings */
165 | enum {
166 | GUEST_ES_SELECTOR = 0x00000800,
167 | GUEST_CS_SELECTOR = 0x00000802,
168 | GUEST_SS_SELECTOR = 0x00000804,
169 | GUEST_DS_SELECTOR = 0x00000806,
170 | GUEST_FS_SELECTOR = 0x00000808,
171 | GUEST_GS_SELECTOR = 0x0000080a,
172 | GUEST_LDTR_SELECTOR = 0x0000080c,
173 | GUEST_TR_SELECTOR = 0x0000080e,
174 | HOST_ES_SELECTOR = 0x00000c00,
175 | HOST_CS_SELECTOR = 0x00000c02,
176 | HOST_SS_SELECTOR = 0x00000c04,
177 | HOST_DS_SELECTOR = 0x00000c06,
178 | HOST_FS_SELECTOR = 0x00000c08,
179 | HOST_GS_SELECTOR = 0x00000c0a,
180 | HOST_TR_SELECTOR = 0x00000c0c,
181 | IO_BITMAP_A = 0x00002000,
182 | IO_BITMAP_A_HIGH = 0x00002001,
183 | IO_BITMAP_B = 0x00002002,
184 | IO_BITMAP_B_HIGH = 0x00002003,
185 | MSR_BITMAP = 0x00002004,
186 | MSR_BITMAP_HIGH = 0x00002005,
187 | VM_EXIT_MSR_STORE_ADDR = 0x00002006,
188 | VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007,
189 | VM_EXIT_MSR_LOAD_ADDR = 0x00002008,
190 | VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009,
191 | VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a,
192 | VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b,
193 | TSC_OFFSET = 0x00002010,
194 | TSC_OFFSET_HIGH = 0x00002011,
195 | VIRTUAL_APIC_PAGE_ADDR = 0x00002012,
196 | VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
197 | VMCS_LINK_POINTER = 0x00002800,
198 | VMCS_LINK_POINTER_HIGH = 0x00002801,
199 | GUEST_IA32_DEBUGCTL = 0x00002802,
200 | GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
201 | PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
202 | CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
203 | EXCEPTION_BITMAP = 0x00004004,
204 | PAGE_FAULT_ERROR_CODE_MASK = 0x00004006,
205 | PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008,
206 | CR3_TARGET_COUNT = 0x0000400a,
207 | VM_EXIT_CONTROLS = 0x0000400c,
208 | VM_EXIT_MSR_STORE_COUNT = 0x0000400e,
209 | VM_EXIT_MSR_LOAD_COUNT = 0x00004010,
210 | VM_ENTRY_CONTROLS = 0x00004012,
211 | VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,
212 | VM_ENTRY_INTR_INFO_FIELD = 0x00004016,
213 | VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,
214 | VM_ENTRY_INSTRUCTION_LEN = 0x0000401a,
215 | TPR_THRESHOLD = 0x0000401c,
216 | SECONDARY_VM_EXEC_CONTROL = 0x0000401e,
217 | VM_INSTRUCTION_ERROR = 0x00004400,
218 | VM_EXIT_REASON = 0x00004402,
219 | VM_EXIT_INTR_INFO = 0x00004404,
220 | VM_EXIT_INTR_ERROR_CODE = 0x00004406,
221 | IDT_VECTORING_INFO_FIELD = 0x00004408,
222 | IDT_VECTORING_ERROR_CODE = 0x0000440a,
223 | VM_EXIT_INSTRUCTION_LEN = 0x0000440c,
224 | VMX_INSTRUCTION_INFO = 0x0000440e,
225 | GUEST_ES_LIMIT = 0x00004800,
226 | GUEST_CS_LIMIT = 0x00004802,
227 | GUEST_SS_LIMIT = 0x00004804,
228 | GUEST_DS_LIMIT = 0x00004806,
229 | GUEST_FS_LIMIT = 0x00004808,
230 | GUEST_GS_LIMIT = 0x0000480a,
231 | GUEST_LDTR_LIMIT = 0x0000480c,
232 | GUEST_TR_LIMIT = 0x0000480e,
233 | GUEST_GDTR_LIMIT = 0x00004810,
234 | GUEST_IDTR_LIMIT = 0x00004812,
235 | GUEST_ES_AR_BYTES = 0x00004814,
236 | GUEST_CS_AR_BYTES = 0x00004816,
237 | GUEST_SS_AR_BYTES = 0x00004818,
238 | GUEST_DS_AR_BYTES = 0x0000481a,
239 | GUEST_FS_AR_BYTES = 0x0000481c,
240 | GUEST_GS_AR_BYTES = 0x0000481e,
241 | GUEST_LDTR_AR_BYTES = 0x00004820,
242 | GUEST_TR_AR_BYTES = 0x00004822,
243 | GUEST_INTERRUPTIBILITY_INFO = 0x00004824,
244 | GUEST_ACTIVITY_STATE = 0x00004826,
245 | GUEST_SM_BASE = 0x00004828,
246 | GUEST_SYSENTER_CS = 0x0000482A,
247 | HOST_IA32_SYSENTER_CS = 0x00004c00,
248 | CR0_GUEST_HOST_MASK = 0x00006000,
249 | CR4_GUEST_HOST_MASK = 0x00006002,
250 | CR0_READ_SHADOW = 0x00006004,
251 | CR4_READ_SHADOW = 0x00006006,
252 | CR3_TARGET_VALUE0 = 0x00006008,
253 | CR3_TARGET_VALUE1 = 0x0000600a,
254 | CR3_TARGET_VALUE2 = 0x0000600c,
255 | CR3_TARGET_VALUE3 = 0x0000600e,
256 | EXIT_QUALIFICATION = 0x00006400,
257 | GUEST_LINEAR_ADDRESS = 0x0000640a,
258 | GUEST_CR0 = 0x00006800,
259 | GUEST_CR3 = 0x00006802,
260 | GUEST_CR4 = 0x00006804,
261 | GUEST_ES_BASE = 0x00006806,
262 | GUEST_CS_BASE = 0x00006808,
263 | GUEST_SS_BASE = 0x0000680a,
264 | GUEST_DS_BASE = 0x0000680c,
265 | GUEST_FS_BASE = 0x0000680e,
266 | GUEST_GS_BASE = 0x00006810,
267 | GUEST_LDTR_BASE = 0x00006812,
268 | GUEST_TR_BASE = 0x00006814,
269 | GUEST_GDTR_BASE = 0x00006816,
270 | GUEST_IDTR_BASE = 0x00006818,
271 | GUEST_DR7 = 0x0000681a,
272 | GUEST_RSP = 0x0000681c,
273 | GUEST_RIP = 0x0000681e,
274 | GUEST_RFLAGS = 0x00006820,
275 | GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822,
276 | GUEST_SYSENTER_ESP = 0x00006824,
277 | GUEST_SYSENTER_EIP = 0x00006826,
278 | HOST_CR0 = 0x00006c00,
279 | HOST_CR3 = 0x00006c02,
280 | HOST_CR4 = 0x00006c04,
281 | HOST_FS_BASE = 0x00006c06,
282 | HOST_GS_BASE = 0x00006c08,
283 | HOST_TR_BASE = 0x00006c0a,
284 | HOST_GDTR_BASE = 0x00006c0c,
285 | HOST_IDTR_BASE = 0x00006c0e,
286 | HOST_IA32_SYSENTER_ESP = 0x00006c10,
287 | HOST_IA32_SYSENTER_EIP = 0x00006c12,
288 | HOST_RSP = 0x00006c14,
289 | HOST_RIP = 0x00006c16,
290 | };
291 |
292 | typedef struct {
293 | ULONG64 GUEST_ES_SELECTOR;
294 | ULONG64 GUEST_CS_SELECTOR;
295 | ULONG64 GUEST_SS_SELECTOR;
296 | ULONG64 GUEST_DS_SELECTOR;
297 | ULONG64 GUEST_FS_SELECTOR;
298 | ULONG64 GUEST_GS_SELECTOR;
299 | ULONG64 GUEST_LDTR_SELECTOR;
300 | ULONG64 GUEST_TR_SELECTOR;
301 | ULONG64 HOST_ES_SELECTOR;
302 | ULONG64 HOST_CS_SELECTOR;
303 | ULONG64 HOST_SS_SELECTOR;
304 | ULONG64 HOST_DS_SELECTOR;
305 | ULONG64 HOST_FS_SELECTOR;
306 | ULONG64 HOST_GS_SELECTOR;
307 | ULONG64 HOST_TR_SELECTOR;
308 | ULONG64 IO_BITMAP_A;
309 | ULONG64 IO_BITMAP_A_HIGH;
310 | ULONG64 IO_BITMAP_B;
311 | ULONG64 IO_BITMAP_B_HIGH;
312 | ULONG64 MSR_BITMAP;
313 | ULONG64 MSR_BITMAP_HIGH;
314 | ULONG64 VM_EXIT_MSR_STORE_ADDR;
315 | ULONG64 VM_EXIT_MSR_STORE_ADDR_HIGH;
316 | ULONG64 VM_EXIT_MSR_LOAD_ADDR;
317 | ULONG64 VM_EXIT_MSR_LOAD_ADDR_HIGH;
318 | ULONG64 VM_ENTRY_MSR_LOAD_ADDR;
319 | ULONG64 VM_ENTRY_MSR_LOAD_ADDR_HIGH;
320 | ULONG64 TSC_OFFSET;
321 | ULONG64 TSC_OFFSET_HIGH;
322 | ULONG64 VIRTUAL_APIC_PAGE_ADDR;
323 | ULONG64 VIRTUAL_APIC_PAGE_ADDR_HIGH;
324 | ULONG64 VMCS_LINK_POINTER;
325 | ULONG64 VMCS_LINK_POINTER_HIGH;
326 | ULONG64 GUEST_IA32_DEBUGCTL;
327 | ULONG64 GUEST_IA32_DEBUGCTL_HIGH;
328 | ULONG64 PIN_BASED_VM_EXEC_CONTROL;
329 | ULONG64 CPU_BASED_VM_EXEC_CONTROL;
330 | ULONG64 EXCEPTION_BITMAP;
331 | ULONG64 PAGE_FAULT_ERROR_CODE_MASK;
332 | ULONG64 PAGE_FAULT_ERROR_CODE_MATCH;
333 | ULONG64 CR3_TARGET_COUNT;
334 | ULONG64 VM_EXIT_CONTROLS;
335 | ULONG64 VM_EXIT_MSR_STORE_COUNT;
336 | ULONG64 VM_EXIT_MSR_LOAD_COUNT;
337 | ULONG64 VM_ENTRY_CONTROLS;
338 | ULONG64 VM_ENTRY_MSR_LOAD_COUNT;
339 | ULONG64 VM_ENTRY_INTR_INFO_FIELD;
340 | ULONG64 VM_ENTRY_EXCEPTION_ERROR_CODE;
341 | ULONG64 VM_ENTRY_INSTRUCTION_LEN;
342 | ULONG64 TPR_THRESHOLD;
343 | ULONG64 SECONDARY_VM_EXEC_CONTROL;
344 | ULONG64 VM_INSTRUCTION_ERROR;
345 | ULONG64 VM_EXIT_REASON;
346 | ULONG64 VM_EXIT_INTR_INFO;
347 | ULONG64 VM_EXIT_INTR_ERROR_CODE;
348 | ULONG64 IDT_VECTORING_INFO_FIELD;
349 | ULONG64 IDT_VECTORING_ERROR_CODE;
350 | ULONG64 VM_EXIT_INSTRUCTION_LEN;
351 | ULONG64 VMX_INSTRUCTION_INFO;
352 | ULONG64 GUEST_ES_LIMIT;
353 | ULONG64 GUEST_CS_LIMIT;
354 | ULONG64 GUEST_SS_LIMIT;
355 | ULONG64 GUEST_DS_LIMIT;
356 | ULONG64 GUEST_FS_LIMIT;
357 | ULONG64 GUEST_GS_LIMIT;
358 | ULONG64 GUEST_LDTR_LIMIT;
359 | ULONG64 GUEST_TR_LIMIT;
360 | ULONG64 GUEST_GDTR_LIMIT;
361 | ULONG64 GUEST_IDTR_LIMIT;
362 | ULONG64 GUEST_ES_AR_BYTES;
363 | ULONG64 GUEST_CS_AR_BYTES;
364 | ULONG64 GUEST_SS_AR_BYTES;
365 | ULONG64 GUEST_DS_AR_BYTES;
366 | ULONG64 GUEST_FS_AR_BYTES;
367 | ULONG64 GUEST_GS_AR_BYTES;
368 | ULONG64 GUEST_LDTR_AR_BYTES;
369 | ULONG64 GUEST_TR_AR_BYTES;
370 | ULONG64 GUEST_INTERRUPTIBILITY_INFO;
371 | ULONG64 GUEST_ACTIVITY_STATE;
372 | ULONG64 GUEST_SM_BASE;
373 | ULONG64 GUEST_SYSENTER_CS;
374 | ULONG64 HOST_IA32_SYSENTER_CS;
375 | ULONG64 CR0_GUEST_HOST_MASK;
376 | ULONG64 CR4_GUEST_HOST_MASK;
377 | ULONG64 CR0_READ_SHADOW;
378 | ULONG64 CR4_READ_SHADOW;
379 | ULONG64 CR3_TARGET_VALUE0;
380 | ULONG64 CR3_TARGET_VALUE1;
381 | ULONG64 CR3_TARGET_VALUE2;
382 | ULONG64 CR3_TARGET_VALUE3;
383 | ULONG64 EXIT_QUALIFICATION;
384 | ULONG64 GUEST_LINEAR_ADDRESS;
385 | ULONG64 GUEST_CR0;
386 | ULONG64 GUEST_CR3;
387 | ULONG64 GUEST_CR4;
388 | ULONG64 GUEST_ES_BASE;
389 | ULONG64 GUEST_CS_BASE;
390 | ULONG64 GUEST_SS_BASE;
391 | ULONG64 GUEST_DS_BASE;
392 | ULONG64 GUEST_FS_BASE;
393 | ULONG64 GUEST_GS_BASE;
394 | ULONG64 GUEST_LDTR_BASE;
395 | ULONG64 GUEST_TR_BASE;
396 | ULONG64 GUEST_GDTR_BASE;
397 | ULONG64 GUEST_IDTR_BASE;
398 | ULONG64 GUEST_DR7;
399 | ULONG64 GUEST_RSP;
400 | ULONG64 GUEST_RIP;
401 | ULONG64 GUEST_RFLAGS;
402 | ULONG64 GUEST_PENDING_DBG_EXCEPTIONS;
403 | ULONG64 GUEST_SYSENTER_ESP;
404 | ULONG64 GUEST_SYSENTER_EIP;
405 | ULONG64 HOST_CR0;
406 | ULONG64 HOST_CR3;
407 | ULONG64 HOST_CR4;
408 | ULONG64 HOST_FS_BASE;
409 | ULONG64 HOST_GS_BASE;
410 | ULONG64 HOST_TR_BASE;
411 | ULONG64 HOST_GDTR_BASE;
412 | ULONG64 HOST_IDTR_BASE;
413 | ULONG64 HOST_IA32_SYSENTER_ESP;
414 | ULONG64 HOST_IA32_SYSENTER_EIP;
415 | ULONG64 HOST_RSP;
416 | ULONG64 HOST_RIP;
417 | } VMCS, *PVMCS;
418 |
419 | ULONG32 AdjustControls(ULONG32 Ctl, ULONG32 Msr);
420 | VOID DumpGuestRegs(PGUEST_REGS pGuestRegs);
421 |
422 | BOOLEAN IsBitSet(ULONG64 v, UCHAR bitNo);
423 | NTSTATUS InitializeSegmentSelector(PSEGMENT_SELECTOR SegmentSelector,
424 | USHORT Selector, PUCHAR GdtBase);
425 |
426 |
427 | NTSTATUS CheckForVirtualizationSupport();
428 | NTSTATUS ResumeGuest();
429 | NTSTATUS FillGuestSelectorData(PVOID GdtBase, ULONG Segreg, USHORT
430 | Selector);
431 | NTSTATUS SetupVMCS(PVIRT_CPU pCpu, PVOID GuestRsp);
432 | NTSTATUS SetupVMX(PVIRT_CPU pCpu);
433 | NTSTATUS CheckIfVMXIsEnabled();
434 |
435 | NTSTATUS Virtualize(PVIRT_CPU pCpu);
436 | VOID StopVirtualization();
437 |
438 | VOID DumpVirtCpu(PVIRT_CPU pCpu);
439 |
440 |
441 | #endif
442 |
443 |
--------------------------------------------------------------------------------