mireado

starting commit

1 + GNU GENERAL PUBLIC LICENSE
2 + Version 3, 29 June 2007
3 +
4 + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
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 + <one line to give the program's name and a brief idea of what it does.>
635 + Copyright (C) <year> <name of author>
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 <http://www.gnu.org/licenses/>.
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 + <program> Copyright (C) <year> <name of author>
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 +<http://www.gnu.org/licenses/>.
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 +<http://www.gnu.org/philosophy/why-not-lgpl.html>.
1 +# ppsspp.pri
2 +# 12/26/2014 jichi
3 +
4 +DEPENDPATH += $$PWD
5 +
6 +HEADERS += \
7 + $$PWD/funcinfo.h
8 +
9 +# EOF
1 +# ith.pro
2 +# 10/13/2011 jichi
3 +
4 +TEMPLATE = subdirs
5 +
6 +# The order is important!
7 +SUBDIRS += \
8 + sys \
9 + hook hookxp \
10 + host
11 +
12 +OTHER_FILES += dllconfig.pri
13 +
14 +include(common/common.pri) # not used
15 +include(import/mono/mono.pri) # not used
16 +include(import/ppsspp/ppsspp.pri) # not used
17 +
18 +# EOF
1 +# sys.pro
2 +# CONFIG += noqt noeh staticlib
3 +
4 +# CONFIG(noeh) {
5 +# message(CONFIG noeh)
6 +# QMAKE_CXXFLAGS += /GR-
7 +# QMAKE_CXXFLAGS_RTTI_ON -= /GR
8 +# QMAKE_CXXFLAGS_STL_ON -= /EHsc
9 +# QMAKE_CXXFLAGS_EXCEPTIONS_ON -= /EHsc
10 +# CONFIG(dll) {
11 +# QMAKE_LFLAGS += /ENTRY:"DllMain"
12 +# }
13 +# }
14 +
15 +set(vnrsys_src
16 + sys.h
17 + sys.cc
18 +)
19 +
20 +add_library(vnrsys STATIC ${vnrsys_src})
21 +
22 +target_compile_options(vnrsys PRIVATE
23 + # http://msdn.microsoft.com/library/we6hfdy0.aspx
24 + /GR- # disable RTTI
25 + # http://msdn.microsoft.com/library/1deeycx5.aspx
26 + # /EHs-c- # disable exception handling # CMake bug 15243: http://www.cmake.org/Bug/view.php?id=15243
27 + $<$<CONFIG:Release>:>
28 + $<$<CONFIG:Debug>:>
29 +)
30 +
31 +STRING(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
32 +
33 +target_link_libraries(vnrsys comctl32.lib)
34 +
35 +target_compile_definitions(vnrsys
36 + PRIVATE
37 +)
1 +// sys.cc
2 +// 8/21/2013 jichi
3 +// Branch: ITH_SYS/SYS.cpp, rev 126
4 +//
5 +// 8/24/2013 TODO:
6 +// - Clean up the code
7 +// - Move my old create remote thread for ITH2 here
8 +
9 +#include "ith/sys/sys.h"
10 +//#include "ith/common/growl.h"
11 +//#include "ith/common/except.h"
12 +
13 +//#define ITH_SYS_SECTION L"ITH_SysSection"
14 +#define ITH_THREADMAN_SECTION L"VNR_SYS_THREAD"
15 +
16 +// jichi 9/28/2013: Weither use NtThread or RemoteThread
17 +// RemoteThread works on both Windows 7 or Wine, while NtThread does not work on wine
18 +#define ITH_ENABLE_THREADMAN (!IthIsWindows8OrGreater() && !IthIsWine())
19 +//#define ITH_ENABLE_THREADMAN true
20 +
21 +// Helpers
22 +
23 +// jichi 2/3/2015: About GetVersion
24 +// Windows XP SP3: 5.1
25 +// Windows 7: 6.1, 0x1db10106
26 +// Windows 8: 6.2, 0x23f00206
27 +// Windows 10: 6.2, 0x23f00206 (build 9926):
28 +
29 +BOOL IthIsWindowsXp()
30 +{
31 + static BOOL ret = -1; // cached
32 + if (ret < 0) {
33 + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms724439%28v=vs.85%29.aspx
34 + DWORD v = ::GetVersion();
35 + BYTE major = LOBYTE(LOWORD(v));
36 + //DWORD minor = (DWORD)(HIBYTE(LOWORD(v)));
37 +
38 + // Windows XP = 5.1
39 + //ret = major < 6 ? 1 : 0;
40 + ret = major < 6;
41 + }
42 + return ret;
43 +}
44 +
45 +// https://msdn.microsoft.com/en-us/library/windows/desktop/dn424972%28v=vs.85%29.aspx
46 +// The same as IsWindows8OrGreater, which I don't know if the function is available to lower Windows.
47 +static BOOL IthIsWindows8OrGreater() // this function is not exported
48 +{
49 + static BOOL ret = -1; // cached
50 + if (ret < 0) {
51 + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms724439%28v=vs.85%29.aspx
52 + DWORD v = ::GetVersion();
53 + BYTE major = LOBYTE(LOWORD(v)),
54 + minor = HIBYTE(LOWORD(v));
55 + //DWORD minor = (DWORD)(HIBYTE(LOWORD(v)));
56 +
57 + // Windows 8/10 = 6.2
58 + ret = major > 6 || (major == 6 && minor >= 2);
59 + }
60 + return ret;
61 +}
62 +
63 +BOOL IthIsWine()
64 +{
65 + static BOOL ret = -1; // cached
66 + if (ret < 0) {
67 + const wchar_t *path;
68 + wchar_t buffer[MAX_PATH];
69 + if (UINT sz = ::GetSystemDirectoryW(buffer, MAX_PATH)) {
70 + path = buffer;
71 + ::wcscpy(buffer + sz, L"\\winecfg.exe");
72 + } else
73 + path = L"C:\\Windows\\System32\\winecfg.exe";
74 + //ITH_MSG(path);
75 + ret = ::GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES ? TRUE : FALSE;
76 + }
77 + return ret;
78 +}
79 +
80 +// jichi 9/28/2013: prevent parallelization in wine
81 +void IthCoolDown()
82 +{
83 + // http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Thread/NtDelayExecution.html
84 + //const LONGLONG timeout = -10000; // in 100ns, i.e. 1ms
85 + //NtDelayExecution(FALSE, (PLARGE_INTEGER)&timeout);
86 + //NtFlushInstructionCache(NtCurrentProcess(), (LPVOID)hp.addr, hp.recover_len);
87 + // Flush the instruction cache line, and prevent wine from rending things in parallel
88 + if (IthIsWine())
89 + IthSleep(1); // sleep for 1 ms
90 + //__asm
91 + //{
92 + // //mov eax,0x2710 // = 10000
93 + // mov ecx,time
94 + // mul ecx
95 + // neg eax
96 + // adc edx,0
97 + // neg edx
98 + // push edx
99 + // push eax
100 + // push esp
101 + // push 0
102 + // call dword ptr [NtDelayExecution]
103 + // add esp,8
104 + //}
105 +}
106 +
107 +// jichi 9/23/2013: wine deficenciy on mapping sections
108 +// Whe set to false, do not map sections.
109 +//static bool ith_has_section = true;
110 +
111 +//#ifdef ITH_WINE
112 +//# include "winddk/winddk.h"
113 +//#endif // ITH_WINE
114 +
115 +//#define SEC_BASED 0x200000 // jichi 8/24/2013: emoved
116 +
117 +// jichi 10/6/2013
118 +// See: http://stackoverflow.com/questions/557081/how-do-i-get-the-hmodule-for-the-currently-executing-code
119 +// See: http://www.codeproject.com/Articles/16598/Get-Your-DLL-s-Path-Name
120 +EXTERN_C IMAGE_DOS_HEADER __ImageBase;
121 +#define CURRENT_MODULE_HANDLE ((HINSTANCE)&__ImageBase)
122 +size_t IthGetCurrentModulePath(wchar_t *buf, size_t len)
123 +{ return ::GetModuleFileNameW(CURRENT_MODULE_HANDLE, buf, len); }
124 +
125 +// - Global variables -
126 +
127 +#ifdef ITH_HAS_HEAP
128 +HANDLE hHeap; // used in ith/common/memory.h
129 +#endif // ITH_HAS_HEAP
130 +
131 +DWORD current_process_id;
132 +DWORD debug;
133 +BYTE launch_time[0x10];
134 +LPVOID page;
135 +
136 +BYTE LeadByteTable[0x100] = {
137 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
138 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
139 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
140 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
141 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
142 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
143 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
144 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
145 + 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
146 + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
147 + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
148 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
149 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
150 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
151 + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
152 + 2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1
153 +};
154 +
155 +namespace { // unnamed
156 +
157 +WCHAR file_path[MAX_PATH] = L"\\??\\";
158 +LPWSTR current_dir;
159 +DWORD page_locale;
160 +HANDLE root_obj,
161 + dir_obj,
162 + codepage_section,
163 + thread_man_section;
164 +
165 +BYTE file_info[0x1000];
166 +
167 +
168 +// - Helper functions -
169 +
170 +inline DWORD GetShareMemory()
171 +{
172 + __asm
173 + {
174 + mov eax,fs:[0x30]
175 + mov eax,[eax+0x4C]
176 + }
177 +}
178 +
179 +inline LARGE_INTEGER *GetTimeBias()
180 +{ __asm mov eax,0x7ffe0020 }
181 +
182 +
183 +//Get full path of current process.
184 +//inline LPWSTR GetModulePath()
185 +//{
186 +// __asm
187 +// {
188 +// mov eax,fs:[0x30]
189 +// mov eax,[eax+0xC]
190 +// mov eax,[eax+0xC]
191 +// mov eax,[eax+0x28]
192 +// }
193 +//}
194 +
195 +// - Singleton classes -
196 +
197 +BYTE normal_routine[0x14] = {
198 + 0x51,0x52,0x64,0x89,0x23,0x55,0xff,0xd0,0x50,0x6a,0xfe,0xff,0x15,0x14,0x00,0x00,0x00
199 +};
200 +
201 +BYTE except_routine[0xe0] = {
202 + 0xba,0x08,0x00,0x00,0x00,0x8b,0xc1,0x83,0xe0,0x0f,0x83,0xf8,0x0a,0x72,0x02,0x04,
203 + 0x07,0x04,0x30,0x66,0xab,0xc1,0xc9,0x04,0x4a,0x75,0xea,0xc3,0x00,0x00,0x00,0x00,
204 + 0x8b,0x44,0xe4,0x04,0x31,0xf6,0x8b,0x28,0x8b,0x4c,0xe4,0x0c,0x8b,0x99,0xb8,0x00,
205 + 0x00,0x00,0x81,0xec,0x40,0x02,0x00,0x00,0x8d,0x7c,0xe4,0x40,0x89,0xe0,0x56,0x6a,
206 + 0x1c,0x50,0x56,0x53,0x6a,0xff,0xff,0x15,0x18,0x00,0x00,0x00,0x85,0xc0,0x75,0x98,
207 + 0x89,0xe0,0x50,0x68,0x00,0x02,0x00,0x00,0x57,0x6a,0x02,0x53,0x6a,0xff,0xff,0x15,
208 + 0x18,0x00,0x00,0x00,0x85,0xc0,0x75,0xe6,0x5e,0x0f,0xc1,0xf7,0xfd,0xb0,0x5c,0x66,
209 + 0xf2,0xaf,0x66,0xc7,0x47,0x02,0x3a,0x00,0x89,0xd9,0x2b,0x0c,0xe4,0xe8,0x7e,0xff,
210 + 0xff,0xff,0x47,0x47,0x87,0xfe,0x89,0xe9,0xe8,0x73,0xff,0xff,0xff,0x47,0x47,0x31,
211 + 0xc0,0x89,0x47,0x10,0x6a,0x00,0x57,0x56,0x6a,0x00,0xfc,0xff,0x15,0x1c,0x00,0x00,
212 + 0x00,0x83,0xc8,0xff,0xeb,0xbe
213 +};
214 +
215 +// jichi 8/24/2013: Could be initialized using NtMapViewOfSection/ZwMapViewOfSection
216 +// This class cannot have constructor / destructor
217 +struct _ThreadView {
218 + UINT_PTR mutex,
219 + count;
220 + DWORD proc_record[1];
221 +};
222 +
223 +class : private _ThreadView { // ThreadStartManager
224 +
225 + enum {
226 + ADDR0 = 0xD
227 + , ADDR1 = 0x48
228 + , ADDR2 = 0x60
229 + , ADDR3 = 0x9D
230 + };
231 +
232 +public:
233 + LPVOID GetProcAddr(HANDLE hProc)
234 + {
235 + AcquireLock();
236 + DWORD pid,addr,len;
237 + if (hProc == NtCurrentProcess())
238 + pid = ::current_process_id;
239 + else {
240 + PROCESS_BASIC_INFORMATION info;
241 + NtQueryInformationProcess(hProc, ProcessBasicInformation, &info, sizeof(info), &len);
242 + pid=info.uUniqueProcessId;
243 + }
244 + pid >>= 2;
245 + for (UINT_PTR i = 0; i < count; i++)
246 + if (pid == (proc_record[i] & 0xfff)) {
247 + addr = proc_record[i] & ~0xfff;
248 + ReleaseLock();
249 + return (LPVOID)addr;
250 + }
251 + len = 0x1000;
252 + NtAllocateVirtualMemory(hProc, (PVOID *)(proc_record + count), 0, &len,
253 + MEM_COMMIT,PAGE_EXECUTE_READWRITE);
254 + DWORD base = proc_record[count];
255 + proc_record[count] |= pid;
256 + union {
257 + LPVOID buffer;
258 + DWORD b;
259 + };
260 + b = base;
261 + LPVOID fun_table[3];
262 + *(DWORD *)(normal_routine + ADDR0) += base;
263 + NtWriteVirtualMemory(hProc, buffer, normal_routine, 0x14, 0);
264 + *(DWORD *)(normal_routine + ADDR0) -= base;
265 + b += 0x14;
266 + fun_table[0] = NtTerminateThread;
267 + fun_table[1] = NtQueryVirtualMemory;
268 + fun_table[2] = MessageBoxW;
269 + NtWriteVirtualMemory(hProc, buffer, fun_table, 0xC, 0);
270 + b += 0xc;
271 + *(DWORD *)(except_routine + ADDR1) += base;
272 + *(DWORD *)(except_routine + ADDR2) += base;
273 + *(DWORD *)(except_routine + ADDR3) += base;
274 + NtWriteVirtualMemory(hProc, buffer, except_routine, 0xE0, 0);
275 + *(DWORD *)(except_routine + ADDR1) -= base;
276 + *(DWORD *)(except_routine + ADDR2) -= base;
277 + *(DWORD *)(except_routine + ADDR3) -= base;
278 + count++;
279 + ReleaseLock();
280 + return (LPVOID)base;
281 + }
282 + void ReleaseProcessMemory(HANDLE hProc)
283 + {
284 + DWORD pid,addr,len;
285 + AcquireLock();
286 + if (hProc==NtCurrentProcess())
287 + pid = ::current_process_id;
288 + else {
289 + PROCESS_BASIC_INFORMATION info;
290 + NtQueryInformationProcess(hProc,ProcessBasicInformation,&info,sizeof(info),&len);
291 + pid = info.uUniqueProcessId;
292 + }
293 + pid >>= 2;
294 + //NtWaitForSingleObject(thread_man_mutex,0,0);
295 + for (UINT_PTR i = 0; i < count; i++) {
296 + if ((proc_record[i]&0xfff) == pid) {
297 + addr = proc_record[i] & ~0xfff;
298 + DWORD size=0x1000;
299 + NtFreeVirtualMemory(hProc, (PVOID *)&addr, &size, MEM_RELEASE);
300 + count--;
301 + for (UINT_PTR j = i; j < count; j++)
302 + proc_record[j] = proc_record[j + 1];
303 + proc_record[count] = 0;
304 + ReleaseLock();
305 + //NtReleaseMutant(thread_man_mutex,0);
306 + return;
307 + }
308 + }
309 + ReleaseLock();
310 + //NtReleaseMutant(thread_man_mutex,0);
311 + }
312 + void CheckProcessMemory()
313 + {
314 + UINT_PTR i, j, flag, addr;
315 + DWORD len;
316 + CLIENT_ID id;
317 + OBJECT_ATTRIBUTES oa = {};
318 + HANDLE hProc;
319 + BYTE buffer[8];
320 + AcquireLock();
321 + id.UniqueThread = 0;
322 + oa.uLength = sizeof(oa);
323 + for (i = 0; i < count ; i++) {
324 + id.UniqueProcess = (proc_record[i]&0xfff)<<2;
325 + addr = proc_record[i] & ~0xfff;
326 + flag = 0;
327 + if (NT_SUCCESS(NtOpenProcess(&hProc, PROCESS_VM_OPERATION|PROCESS_VM_READ, &oa, &id))) {
328 + if (NT_SUCCESS(NtReadVirtualMemory(hProc, (PVOID)addr, buffer, 8, &len)))
329 + if (::memcmp(buffer, normal_routine, 4) == 0)
330 + flag = 1;
331 + NtClose(hProc);
332 + }
333 + if (flag == 0) {
334 + for (j = i; j < count; j++)
335 + proc_record[j] = proc_record[j + 1];
336 + count--;
337 + i--;
338 + }
339 + }
340 + ReleaseLock();
341 + }
342 + void AcquireLock()
343 + {
344 + LONG *p = (LONG *)&mutex;
345 + while (_interlockedbittestandset(p,0))
346 + YieldProcessor();
347 + }
348 + void ReleaseLock()
349 + {
350 + LONG *p = (LONG*)&mutex;
351 + _interlockedbittestandreset(p, 0);
352 + }
353 +} *thread_man_ = nullptr; // global singleton
354 +
355 +} // unnamed namespace
356 +
357 +// - API functions -
358 +
359 +extern "C" {
360 +
361 +void FreeThreadStart(HANDLE hProc)
362 +{
363 + if (thread_man_)
364 + ::thread_man_->ReleaseProcessMemory(hProc);
365 +}
366 +
367 +void CheckThreadStart()
368 +{
369 + if (thread_man_)
370 + ::thread_man_->CheckProcessMemory();
371 +
372 + // jichi 2/2/2015: This function is only used to wait for injected threads vnrhost.
373 + // Sleep for 100 ms to wait for remote thread to start
374 + //IthSleep(100);
375 + //IthCoolDown();
376 +}
377 +
378 +void IthSleep(int time)
379 +{
380 + __asm
381 + {
382 + mov eax,0x2710 // jichi = 10000
383 + mov ecx,time
384 + mul ecx
385 + neg eax
386 + adc edx,0
387 + neg edx
388 + push edx
389 + push eax
390 + push esp
391 + push 0
392 + call dword ptr [NtDelayExecution]
393 + add esp,8
394 + }
395 +}
396 +
397 +void IthSystemTimeToLocalTime(LARGE_INTEGER *time)
398 +{ time->QuadPart -= GetTimeBias()->QuadPart; }
399 +
400 +int FillRange(LPCWSTR name, DWORD *lower, DWORD *upper)
401 +{
402 + PLDR_DATA_TABLE_ENTRY it;
403 + LIST_ENTRY *begin;
404 + __asm
405 + {
406 + mov eax,fs:[0x30]
407 + mov eax,[eax+0xc]
408 + mov eax,[eax+0xc]
409 + mov it,eax
410 + mov begin,eax
411 + }
412 +
413 + while (it->SizeOfImage) {
414 + if (::_wcsicmp(it->BaseDllName.Buffer, name) == 0) {
415 + *lower = *upper = (DWORD)it->DllBase;
416 + MEMORY_BASIC_INFORMATION info = {};
417 + DWORD l,size;
418 + size = 0;
419 + do {
420 + NtQueryVirtualMemory(NtCurrentProcess(), (LPVOID)(*upper), MemoryBasicInformation, &info, sizeof(info), &l);
421 + if (info.Protect&PAGE_NOACCESS) {
422 + it->SizeOfImage=size;
423 + break;
424 + }
425 + size += info.RegionSize;
426 + *upper += info.RegionSize;
427 + } while (size < it->SizeOfImage);
428 + return 1;
429 + }
430 + it = (PLDR_DATA_TABLE_ENTRY)it->InLoadOrderModuleList.Flink;
431 + if (it->InLoadOrderModuleList.Flink == begin)
432 + break;
433 + }
434 + return 0;
435 +}
436 +
437 +DWORD SearchPattern(DWORD base, DWORD base_length, LPCVOID search, DWORD search_length) // KMP
438 +{
439 + __asm
440 + {
441 + mov eax,search_length
442 +alloc:
443 + push 0
444 + sub eax,1
445 + jnz alloc
446 +
447 + mov edi,search
448 + mov edx,search_length
449 + mov ecx,1
450 + xor esi,esi
451 +build_table:
452 + mov al,byte ptr [edi+esi]
453 + cmp al,byte ptr [edi+ecx]
454 + sete al
455 + test esi,esi
456 + jz pre
457 + test al,al
458 + jnz pre
459 + mov esi,[esp+esi*4-4]
460 + jmp build_table
461 +pre:
462 + test al,al
463 + jz write_table
464 + inc esi
465 +write_table:
466 + mov [esp+ecx*4],esi
467 +
468 + inc ecx
469 + cmp ecx,edx
470 + jb build_table
471 +
472 + mov esi,base
473 + xor edx,edx
474 + mov ecx,edx
475 +matcher:
476 + mov al,byte ptr [edi+ecx]
477 + cmp al,byte ptr [esi+edx]
478 + sete al
479 + test ecx,ecx
480 + jz match
481 + test al,al
482 + jnz match
483 + mov ecx, [esp+ecx*4-4]
484 + jmp matcher
485 +match:
486 + test al,al
487 + jz pre2
488 + inc ecx
489 + cmp ecx,search_length
490 + je finish
491 +pre2:
492 + inc edx
493 + cmp edx,base_length // search_length
494 + jb matcher
495 + mov edx,search_length
496 + dec edx
497 +finish:
498 + mov ecx,search_length
499 + sub edx,ecx
500 + lea eax,[edx+1]
501 + lea ecx,[ecx*4]
502 + add esp,ecx
503 + }
504 +}
505 +
506 +// jichi 2/5/2014: '?' = 0xff
507 +// See: http://sakuradite.com/topic/124
508 +DWORD SearchPatternEx(DWORD base, DWORD base_length, LPCVOID search, DWORD search_length, BYTE wildcard) // KMP
509 +{
510 + __asm
511 + {
512 + // jichi 2/5/2014 BEGIN
513 + mov bl,wildcard
514 + // jichi 2/5/2014 END
515 + mov eax,search_length
516 +alloc:
517 + push 0
518 + sub eax,1
519 + jnz alloc // jichi 2/5/2014: this will also set %eax to zero
520 +
521 + mov edi,search
522 + mov edx,search_length
523 + mov ecx,1
524 + xor esi,esi
525 +build_table:
526 + mov al,byte ptr [edi+esi]
527 + cmp al,byte ptr [edi+ecx]
528 + sete al
529 + test esi,esi
530 + jz pre
531 + test al,al
532 + jnz pre
533 + mov esi,[esp+esi*4-4]
534 + jmp build_table
535 +pre:
536 + test al,al
537 + jz write_table
538 + inc esi
539 +write_table:
540 + mov [esp+ecx*4],esi
541 +
542 + inc ecx
543 + cmp ecx,edx
544 + jb build_table
545 +
546 + mov esi,base
547 + xor edx,edx
548 + mov ecx,edx
549 +matcher:
550 + mov al,byte ptr [edi+ecx] // search
551 + // jichi 2/5/2014 BEGIN
552 + mov bh,al // save loaded byte to reduce cache access. %ah is not used and always zero
553 + cmp al,bl // %bl is the wildcard byte
554 + sete al
555 + test al,al
556 + jnz wildcard_matched
557 + mov al,bh // restore the loaded byte
558 + // jichi 2/5/2014 END
559 + cmp al,byte ptr [esi+edx] // base
560 + sete al
561 + // jichi 2/5/2014 BEGIN
562 +wildcard_matched:
563 + // jichi 2/5/2014 END
564 + test ecx,ecx
565 + jz match
566 + test al,al
567 + jnz match
568 + mov ecx, [esp+ecx*4-4]
569 + jmp matcher
570 +match:
571 + test al,al
572 + jz pre2
573 + inc ecx
574 + cmp ecx,search_length
575 + je finish
576 +pre2:
577 + inc edx
578 + cmp edx,base_length // search_length
579 + jb matcher
580 + mov edx,search_length
581 + dec edx
582 +finish:
583 + mov ecx,search_length
584 + sub edx,ecx
585 + lea eax,[edx+1]
586 + lea ecx,[ecx*4]
587 + add esp,ecx
588 + }
589 +}
590 +
591 +DWORD IthGetMemoryRange(LPCVOID mem, DWORD *base, DWORD *size)
592 +{
593 + DWORD r;
594 + MEMORY_BASIC_INFORMATION info;
595 + NtQueryVirtualMemory(NtCurrentProcess(), const_cast<LPVOID>(mem), MemoryBasicInformation, &info, sizeof(info), &r);
596 + if (base)
597 + *base = (DWORD)info.BaseAddress;
598 + if (size)
599 + *size = info.RegionSize;
600 + return (info.Type&PAGE_NOACCESS) == 0;
601 +}
602 +
603 +// jichi 9/25/2013
604 +// See: http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.nls/doc/nlsgdrf/multi-byte_widechar_subr.htm
605 +// SJIS->Unicode. 'mb' must be null-terminated. 'wc' should have enough space ( 2*strlen(mb) is safe).
606 +//#ifdef ITH_WINE
607 +//int MB_WC(char *mb, wchar_t *wc)
608 +//{ return mbstowcs(wc, mb, 0x100); }
609 +//
610 +//#else
611 +int MB_WC(char *mb, wchar_t *wc)
612 +{
613 + __asm
614 + {
615 + mov esi,mb
616 + mov edi,wc
617 + mov edx,page
618 + lea ebx,LeadByteTable
619 + add edx,0x220
620 + push 0
621 +_mb_translate:
622 + movzx eax,word ptr [esi]
623 + test al,al
624 + jz _mb_fin
625 + movzx ecx,al
626 + xlat
627 + test al,1
628 + cmovnz cx, word ptr [ecx*2+edx-0x204]
629 + jnz _mb_next
630 + mov cx,word ptr [ecx*2+edx]
631 + mov cl,ah
632 + mov cx, word ptr [ecx*2+edx]
633 +_mb_next:
634 + mov [edi],cx
635 + add edi,2
636 + movzx eax,al
637 + add esi,eax
638 + inc dword ptr [esp]
639 + jmp _mb_translate
640 +_mb_fin:
641 + pop eax
642 + }
643 +}
644 +
645 +// Count characters of 'mb' string. 'mb_length' is max length.
646 +// jichi 9/25/2013: This function is not used
647 +//int MB_WC_count(char *mb, int mb_length)
648 +//{
649 +// __asm
650 +// {
651 +// xor eax,eax
652 +// xor edx,edx
653 +// mov esi,mb
654 +// mov edi,mb_length
655 +// lea ebx,LeadByteTable
656 +//_mbc_count:
657 +// mov dl,byte ptr [esi]
658 +// test dl,dl
659 +// jz _mbc_finish
660 +// movzx ecx, byte ptr [ebx+edx]
661 +// add esi,ecx
662 +// inc eax
663 +// sub edi,ecx
664 +// ja _mbc_count
665 +//_mbc_finish:
666 +// }
667 +//}
668 +
669 +// jichi 9/25/2013
670 +// See: http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.nls/doc/nlsgdrf/multi-byte_widechar_subr.htm
671 +// Unicode->SJIS. Analogous to MB_WC.
672 +//#ifdef ITH_WINE
673 +//int WC_MB(wchar_t *wc, char *mb)
674 +//{ return wcstombs(mb, wc, 0x100); }
675 +//
676 +//#else
677 +int WC_MB(wchar_t *wc, char *mb)
678 +{
679 + __asm
680 + {
681 + mov esi,wc
682 + mov edi,mb
683 + mov edx,page
684 + add edx,0x7C22
685 + xor ebx,ebx
686 +_wc_translate:
687 + movzx eax,word ptr [esi]
688 + test eax,eax
689 + jz _wc_fin
690 + mov cx,word ptr [eax*2+edx]
691 + test ch,ch
692 + jz _wc_single
693 + mov [edi+ebx],ch
694 + inc ebx
695 +_wc_single:
696 + mov [edi+ebx],cl
697 + inc ebx
698 + add esi,2
699 + jmp _wc_translate
700 +_wc_fin:
701 + mov eax,ebx
702 + }
703 +}
704 +
705 +//Initialize environment for NT native calls. Not thread safe so only call it once in one module.
706 +//1. Create new heap. Future memory requests are handled by this heap.
707 +//Destroying this heap will completely release all dynamically allocated memory, thus prevent memory leaks on unload.
708 +//2. Create handle to root directory of process objects (section/event/mutex/semaphore).
709 +//NtCreate* calls will use this handle as base directory.
710 +//3. Load SJIS code page. First check for Japanese locale. If not then load from 'C_932.nls' in system folder.
711 +//MB_WC & WC_MB use this code page for translation.
712 +//4. Locate current NT path (start with \??\).
713 +//NtCreateFile requires full path or a root handle. But this handle is different from object.
714 +//5. Map shared memory for ThreadStartManager into virtual address space.
715 +//This will allow IthCreateThread function properly.
716 +BOOL IthInitSystemService()
717 +{
718 + PPEB peb;
719 + //NTSTATUS status;
720 + DWORD size;
721 + ULONG LowFragmentHeap;
722 + UNICODE_STRING us;
723 + OBJECT_ATTRIBUTES oa = {sizeof(oa), 0, &us, OBJ_CASE_INSENSITIVE, 0, 0};
724 + IO_STATUS_BLOCK ios;
725 + HANDLE codepage_file;
726 + LARGE_INTEGER sec_size = {0x1000, 0};
727 + __asm
728 + {
729 + mov eax,fs:[0x18]
730 + mov ecx,[eax+0x20]
731 + mov eax,[eax+0x30]
732 + mov peb,eax
733 + mov current_process_id,ecx
734 + }
735 + debug = peb->BeingDebugged;
736 + LowFragmentHeap = 2;
737 +
738 +#ifdef ITH_HAS_HEAP
739 + ::hHeap = RtlCreateHeap(0x1002, 0, 0, 0, 0, 0);
740 + RtlSetHeapInformation(::hHeap, HeapCompatibilityInformation, &LowFragmentHeap, sizeof(LowFragmentHeap));
741 +#endif // ITH_HAS_HEAP
742 +
743 + LPWSTR t = nullptr, // jichi: path to system32, such as "c:\windows\system32"
744 + obj = nullptr; // jichi: path to current kernel session, such as "Sessions\\1\\BaseNamedObjects"
745 + // jichi 9/22/2013: This would crash wine with access violation exception.
746 + if (!IthIsWine()) {
747 + // jichi 9/22/2013: For ChuSingura46+1 on Windows 7
748 + // t = L"C:\\Windows\\system32";
749 + // obj = L"\\Sessions\\1\\BaseNamedObjects";
750 + // On Windows XP
751 + // t = L"C:\\WINDOWS\\system32";
752 + // obj = L"\\BaseNamedObjects";
753 + MEMORY_BASIC_INFORMATION info;
754 + if (!NT_SUCCESS(NtQueryVirtualMemory(NtCurrentProcess(), peb->ReadOnlySharedMemoryBase, MemoryBasicInformation, &info, sizeof(info), &size)))
755 + return FALSE;
756 + DWORD base = (DWORD)peb->ReadOnlySharedMemoryBase;
757 + DWORD end = base + info.RegionSize - 0x40;
758 + static WCHAR system32[] = L"system32";
759 + for (;base < end; base += 2)
760 + if (::memcmp((PVOID)base, system32, 0x10) == 0) {
761 + t = (LPWSTR)base;
762 + while (*t-- != L':');
763 + obj = (LPWSTR)base;
764 + while (*obj != L'\\') obj++;
765 + break;
766 + }
767 + if (base == end)
768 + return FALSE;
769 + }
770 + //ITH_MSG(t);
771 + //ITH_MSG(obj);
772 +
773 + LDR_DATA_TABLE_ENTRY *ldr_entry = (LDR_DATA_TABLE_ENTRY*)peb->Ldr->InLoadOrderModuleList.Flink;
774 + wcscpy(file_path + 4, ldr_entry->FullDllName.Buffer);
775 + current_dir = wcsrchr(file_path,L'\\') + 1;
776 + *current_dir = 0;
777 + RtlInitUnicodeString(&us, file_path);
778 + if (!NT_SUCCESS(NtOpenFile(&dir_obj,FILE_LIST_DIRECTORY|FILE_TRAVERSE|SYNCHRONIZE,
779 + &oa,&ios,FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT)))
780 + return FALSE;
781 +
782 + // jichi 9/22/2013: Get kernel object session ID
783 + // See: http://www.brianbondy.com/blog/id/100/
784 + // It seems that on sessionId is 0 on Windows XP, and 1 on Windows Vista and later
785 + // I assume that sessionId is in [0,9]
786 + // For ChuSingura46+1 on Windows 7
787 + // obj = L"\\Sessions\\1\\BaseNamedObjects";
788 + // On Windows XP
789 + // obj = L"\\BaseNamedObjects";
790 + //ITH_MSG(obj);
791 + {
792 + if (obj)
793 + RtlInitUnicodeString(&us, obj);
794 + else { // jichi ITH is on Wine
795 + // Get session ID in PEB
796 + // See: http://msdn.microsoft.com/en-us/library/bb432286%28v=vs.85%29.aspx
797 + DWORD sessionId = peb->SessionId;
798 + if (!sessionId) // Windows XP
799 + RtlInitUnicodeString(&us, L"\\BaseNamedObjects");
800 + else { // Windows Vista +
801 + wchar_t path[] = L"\\Sessions\\0\\BaseNamedObjects";
802 + path[10] += (wchar_t)sessionId; // replace 0 with the session ID
803 + RtlInitUnicodeString(&us, path);
804 + }
805 + }
806 + }
807 +
808 + if (!NT_SUCCESS(NtOpenDirectoryObject(&::root_obj, READ_CONTROL|0xF, &oa)))
809 + return FALSE;
810 +
811 + ::page = peb->InitAnsiCodePageData;
812 +
813 + // jichi 9/23/2013: Access violation on Wine
814 + if (IthIsWine())
815 + // One wine, there is no C_932.nls
816 + //page_locale = 0x4e4; // 1252, English
817 + //page_locale = GetACP(); // This will return 932 when LC_ALL=ja_JP.UTF-8 on wine
818 + // Always set locale to CP932 on Wine, since C_932.nls could be missing.
819 + ::page_locale = 0x3a4; // = 932
820 + else
821 + ::page_locale = *(DWORD *)page >> 16;
822 +
823 + if (::page_locale == 0x3a4) {
824 + oa.hRootDirectory = ::root_obj;
825 + oa.uAttributes |= OBJ_OPENIF;
826 + } else { // Unreachable or wine
827 +//#ifdef ITH_WINE
828 +// // jichi 9/22/2013: For ChuSingura46+1 on Windows 7
829 +// //t = L"C:\\Windows\\system32";
830 +// wchar_t buffer[MAX_PATH];
831 +// if (!t) { // jichi 9/22/2013: ITH is one wine
832 +// if (UINT sz = ::GetSystemDirectoryW(buffer, MAX_PATH)) {
833 +// buffer[sz] = 0;
834 +// t = buffer;
835 +// } else
836 +// t = L"C:\\Windows\\System32"; // jichi 9/29/2013: sth is wrong here
837 +// }
838 +//#endif // ITH_WINE
839 +
840 + ::wcscpy(file_path + 4, t);
841 + t = file_path;
842 + while(*++t);
843 + if (*(t-1)!=L'\\')
844 + *t++=L'\\';
845 + ::wcscpy(t,L"C_932.nls");
846 + RtlInitUnicodeString(&us, file_path);
847 + if (!NT_SUCCESS(NtOpenFile(&codepage_file, FILE_READ_DATA, &oa, &ios,FILE_SHARE_READ,0)))
848 + return FALSE;
849 + oa.hRootDirectory = ::root_obj;
850 + oa.uAttributes |= OBJ_OPENIF;
851 + RtlInitUnicodeString(&us, L"JPN_CodePage");
852 + if (!NT_SUCCESS(NtCreateSection(&codepage_section, SECTION_MAP_READ,
853 + &oa,0, PAGE_READONLY, SEC_COMMIT, codepage_file)))
854 + return FALSE;
855 + NtClose(codepage_file);
856 + size = 0;
857 + ::page = nullptr;
858 + if (!NT_SUCCESS(NtMapViewOfSection(::codepage_section, NtCurrentProcess(),
859 + &::page,
860 + 0, 0, 0, &size, ViewUnmap, 0,
861 + PAGE_READONLY)))
862 + return FALSE;
863 + }
864 + if (ITH_ENABLE_THREADMAN) {
865 + RtlInitUnicodeString(&us, ITH_THREADMAN_SECTION);
866 + if (!NT_SUCCESS(NtCreateSection(&thread_man_section, SECTION_ALL_ACCESS, &oa, &sec_size,
867 + PAGE_EXECUTE_READWRITE, SEC_COMMIT, 0)))
868 + return FALSE;
869 + size = 0;
870 + // http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Section/NtMapViewOfSection.html
871 + thread_man_ = nullptr;
872 + if (!NT_SUCCESS(NtMapViewOfSection(thread_man_section, NtCurrentProcess(),
873 + (LPVOID *)&thread_man_,
874 + 0,0,0, &size, ViewUnmap, 0,
875 + PAGE_EXECUTE_READWRITE)))
876 + return FALSE;
877 + }
878 + return TRUE;
879 +}
880 +
881 +//Release resources allocated by IthInitSystemService.
882 +//After destroying the heap, all memory allocated by ITH module is returned to system.
883 +void IthCloseSystemService()
884 +{
885 + if (::page_locale != 0x3a4) {
886 + NtUnmapViewOfSection(NtCurrentProcess(), ::page);
887 + NtClose(::codepage_section);
888 + }
889 + if (ITH_ENABLE_THREADMAN) {
890 + NtUnmapViewOfSection(NtCurrentProcess(), ::thread_man_);
891 + NtClose(::thread_man_section);
892 + }
893 + NtClose(::root_obj);
894 +#ifdef ITH_HAS_HEAP
895 + RtlDestroyHeap(::hHeap);
896 +#endif // ITH_HAS_HEAP
897 +}
898 +
899 +//Check for existence of a file in current folder. Thread safe after init.
900 +//For ITH main module, it's ITH folder. For target process it's the target process's current folder.
901 +BOOL IthCheckFile(LPCWSTR file)
902 +{
903 + //return PathFileExistsW(file); // jichi: need Shlwapi.lib
904 +
905 + //return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
906 + //return GetFileAttributesW(file) != INVALID_FILE_ATTRIBUTES; // jichi: does not consider the current app's path
907 +
908 + // jichi 9/22/2013: Following code does not work in Wine
909 + // See: http://stackoverflow.com/questions/3828835/how-can-we-check-if-a-file-exists-or-not-using-win32-program
910 + //WIN32_FIND_DATA FindFileData;
911 + //HANDLE handle = FindFirstFileW(file, &FindFileData);
912 + //if (handle != INVALID_HANDLE_VALUE) {
913 + // FindClose(handle);
914 + // return TRUE;
915 + //}
916 + //return FALSE;
917 + if (IthIsWine()) {
918 + HANDLE hFile = CreateFileW(file, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, 0);
919 + if (hFile != INVALID_HANDLE_VALUE) {
920 + CloseHandle(hFile);
921 + return TRUE;
922 + } else if (!wcschr(file, L':')) { // jichi: this is relative path
923 + // jichi 9/22/2013: Change current directory to the same as main module path
924 + // Otherwise NtFile* would not work for files with relative paths.
925 + if (const wchar_t *path = GetMainModulePath()) // path to VNR's python exe
926 + if (const wchar_t *base = wcsrchr(path, L'\\')) {
927 + size_t dirlen = base - path + 1;
928 + if (dirlen + wcslen(file) < MAX_PATH) {
929 + wchar_t buf[MAX_PATH];
930 + wcsncpy(buf, path, dirlen);
931 + wcscpy(buf + dirlen, file);
932 + return IthCheckFile(buf);
933 + }
934 + }
935 + }
936 + } else { // not wine
937 + HANDLE hFile;
938 + IO_STATUS_BLOCK isb;
939 + UNICODE_STRING us;
940 + RtlInitUnicodeString(&us, file);
941 + OBJECT_ATTRIBUTES oa = { sizeof(oa), dir_obj, &us, 0, 0, 0};
942 + // jichi 9/22/2013: Following code does not work in Wine
943 + if (NT_SUCCESS(NtCreateFile(&hFile, FILE_READ_DATA, &oa, &isb, 0, 0, FILE_SHARE_READ, FILE_OPEN, 0, 0, 0))) {
944 + NtClose(hFile);
945 + return TRUE;
946 + }
947 + }
948 + return FALSE;
949 + //return IthGetFileInfo(file,file_info);
950 + //wcscpy(current_dir,file);
951 +}
952 +
953 +//Check for existence of files in current folder.
954 +//Unlike IthCheckFile, this function allows wildcard character.
955 +BOOL IthFindFile(LPCWSTR file)
956 +{
957 + NTSTATUS status;
958 + HANDLE h;
959 + UNICODE_STRING us;
960 + OBJECT_ATTRIBUTES oa = {sizeof(oa), dir_obj, &us, OBJ_CASE_INSENSITIVE, 0, 0};
961 + us.Buffer = const_cast<LPWSTR>(file);
962 + LPCWSTR path = wcsrchr(file, L'\\');
963 + if (path) {
964 + us.Length = (path - file) << 1;
965 + us.MaximumLength = us.Length;
966 + } else {
967 + us.Length = 0;
968 + us.MaximumLength = 0;
969 + }
970 + IO_STATUS_BLOCK ios;
971 + if (NT_SUCCESS(NtOpenFile(&h,FILE_LIST_DIRECTORY|SYNCHRONIZE,
972 + &oa,&ios,FILE_SHARE_READ,FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT))) {
973 + BYTE info[0x400];
974 + if (path)
975 + RtlInitUnicodeString(&us, path + 1);
976 + else
977 + RtlInitUnicodeString(&us, file);
978 + status = NtQueryDirectoryFile(h,0,0,0,&ios,info,0x400,FileBothDirectoryInformation,TRUE,&us,TRUE);
979 + NtClose(h);
980 + return NT_SUCCESS(status);
981 + }
982 + return FALSE;
983 +}
984 +//Analogous to IthFindFile, but return detail information in 'info'.
985 +BOOL IthGetFileInfo(LPCWSTR file, LPVOID info, DWORD size)
986 +{
987 + NTSTATUS status;
988 + HANDLE h;
989 + UNICODE_STRING us;
990 + LPCWSTR path = wcsrchr(file, L'\\');
991 + us.Buffer = const_cast<LPWSTR>(file);
992 + if (path) {
993 + us.Length = (path - file) << 1;
994 + us.MaximumLength = us.Length;
995 + } else {
996 + us.Length = 0;
997 + us.MaximumLength = 0;
998 + }
999 + //RtlInitUnicodeString(&us,file);
1000 + OBJECT_ATTRIBUTES oa = {sizeof(oa), dir_obj, &us, OBJ_CASE_INSENSITIVE, 0, 0};
1001 + IO_STATUS_BLOCK ios;
1002 + if (NT_SUCCESS(NtOpenFile(&h,FILE_LIST_DIRECTORY|SYNCHRONIZE,
1003 + &oa,&ios,FILE_SHARE_READ,FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT))) {
1004 + RtlInitUnicodeString(&us,file);
1005 + status = NtQueryDirectoryFile(h,0,0,0,&ios,info,size,FileBothDirectoryInformation,0,&us,0);
1006 + status = NT_SUCCESS(status);
1007 + NtClose(h);
1008 + } else
1009 + status = FALSE;
1010 + return status;
1011 +}
1012 +
1013 +//Check for existence of a file with full NT path(start with \??\).
1014 +BOOL IthCheckFileFullPath(LPCWSTR file)
1015 +{
1016 + UNICODE_STRING us;
1017 + RtlInitUnicodeString(&us, file);
1018 + OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &us, OBJ_CASE_INSENSITIVE, 0, 0};
1019 + HANDLE hFile;
1020 + IO_STATUS_BLOCK isb;
1021 + if (NT_SUCCESS(NtCreateFile(&hFile,FILE_READ_DATA,&oa,&isb,0,0,FILE_SHARE_READ,FILE_OPEN,0,0,0))) {
1022 + NtClose(hFile);
1023 + return TRUE;
1024 + } else
1025 + return FALSE;
1026 +}
1027 +//Create or open file in current folder. Analogous to Win32 CreateFile.
1028 +//option: GENERIC_READ / GENERIC_WRITE.
1029 +//share: FILE_SHARE_READ / FILE_SHARE_WRITE / FILE_SHARE_DELETE. 0 for exclusive access.
1030 +//disposition: FILE_OPEN / FILE_OPEN_IF.
1031 +//Use FILE_OPEN instead of OPEN_EXISTING and FILE_OPEN_IF for CREATE_ALWAYS.
1032 +HANDLE IthCreateFile(LPCWSTR name, DWORD option, DWORD share, DWORD disposition)
1033 +{
1034 + UNICODE_STRING us;
1035 + RtlInitUnicodeString(&us, name);
1036 + OBJECT_ATTRIBUTES oa = { sizeof(oa), dir_obj, &us, OBJ_CASE_INSENSITIVE, 0, 0 };
1037 + HANDLE hFile;
1038 + IO_STATUS_BLOCK isb;
1039 + return NT_SUCCESS(NtCreateFile(&hFile,
1040 + option|FILE_READ_ATTRIBUTES|SYNCHRONIZE,
1041 + &oa,&isb,0,0,share,disposition,
1042 + FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE,0,0)) ?
1043 + hFile : INVALID_HANDLE_VALUE;
1044 +}
1045 +//Create a directory file in current folder.
1046 +HANDLE IthCreateDirectory(LPCWSTR name)
1047 +{
1048 + UNICODE_STRING us;
1049 + RtlInitUnicodeString(&us,name);
1050 + OBJECT_ATTRIBUTES oa = {sizeof(oa), dir_obj, &us, OBJ_CASE_INSENSITIVE, 0, 0};
1051 + HANDLE hFile;
1052 + IO_STATUS_BLOCK isb;
1053 + return NT_SUCCESS(NtCreateFile(&hFile,FILE_LIST_DIRECTORY|FILE_TRAVERSE|SYNCHRONIZE,&oa,&isb,0,0,
1054 + FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_OPEN_IF,FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT,0,0)) ?
1055 + hFile : INVALID_HANDLE_VALUE;
1056 +}
1057 +
1058 +HANDLE IthCreateFileInDirectory(LPCWSTR name, HANDLE dir, DWORD option, DWORD share, DWORD disposition)
1059 +{
1060 + UNICODE_STRING us;
1061 + RtlInitUnicodeString(&us,name);
1062 + if (dir == 0) dir = dir_obj;
1063 + OBJECT_ATTRIBUTES oa = {sizeof(oa), dir, &us, OBJ_CASE_INSENSITIVE, 0, 0};
1064 + HANDLE hFile;
1065 + IO_STATUS_BLOCK isb;
1066 + return NT_SUCCESS(NtCreateFile(&hFile,
1067 + option|FILE_READ_ATTRIBUTES|SYNCHRONIZE,
1068 + &oa,&isb,0,0,share,disposition,
1069 + FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE,0,0)) ?
1070 + hFile : INVALID_HANDLE_VALUE;
1071 +}
1072 +
1073 +//Analogous to IthCreateFile, but with full NT path.
1074 +HANDLE IthCreateFileFullPath(LPCWSTR path, DWORD option, DWORD share, DWORD disposition)
1075 +{
1076 + UNICODE_STRING us;
1077 + RtlInitUnicodeString(&us,path);
1078 + OBJECT_ATTRIBUTES oa = {sizeof(oa), 0, &us, OBJ_CASE_INSENSITIVE, 0, 0};
1079 + HANDLE hFile;
1080 + IO_STATUS_BLOCK isb;
1081 + return NT_SUCCESS(NtCreateFile(&hFile,
1082 + option|FILE_READ_ATTRIBUTES|SYNCHRONIZE,
1083 + &oa,&isb,0,0,share,disposition,
1084 + FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE,0,0)) ?
1085 + hFile : INVALID_HANDLE_VALUE;
1086 +}
1087 +
1088 +//Create section object for sharing memory between processes.
1089 +//Similar to CreateFileMapping.
1090 +HANDLE IthCreateSection(LPCWSTR name, DWORD size, DWORD right)
1091 +{
1092 +// jichi 9/25/2013: GENERIC_ALL does NOT work one wine
1093 +// See ZwCreateSection: http://msdn.microsoft.com/en-us/library/windows/hardware/ff566428%28v=vs.85%29.aspx
1094 +//#ifdef ITH_WINE
1095 + enum { DesiredAccess = SECTION_ALL_ACCESS };
1096 +//#else
1097 +// enum { DesiredAccess = GENERIC_ALL }; // jichi 9/25/2013: not sure whhy ITH is usin GENERIC_ALL
1098 +//#endif // ITH_WINE
1099 +#define eval (NT_SUCCESS(NtCreateSection(&hSection, DesiredAccess, poa, &s, \
1100 + right, SEC_COMMIT, 0)) ? hSection : INVALID_HANDLE_VALUE)
1101 + HANDLE hSection;
1102 + LARGE_INTEGER s = {size, 0};
1103 + OBJECT_ATTRIBUTES *poa = nullptr;
1104 + // jichi 9/25/2013: What the fxxx?! poa in the orignal source code of ITH
1105 + // is pointed to freed object on the stack?! This will crash wine!
1106 + if (name) {
1107 + UNICODE_STRING us;
1108 + RtlInitUnicodeString(&us, name);
1109 + OBJECT_ATTRIBUTES oa = {sizeof(oa), root_obj, &us,OBJ_OPENIF,0,0};
1110 + poa = &oa;
1111 + return eval;
1112 + } else
1113 + return eval;
1114 +#undef retval
1115 +}
1116 +
1117 +//Create event object. Similar to CreateEvent.
1118 +HANDLE IthCreateEvent(LPCWSTR name, DWORD auto_reset, DWORD init_state)
1119 +{
1120 +#define eval (NT_SUCCESS(NtCreateEvent(&hEvent, EVENT_ALL_ACCESS, poa, auto_reset, init_state)) ? \
1121 + hEvent : INVALID_HANDLE_VALUE)
1122 + HANDLE hEvent;
1123 + OBJECT_ATTRIBUTES *poa = nullptr;
1124 + // jichi 9/25/2013: What the fxxx?! poa in the orignal source code of ITH
1125 + // is pointed to freed object on the stack?! This will crash wine!
1126 + if (name) {
1127 + UNICODE_STRING us;
1128 + RtlInitUnicodeString(&us,name);
1129 + OBJECT_ATTRIBUTES oa = {sizeof(oa), root_obj, &us, OBJ_OPENIF, 0, 0};
1130 + poa = &oa;
1131 + return eval;
1132 + } else
1133 + return eval;
1134 +#undef eval
1135 +}
1136 +
1137 +HANDLE IthOpenEvent(LPCWSTR name)
1138 +{
1139 + UNICODE_STRING us;
1140 + RtlInitUnicodeString(&us, name);
1141 + OBJECT_ATTRIBUTES oa = { sizeof(oa), root_obj, &us, 0, 0, 0 };
1142 + HANDLE hEvent;
1143 + return NT_SUCCESS(NtOpenEvent(&hEvent, EVENT_ALL_ACCESS, &oa)) ?
1144 + hEvent : INVALID_HANDLE_VALUE;
1145 +}
1146 +
1147 +void IthSetEvent(HANDLE hEvent) { NtSetEvent(hEvent, 0); }
1148 +
1149 +void IthResetEvent(HANDLE hEvent) { NtClearEvent(hEvent); }
1150 +
1151 +//Create mutex object. Similar to CreateMutex.
1152 +//If 'exist' is not null, it will be written 1 if mutex exist.
1153 +HANDLE IthCreateMutex(LPCWSTR name, BOOL InitialOwner, DWORD *exist)
1154 +{
1155 +#define eval NtCreateMutant(&hMutex, MUTEX_ALL_ACCESS, poa, InitialOwner)
1156 + UNICODE_STRING us;
1157 + HANDLE hMutex;
1158 + NTSTATUS status;
1159 + OBJECT_ATTRIBUTES *poa = nullptr;
1160 + // jichi 9/25/2013: What the fxxx?! poa in the orignal source code of ITH
1161 + // is pointed to freed object on the stack?! This will crash wine!
1162 + if (name) {
1163 + RtlInitUnicodeString(&us, name);
1164 + OBJECT_ATTRIBUTES oa = {sizeof(oa), root_obj, &us, OBJ_OPENIF, 0, 0};
1165 + poa = &oa;
1166 + status = eval;
1167 + } else
1168 + status = eval;
1169 + if (NT_SUCCESS(status)) {
1170 + if (exist)
1171 + *exist = status == STATUS_OBJECT_NAME_EXISTS;
1172 + return hMutex;
1173 + } else
1174 + return INVALID_HANDLE_VALUE;
1175 +#undef eval
1176 +}
1177 +
1178 +HANDLE IthOpenMutex(LPCWSTR name)
1179 +{
1180 + UNICODE_STRING us;
1181 + RtlInitUnicodeString(&us, name);
1182 + OBJECT_ATTRIBUTES oa = {sizeof(oa), root_obj, &us, 0, 0, 0};
1183 + HANDLE hMutex;
1184 + if (NT_SUCCESS(NtOpenMutant(&hMutex, MUTEX_ALL_ACCESS, &oa)))
1185 + return hMutex;
1186 + else
1187 + return INVALID_HANDLE_VALUE;
1188 +}
1189 +
1190 +BOOL IthReleaseMutex(HANDLE hMutex)
1191 +{ return NT_SUCCESS(NtReleaseMutant(hMutex, 0)); }
1192 +
1193 +//Create new thread. 'hProc' must have following right.
1194 +//PROCESS_CREATE_THREAD, PROCESS_VM_OPERATION, PROCESS_VM_READ, PROCESS_VM_WRITE.
1195 +HANDLE IthCreateThread(LPCVOID start_addr, DWORD param, HANDLE hProc)
1196 +{
1197 + HANDLE hThread;
1198 + // jichi 9/27/2013: NtCreateThread is not implemented in Wine 1.7
1199 + if (thread_man_) { // Windows XP
1200 + // jichi 9/29/2013: Reserved && commit stack size
1201 + // See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366803%28v=vs.85%29.aspx
1202 + // See: http://msdn.microsoft.com/en-us/library/ms810627.aspx
1203 + enum { DEFAULT_STACK_LIMIT = 0x400000 };
1204 + enum { DEFAULT_STACK_COMMIT = 0x10000 };
1205 + enum { PAGE_SIZE = 0x1000 };
1206 + CLIENT_ID id;
1207 + LPVOID protect;
1208 + USER_STACK stack = {};
1209 + CONTEXT ctx = {CONTEXT_FULL};
1210 + DWORD size = DEFAULT_STACK_LIMIT,
1211 + commit = DEFAULT_STACK_COMMIT;
1212 + if (!NT_SUCCESS(NtAllocateVirtualMemory(hProc, &stack.ExpandableStackBottom, 0, &size, MEM_RESERVE, PAGE_READWRITE)))
1213 + return INVALID_HANDLE_VALUE;
1214 +
1215 + stack.ExpandableStackBase = (char *)stack.ExpandableStackBottom + size;
1216 + stack.ExpandableStackLimit = (char *)stack.ExpandableStackBase - commit;
1217 + size = PAGE_SIZE;
1218 + commit += size;
1219 + protect = (char *)stack.ExpandableStackBase - commit;
1220 + NtAllocateVirtualMemory(hProc, &protect, 0, &commit, MEM_COMMIT, PAGE_READWRITE);
1221 + DWORD oldAccess; // jichi 9/29/2013: unused
1222 + NtProtectVirtualMemory(hProc, &protect, &size, PAGE_READWRITE|PAGE_GUARD, &oldAccess);
1223 + ctx.SegGs = 0;
1224 + ctx.SegFs = 0x38;
1225 + ctx.SegEs = 0x20;
1226 + ctx.SegDs = 0x20;
1227 + ctx.SegSs = 0x20;
1228 + ctx.SegCs = 0x18;
1229 + ctx.EFlags = 0x3000;
1230 + ctx.Eip = (DWORD)thread_man_->GetProcAddr(hProc);
1231 + ctx.Eax = (DWORD)start_addr;
1232 + ctx.Ecx = ctx.Eip + 0x40;
1233 + ctx.Edx = 0xffffffff;
1234 + ctx.Esp = (DWORD)stack.ExpandableStackBase - 0x10;
1235 + ctx.Ebp = param;
1236 +
1237 + // NTSYSAPI
1238 + // NTSTATUS
1239 + // NTAPI
1240 + // NtCreateThread(
1241 + // _Out_ PHANDLE ThreadHandle,
1242 + // _In_ ACCESS_MASK DesiredAccess,
1243 + // _In_ POBJECT_ATTRIBUTES ObjectAttributes,
1244 + // _In_ HANDLE ProcessHandle,
1245 + // _Out_ PCLIENT_ID ClientId,
1246 + // _In_ PCONTEXT ThreadContext,
1247 + // _In_ PUSER_STACK UserStack,
1248 + // _In_ BOOLEAN CreateSuspended
1249 + // );
1250 + if (NT_SUCCESS(NtCreateThread(
1251 + &hThread, // _Out_ PHANDLE ThreadHandle,
1252 + THREAD_ALL_ACCESS, // _In_ ACCESS_MASK DesiredAccess,
1253 + nullptr, // _In_ POBJECT_ATTRIBUTES ObjectAttributes,
1254 + hProc, // _In_ HANDLE ProcessHandle,
1255 + &id, // _Out_ PCLIENT_ID ClientId,
1256 + &ctx, // _In_ PCONTEXT ThreadContext,
1257 + &stack, // _In_ PUSER_STACK UserStack,
1258 + TRUE // _In_ BOOLEAN CreateSuspended
1259 + ))) {
1260 + // On x64 Windows, NtCreateThread in ntdll calls NtCreateThread in ntoskrnl via WOW64,
1261 + // which maps 32-bit system call to the correspond 64-bit version.
1262 + // This layer doesn't correctly copy whole CONTEXT structure, so we must set it manually
1263 + // after the thread is created.
1264 + // On x86 Windows, this step is not necessary.
1265 + NtSetContextThread(hThread, &ctx);
1266 + NtResumeThread(hThread, 0);
1267 + } else
1268 + hThread = INVALID_HANDLE_VALUE;
1269 +
1270 + } else {
1271 + // jichi 9/27/2013: CreateRemoteThread works on both Wine and Windows 7
1272 + // Use CreateRemoteThread instead
1273 + // FIXME 10/5/2031: Though sometimes works, CreateRemoteThread randomly crashes on wine.
1274 + // See:
1275 + // - http://www.unknowncheats.me/forum/c-and-c/64775-createremotethread-dll-injection.html
1276 + // - http://source.winehq.org/WineAPI/CreateRemoteThread.html
1277 + // - http://msdn.microsoft.com/en-us/library/windows/desktop/ms682437%28v=vs.85%29.aspx
1278 + // HANDLE WINAPI CreateRemoteThread(
1279 + // _In_ HANDLE hProcess,
1280 + // _In_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
1281 + // _In_ SIZE_T dwStackSize,
1282 + // _In_ LPTHREAD_START_ROUTINE lpStartAddress,
1283 + // _In_ LPVOID lpParameter,
1284 + // _In_ DWORD dwCreationFlags,
1285 + // _Out_ LPDWORD lpThreadId
1286 + // );
1287 + //ITH_TRY {
1288 + if (hProc == INVALID_HANDLE_VALUE)
1289 + hProc = GetCurrentProcess();
1290 + //DWORD dwThreadId;
1291 + hThread = CreateRemoteThread(
1292 + hProc, // _In_ HANDLE hProcess,
1293 + nullptr, // _In_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
1294 + 0, // _In_ SIZE_T dwStackSize,
1295 + (LPTHREAD_START_ROUTINE)start_addr, // _In_ LPTHREAD_START_ROUTINE lpStartAddress,
1296 + (LPVOID)param, // _In_ LPVOID lpParameter,
1297 + 0, //STACK_SIZE_PARAM_IS_A_RESERVATION // _In_ DWORD dwCreationFlags,
1298 + nullptr // _Out_ LPDWORD lpThreadId
1299 + );
1300 + if (!hThread) // jichi: this function returns nullptr instead of -1
1301 + hThread = INVALID_HANDLE_VALUE;
1302 + //} ITH_EXCEPT {
1303 + // ITH_WARN(L"exception");
1304 + // hThread = INVALID_HANDLE_VALUE;
1305 + //}
1306 + }
1307 + /*
1308 + else {
1309 + // jichi 9/29/2013: Also work on Wine and Windows 7
1310 + // See: http://waleedassar.blogspot.com/2012/06/createremotethread-vs.html
1311 + CLIENT_ID id;
1312 + //DWORD size = DEFAULT_STACK_LIMIT,
1313 + // commit = DEFAULT_STACK_COMMIT;
1314 + DWORD reserve = 0,
1315 + commit = 0;
1316 + // http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlCreateUserThread.html
1317 + // NTSYSAPI
1318 + // NTSTATUS
1319 + // NTAPI
1320 + // RtlCreateUserThread(
1321 + // IN HANDLE ProcessHandle,
1322 + // IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
1323 + // IN BOOLEAN CreateSuspended,
1324 + // IN ULONG StackZeroBits,
1325 + // IN OUT PULONG StackReserved,
1326 + // IN OUT PULONG StackCommit,
1327 + // IN PVOID StartAddress,
1328 + // IN PVOID StartParameter OPTIONAL,
1329 + // OUT PHANDLE ThreadHandle,
1330 + // OUT PCLIENT_ID ClientID);
1331 + if (!NT_SUCCESS(RtlCreateUserThread(
1332 + hProc, // HANDLE hProcess,
1333 + nullptr, // IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
1334 + FALSE, // IN BOOLEAN CreateSuspended,
1335 + 0, // IN ULONG StackZeroBits,
1336 + &reserve, // IN OUT PULONG StackReserved,
1337 + &commit, // IN OUT PULONG StackCommit,
1338 + (LPVOID)start_addr, // IN PVOID StartAddress,
1339 + (LPVOID)param,// IN PVOID StartParameter OPTIONAL,
1340 + &hThread, // OUT PHANDLE ThreadHandle,
1341 + &id // OUT PCLIENT_ID ClientID
1342 + )))
1343 + hThread = INVALID_HANDLE_VALUE;
1344 + }
1345 + */
1346 + return hThread;
1347 +}
1348 +
1349 +//Query module export table. Return function address if found.
1350 +//Similar to GetProcAddress
1351 +DWORD GetExportAddress(DWORD hModule,DWORD hash)
1352 +{
1353 + IMAGE_DOS_HEADER *DosHdr;
1354 + IMAGE_NT_HEADERS *NtHdr;
1355 + IMAGE_EXPORT_DIRECTORY *ExtDir;
1356 + UINT uj;
1357 + char* pcExportAddr,*pcFuncPtr,*pcBuffer;
1358 + DWORD dwReadAddr,dwFuncAddr,dwFuncName;
1359 + WORD wOrd;
1360 + DosHdr = (IMAGE_DOS_HEADER*)hModule;
1361 + if (IMAGE_DOS_SIGNATURE==DosHdr->e_magic) {
1362 + dwReadAddr=hModule+DosHdr->e_lfanew;
1363 + NtHdr=(IMAGE_NT_HEADERS*)dwReadAddr;
1364 + if (IMAGE_NT_SIGNATURE == NtHdr->Signature) {
1365 + pcExportAddr = (char*)((DWORD)hModule+
1366 + (DWORD)NtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
1367 + if (!pcExportAddr)
1368 + return 0;
1369 + ExtDir = (IMAGE_EXPORT_DIRECTORY*)pcExportAddr;
1370 + pcExportAddr = (char*)((DWORD)hModule+(DWORD)ExtDir->AddressOfNames);
1371 +
1372 + for (uj = 0; uj < ExtDir->NumberOfNames; uj++) {
1373 + dwFuncName = *(DWORD *)pcExportAddr;
1374 + pcBuffer = (char*)((DWORD)hModule+dwFuncName);
1375 + if (GetHash(pcBuffer) == hash) {
1376 + pcFuncPtr = (char*)((DWORD)hModule+(DWORD)ExtDir->AddressOfNameOrdinals+(uj*sizeof(WORD)));
1377 + wOrd = *(WORD*)pcFuncPtr;
1378 + pcFuncPtr = (char*)((DWORD)hModule+(DWORD)ExtDir->AddressOfFunctions+(wOrd*sizeof(DWORD)));
1379 + dwFuncAddr = *(DWORD *)pcFuncPtr;
1380 + return hModule+dwFuncAddr;
1381 + }
1382 + pcExportAddr += sizeof(DWORD);
1383 + }
1384 + }
1385 + }
1386 + return 0;
1387 +}
1388 +
1389 +} // extern "C"
1390 +
1391 +// EOF
1392 +
1393 +/*__declspec(naked) void normal_asm()
1394 +{
1395 + __asm
1396 + {
1397 + push ecx
1398 + push edx
1399 + mov fs:[0],esp
1400 + push ebp
1401 + call eax
1402 +_terminate:
1403 + push eax
1404 + push -2
1405 + call dword ptr [NtTerminateThread]
1406 + }
1407 +}*/
1408 +
1409 +/*
1410 +__declspec(naked) void RegToStrAsm()
1411 +{
1412 + __asm
1413 + {
1414 + mov edx, 8
1415 +_cvt_loop:
1416 + mov eax, ecx
1417 + and eax, 0xF
1418 + cmp eax, 0xA
1419 + jb _below_ten
1420 + add al,7
1421 +_below_ten:
1422 + add al,0x30
1423 + stosw
1424 + ror ecx,4
1425 + dec edx
1426 + jne _cvt_loop
1427 + retn
1428 + }
1429 +}
1430 +__declspec(naked) void except_asm()
1431 +{
1432 + __asm
1433 + {
1434 + mov eax,[esp + 4]
1435 + xor esi,esi
1436 + mov ebp,[eax]
1437 + mov ecx,[esp + 0xC]
1438 + mov ebx,[ecx + 0xB8]
1439 + sub esp,0x240
1440 + lea edi,[esp + 0x40]
1441 + mov eax,esp
1442 + push esi
1443 + push 0x1C
1444 + push eax
1445 + push esi
1446 + push ebx
1447 + push -1
1448 + call dword ptr [NtQueryVirtualMemory]
1449 + test eax,eax
1450 + jne _terminate
1451 + mov eax,esp
1452 + push eax
1453 + push 0x200
1454 + push edi
1455 + push 2
1456 + push ebx
1457 + push -1
1458 + call dword ptr [NtQueryVirtualMemory]
1459 + test eax,eax
1460 + jne _terminate
1461 + pop esi
1462 + xadd edi,esi
1463 + std
1464 + mov al,0x5C
1465 + repen scasw
1466 + mov word ptr [edi + 2], 0x3A
1467 + mov ecx,ebx
1468 + sub ecx,[esp]
1469 + call RegToStrAsm
1470 + inc edi
1471 + inc edi
1472 + xchg esi,edi
1473 + mov ecx,ebp
1474 + call RegToStrAsm
1475 + inc edi
1476 + inc edi
1477 + xor eax,eax
1478 + mov [edi + 0x10], eax
1479 + push 0
1480 + push edi
1481 + push esi
1482 + push 0
1483 + call dword ptr [MessageBoxW]
1484 + or eax, -1
1485 + jmp _terminate
1486 + }
1487 +}
1488 +
1489 +//Prompt for file name.
1490 +HANDLE IthPromptCreateFile(DWORD option, DWORD share, DWORD disposition)
1491 +{
1492 + OPENFILENAME ofn = {sizeof(ofn)}; // common dialog box structure
1493 + WCHAR szFile[MAX_PATH]; // buffer for file name
1494 + wcscpy(current_dir,L"ITH_export.txt");
1495 + wcscpy(szFile,file_path);
1496 +
1497 + //szFile[0]=0;
1498 + ofn.lpstrFile = szFile + 4;
1499 + ofn.nMaxFile = MAX_PATH;
1500 + ofn.lpstrFilter = L"Text\0*.txt";
1501 + BOOL result;
1502 + if (disposition==FILE_OPEN)
1503 + result=GetOpenFileName(&ofn);
1504 + else
1505 + result=GetSaveFileName(&ofn);
1506 + if (result)
1507 + {
1508 + LPWSTR s=szFile+wcslen(szFile) - 4;
1509 + if (_wcsicmp(s,L".txt")!=0) wcscpy(s + 4,L".txt");
1510 + return IthCreateFileFullPath(szFile,option,share,disposition);
1511 + }
1512 + else return INVALID_HANDLE_VALUE;
1513 +}
1514 +*/
1 +#pragma once
2 +
3 +// ith/sys.h
4 +// 8/23/2013 jichi
5 +// Branch: ITH/IHF_SYS.h, rev 111
6 +
7 +#ifdef _MSC_VER
8 +# pragma warning(disable:4800) // C4800: forcing value to bool
9 +#endif // _MSC_VER
10 +
11 +#include "ntdll/ntdll.h"
12 +
13 +// jichi 8/24/2013: Why extern "C"? Any specific reason to use C instead of C++ naming?
14 +extern "C" {
15 +//int disasm(BYTE *opcode0); // jichi 8/15/2013: move disasm to separate file
16 +extern WORD *NlsAnsiCodePage;
17 +int FillRange(LPCWSTR name,DWORD *lower, DWORD *upper);
18 +int MB_WC(char *mb, wchar_t *wc);
19 +//int MB_WC_count(char *mb, int mb_length);
20 +int WC_MB(wchar_t *wc, char *mb);
21 +
22 +// jichi 10/1/2013: Return 0 if failed. So, it is ambiguous if the search pattern starts at 0
23 +DWORD SearchPattern(DWORD base, DWORD base_length, LPCVOID search, DWORD search_length); // KMP
24 +
25 +// jichi 2/5/2014: The same as SearchPattern except it uses 0xff to match everything
26 +// According to @Andys, 0xff seldom appear in the source code: http://sakuradite.com/topic/124
27 +enum : BYTE { SP_ANY = 0xff };
28 +#define SP_ANY_2 SP_ANY,SP_ANY
29 +#define SP_ANY_3 SP_ANY,SP_ANY,SP_ANY
30 +#define SP_ANY_4 SP_ANY,SP_ANY,SP_ANY,SP_ANY
31 +DWORD SearchPatternEx(DWORD base, DWORD base_length, LPCVOID search, DWORD search_length, BYTE wildcard=SP_ANY);
32 +
33 +BOOL IthInitSystemService();
34 +void IthCloseSystemService();
35 +DWORD IthGetMemoryRange(LPCVOID mem, DWORD *base, DWORD *size);
36 +BOOL IthCheckFile(LPCWSTR file);
37 +BOOL IthFindFile(LPCWSTR file);
38 +BOOL IthGetFileInfo(LPCWSTR file, LPVOID info, DWORD size = 0x1000);
39 +BOOL IthCheckFileFullPath(LPCWSTR file);
40 +HANDLE IthCreateFile(LPCWSTR name, DWORD option, DWORD share, DWORD disposition);
41 +HANDLE IthCreateFileInDirectory(LPCWSTR name, HANDLE dir, DWORD option, DWORD share, DWORD disposition);
42 +HANDLE IthCreateDirectory(LPCWSTR name);
43 +HANDLE IthCreateFileFullPath(LPCWSTR fullpath, DWORD option, DWORD share, DWORD disposition);
44 +HANDLE IthPromptCreateFile(DWORD option, DWORD share, DWORD disposition);
45 +HANDLE IthCreateSection(LPCWSTR name, DWORD size, DWORD right);
46 +HANDLE IthCreateEvent(LPCWSTR name, DWORD auto_reset=0, DWORD init_state=0);
47 +HANDLE IthOpenEvent(LPCWSTR name);
48 +void IthSetEvent(HANDLE hEvent);
49 +void IthResetEvent(HANDLE hEvent);
50 +HANDLE IthCreateMutex(LPCWSTR name, BOOL InitialOwner, DWORD *exist=0);
51 +HANDLE IthOpenMutex(LPCWSTR name);
52 +BOOL IthReleaseMutex(HANDLE hMutex);
53 +//DWORD IthWaitForSingleObject(HANDLE hObject, DWORD dwTime);
54 +HANDLE IthCreateThread(LPCVOID start_addr, DWORD param, HANDLE hProc=(HANDLE)-1);
55 +DWORD GetExportAddress(DWORD hModule,DWORD hash);
56 +void IthSleep(int time); // jichi 9/28/2013: in ms
57 +void IthSystemTimeToLocalTime(LARGE_INTEGER *ptime);
58 +void FreeThreadStart(HANDLE hProc);
59 +void CheckThreadStart();
60 +} // extern "C"
61 +
62 +#ifdef ITH_HAS_HEAP
63 +extern HANDLE hHeap; // used in ith/common/memory.h
64 +#endif // ITH_HAS_HEAP
65 +
66 +extern DWORD current_process_id;
67 +extern DWORD debug;
68 +extern BYTE LeadByteTable[];
69 +extern LPVOID page;
70 +extern BYTE launch_time[];
71 +
72 +inline DWORD GetHash(LPSTR str)
73 +{
74 + DWORD hash = 0;
75 + //for (; *str; str++)
76 + while (*str)
77 + hash = ((hash>>7) | (hash<<25)) + *str++;
78 + return hash;
79 +}
80 +
81 +inline DWORD GetHash(LPCWSTR str)
82 +{
83 + DWORD hash = 0;
84 + //for (; *str; str++)
85 + while (*str)
86 + hash = ((hash>>7) | (hash<<25)) + *str++;
87 + return hash;
88 +}
89 +
90 +inline void IthBreak()
91 +{ if (debug) __debugbreak(); }
92 +
93 +inline LPCWSTR GetMainModulePath()
94 +{
95 + __asm
96 + {
97 + mov eax, fs:[0x30]
98 + mov eax, [eax + 0xC]
99 + mov eax, [eax + 0xC]
100 + mov eax, [eax + 0x28]
101 + }
102 +}
103 +
104 +// jichi 9/28/2013: Add this to lock NtWriteFile in wine
105 +class IthMutexLocker
106 +{
107 + HANDLE m;
108 +public:
109 + explicit IthMutexLocker(HANDLE mutex) : m(mutex)
110 + { NtWaitForSingleObject(m, 0, 0); }
111 +
112 + ~IthMutexLocker() { if (m != INVALID_HANDLE_VALUE) IthReleaseMutex(m); }
113 +
114 + bool locked() const { return m != INVALID_HANDLE_VALUE; }
115 +
116 + void unlock() { if (m != INVALID_HANDLE_VALUE) { IthReleaseMutex(m); m = INVALID_HANDLE_VALUE; } }
117 +};
118 +
119 +void IthCoolDown();
120 +
121 +BOOL IthIsWine();
122 +BOOL IthIsWindowsXp();
123 +//BOOL IthIsWindows8OrGreater(); // not public
124 +
125 +/** Get current dll path.
126 + * @param buf
127 + * @param len
128 + * @return length of the path excluding \0
129 + */
130 +size_t IthGetCurrentModulePath(wchar_t *buf, size_t len);
131 +
132 +// EOF
1 +# sys.pri
2 +# 8/21/2013 jichi
3 +
4 +DEFINES += WITH_LIB_ITH_SYS
5 +LIBS += -lvnrsys
6 +DEPENDPATH += $$PWD
7 +HEADERS += $$PWD/sys.h
8 +#SOURCES += $$PWD/sys.cc
9 +
10 +#include($$LIBDIR/winddk/winddk.pri)
11 +#LIBS += -L$$WDK/lib/wxp/i386
12 +
13 +# EOF
1 +# sys.pro
2 +# 8/21/2013 jichi
3 +# Build vnrsys.lib
4 +
5 +CONFIG += noqt noeh staticlib
6 +
7 +include(../../../../config.pri)
8 +include($$LIBDIR/ntdll/ntdll.pri)
9 +
10 +#include($$LIBDIR/winddk/winddk.pri)
11 +#LIBS += -L$$WDK/lib/wxp/i386
12 +
13 +# jichi 9/22/2013: When ITH is on wine, certain NT functions are replaced
14 +#DEFINES += ITH_WINE
15 +
16 +# jichi 9/14/2013: Windows XP's msvnrt does not have except handler
17 +DEFINES -= ITH_HAS_SEH
18 +
19 +# jichi 11/24/2013: Disable manual heap
20 +DEFINES -= ITH_HAS_HEAP
21 +
22 +## Libraries
23 +
24 +#INCLUDEPATH += $$ITH_HOME/include
25 +#INCLUDEPATH += $$WDK7_HOME/inc/ddk
26 +
27 +#LIBS += -lgdi32 -luser32 -lkernel32
28 +#LIBS += -L$$WDK7_HOME/lib/wxp/i386 -lntdll
29 +#LIBS += $$WDK7_HOME/lib/crt/i386/msvcrt.lib # Override msvcrt10
30 +
31 +#DEFINES += ITH_HAS_CXX
32 +
33 +#LIBS += -lith_sys -lntdll
34 +#LIBS += -lith_tls -lntdll
35 +#LIBS += -lntoskrnl
36 +
37 +DEFINES += _CRT_NON_CONFORMING_SWPRINTFS
38 +
39 +## Sources
40 +
41 +TEMPLATE = lib
42 +TARGET = vnrsys
43 +
44 +HEADERS += sys.h
45 +SOURCES += sys.cc
46 +
47 +OTHER_FILES += sys.pri
48 +
49 +# EOF
1 +12/16/2013
2 +
3 +Differences between xp.dll and non-xp.dll for vnrhook.
4 +
5 +non-xp:
6 + CONFIG += eh
7 +
8 +xp:
9 + CONFIG += noeh
10 + CONFIG -= embed_manifest_dll # Pure dynamic determined. The manifest would break Windows XP support
11 + include($$LIBDIR/winseh/winseh_safe.pri)
1 +#ifndef _MEMDBG_H
2 +#define _MEMDBG_H
3 +
4 +// memdbg.h
5 +// 4/20/2014 jichi
6 +
7 +#ifndef MEMDBG_BEGIN_NAMESPACE
8 +# define MEMDBG_BEGIN_NAMESPACE namespace MemDbg {
9 +#endif
10 +#ifndef MEMDBG_END_NAMESPACE
11 +# define MEMDBG_END_NAMESPACE } // MemDbg
12 +#endif
13 +
14 +MEMDBG_BEGIN_NAMESPACE
15 +
16 +typedef unsigned char byte_t;
17 +typedef unsigned long dword_t;
18 +
19 +//typedef void *address_t; // LPVOID
20 +//typedef const void *const_address_t; // LPCVOID
21 +
22 +MEMDBG_END_NAMESPACE
23 +
24 +
25 +#endif // _MEMDBG_H
1 +# ntinspect.pri
2 +# 4/20/2014 jichi
3 +win32 {
4 +
5 +DEFINES += WITH_LIB_MEMDBG
6 +
7 +DEPENDPATH += $$PWD
8 +
9 +HEADERS += \
10 + $$PWD/memdbg.h \
11 + $$PWD/memsearch.h
12 +
13 +SOURCES += \
14 + $$PWD/memsearch.cc
15 +}
16 +
17 +# EOF
1 +// memsearch.cc
2 +// 4/20/2014 jichi
3 +#include "memdbg/memsearch.h"
4 +#include <windows.h>
5 +
6 +// Helpers
7 +
8 +namespace { // unnamed
9 +
10 +enum : BYTE { byte_nop = 0x90 };
11 +enum : BYTE { byte_int3 = 0xcc };
12 +enum : WORD { word_2int3 = 0xcccc };
13 +
14 +// jichi 4/19/2014: Return the integer that can mask the signature
15 +DWORD sigMask(DWORD sig)
16 +{
17 + __asm
18 + {
19 + xor ecx,ecx
20 + mov eax,sig
21 +_mask:
22 + shr eax,8
23 + inc ecx
24 + test eax,eax
25 + jnz _mask
26 + sub ecx,4
27 + neg ecx
28 + or eax,-1
29 + shl ecx,3
30 + shr eax,cl
31 + }
32 +}
33 +
34 +/**
35 + * Return the address of the first matched pattern.
36 + * The same as ITH SearchPattern(). KMP is used.
37 + * Return 0 if failed. The return result is ambiguous if the pattern address is 0.
38 + *
39 + * @param startAddress search start address
40 + * @param range search range
41 + * @param pattern array of bytes to match
42 + * @param patternSize size of the pattern array
43 + * @return relative offset from the startAddress
44 + */
45 +DWORD searchPattern(DWORD base, DWORD base_length, LPCVOID search, DWORD search_length) // KMP
46 +{
47 + __asm
48 + {
49 + mov eax,search_length
50 +alloc:
51 + push 0
52 + sub eax,1
53 + jnz alloc
54 +
55 + mov edi,search
56 + mov edx,search_length
57 + mov ecx,1
58 + xor esi,esi
59 +build_table:
60 + mov al,byte ptr [edi+esi]
61 + cmp al,byte ptr [edi+ecx]
62 + sete al
63 + test esi,esi
64 + jz pre
65 + test al,al
66 + jnz pre
67 + mov esi,[esp+esi*4-4]
68 + jmp build_table
69 +pre:
70 + test al,al
71 + jz write_table
72 + inc esi
73 +write_table:
74 + mov [esp+ecx*4],esi
75 +
76 + inc ecx
77 + cmp ecx,edx
78 + jb build_table
79 +
80 + mov esi,base
81 + xor edx,edx
82 + mov ecx,edx
83 +matcher:
84 + mov al,byte ptr [edi+ecx]
85 + cmp al,byte ptr [esi+edx]
86 + sete al
87 + test ecx,ecx
88 + jz match
89 + test al,al
90 + jnz match
91 + mov ecx, [esp+ecx*4-4]
92 + jmp matcher
93 +match:
94 + test al,al
95 + jz pre2
96 + inc ecx
97 + cmp ecx,search_length
98 + je finish
99 +pre2:
100 + inc edx
101 + cmp edx,base_length // search_length
102 + jb matcher
103 + mov edx,search_length
104 + dec edx
105 +finish:
106 + mov ecx,search_length
107 + sub edx,ecx
108 + lea eax,[edx+1]
109 + lea ecx,[ecx*4]
110 + add esp,ecx
111 + }
112 +}
113 +
114 +/**
115 + * jichi 2/5/2014: The same as SearchPattern except it uses 0xff to match everything
116 + * According to @Andys, 0xff seldom appears in the source code: http://sakuradite.com/topic/124
117 + */
118 +DWORD searchPatternEx(DWORD base, DWORD base_length, LPCVOID search, DWORD search_length, BYTE wildcard) // KMP
119 +{
120 + __asm
121 + {
122 + // jichi 2/5/2014 BEGIN
123 + mov bl,wildcard
124 + // jichi 2/5/2014 END
125 + mov eax,search_length
126 +alloc:
127 + push 0
128 + sub eax,1
129 + jnz alloc // jichi 2/5/2014: this will also set %eax to zero
130 +
131 + mov edi,search
132 + mov edx,search_length
133 + mov ecx,1
134 + xor esi,esi
135 +build_table:
136 + mov al,byte ptr [edi+esi]
137 + cmp al,byte ptr [edi+ecx]
138 + sete al
139 + test esi,esi
140 + jz pre
141 + test al,al
142 + jnz pre
143 + mov esi,[esp+esi*4-4]
144 + jmp build_table
145 +pre:
146 + test al,al
147 + jz write_table
148 + inc esi
149 +write_table:
150 + mov [esp+ecx*4],esi
151 +
152 + inc ecx
153 + cmp ecx,edx
154 + jb build_table
155 +
156 + mov esi,base
157 + xor edx,edx
158 + mov ecx,edx
159 +matcher:
160 + mov al,byte ptr [edi+ecx] // search
161 + // jichi 2/5/2014 BEGIN
162 + mov bh,al // save loaded byte to reduce cache access. %ah is not used and always zero
163 + cmp al,bl // %bl is the wildcard byte
164 + sete al
165 + test al,al
166 + jnz wildcard_matched
167 + mov al,bh // restore the loaded byte
168 + // jichi 2/5/2014 END
169 + cmp al,byte ptr [esi+edx] // base
170 + sete al
171 + // jichi 2/5/2014 BEGIN
172 +wildcard_matched:
173 + // jichi 2/5/2014 END
174 + test ecx,ecx
175 + jz match
176 + test al,al
177 + jnz match
178 + mov ecx, [esp+ecx*4-4]
179 + jmp matcher
180 +match:
181 + test al,al
182 + jz pre2
183 + inc ecx
184 + cmp ecx,search_length
185 + je finish
186 +pre2:
187 + inc edx
188 + cmp edx,base_length // search_length
189 + jb matcher
190 + mov edx,search_length
191 + dec edx
192 +finish:
193 + mov ecx,search_length
194 + sub edx,ecx
195 + lea eax,[edx+1]
196 + lea ecx,[ecx*4]
197 + add esp,ecx
198 + }
199 +}
200 +
201 +// Modified from ITH findCallOrJmpAbs
202 +// Example call:
203 +// 00449063 |. ff15 5cf05300 call dword ptr ds:[<&gdi32.getglyphoutli>; \GetGlyphOutlineA
204 +enum : WORD {
205 + word_jmp = 0x25ff
206 + , word_call = 0x15ff // far call
207 +};
208 +/***
209 + * Return the absolute address of op. Op takes 1 parameter.
210 + *
211 + * @param op first half of the operator
212 + * @param arg1 the function address
213 + * @param start address
214 + * @param search range
215 + * @return absolute address or 0
216 + */
217 +DWORD findWordCall(WORD op, DWORD arg1, DWORD start, DWORD size)
218 +{
219 + typedef WORD optype;
220 + typedef DWORD argtype;
221 +
222 + enum { START = 0x1000 }; // leading size to skip
223 + for (DWORD i = START; i < size - sizeof(argtype); i++)
224 + if (op == *(optype *)(start + i)) {
225 + DWORD t = *(DWORD *)(start + i + sizeof(optype));
226 + if (t > start && t < start + size) {
227 + if (arg1 == *(argtype *)t)
228 + return start + i;
229 + else
230 + i += sizeof(optype) + sizeof(argtype) - 1; // == 5
231 + }
232 + }
233 + return 0;
234 +}
235 +
236 +// Modified from ITH findCallOrJmpAbs
237 +enum : BYTE {
238 + byte_call = 0xe8 // near call
239 + , byte_push_small = 0x6a // push byte operand
240 + , byte_push_large = 0x68 // push operand > 0xff
241 +};
242 +
243 +/***
244 + * Return the absolute address of op. Op takes 1 address parameter.
245 + *
246 + * @param op first half of the operator
247 + * @param arg1 the function address
248 + * @param start address
249 + * @param search range
250 + * @return absolute address or 0
251 + */
252 +DWORD findByteCall(BYTE op, DWORD arg1, DWORD start, DWORD size)
253 +{
254 + typedef BYTE optype;
255 + typedef DWORD argtype;
256 +
257 + enum { START = 0x1000 }; // leading size to skip
258 + for (DWORD i = START; i < size - sizeof(argtype); i++)
259 + if (op == *(optype *)(start + i)) {
260 + DWORD t = *(DWORD *)(start + i + sizeof(optype));
261 + if (t > start && t < start + size) {
262 + if (arg1 == *(argtype *)t)
263 + return start + i;
264 + else
265 + i += sizeof(optype) + sizeof(argtype) - 1; // == 4
266 + }
267 + }
268 + return 0;
269 +}
270 +
271 +/***
272 + * Return the absolute address of op. Op takes 1 parameter.
273 + *
274 + * @param op first half of the operator
275 + * @param arg1 the first operand
276 + * @param start address
277 + * @param search range
278 + * @return absolute address or 0
279 + */
280 +//DWORD findByteOp1(BYTE op, DWORD arg1, DWORD start, DWORD size)
281 +//{
282 +// typedef BYTE optype;
283 +// typedef DWORD argtype;
284 +//
285 +// enum { START = 0x1000 }; // leading size to skip
286 +// for (DWORD i = START; i < size - sizeof(argtype); i++)
287 +// if (op == *(optype *)(start + i)) {
288 +// DWORD t = *(DWORD *)(start + i + sizeof(optype));
289 +// if (t == arg1) {
290 +// return start + i;
291 +// else
292 +// i += sizeof(optype) + sizeof(argtype) - 1; // == 4
293 +// }
294 +// }
295 +// return 0;
296 +//}
297 +
298 +} // namespace unnamed
299 +
300 +MEMDBG_BEGIN_NAMESPACE
301 +
302 +DWORD findJumpAddress(DWORD funcAddr, DWORD lowerBound, DWORD upperBound)
303 +{ return findWordCall(word_jmp, funcAddr, lowerBound, upperBound - lowerBound); }
304 +
305 +DWORD findFarCallAddress(DWORD funcAddr, DWORD lowerBound, DWORD upperBound)
306 +{ return findWordCall(word_call, funcAddr, lowerBound, upperBound - lowerBound); }
307 +
308 +DWORD findNearCallAddress(DWORD funcAddr, DWORD lowerBound, DWORD upperBound)
309 +{ return findByteCall(byte_call, funcAddr, lowerBound, upperBound - lowerBound); }
310 +
311 +DWORD findPushDwordAddress(DWORD value, DWORD lowerBound, DWORD upperBound)
312 +{
313 + //value = _byteswap_ulong(value); // swap to bigendian
314 + const BYTE *p = (BYTE *)&value;
315 + const BYTE bytes[] = {byte_push_large, p[0], p[1], p[2], p[3]};
316 + return findBytes(bytes, sizeof(bytes), lowerBound, upperBound);
317 +}
318 +
319 +DWORD findPushByteAddress(BYTE value, DWORD lowerBound, DWORD upperBound)
320 +{
321 + const BYTE bytes[] = {byte_push_small, value};
322 + return findBytes(bytes, sizeof(bytes), lowerBound, upperBound);
323 +}
324 +
325 +DWORD findCallerAddress(DWORD funcAddr, DWORD sig, DWORD lowerBound, DWORD upperBound, DWORD reverseLength)
326 +{
327 + enum { Start = 0x1000 };
328 + enum { PatternSize = 4 };
329 + const DWORD size = upperBound - lowerBound - PatternSize;
330 + const DWORD fun = (DWORD)funcAddr;
331 + // Example function call:
332 + // 00449063 |. ff15 5cf05300 call dword ptr ds:[<&gdi32.getglyphoutli>; \GetGlyphOutlineA
333 + //WCHAR str[0x40];
334 + const DWORD mask = sigMask(sig);
335 + for (DWORD i = Start; i < size; i++)
336 + if (*(WORD *)(lowerBound + i) == word_call) {
337 + DWORD t = *(DWORD *)(lowerBound + i + 2);
338 + if (t >= lowerBound && t <= upperBound - PatternSize) {
339 + if (*(DWORD *)t == fun)
340 + //swprintf(str,L"CALL addr: 0x%.8X",lowerBound + i);
341 + //OutputConsole(str);
342 + for (DWORD j = i ; j > i - reverseLength; j--)
343 + if ((*(DWORD *)(lowerBound + j) & mask) == sig) // Fun entry 1.
344 + //swprintf(str,L"Entry: 0x%.8X",lowerBound + j);
345 + //OutputConsole(str);
346 + return lowerBound + j;
347 +
348 + } else
349 + i += 6;
350 + }
351 + //OutputConsole(L"Find call and entry failed.");
352 + return 0;
353 +}
354 +
355 +DWORD findMultiCallerAddress(DWORD funcAddr, const DWORD sigs[], DWORD sigCount, DWORD lowerBound, DWORD upperBound, DWORD reverseLength)
356 +{
357 + enum { Start = 0x1000 };
358 + enum { PatternSize = 4 };
359 + const DWORD size = upperBound - lowerBound - PatternSize;
360 + const DWORD fun = (DWORD)funcAddr;
361 + // Example function call:
362 + // 00449063 |. ff15 5cf05300 call dword ptr ds:[<&gdi32.getglyphoutli>; \GetGlyphOutlineA
363 + //WCHAR str[0x40];
364 +
365 + enum { MaxSigCount = 0x10 }; // mast be larger than maximum sigCount
366 + DWORD masks[MaxSigCount];
367 + for (DWORD k = 0; k < sigCount; k++)
368 + masks[k] = sigMask(sigs[k]);
369 +
370 + for (DWORD i = Start; i < size; i++)
371 + if (*(WORD *)(lowerBound + i) == word_call) {
372 + DWORD t = *(DWORD *)(lowerBound + i + 2);
373 + if (t >= lowerBound && t <= upperBound - PatternSize) {
374 + if (*(DWORD *)t == fun)
375 + //swprintf(str,L"CALL addr: 0x%.8X",lowerBound + i);
376 + //OutputConsole(str);
377 + for (DWORD j = i ; j > i - reverseLength; j--) {
378 + DWORD ret = lowerBound + j,
379 + inst = *(DWORD *)ret;
380 + for (DWORD k = 0; k < sigCount; k++)
381 + if ((inst & masks[k]) == sigs[k]) // Fun entry 1.
382 + //swprintf(str,L"Entry: 0x%.8X",lowerBound + j);
383 + //OutputConsole(str);
384 + return ret;
385 + }
386 +
387 + } else
388 + i += 6;
389 + }
390 + //OutputConsole(L"Find call and entry failed.");
391 + return 0;
392 +}
393 +
394 +DWORD findLastCallerAddress(DWORD funcAddr, DWORD sig, DWORD lowerBound, DWORD upperBound, DWORD reverseLength)
395 +{
396 + enum { Start = 0x1000 };
397 + enum { PatternSize = 4 };
398 + const DWORD size = upperBound - lowerBound - PatternSize;
399 + const DWORD fun = (DWORD)funcAddr;
400 + //WCHAR str[0x40];
401 + DWORD ret = 0;
402 + const DWORD mask = sigMask(sig);
403 + for (DWORD i = Start; i < size; i++)
404 + if (*(WORD *)(lowerBound + i) == word_call) {
405 + DWORD t = *(DWORD *)(lowerBound + i + 2);
406 + if (t >= lowerBound && t <= upperBound - PatternSize) {
407 + if (*(DWORD *)t == fun)
408 + //swprintf(str,L"CALL addr: 0x%.8X",lowerBound + i);
409 + //OutputConsole(str);
410 + for (DWORD j = i ; j > i - reverseLength; j--)
411 + if ((*(DWORD *)(lowerBound + j) & mask) == sig) // Fun entry 1.
412 + //swprintf(str,L"Entry: 0x%.8X",lowerBound + j);
413 + //OutputConsole(str);
414 + ret = lowerBound + j;
415 +
416 + } else
417 + i += 6;
418 + }
419 + //OutputConsole(L"Find call and entry failed.");
420 + return ret;
421 +}
422 +
423 +DWORD findCallerAddressAfterInt3(dword_t funcAddr, dword_t lowerBound, dword_t upperBound, dword_t callerSearchSize)
424 +{
425 + DWORD addr = findCallerAddress(funcAddr, word_2int3, lowerBound, upperBound, callerSearchSize);
426 + if (addr)
427 + while (byte_int3 == *(BYTE *)++addr);
428 + return addr;
429 +}
430 +
431 +DWORD findLastCallerAddressAfterInt3(dword_t funcAddr, dword_t lowerBound, dword_t upperBound, dword_t callerSearchSize)
432 +{
433 + DWORD addr = findLastCallerAddress(funcAddr, word_2int3, lowerBound, upperBound, callerSearchSize);
434 + if (addr)
435 + while (byte_int3 == *(BYTE *)++addr);
436 + return addr;
437 +}
438 +
439 +DWORD findEnclosingAlignedFunction(DWORD start, DWORD back_range)
440 +{
441 + start &= ~0xf;
442 + for (DWORD i = start, j = start - back_range; i > j; i-=0x10) {
443 + DWORD k = *(DWORD *)(i-4);
444 + if (k == 0xcccccccc
445 + || k == 0x90909090
446 + || k == 0xccccccc3
447 + || k == 0x909090c3
448 + )
449 + return i;
450 + DWORD t = k & 0xff0000ff;
451 + if (t == 0xcc0000c2 || t == 0x900000c2)
452 + return i;
453 + k >>= 8;
454 + if (k == 0xccccc3 || k == 0x9090c3)
455 + return i;
456 + t = k & 0xff;
457 + if (t == 0xc2)
458 + return i;
459 + k >>= 8;
460 + if (k == 0xccc3 || k == 0x90c3)
461 + return i;
462 + k >>= 8;
463 + if (k == 0xc3)
464 + return i;
465 + }
466 + return 0;
467 +}
468 +
469 +DWORD findBytes(const void *pattern, DWORD patternSize, DWORD lowerBound, DWORD upperBound)
470 +{
471 + DWORD reladdr = searchPattern(lowerBound, upperBound - lowerBound, pattern, patternSize);
472 + return reladdr ? lowerBound + reladdr : 0;
473 +}
474 +
475 +DWORD matchBytes(const void *pattern, DWORD patternSize, DWORD lowerBound, DWORD upperBound, BYTE wildcard)
476 +{
477 + DWORD reladdr = searchPatternEx(lowerBound, upperBound - lowerBound, pattern, patternSize, wildcard);
478 + return reladdr ? lowerBound + reladdr : 0;
479 +}
480 +
481 +#if 0 // not used
482 +DWORD findBytesInPages(const void *pattern, DWORD patternSize, DWORD lowerBound, DWORD upperBound, SearchType search)
483 +{
484 + //enum { MinPageSize = 4 * 1024 }; // 4k
485 + DWORD ret = 0;
486 + DWORD start = lowerBound,
487 + stop = start;
488 + MEMORY_BASIC_INFORMATION mbi = {};
489 +
490 + //lowerBound = 0x10000000;
491 + //upperBound = 0x14000000;
492 + //SIZE_T ok = ::VirtualQuery((LPCVOID)lowerBound, &mbi, sizeof(mbi));
493 + //ITH_GROWL_DWORD7(1, start, stop, mbi.RegionSize, mbi.Protect, mbi.Type, mbi.State);
494 + //return matchBytes(pattern, patternSize, lowerBound, upperBound, wildcard);
495 + while (stop < upperBound) {
496 + SIZE_T ok = ::VirtualQuery((LPCVOID)start, &mbi, sizeof(mbi));
497 + if (!mbi.RegionSize)
498 + break;
499 + // Only visit readable and committed region
500 + // Protect could be zero if not allowed to query
501 + if (!ok || !mbi.Protect || mbi.Protect&PAGE_NOACCESS) {
502 + if (stop > start && (ret = findBytes(pattern, patternSize, lowerBound, upperBound)))
503 + return ret;
504 + if (search != SearchAll)
505 + return 0;
506 + stop += mbi.RegionSize;
507 + start = stop;
508 + } else
509 + stop += mbi.RegionSize;
510 + }
511 + if (stop > start)
512 + ret = findBytes(pattern, patternSize, start, min(upperBound, stop));
513 + return ret;
514 +}
515 +
516 +DWORD matchBytesInPages(const void *pattern, DWORD patternSize, DWORD lowerBound, DWORD upperBound, BYTE wildcard, SearchType search)
517 +{
518 + //enum { MinPageSize = 4 * 1024 }; // 4k
519 + DWORD ret = 0;
520 + DWORD start = lowerBound,
521 + stop = start;
522 + MEMORY_BASIC_INFORMATION mbi = {};
523 +
524 + //lowerBound = 0x10000000;
525 + //upperBound = 0x14000000;
526 + //SIZE_T ok = ::VirtualQuery((LPCVOID)lowerBound, &mbi, sizeof(mbi));
527 + //ITH_GROWL_DWORD7(1, start, stop, mbi.RegionSize, mbi.Protect, mbi.Type, mbi.State);
528 + //return matchBytes(pattern, patternSize, lowerBound, upperBound, wildcard);
529 + while (stop < upperBound) {
530 + SIZE_T ok = ::VirtualQuery((LPCVOID)start, &mbi, sizeof(mbi));
531 + if (!mbi.RegionSize)
532 + break;
533 + // Only visit readable and committed region
534 + // Protect could be zero if not allowed to query
535 + if (!ok || !mbi.Protect || mbi.Protect&PAGE_NOACCESS) {
536 + if (stop > start && (ret = matchBytes(pattern, patternSize, lowerBound, upperBound, wildcard)))
537 + return ret;
538 + if (search != SearchAll)
539 + return 0;
540 + stop += mbi.RegionSize;
541 + start = stop;
542 + } else
543 + stop += mbi.RegionSize;
544 + }
545 + if (stop > start)
546 + ret = matchBytes(pattern, patternSize, start, min(upperBound, stop), wildcard);
547 + return ret;
548 +}
549 +
550 +#endif // 0
551 +
552 +MEMDBG_END_NAMESPACE
553 +
554 +// EOF
555 +
556 +#if 0 // disabled
557 +
558 +/**
559 + * Search from stopAddres back to startAddress - range
560 + * This function is not well debugged
561 + */
562 +DWORD reverseSearchPattern(DWORD base, DWORD base_length, LPCVOID search, DWORD search_length) // KMP
563 +{
564 + __asm
565 + {
566 + mov eax,search_length
567 +alloc:
568 + push 0
569 + sub eax,1
570 + jnz alloc
571 +
572 + mov edi,search
573 + mov edx,search_length
574 + mov ecx,1
575 + xor esi,esi
576 +build_table:
577 + mov al,byte ptr [edi+esi]
578 + cmp al,byte ptr [edi+ecx]
579 + sete al
580 + test esi,esi
581 + jz pre
582 + test al,al
583 + jnz pre
584 + mov esi,[esp+esi*4-4]
585 + jmp build_table
586 +pre:
587 + test al,al
588 + jz write_table
589 + inc esi
590 +write_table:
591 + mov [esp+ecx*4],esi
592 +
593 + inc ecx
594 + cmp ecx,edx
595 + jb build_table
596 +
597 + mov esi,base
598 + xor edx,edx
599 + mov ecx,edx
600 +matcher:
601 + mov al,byte ptr [edi+ecx]
602 + cmp al,byte ptr [esi-edx] // jichi 6/1/2014: The only place that is modified
603 + sete al
604 + test ecx,ecx
605 + jz match
606 + test al,al
607 + jnz match
608 + mov ecx, [esp+ecx*4-4]
609 + jmp matcher
610 +match:
611 + test al,al
612 + jz pre2
613 + inc ecx
614 + cmp ecx,search_length
615 + je finish
616 +pre2:
617 + inc edx
618 + cmp edx,base_length // search_length
619 + jb matcher
620 + mov edx,search_length
621 + dec edx
622 +finish:
623 + mov ecx,search_length
624 + sub edx,ecx
625 + lea eax,[edx+1]
626 + lea ecx,[ecx*4]
627 + add esp,ecx
628 + }
629 +}
630 +
631 +#endif // 0, disabled
632 +
1 +#ifndef _MEMDBG_MEMSEARCH_H
2 +#define _MEMDBG_MEMSEARCH_H
3 +
4 +// memsearch.h
5 +// 4/20/2014 jichi
6 +
7 +#include "memdbg/memdbg.h"
8 +
9 +MEMDBG_BEGIN_NAMESPACE
10 +
11 +/// Estimated maximum size of the caller function, the same as ITH FindCallAndEntryAbs
12 +enum { MaximumFunctionSize = 0x800 };
13 +
14 +/**
15 + * Return the absolute address of the caller function
16 + * The same as ITH FindCallAndEntryAbs().
17 + *
18 + * @param funcAddr callee function address
19 + * @param funcInst the machine code where the caller function starts
20 + * @param lowerBound the lower memory address to search
21 + * @param upperBound the upper memory address to search
22 + * @param* callerSearchSize the maximum size of caller
23 + * @return the caller absolute address if succeed or 0 if fail
24 + *
25 + * Example funcInst:
26 + * 0x55: push ebp
27 + * 0x81,0xec: sub esp XXOO (0xec81)
28 + * 0x83,0xec: sub esp XXOO (0xec83)
29 + */
30 +dword_t findCallerAddress(dword_t funcAddr, dword_t funcInst, dword_t lowerBound, dword_t upperBound, dword_t callerSearchSize = MaximumFunctionSize);
31 +dword_t findCallerAddressAfterInt3(dword_t funcAddr, dword_t lowerBound, dword_t upperBound, dword_t callerSearchSize = MaximumFunctionSize);
32 +dword_t findLastCallerAddress(dword_t funcAddr, dword_t funcInst, dword_t lowerBound, dword_t upperBound, dword_t callerSearchSize = MaximumFunctionSize);
33 +dword_t findLastCallerAddressAfterInt3(dword_t funcAddr, dword_t lowerBound, dword_t upperBound, dword_t callerSearchSize = MaximumFunctionSize);
34 +
35 +dword_t findMultiCallerAddress(dword_t funcAddr, const dword_t funcInsts[], dword_t funcInstCount, dword_t lowerBound, dword_t upperBound, dword_t callerSearchSize = MaximumFunctionSize);
36 +
37 +/**
38 + * Return the absolute address of the long jump (not short jump) instruction address.
39 + * The same as ITH FindCallOrJmpAbs(false).
40 + *
41 + * @param funcAddr callee function address
42 + * @param lowerBound the lower memory address to search
43 + * @param upperBound the upper memory address to search
44 + * @return the call instruction address if succeed or 0 if fail
45 + */
46 +dword_t findJumpAddress(dword_t funcAddr, dword_t lowerBound, dword_t upperBound);
47 +
48 +/**
49 + * Return the absolute address of the far call (inter-module) instruction address.
50 + * The same as ITH FindCallOrJmpAbs(true).
51 + *
52 + * @param funcAddr callee function address
53 + * @param lowerBound the lower memory address to search
54 + * @param upperBound the upper memory address to search
55 + * @return the call instruction address if succeed or 0 if fail
56 + */
57 +dword_t findFarCallAddress(dword_t funcAddr, dword_t lowerBound, dword_t upperBound);
58 +
59 +/// Near call (intra-module)
60 +dword_t findNearCallAddress(dword_t funcAddr, dword_t lowerBound, dword_t upperBound);
61 +
62 +/// Default to far call
63 +inline dword_t findCallAddress(dword_t funcAddr, dword_t lowerBound, dword_t upperBound)
64 +{ return findFarCallAddress(funcAddr, lowerBound, upperBound); }
65 +
66 +/// Push value >= 0xff
67 +dword_t findPushDwordAddress(dword_t value, dword_t lowerBound, dword_t upperBound);
68 +
69 +/// Push value <= 0xff
70 +dword_t findPushByteAddress(byte_t value, dword_t lowerBound, dword_t upperBound);
71 +
72 +/// Default to push DWORD
73 +inline dword_t findPushAddress(dword_t value, dword_t lowerBound, dword_t upperBound)
74 +{ return findPushDwordAddress(value, lowerBound, upperBound); }
75 +
76 +/**
77 + * Return the enclosing function address outside the given address.
78 + * The same as ITH FindEntryAligned().
79 + * "Aligned" here means the function must be after in3 (0xcc) or nop (0x90).
80 + *
81 + * If the function does NOT exist, this function might raise without admin privilege.
82 + * It is safer to wrap this function within SEH.
83 + *
84 + * @param addr address within th function
85 + * @param searchSize max backward search size
86 + * @return beginning address of the function
87 + * @exception illegal memory access
88 + */
89 +dword_t findEnclosingAlignedFunction(dword_t addr, dword_t searchSize = MaximumFunctionSize);
90 +
91 +/**
92 + * Return the address of the first matched pattern.
93 + * Return 0 if failed. The return result is ambiguous if the pattern address is 0.
94 + * This function simpily traverse all bytes in memory range and would raise
95 + * if no access to the region.
96 + *
97 + * @param pattern array of bytes to match
98 + * @param patternSize size of the pattern array
99 + * @param lowerBound search start address
100 + * @param upperBound search stop address
101 + * @return absolute address
102 + * @exception illegal memory access
103 + */
104 +dword_t findBytes(const void *pattern, dword_t patternSize, dword_t lowerBound, dword_t upperBound);
105 +
106 +/**
107 + * jichi 2/5/2014: The same as findBytes except it uses widecard to match everything.
108 + * The widecard should use the byte seldom appears in the pattern.
109 + * See: http://sakuradite.com/topic/124
110 + *
111 + * @param pattern array of bytes to match
112 + * @param patternSize size of the pattern array
113 + * @param lowerBound search start address
114 + * @param upperBound search stop address
115 + * @param* widecard the character to match everything
116 + * @return absolute address
117 + * @exception illegal memory access
118 + */
119 +enum : byte_t { WidecardByte = 0x11 }; // jichi 7/17/2014: 0x11 seldom appear in PSP code pattern
120 +//enum : WORD { WidecardWord = 0xffff };
121 +dword_t matchBytes(const void *pattern, dword_t patternSize, dword_t lowerBound, dword_t upperBound,
122 + byte_t wildcard = WidecardByte);
123 +
124 +// User space: 0 - 2G (0 - 0x7ffeffff)
125 +// Kernel space: 2G - 4G (0x80000000 - 0xffffffff)
126 +//
127 +// http://msdn.microsoft.com/en-us/library/windows/hardware/ff560042%28v=vs.85%29.aspx
128 +// http://codesequoia.wordpress.com/2008/11/28/understand-process-address-space-usage/
129 +// http://stackoverflow.com/questions/17244912/open-process-with-debug-privileges-and-read-write-memory
130 +enum MemoryRange : dword_t {
131 + UserMemoryStartAddress = 0, UserMemoryStopAddress = 0x7ffeffff
132 + , KernelMemoryStartAddress = 0x80000000, KernelMemoryStopAddress = 0xffffffff
133 + , MappedMemoryStartAddress = 0x01000000
134 +
135 + , MemoryStartAddress = UserMemoryStartAddress, MemoryStopAddress = UserMemoryStopAddress
136 +};
137 +
138 +#if 0 // not used
139 +/**
140 + * Traverse memory continues pages and return the address of the first matched pattern.
141 + *
142 + * @param pattern array of bytes to match
143 + * @param patternSize size of the pattern array
144 + * @param lowerBound search start address
145 + * @param upperBound search stop address
146 + * @param* search search all pages (SearchAll) or stop on first illegal access (SearchFirst)
147 + * @return absolute address
148 + */
149 +enum SearchType : byte_t { SearchAll = 0 , SearchFirst };
150 +
151 +dword_t findBytesInPages(const void *pattern, dword_t patternSize,
152 + dword_t lowerBound = MemoryStartAddress, dword_t upperBound = MemoryStopAddress,
153 + SearchType search = SearchAll);
154 +dword_t matchBytesInPages(const void *pattern, dword_t patternSize,
155 + dword_t lowerBound = MemoryStartAddress, dword_t upperBound = MemoryStopAddress,
156 + byte_t wildcard = WidecardByte, SearchType search = SearchAll);
157 +
158 +#endif // 0
159 +
160 +MEMDBG_END_NAMESPACE
161 +
162 +#endif // _MEMDBG_MEMSEARCH_H