From 729c51d32cf83bf4c664ab6234c12d0f572fdaef Mon Sep 17 00:00:00 2001 From: ufrisk Date: Mon, 24 May 2021 08:01:13 +0200 Subject: [PATCH] Version 4.10 --- LICENSE | 159 ++-- includes/leechcore.h | 32 +- includes/lib64/leechcore.lib | Bin 5268 -> 5268 bytes includes/lib64/vmm.lib | Bin 15210 -> 21426 bytes includes/vmmdll.h | 680 ++++++++++++------ pcileech/Makefile | 16 +- pcileech/executor.c | 6 +- pcileech/extra.c | 5 + pcileech/help.c | 23 +- pcileech/kmd.c | 60 +- pcileech/oscompatibility.h | 23 +- pcileech/umd.c | 69 +- pcileech/version.h | 4 +- pcileech/vmmx.c | 18 +- pcileech/vmmx.h | 40 +- pcileech_gensig/pcileech_gensig.c | 251 ------- pcileech_gensig/pcileech_gensig.vcxproj | 123 ---- .../pcileech_gensig.vcxproj.filters | 22 - pcileech_gensig/pcileech_gensig.vcxproj.user | 4 - readme.md | 29 +- 20 files changed, 640 insertions(+), 924 deletions(-) delete mode 100644 pcileech_gensig/pcileech_gensig.c delete mode 100644 pcileech_gensig/pcileech_gensig.vcxproj delete mode 100644 pcileech_gensig/pcileech_gensig.vcxproj.filters delete mode 100644 pcileech_gensig/pcileech_gensig.vcxproj.user diff --git a/LICENSE b/LICENSE index 9cecc1d..0ad25db 100644 --- a/LICENSE +++ b/LICENSE @@ -1,23 +1,21 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble - The GNU General Public License is a free, copyleft license for -software and other kinds of works. + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to +our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. +software for all its users. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you @@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. The precise terms and conditions for copying, distribution and modification follow. @@ -72,7 +60,7 @@ modification follow. 0. Definitions. - "This License" refers to version 3 of the GNU General Public License. + "This License" refers to version 3 of the GNU Affero General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. @@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. - 13. Use with the GNU Affero General Public License. + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single +under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General +Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published +GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's +versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. @@ -631,44 +629,33 @@ to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - {one line to give the program's name and a brief idea of what it does.} - Copyright (C) {year} {name of author} + + Copyright (C) This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU Affero General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - {project} Copyright (C) {year} {fullname} - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/includes/leechcore.h b/includes/leechcore.h index b08d87c..b1ef5cd 100644 --- a/includes/leechcore.h +++ b/includes/leechcore.h @@ -14,7 +14,7 @@ // (c) Ulf Frisk, 2020-2021 // Author: Ulf Frisk, pcileech@frizk.net // -// Header Version: 2.5 +// Header Version: 2.6 // #ifndef __LEECHCORE_H__ @@ -28,23 +28,25 @@ extern "C" { //----------------------------------------------------------------------------- #ifdef _WIN32 -#include +#include #define EXPORTED_FUNCTION __declspec(dllexport) -typedef ULONG64 QWORD, *PQWORD; +typedef unsigned __int64 QWORD, *PQWORD; + #endif /* _WIN32 */ #ifdef LINUX + #include #include - #define EXPORTED_FUNCTION __attribute__((visibility("default"))) -typedef void VOID, *PVOID, *HANDLE; -typedef long long unsigned int QWORD, *PQWORD, ULONG64; -typedef uint32_t DWORD, *PDWORD, BOOL; -typedef uint8_t BYTE, *PBYTE; -typedef char CHAR, *LPSTR; -typedef const char *LPCSTR; -typedef wchar_t WCHAR, *PWCHAR, *LPWSTR; +typedef void VOID, *PVOID, *HANDLE, **PHANDLE, *HMODULE; +typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64; +typedef uint64_t SIZE_T, *PSIZE_T, FILETIME, *PFILETIME; +typedef uint32_t DWORD, *PDWORD, *LPDWORD, BOOL, *PBOOL, NTSTATUS; +typedef uint16_t WORD, *PWORD; +typedef uint8_t BYTE, *PBYTE, *LPBYTE, UCHAR; +typedef char CHAR, *PCHAR, *LPSTR, *LPCSTR; +typedef uint16_t WCHAR, *PWCHAR, *LPWSTR, *LPCWSTR; #define MAX_PATH 260 #define _In_ #define _In_z_ @@ -52,16 +54,22 @@ typedef wchar_t WCHAR, *PWCHAR, *LPWSTR; #define _In_reads_(x) #define _In_reads_opt_(x) #define _Inout_ +#define _Inout_bytecount_(x) +#define _Inout_opt_ +#define _Inout_updates_opt_(x) #define _Out_ #define _Out_opt_ #define _Out_writes_(x) +#define _Out_writes_bytes_opt_(x) #define _Out_writes_opt_(x) -#define _Inout_updates_opt_(x) +#define _Out_writes_to_(x,y) +#define _When_(x,y) #define _Frees_ptr_opt_ #define _Post_ptr_invalid_ #define _Check_return_opt_ #define _Printf_format_string_ #define _Success_(x) + #endif /* LINUX */ diff --git a/includes/lib64/leechcore.lib b/includes/lib64/leechcore.lib index 145bcbe39516334c3c9a8aeaa5c42ef7176c3994..72c29788ab2ce248fd00bc19c87528aaea715137 100644 GIT binary patch delta 106 zcmbQDIYo2BH+D|OAkM4&j0_AMlMT6~CrfcmV!S` wi)u{1&&2^`adApdX6BA%J^SSSultjAx#WTRq$khkE(fbpL8#gs&tu8~04)t8LjV8( delta 106 zcmbQDIYo2BH+IhJhx(83Gcqu6Og7|_o-D;NiSgFtwHz^ww>EQe$}zGy+P?fdS%<3& wEUGd2J{Jd&#lyuU;uEP60*?3=oWk; zmF{+FRXqSv*?yNQD*=cqUUn&Z1%N|u;1j8&SrB5DAgx#?=q`LBE&bA^Wr$C-be^D_ z@QJkYYC-SelL*^N6v4hDik{@sl6wJ&B4{ho@g>(Y`+tcO&5 znM=zKU^|c&-yrC7d?Hoh7!y@bbg2^im#8Y=rP_@E4q-pkBGse?9l|G4_4R_#-fE=g zr(9|&1t40xUC=xDL~6zHCTc;yB8p*~9l9BxNNdNt)cOp{A+?pcvG(vd z=yj?5Bm9k2S5MT{)zB1cX>ISSu4$`kZHTqEw03niH9=Qbb4O#N&4h0v*X6a>cQmi* zs;+3S04%E}>HcIo+1;1CDuMNrTep!WqueT~*&ZZ|93frRH!x_Zbc+PPDY3OSl`te^ zp@kUh8`_fW9}I$(Y>7S4-;>-@mq_dKRbH_s*T&0Hv5@QR8Ei}rraN?XUa2m%j+I(x z=<2G7$7_>)hW$dN$J8~;Vje+p?ON5zRAO^_AT`XkjcO{147G!Sz3P5DTNB-JyU*NG zg+jk=#crvRT9-snf?N7mztWzbVSIz6sf20fK6EsY~L$C1*tI9=v+PoN4zB&dF{DN2E62QC9NHf@`` z)9FM?Z@s}2n4&b+y~UVOeugf~s+F@;R5KSkRjhQyQi+~KdUG#f8w(VQ>s(dKvD|8c zTdJfwlc{uZtasSft2jbBmW(7mk-i<=YX;@9M3 zShB|aQ?lL+6h*O~e!aoIa$PHR0(K`aEqHp3j=@A~&{#2qdck7k`IbBKX4~5msVkD3 z69Ev4tE0$r9!PQZS}|+wlO072OO{uTN=zF%tp!@>br`x{EaLS#3`^FUIz^Y3C80n^PRE#O0pf#CH z8Uh>O)4FDA03+^r(Hs#g2(wnUqiFF6X zlLMlPpD$|CZV>lNef5d$6@#0TNxf|rH+%-O#LHl=2Y{XP0e-Up;Eja<{fhwhAw>!S zF2TH1brHa=_%!eWfHPqR%!IGNL^us5!6|SmOol0NI!uKISPjk40x?(% zYoHODpcUF+4CMV^wRf!CyJ)Gw40$>+)qF`yt3+)tl$4Pl6nl%HkXNV_Qkf$`Lzbdd zy(lRD)ur5*w%jsB|zrF>OnmYf8ZQbko{7EF~| zxgV^oMK$uxE2`knpw}Y%hNV{`^M2!AmTc0<%sP2Hp%6O@*>tb2e;1XBDYi(Khzg6n z(d1%o&vz8l7tu3SeO#ul+>S66CCjU2MF_$MF3Zg1YspucuFE_`;I)Mdko82!tuQB@-eANOdTrri&GDI1A*1)x1aA=;1_TTJP8cW ztzDEb!e;qvX^@7)9ZB=e=9~DQ21R9P%FbH568z3V{;3~<)5X%cn zZ`pfvf#l@KI8}O(U~FWyP(g+nyeY1pO!fJCna&9K8iCpWOu7CHnQ$IOh8es?lFQf4 zkWth_4qmw~!$XX8Ou^T30~O8Om7$JVs0Tbem(4kt!H-$h%NOVjJrFW^cJ@n!7xJw)%9N}zhDwh=K+^HK z7%Fon*&i$g=u#qqE%Jp%#{5vN_Q?e5k&#lM5-DJ4umUR06fPh%u0No&JBIA`ORNjL zOI8@~>+@2YBi+V~EL|$@Wp11hziupi@w4ggjU9veK+Lz%r!bz_G_<7vGjr|-(~hu1 z{t(Y{m{eJqjCZHI3ot|Iex~B%X{6W0@3HtShoap=4l|SPhj2bal5$j94*9$D@Odic z`{;8bM$u%{`EdHA6Y=*RrHG^?=jS&zG-FED{!GLoY6KCc zW1Vl4@ZS@hZvp|zHxF#xhHd<7dd!$($NbVLhABNFX=*uUV5y{6mN-Va7(ymOGAN>C zqN;?-&!&IGhjig(O!12zd6-&+@S#0>$#8-&anzns94Ya6Mjjm5{`L2M?=*^<#(PHG zWqJSlJOlH`?uR_%4*5eo$un|3;-eYMS=fNU%bKBkZ0RyzkBx=TFP!wkUl70@SiZ+H z%q7ngXpYca@_)*qT+SuT*t;K+dr|%nPm;@N&yJ>7XCOH1gkgI$;@u^uyW%t<Jv|Z?!;1{;Bj+I2NfwsxZAEA z6Gq~sD7$`)Fj!Z9ZPuHF^%V}>p%Bhd6=*!a#*ShL;HP{nbmi`^YQcZ5bG2R z%glJmDG+w#IMgf4etL*dPaOeO85clu%4V9c=a)WLdoBgd_i zyDs?YOSDeTw9xeA_i^+o^G?`v&wZZ|>RBV8=C)^3-+uoH_3YU;>Y($t2J!_IeqCY4 zvG(on9VE0_Jeo2sJQ~xZx9_<1-xNEaW1+c64brsG9?C>2AK!Sb6BV7yVJSxmZx@60 z{gt!cqLn3|!#bWmWcCF2RNwf~G{lB7+K1>=8HuKDF|^1t~CM;`l0b3%Is7a2Ug{+?s`h;yNaqn{*7z|eLvEBwv} zdydiyzktDW&L$;TcmI zdgY9kAmSLcTaNvUiy`cgU~&;#Y4I za#?0%@0M_O$lUsr_jKpqXnk5`A*;(S+7O5LWoD&#c>3iBX{9L7fT|C0SdWe{G1>Zq zkME-hx*_o!d{ML&Kj8b9<9-r5@jxk9f6#c*?-ABguJY zs<8Dj@|Zde&%L504a)^i|9xM5l5pxRoa3;Ec|Xp$ZO*%tTWHX5#5FQ$P-xHK&hT5- z{`WaTT5TgKlR_g!8JiZCfBG+a=dV#n_FXo$kmLk2{lmLIA(B~=#TlX^I$QeYp;L`Os|bbnT<7q7EyX%{ycNG@8aMY1Gwc_E`;I2cr?;xE)M zVZS>E8#0x6G}9#74vhkPELN<{&%_}&!?SKBZDm?xCaaTL9a*{9oaMkQtqvV_`F?K> z2^-o;Dz#nsBW)PdbTy+xx+i3mZ-M*y)<6k&(gJYN29WIlc+m-JS4a)8@}hFBW}_=I9_JFy}R zFkB6wr)=9zOi({S{TtNI_5oZY27Ph*qB4Nh#0*WQas#QrARSUb4hkrQ5-0*MxWNNf zuz?+%kO#$301j|LKBPeoWP=e5pa&D=LIi4|2I`>>EMSH*CpUyOcy1QYBx6aH(-VIc>DdwMQnBugdct05_IY(_C zgNzp{UYA5BKBY6@Gg=pZQ1}$ay$`0WZhZX?&Us&!&EbxcLVUHzC!5>vGvm#o|FXZ^ zkNoX8#bFZ8d(EgX=@o#Jlt4=Wy^H(O}~EsmK*Is1O7~< zM!u5pSl@hsdsKbJBd^%pBaLFGm3#lnM`hp(p&mB;+OkinCV?8|RZ-!k_AkzJ+@ARr zFT9jLR}sONR_f&D(_`1|xU$lK6X^=E13Clw<0JY@Rvahoqs}z^T6Ki)mi;6;d6`NJ zXfZQl7h^LTboT4bbN`@X}GR2lHw zCWcSegm6!-j#c)JziT9)+4#%aZkFcSaLz$JBWBd~vClM9pK@Cc?yBon?wJ2WsiKve~RCf2|Mc7u~)}#E%1{u;~Vuc)#QJgF7n-4Xt%haFyaqdTi8b3 z@u?hATJbNKYK$pahvbNk3FqsOl^&_XEp05>Ggtg(mcek-&A{{^>_Sy0-uKzRlK&1 z+Xh6`(GcVF#vk6~LxNu#62*q#p<-;%kn;vlp;e}2E#tY@Rr?Z1Ket-Hd*H)3%gqv4(C||#}|E`@hVG2I! zmxKa`8>_evrDp2kxB2MmgiWbU$F69ra-_?A$3gmt(C1?G>upN8{KiRsZ#AUrw_6od LMtr@SHo^Y@+)fl} diff --git a/includes/vmmdll.h b/includes/vmmdll.h index 1fa9b60..08d17a6 100644 --- a/includes/vmmdll.h +++ b/includes/vmmdll.h @@ -1,13 +1,15 @@ -// vmmdll.h : header file to include in projects that use vmm.dll either as -// stand-alone projects or as native plugins to vmm.dll. +// vmmdll.h : header file to include in projects that use vmm.dll / vmm.so +// +// Windows may access both UTF-8 *U and Wide-Char *W versions of functions +// while Linux may only access UTF-8 versions. Some functionality may also +// be degraded or unavailable on Linux. // // (c) Ulf Frisk, 2018-2021 // Author: Ulf Frisk, pcileech@frizk.net // -// Header Version: 3.10 +// Header Version: 4.0 // -#include #include "leechcore.h" #ifndef __VMMDLL_H__ @@ -16,6 +18,55 @@ extern "C" { #endif /* __cplusplus */ +#ifdef _WIN32 + +#include +#undef EXPORTED_FUNCTION +#define EXPORTED_FUNCTION +typedef unsigned __int64 QWORD, *PQWORD; + +#endif /* _WIN32 */ +#ifdef LINUX + +#include +#include +#undef EXPORTED_FUNCTION +#define EXPORTED_FUNCTION __attribute__((visibility("default"))) +typedef void VOID, *PVOID, *HANDLE, **PHANDLE, *HMODULE; +typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64; +typedef uint64_t SIZE_T, *PSIZE_T, FILETIME, *PFILETIME; +typedef uint32_t DWORD, *PDWORD, *LPDWORD, BOOL, *PBOOL, NTSTATUS; +typedef uint16_t WORD, *PWORD; +typedef uint8_t BYTE, *PBYTE, *LPBYTE, UCHAR; +typedef char CHAR, *PCHAR, *LPSTR, *LPCSTR; +typedef uint16_t WCHAR, *PWCHAR, *LPWSTR, *LPCWSTR; +#define MAX_PATH 260 +#define _In_ +#define _In_z_ +#define _In_opt_ +#define _In_reads_(x) +#define _In_reads_opt_(x) +#define _Inout_ +#define _Inout_bytecount_(x) +#define _Inout_opt_ +#define _Inout_updates_opt_(x) +#define _Out_ +#define _Out_opt_ +#define _Out_writes_(x) +#define _Out_writes_bytes_opt_(x) +#define _Out_writes_opt_(x) +#define _Out_writes_to_(x,y) +#define _When_(x,y) +#define _Frees_ptr_opt_ +#define _Post_ptr_invalid_ +#define _Check_return_opt_ +#define _Printf_format_string_ +#define _Success_(x) + +#endif /* LINUX */ + + + //----------------------------------------------------------------------------- // INITIALIZATION FUNCTIONALITY BELOW: // Choose one way of initializing the VMM / MemProcFS. @@ -70,10 +121,10 @@ extern "C" { * calling LcMemFree(). * -- return = success/fail */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_Initialize(_In_ DWORD argc, _In_ LPSTR argv[]); -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_InitializeEx(_In_ DWORD argc, _In_ LPSTR argv[], _Out_opt_ PPLC_CONFIG_ERRORINFO ppLcErrorInfo); /* @@ -81,16 +132,18 @@ BOOL VMMDLL_InitializeEx(_In_ DWORD argc, _In_ LPSTR argv[], _Out_opt_ PPLC_CONF * including plugins, linked PCILeech.DLL and other memory resources. * -- return = success/fail. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_Close(); /* * Free memory allocated by the VMMDLL. * -- pvMem */ +EXPORTED_FUNCTION VOID VMMDLL_MemFree(_Frees_ptr_opt_ PVOID pvMem); + //----------------------------------------------------------------------------- // CONFIGURATION SETTINGS BELOW: // Configure MemProcFS or the underlying memory @@ -103,50 +156,50 @@ VOID VMMDLL_MemFree(_Frees_ptr_opt_ PVOID pvMem); * LC_OPT_* in leechcore.h * For more detailed information check the sources for individual device types. */ -#define VMMDLL_OPT_CORE_PRINTF_ENABLE 0x40000001'00000000 // RW -#define VMMDLL_OPT_CORE_VERBOSE 0x40000002'00000000 // RW -#define VMMDLL_OPT_CORE_VERBOSE_EXTRA 0x40000003'00000000 // RW -#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x40000004'00000000 // RW -#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x40000008'00000000 // R - -#define VMMDLL_OPT_CORE_SYSTEM 0x20000001'00000000 // R -#define VMMDLL_OPT_CORE_MEMORYMODEL 0x20000002'00000000 // R - -#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x20000003'00000000 // R - 1/0 -#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x20000004'00000000 // RW - base tick period in ms -#define VMMDLL_OPT_CONFIG_READCACHE_TICKS 0x20000005'00000000 // RW - memory cache validity period (in ticks) -#define VMMDLL_OPT_CONFIG_TLBCACHE_TICKS 0x20000006'00000000 // RW - page table (tlb) cache validity period (in ticks) -#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL 0x20000007'00000000 // RW - process refresh (partial) period (in ticks) -#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_TOTAL 0x20000008'00000000 // RW - process refresh (full) period (in ticks) -#define VMMDLL_OPT_CONFIG_VMM_VERSION_MAJOR 0x20000009'00000000 // R -#define VMMDLL_OPT_CONFIG_VMM_VERSION_MINOR 0x2000000A'00000000 // R -#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x2000000B'00000000 // R -#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x2000000C'00000000 // RW - enable function call statistics (.status/statistics_fncall file) -#define VMMDLL_OPT_CONFIG_IS_PAGING_ENABLED 0x2000000D'00000000 // RW - 1/0 - -#define VMMDLL_OPT_WIN_VERSION_MAJOR 0x20000101'00000000 // R -#define VMMDLL_OPT_WIN_VERSION_MINOR 0x20000102'00000000 // R -#define VMMDLL_OPT_WIN_VERSION_BUILD 0x20000103'00000000 // R -#define VMMDLL_OPT_WIN_SYSTEM_UNIQUE_ID 0x20000104'00000000 // R - -#define VMMDLL_OPT_FORENSIC_MODE 0x20000201'00000000 // RW - enable/retrieve forensic mode type [0-4]. - -#define VMMDLL_OPT_REFRESH_ALL 0x2001ffff'00000000 // W - refresh all caches -#define VMMDLL_OPT_REFRESH_FREQ_MEM 0x20010002'00000000 // W - refresh memory cache (excl. TLB) [partial 33%/call] -#define VMMDLL_OPT_REFRESH_FREQ_TLB 0x20010004'00000000 // W - refresh page table (TLB) cache [partial 33%/call] -#define VMMDLL_OPT_REFRESH_FREQ_FAST 0x20010400'00000000 // W - refresh fast frequency - incl. partial process refresh -#define VMMDLL_OPT_REFRESH_FREQ_MEDIUM 0x20010001'00000000 // W - refresh medium frequency - incl. full process refresh -#define VMMDLL_OPT_REFRESH_FREQ_SLOW 0x20010010'00000000 // W - refresh slow frequency. -#define VMMDLL_OPT_REFRESH_PROCESS 0x20010001'00000000 // W - DEPRECATED: refresh process listings -#define VMMDLL_OPT_REFRESH_READ 0x20010002'00000000 // W - DEPRECATED: refresh physical read cache -#define VMMDLL_OPT_REFRESH_TLB 0x20010004'00000000 // W - DEPRECATED: refresh page table (TLB) cache -#define VMMDLL_OPT_REFRESH_PAGING 0x20010008'00000000 // W - DEPRECATED: refresh virtual memory 'paging' cache -#define VMMDLL_OPT_REFRESH_REGISTRY 0x20010010'00000000 // W - DEPRECATED: -#define VMMDLL_OPT_REFRESH_USER 0x20010020'00000000 // W - DEPRECATED: -#define VMMDLL_OPT_REFRESH_PHYSMEMMAP 0x20010040'00000000 // W - DEPRECATED: -#define VMMDLL_OPT_REFRESH_PFN 0x20010080'00000000 // W - DEPRECATED: -#define VMMDLL_OPT_REFRESH_OBJ 0x20010100'00000000 // W - DEPRECATED: -#define VMMDLL_OPT_REFRESH_NET 0x20010200'00000000 // W - DEPRECATED: +#define VMMDLL_OPT_CORE_PRINTF_ENABLE 0x4000000100000000 // RW +#define VMMDLL_OPT_CORE_VERBOSE 0x4000000200000000 // RW +#define VMMDLL_OPT_CORE_VERBOSE_EXTRA 0x4000000300000000 // RW +#define VMMDLL_OPT_CORE_VERBOSE_EXTRA_TLP 0x4000000400000000 // RW +#define VMMDLL_OPT_CORE_MAX_NATIVE_ADDRESS 0x4000000800000000 // R + +#define VMMDLL_OPT_CORE_SYSTEM 0x2000000100000000 // R +#define VMMDLL_OPT_CORE_MEMORYMODEL 0x2000000200000000 // R + +#define VMMDLL_OPT_CONFIG_IS_REFRESH_ENABLED 0x2000000300000000 // R - 1/0 +#define VMMDLL_OPT_CONFIG_TICK_PERIOD 0x2000000400000000 // RW - base tick period in ms +#define VMMDLL_OPT_CONFIG_READCACHE_TICKS 0x2000000500000000 // RW - memory cache validity period (in ticks) +#define VMMDLL_OPT_CONFIG_TLBCACHE_TICKS 0x2000000600000000 // RW - page table (tlb) cache validity period (in ticks) +#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_PARTIAL 0x2000000700000000 // RW - process refresh (partial) period (in ticks) +#define VMMDLL_OPT_CONFIG_PROCCACHE_TICKS_TOTAL 0x2000000800000000 // RW - process refresh (full) period (in ticks) +#define VMMDLL_OPT_CONFIG_VMM_VERSION_MAJOR 0x2000000900000000 // R +#define VMMDLL_OPT_CONFIG_VMM_VERSION_MINOR 0x2000000A00000000 // R +#define VMMDLL_OPT_CONFIG_VMM_VERSION_REVISION 0x2000000B00000000 // R +#define VMMDLL_OPT_CONFIG_STATISTICS_FUNCTIONCALL 0x2000000C00000000 // RW - enable function call statistics (.status/statistics_fncall file) +#define VMMDLL_OPT_CONFIG_IS_PAGING_ENABLED 0x2000000D00000000 // RW - 1/0 + +#define VMMDLL_OPT_WIN_VERSION_MAJOR 0x2000010100000000 // R +#define VMMDLL_OPT_WIN_VERSION_MINOR 0x2000010200000000 // R +#define VMMDLL_OPT_WIN_VERSION_BUILD 0x2000010300000000 // R +#define VMMDLL_OPT_WIN_SYSTEM_UNIQUE_ID 0x2000010400000000 // R + +#define VMMDLL_OPT_FORENSIC_MODE 0x2000020100000000 // RW - enable/retrieve forensic mode type [0-4]. + +#define VMMDLL_OPT_REFRESH_ALL 0x2001ffff00000000 // W - refresh all caches +#define VMMDLL_OPT_REFRESH_FREQ_MEM 0x2001000200000000 // W - refresh memory cache (excl. TLB) [partial 33%/call] +#define VMMDLL_OPT_REFRESH_FREQ_TLB 0x2001000400000000 // W - refresh page table (TLB) cache [partial 33%/call] +#define VMMDLL_OPT_REFRESH_FREQ_FAST 0x2001040000000000 // W - refresh fast frequency - incl. partial process refresh +#define VMMDLL_OPT_REFRESH_FREQ_MEDIUM 0x2001000100000000 // W - refresh medium frequency - incl. full process refresh +#define VMMDLL_OPT_REFRESH_FREQ_SLOW 0x2001001000000000 // W - refresh slow frequency. +#define VMMDLL_OPT_REFRESH_PROCESS 0x2001000100000000 // W - DEPRECATED: refresh process listings +#define VMMDLL_OPT_REFRESH_READ 0x2001000200000000 // W - DEPRECATED: refresh physical read cache +#define VMMDLL_OPT_REFRESH_TLB 0x2001000400000000 // W - DEPRECATED: refresh page table (TLB) cache +#define VMMDLL_OPT_REFRESH_PAGING 0x2001000800000000 // W - DEPRECATED: refresh virtual memory 'paging' cache +#define VMMDLL_OPT_REFRESH_REGISTRY 0x2001001000000000 // W - DEPRECATED: +#define VMMDLL_OPT_REFRESH_USER 0x2001002000000000 // W - DEPRECATED: +#define VMMDLL_OPT_REFRESH_PHYSMEMMAP 0x2001004000000000 // W - DEPRECATED: +#define VMMDLL_OPT_REFRESH_PFN 0x2001008000000000 // W - DEPRECATED: +#define VMMDLL_OPT_REFRESH_OBJ 0x2001010000000000 // W - DEPRECATED: +#define VMMDLL_OPT_REFRESH_NET 0x2001020000000000 // W - DEPRECATED: static LPCSTR VMMDLL_MEMORYMODEL_TOSTRING[4] = { "N/A", "X86", "X86PAE", "X64" }; @@ -172,7 +225,7 @@ typedef enum tdVMMDLL_SYSTEM_TP { * -- pqwValue = pointer to ULONG64 to receive option value. * -- return = success/fail. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue); /* @@ -183,7 +236,7 @@ BOOL VMMDLL_ConfigGet(_In_ ULONG64 fOption, _Out_ PULONG64 pqwValue); * -- qwValue * -- return = success/fail. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_ConfigSet(_In_ ULONG64 fOption, _In_ ULONG64 qwValue); @@ -196,11 +249,53 @@ typedef struct tdVMMDLL_MAP_PFN *PVMMDLL_MAP_PFN; +//----------------------------------------------------------------------------- +// LINUX SPECIFIC DEFINES: +//----------------------------------------------------------------------------- +#ifdef LINUX + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +typedef struct _IMAGE_SECTION_HEADER { + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +typedef struct _SERVICE_STATUS { + DWORD dwServiceType; + DWORD dwCurrentState; + DWORD dwControlsAccepted; + DWORD dwWin32ExitCode; + DWORD dwServiceSpecificExitCode; + DWORD dwCheckPoint; + DWORD dwWaitHint; +} SERVICE_STATUS, *LPSERVICE_STATUS; +#endif /* LINUX */ + + + //----------------------------------------------------------------------------- // VFS - VIRTUAL FILE SYSTEM FUNCTIONALITY BELOW: -// NB! VFS FUNCTIONALITY REQUIRES PLUGINS TO BE INITIALZED VIA CALL TO VMMDLL_InitializePlugins(). +// NB! VFS FUNCTIONALITY REQUIRES PLUGINS TO BE INITIALIZED +// WITH CALL TO VMMDLL_InitializePlugins(). // This is the core of MemProcFS. All implementation and analysis towards -// the file system is possible by using functionality below. +// the virtual file system (vfs) is possible by using functionality below. //----------------------------------------------------------------------------- #define VMMDLL_STATUS_SUCCESS ((NTSTATUS)0x00000000L) @@ -229,52 +324,40 @@ typedef struct tdVMMDLL_VFS_FILELIST_EXINFO { }; } VMMDLL_VFS_FILELIST_EXINFO, *PVMMDLL_VFS_FILELIST_EXINFO; -typedef struct tdVMMDLL_VFS_FILELIST { +typedef struct tdVMMDLL_VFS_FILELIST2 { DWORD dwVersion; - VOID(*pfnAddFile) (_Inout_ HANDLE h, _In_ LPWSTR wszName, _In_ ULONG64 cb, _In_opt_ PVMMDLL_VFS_FILELIST_EXINFO pExInfo); - VOID(*pfnAddDirectory)(_Inout_ HANDLE h, _In_ LPWSTR wszName, _In_opt_ PVMMDLL_VFS_FILELIST_EXINFO pExInfo); + VOID(*pfnAddFile) (_Inout_ HANDLE h, _In_ LPSTR uszName, _In_ ULONG64 cb, _In_opt_ PVMMDLL_VFS_FILELIST_EXINFO pExInfo); + VOID(*pfnAddDirectory)(_Inout_ HANDLE h, _In_ LPSTR uszName, _In_opt_ PVMMDLL_VFS_FILELIST_EXINFO pExInfo); HANDLE h; -} VMMDLL_VFS_FILELIST, *PVMMDLL_VFS_FILELIST; +} VMMDLL_VFS_FILELIST2, *PVMMDLL_VFS_FILELIST2; /* -* Helper inline functions for callbacks into the VMM_VFS_FILELIST structure. +* Helper functions for callbacks into the VMM_VFS_FILELIST structure. */ - -inline VOID VMMDLL_VfsList_AddFile(_In_ HANDLE pFileList, _In_ LPWSTR wszName, _In_ ULONG64 cb, _In_opt_ PVMMDLL_VFS_FILELIST_EXINFO pExInfo) -{ - ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddFile(((PVMMDLL_VFS_FILELIST)pFileList)->h, wszName, cb, pExInfo); -} - -inline VOID VMMDLL_VfsList_AddFile_NOZERO(_In_ HANDLE pFileList, _In_ LPWSTR wszName, _In_ ULONG64 cb, _In_opt_ PVMMDLL_VFS_FILELIST_EXINFO pExInfo) -{ - if(cb) { VMMDLL_VfsList_AddFile(pFileList, wszName, cb, pExInfo); } -} - -inline VOID VMMDLL_VfsList_AddDirectory(_In_ HANDLE pFileList, _In_ LPWSTR wszName, _In_opt_ PVMMDLL_VFS_FILELIST_EXINFO pExInfo) -{ - ((PVMMDLL_VFS_FILELIST)pFileList)->pfnAddDirectory(((PVMMDLL_VFS_FILELIST)pFileList)->h, wszName, pExInfo); -} - -inline BOOL VMMDLL_VfsList_IsHandleValid(_In_ HANDLE pFileList) -{ - return ((PVMMDLL_VFS_FILELIST)pFileList)->dwVersion == VMMDLL_VFS_FILELIST_VERSION; -} +EXPORTED_FUNCTION +VOID VMMDLL_VfsList_AddFile(_In_ HANDLE pFileList, _In_ LPSTR uszName, _In_ ULONG64 cb, _In_opt_ PVMMDLL_VFS_FILELIST_EXINFO pExInfo); +VOID VMMDLL_VfsList_AddFileW(_In_ HANDLE pFileList, _In_ LPWSTR wszName, _In_ ULONG64 cb, _In_opt_ PVMMDLL_VFS_FILELIST_EXINFO pExInfo); +EXPORTED_FUNCTION +VOID VMMDLL_VfsList_AddDirectory(_In_ HANDLE pFileList, _In_ LPSTR uszName, _In_opt_ PVMMDLL_VFS_FILELIST_EXINFO pExInfo); +VOID VMMDLL_VfsList_AddDirectoryW(_In_ HANDLE pFileList, _In_ LPWSTR wszName, _In_opt_ PVMMDLL_VFS_FILELIST_EXINFO pExInfo); +EXPORTED_FUNCTION BOOL VMMDLL_VfsList_IsHandleValid(_In_ HANDLE pFileList); /* * List a directory of files in MemProcFS. Directories and files will be listed * by callbacks into functions supplied in the pFileList parameter. * If information of an individual file is needed it's neccessary to list all * files in its directory. -* -- wcsPath +* -- [uw]szPath * -- pFileList * -- return */ -_Success_(return) -BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_VfsListU(_In_ LPSTR uszPath, _Inout_ PVMMDLL_VFS_FILELIST2 pFileList); +_Success_(return) BOOL VMMDLL_VfsListW(_In_ LPWSTR wszPath, _Inout_ PVMMDLL_VFS_FILELIST2 pFileList); /* * Read select parts of a file in MemProcFS. -* -- wcsFileName +* -- [uw]szFileName * -- pb * -- cb * -- pcbRead @@ -282,29 +365,34 @@ BOOL VMMDLL_VfsList(_In_ LPCWSTR wcsPath, _Inout_ PVMMDLL_VFS_FILELIST pFileList * -- return * */ -NTSTATUS VMMDLL_VfsRead(_In_ LPCWSTR wcsFileName, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset); +EXPORTED_FUNCTION +NTSTATUS VMMDLL_VfsReadU(_In_ LPSTR uszFileName, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset); +NTSTATUS VMMDLL_VfsReadW(_In_ LPWSTR wszFileName, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset); /* * Write select parts to a file in MemProcFS. -* -- wcsFileName +* -- [uw]szFileName * -- pb * -- cb * -- pcbWrite * -- cbOffset * -- return */ -NTSTATUS VMMDLL_VfsWrite(_In_ LPCWSTR wcsFileName, _In_reads_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset); +EXPORTED_FUNCTION +NTSTATUS VMMDLL_VfsWriteU(_In_ LPSTR uszFileName, _In_reads_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset); +NTSTATUS VMMDLL_VfsWriteW(_In_ LPWSTR wszFileName, _In_reads_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset); /* * Utility functions for MemProcFS read/write towards different underlying data * representations. */ -NTSTATUS VMMDLL_UtilVfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ ULONG64 cbFile, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset); -NTSTATUS VMMDLL_UtilVfsReadFile_FromQWORD(_In_ ULONG64 qwValue, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix); -NTSTATUS VMMDLL_UtilVfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix); -NTSTATUS VMMDLL_UtilVfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset); -NTSTATUS VMMDLL_UtilVfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_reads_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset); -NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_reads_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset, _In_ DWORD dwMinAllow); +EXPORTED_FUNCTION NTSTATUS VMMDLL_UtilVfsReadFile_FromPBYTE(_In_ PBYTE pbFile, _In_ ULONG64 cbFile, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset); +EXPORTED_FUNCTION NTSTATUS VMMDLL_UtilVfsReadFile_FromQWORD(_In_ ULONG64 qwValue, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix); +EXPORTED_FUNCTION NTSTATUS VMMDLL_UtilVfsReadFile_FromDWORD(_In_ DWORD dwValue, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset, _In_ BOOL fPrefix); +EXPORTED_FUNCTION NTSTATUS VMMDLL_UtilVfsReadFile_FromBOOL(_In_ BOOL fValue, _Out_writes_to_(cb, *pcbRead) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbRead, _In_ ULONG64 cbOffset); +EXPORTED_FUNCTION NTSTATUS VMMDLL_UtilVfsWriteFile_BOOL(_Inout_ PBOOL pfTarget, _In_reads_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset); +EXPORTED_FUNCTION NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_reads_(cb) PBYTE pb, _In_ DWORD cb, _Out_ PDWORD pcbWrite, _In_ ULONG64 cbOffset, _In_ DWORD dwMinAllow); + //----------------------------------------------------------------------------- @@ -326,7 +414,7 @@ NTSTATUS VMMDLL_UtilVfsWriteFile_DWORD(_Inout_ PDWORD pdwTarget, _In_reads_(cb) * general close of the vmm dll. * -- return */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_InitializePlugins(); #define VMMDLL_PLUGIN_CONTEXT_MAGIC 0xc0ffee663df9301c @@ -351,8 +439,8 @@ typedef struct tdVMMDLL_PLUGIN_CONTEXT { WORD wSize; DWORD dwPID; PVOID pProcess; - LPWSTR wszModule; - LPWSTR wszPath; + LPSTR uszModule; + LPSTR uszPath; PVOID pvReserved1; PVMMDLL_PLUGIN_INTERNAL_CONTEXT ctxM; // optional internal module context. } VMMDLL_PLUGIN_CONTEXT, *PVMMDLL_PLUGIN_CONTEXT; @@ -370,9 +458,8 @@ typedef struct tdVMMDLL_PLUGIN_FORENSIC_JSONDATA { QWORD qwNum[2]; BOOL fHex[2]; // log hex even if zero QWORD qwHex[2]; - // str: will be prioritized in order: szj > szu > wsz. - LPCSTR szj[2]; // str: json encoded - LPCSTR szu[2]; // str: utf-8 encoded + // str: will be prioritized in order: szu > wsz. + LPCSTR usz[2]; // str: utf-8 encoded LPCWSTR wsz[2]; // str: wide BYTE _Reserved[0x4000+256]; } VMMDLL_PLUGIN_FORENSIC_JSONDATA, *PVMMDLL_PLUGIN_FORENSIC_JSONDATA; @@ -404,14 +491,14 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO { // general plugin registration info to be filled out by the plugin below: struct { PVMMDLL_PLUGIN_INTERNAL_CONTEXT ctxM; // optional internal module context [must be cleaned by pfnClose() call]. - WCHAR wszPathName[128]; + CHAR uszPathName[128]; BOOL fRootModule; BOOL fProcessModule; BOOL fRootModuleHidden; BOOL fProcessModuleHidden; CHAR sTimelineNameShort[6]; CHAR _Reserved[2]; - CHAR szTimelineFileUTF8[32]; + CHAR uszTimelineFile[32]; CHAR _Reserved2[32]; } reg_info; // function plugin registration info to be filled out by the plugin below: @@ -436,7 +523,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO { VOID(*pfnTimeline)( _In_opt_ PVOID ctxfc, _In_ HANDLE hTimeline, - _In_ VOID(*pfnAddEntry)(_In_ HANDLE hTimeline, _In_ QWORD ft, _In_ DWORD dwAction, _In_ DWORD dwPID, _In_ DWORD dwData32, _In_ QWORD qwData64, _In_ LPWSTR wszText), + _In_ VOID(*pfnAddEntry)(_In_ HANDLE hTimeline, _In_ QWORD ft, _In_ DWORD dwAction, _In_ DWORD dwPID, _In_ DWORD dwData32, _In_ QWORD qwData64, _In_ LPSTR uszText), _In_ VOID(*pfnEntryAddBySql)(_In_ HANDLE hTimeline, _In_ DWORD cEntrySql, _In_ LPSTR *pszEntrySql)); VOID(*pfnIngestPhysmem)(_In_opt_ PVOID ctxfc, _In_ PVMMDLL_PLUGIN_FORENSIC_INGEST_PHYSMEM pIngestPhysmem); VOID(*pfnIngestFinalize)(_In_opt_ PVOID ctxfc); @@ -490,6 +577,7 @@ typedef struct tdVMMDLL_PLUGIN_REGINFO { * -- flags = optional flags as given by VMMDLL_FLAG_* * -- return = the number of successfully read items. */ +EXPORTED_FUNCTION DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPMEM_SCATTER ppMEMs, _In_ DWORD cpMEMs, _In_ DWORD flags); /* @@ -499,7 +587,7 @@ DWORD VMMDLL_MemReadScatter(_In_ DWORD dwPID, _Inout_ PPMEM_SCATTER ppMEMs, _In_ * -- pbPage * -- return = success/fail (depending if all requested bytes are read or not). */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwA, _Inout_bytecount_(4096) PBYTE pbPage); /* @@ -510,7 +598,7 @@ BOOL VMMDLL_MemReadPage(_In_ DWORD dwPID, _In_ ULONG64 qwA, _Inout_bytecount_(40 * -- cb * -- return = success/fail (depending if all requested bytes are read or not). */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwA, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb); /* @@ -524,7 +612,7 @@ BOOL VMMDLL_MemRead(_In_ DWORD dwPID, _In_ ULONG64 qwA, _Out_writes_(cb) PBYTE p * -- return = success/fail. NB! reads may report as success even if 0 bytes are * read - it's recommended to verify pcbReadOpt parameter. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwA, _Out_writes_(cb) PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags); /* @@ -536,7 +624,7 @@ BOOL VMMDLL_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwA, _Out_writes_(cb) PBYTE * -- pPrefetchAddresses = array of addresses to read into cache. * -- cPrefetchAddresses */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_MemPrefetchPages(_In_ DWORD dwPID, _In_reads_(cPrefetchAddresses) PULONG64 pPrefetchAddresses, _In_ DWORD cPrefetchAddresses); /* @@ -552,7 +640,7 @@ BOOL VMMDLL_MemPrefetchPages(_In_ DWORD dwPID, _In_reads_(cPrefetchAddresses) PU * -- cb * -- return = TRUE on success, FALSE on partial or zero write. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwA, _In_reads_(cb) PBYTE pb, _In_ DWORD cb); /* @@ -563,7 +651,7 @@ BOOL VMMDLL_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwA, _In_reads_(cb) PBYTE pb * -- pqwPA * -- return = success/fail. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqwPA); @@ -575,20 +663,20 @@ BOOL VMMDLL_MemVirt2Phys(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PULONG64 pqw // heaps and threads. //----------------------------------------------------------------------------- -#define VMMDLL_MAP_PTE_VERSION 1 -#define VMMDLL_MAP_VAD_VERSION 5 -#define VMMDLL_MAP_VADEX_VERSION 2 -#define VMMDLL_MAP_MODULE_VERSION 4 -#define VMMDLL_MAP_UNLOADEDMODULE_VERSION 1 -#define VMMDLL_MAP_EAT_VERSION 1 -#define VMMDLL_MAP_IAT_VERSION 1 -#define VMMDLL_MAP_HEAP_VERSION 1 -#define VMMDLL_MAP_THREAD_VERSION 2 -#define VMMDLL_MAP_HANDLE_VERSION 1 -#define VMMDLL_MAP_NET_VERSION 2 -#define VMMDLL_MAP_PHYSMEM_VERSION 1 -#define VMMDLL_MAP_USER_VERSION 1 -#define VMMDLL_MAP_SERVICE_VERSION 2 +#define VMMDLL_MAP_PTE_VERSION 2 +#define VMMDLL_MAP_VAD_VERSION 6 +#define VMMDLL_MAP_VADEX_VERSION 3 +#define VMMDLL_MAP_MODULE_VERSION 5 +#define VMMDLL_MAP_UNLOADEDMODULE_VERSION 2 +#define VMMDLL_MAP_EAT_VERSION 2 +#define VMMDLL_MAP_IAT_VERSION 2 +#define VMMDLL_MAP_HEAP_VERSION 2 +#define VMMDLL_MAP_THREAD_VERSION 3 +#define VMMDLL_MAP_HANDLE_VERSION 2 +#define VMMDLL_MAP_NET_VERSION 3 +#define VMMDLL_MAP_PHYSMEM_VERSION 2 +#define VMMDLL_MAP_USER_VERSION 2 +#define VMMDLL_MAP_SERVICE_VERSION 3 // flags to check for existence in the fPage field of VMMDLL_MAP_PTEENTRY #define VMMDLL_MEMMAP_FLAG_PAGE_W 0x0000000000000002 @@ -611,8 +699,8 @@ typedef struct tdVMMDLL_MAP_PTEENTRY { QWORD cPages; QWORD fPage; BOOL fWoW64; - DWORD cwszText; - LPWSTR wszText; + DWORD _FutureUse1; + union { LPSTR uszText; LPWSTR wszText; }; // U/W dependant DWORD _Reserved1; DWORD cSoftware; // # software (non active) PTEs in region } VMMDLL_MAP_PTEENTRY, *PVMMDLL_MAP_PTEENTRY; @@ -641,8 +729,8 @@ typedef struct tdVMMDLL_MAP_VADENTRY { DWORD cbPrototypePte; QWORD vaPrototypePte; QWORD vaSubsection; - LPWSTR wszText; // optional LPWSTR pointed into VMMDLL_MAP_VAD.wszMultiText - DWORD cwszText; // WCHAR count not including terminating null + union { LPSTR uszText; LPWSTR wszText; }; // U/W dependant + DWORD _FutureUse1; DWORD _Reserved1; QWORD vaFileObject; // only valid if fFile/fImage _and_ after wszText is initialized DWORD cVadExPages; // number of "valid" VadEx pages in this VAD. @@ -677,24 +765,25 @@ typedef struct tdVMMDLL_MAP_MODULEENTRY { QWORD vaEntry; DWORD cbImageSize; BOOL fWoW64; - LPWSTR wszText; - DWORD cwszText; // wchar count not including terminating null - DWORD cwszFullName; // wchar count not including terminating null - LPWSTR wszFullName; + union { LPSTR uszText; LPWSTR wszText; }; // U/W dependant + DWORD _Reserved3; + DWORD _Reserved4; + union { LPSTR uszFullName; LPWSTR wszFullName; }; // U/W dependant VMMDLL_MODULE_TP tp; DWORD cbFileSizeRaw; DWORD cSection; DWORD cEAT; DWORD cIAT; - DWORD _Reserved1[3]; + DWORD _Reserved2; + QWORD _Reserved1[2]; } VMMDLL_MAP_MODULEENTRY, *PVMMDLL_MAP_MODULEENTRY; typedef struct tdVMMDLL_MAP_UNLOADEDMODULEENTRY { QWORD vaBase; DWORD cbImageSize; BOOL fWoW64; - LPWSTR wszText; // LPWSTR to name pointed into VMMDLL_MAP_UNLOADEDMODULE.wszMultiText - DWORD cwszText; // WCHAR count not including terminating null + union { LPSTR uszText; LPWSTR wszText; }; // U/W dependant + DWORD _FutureUse1; DWORD dwCheckSum; // user-mode only DWORD dwTimeDateStamp; // user-mode only DWORD _Reserved1; @@ -706,16 +795,16 @@ typedef struct tdVMMDLL_MAP_EATENTRY { DWORD dwOrdinal; DWORD oFunctionsArray; // PIMAGE_EXPORT_DIRECTORY->AddressOfFunctions[oFunctionsArray] DWORD oNamesArray; // PIMAGE_EXPORT_DIRECTORY->AddressOfNames[oNamesArray] - DWORD cwszFunction; // WCHAR count not including terminating null - LPWSTR wszFunction; // LPWSTR to name pointed into VMMDLL_MAP_EATMODULE.wszMultiText + DWORD _FutureUse1; + union { LPSTR uszFunction; LPWSTR wszFunction; }; // U/W dependant } VMMDLL_MAP_EATENTRY, *PVMMDLL_MAP_EATENTRY; typedef struct tdVMMDLL_MAP_IATENTRY { QWORD vaFunction; - LPWSTR wszFunction; - DWORD cwszFunction; - DWORD cwszModule; - LPWSTR wszModule; + union { LPSTR uszFunction; LPWSTR wszFunction; }; // U/W dependant + DWORD _FutureUse1; + DWORD _FutureUse2; + union { LPSTR uszModule; LPWSTR wszModule; }; // U/W dependant struct { BOOL f32; WORD wHint; @@ -772,13 +861,12 @@ typedef struct tdVMMDLL_MAP_HANDLEENTRY { QWORD qwPointerCount; QWORD vaObjectCreateInfo; QWORD vaSecurityDescriptor; - LPWSTR wszText; - DWORD cwszText; + union { LPSTR uszText; LPWSTR wszText; }; // U/W dependant + DWORD _FutureUse2; DWORD dwPID; DWORD dwPoolTag; - DWORD _FutureUse[4]; - DWORD cwszType; - LPWSTR wszType; + DWORD _FutureUse[5]; + union { LPSTR uszType; LPWSTR wszType; }; // U/W dependant } VMMDLL_MAP_HANDLEENTRY, *PVMMDLL_MAP_HANDLEENTRY; typedef struct tdVMMDLL_MAP_NETENTRY { @@ -791,20 +879,20 @@ typedef struct tdVMMDLL_MAP_NETENTRY { WORD _Reserved; WORD port; BYTE pbAddr[16]; // ipv4 = 1st 4 bytes, ipv6 = all bytes - LPWSTR wszText; + union { LPSTR uszText; LPWSTR wszText; }; // U/W dependant } Src; struct { BOOL fValid; WORD _Reserved; WORD port; BYTE pbAddr[16]; // ipv4 = 1st 4 bytes, ipv6 = all bytes - LPWSTR wszText; + union { LPSTR uszText; LPWSTR wszText; }; // U/W dependant } Dst; QWORD vaObj; QWORD ftTime; DWORD dwPoolTag; - DWORD cwszText; // WCHAR count not including terminating null - LPWSTR wszText; // LPWSTR pointed into VMMOB_MAP_NET.wszMultiText + DWORD _FutureUse4; + union { LPSTR uszText; LPWSTR wszText; }; // U/W dependant DWORD _FutureUse2[4]; } VMMDLL_MAP_NETENTRY, *PVMMDLL_MAP_NETENTRY; @@ -814,11 +902,11 @@ typedef struct tdVMMDLL_MAP_PHYSMEMENTRY { } VMMDLL_MAP_PHYSMEMENTRY, *PVMMDLL_MAP_PHYSMEMENTRY; typedef struct tdVMMDLL_MAP_USERENTRY { - DWORD cwszText; // WCHAR count not including terminating null - LPWSTR wszText; // LPWSTR pointed into VMMOB_MAP_USER.wszMultiText + DWORD _FutureUse1[2]; + union { LPSTR uszText; LPWSTR wszText; }; // U/W dependant ULONG64 vaRegHive; - CHAR szSID[MAX_PATH]; - DWORD _FutureUse[9]; + union { LPSTR uszSID; LPWSTR wszSID; }; // U/W dependant + DWORD _FutureUse2[2]; } VMMDLL_MAP_USERENTRY, *PVMMDLL_MAP_USERENTRY; typedef struct tdVMMDLL_MAP_SERVICEENTRY { @@ -826,12 +914,12 @@ typedef struct tdVMMDLL_MAP_SERVICEENTRY { DWORD dwOrdinal; DWORD dwStartType; SERVICE_STATUS ServiceStatus; - LPWSTR wszServiceName; - LPWSTR wszDisplayName; - LPWSTR wszPath; - LPWSTR wszUserTp; - LPWSTR wszUserAcct; - LPWSTR wszImagePath; + union { LPSTR uszServiceName; LPWSTR wszServiceName; };// U/W dependant + union { LPSTR uszDisplayName; LPWSTR wszDisplayName; };// U/W dependant + union { LPSTR uszPath; LPWSTR wszPath; }; // U/W dependant + union { LPSTR uszUserTp; LPWSTR wszUserTp; }; // U/W dependant + union { LPSTR uszUserAcct; LPWSTR wszUserAcct; }; // U/W dependant + union { LPSTR uszImagePath; LPWSTR wszImagePath; }; // U/W dependant DWORD dwPID; DWORD _FutureUse1; QWORD _FutureUse2; @@ -840,7 +928,7 @@ typedef struct tdVMMDLL_MAP_SERVICEENTRY { typedef struct tdVMMDLL_MAP_PTE { DWORD dwVersion; DWORD _Reserved1[5]; - LPWSTR wszMultiText; // NULL or multi-wstr pointed into by VMMDLL_MAP_VADENTRY.wszText + PBYTE pbMultiText; // NULL or multi-wstr pointed into by VMMDLL_MAP_VADENTRY.wszText DWORD cbMultiText; DWORD cMap; // # map entries. VMMDLL_MAP_PTEENTRY pMap[]; // map entries. @@ -850,7 +938,7 @@ typedef struct tdVMMDLL_MAP_VAD { DWORD dwVersion; DWORD _Reserved1[4]; DWORD cPage; // # pages in vad map. - LPWSTR wszMultiText; // NULL or multi-wstr pointed into by VMMDLL_MAP_VADENTRY.wszText + PBYTE pbMultiText; // NULL or multi-wstr pointed into by VMMDLL_MAP_VADENTRY.wszText DWORD cbMultiText; DWORD cMap; // # map entries. VMMDLL_MAP_VADENTRY pMap[]; // map entries. @@ -866,7 +954,7 @@ typedef struct tdVMMDLL_MAP_VADEX { typedef struct tdVMMDLL_MAP_MODULE { DWORD dwVersion; DWORD _Reserved1[5]; - LPWSTR wszMultiText; // multi-wstr pointed into by VMMDLL_MAP_MODULEENTRY.wszText + PBYTE pbMultiText; // multi-wstr pointed into by VMMDLL_MAP_MODULEENTRY.wszText DWORD cbMultiText; DWORD cMap; // # map entries. VMMDLL_MAP_MODULEENTRY pMap[]; // map entries. @@ -875,7 +963,7 @@ typedef struct tdVMMDLL_MAP_MODULE { typedef struct tdVMMDLL_MAP_UNLOADEDMODULE { DWORD dwVersion; DWORD _Reserved1[5]; - LPWSTR wszMultiText; // multi-wstr pointed into by VMMDLL_MAP_MODULEENTRY.wszText + PBYTE pbMultiText; // multi-wstr pointed into by VMMDLL_MAP_MODULEENTRY.wszText DWORD cbMultiText; DWORD cMap; // # map entries. VMMDLL_MAP_UNLOADEDMODULEENTRY pMap[]; // map entries. @@ -890,7 +978,7 @@ typedef struct tdVMMDLL_MAP_EAT { QWORD vaModuleBase; QWORD vaAddressOfFunctions; QWORD vaAddressOfNames; - LPWSTR wszMultiText; // multi-str pointed into by VMM_MAP_EATENTRY.wszFunction + PBYTE pbMultiText; // multi-str pointed into by VMM_MAP_EATENTRY.wszFunction DWORD cbMultiText; DWORD cMap; // # map entries. VMMDLL_MAP_EATENTRY pMap[]; // map entries. @@ -900,7 +988,7 @@ typedef struct tdVMMDLL_MAP_IAT { DWORD dwVersion; DWORD _Reserved1[5]; QWORD vaModuleBase; - LPWSTR wszMultiText; // multi-str pointed into by VMM_MAP_EATENTRY.[wszFunction|wszModule] + PBYTE pbMultiText; // multi-str pointed into by VMM_MAP_EATENTRY.[wszFunction|wszModule] DWORD cbMultiText; DWORD cMap; // # map entries. VMMDLL_MAP_IATENTRY pMap[]; // map entries. @@ -923,7 +1011,7 @@ typedef struct tdVMMDLL_MAP_THREAD { typedef struct tdVMMDLL_MAP_HANDLE { DWORD dwVersion; DWORD _Reserved1[5]; - LPWSTR wszMultiText; // multi-wstr pointed into by VMMDLL_MAP_HANDLEENTRY.wszText + PBYTE pbMultiText; // multi-wstr pointed into by VMMDLL_MAP_HANDLEENTRY.wszText DWORD cbMultiText; DWORD cMap; // # map entries. VMMDLL_MAP_HANDLEENTRY pMap[]; // map entries. @@ -932,7 +1020,7 @@ typedef struct tdVMMDLL_MAP_HANDLE { typedef struct tdVMMDLL_MAP_NET { DWORD dwVersion; DWORD _Reserved1; - LPWSTR wszMultiText; // multi-wstr pointed into by VMM_MAP_USERENTRY.wszText + PBYTE pbMultiText; // multi-wstr pointed into by VMM_MAP_NETENTRY.wszText DWORD cbMultiText; DWORD cMap; // # map entries. VMMDLL_MAP_NETENTRY pMap[]; // map entries. @@ -949,7 +1037,7 @@ typedef struct tdVMMDLL_MAP_PHYSMEM { typedef struct tdVMMDLL_MAP_USER { DWORD dwVersion; DWORD _Reserved1[5]; - LPWSTR wszMultiText; // multi-wstr pointed into by VMMDLL_MAP_HANDLEENTRY.wszText + PBYTE pbMultiText; // multi-wstr pointed into by VMMDLL_MAP_USERENTRY.wszText DWORD cbMultiText; DWORD cMap; // # map entries. VMMDLL_MAP_USERENTRY pMap[]; // map entries. @@ -958,7 +1046,7 @@ typedef struct tdVMMDLL_MAP_USER { typedef struct tdVMMDLL_MAP_SERVICE { DWORD dwVersion; DWORD _Reserved1[5]; - LPWSTR wszMultiText; // multi-wstr pointed into by VMMDLL_MAP_SERVICEENTRY.wsz* + PBYTE pbMultiText; // multi-wstr pointed into by VMMDLL_MAP_SERVICEENTRY.wsz* DWORD cbMultiText; DWORD cMap; // # map entries. VMMDLL_MAP_SERVICEENTRY pMap[]; // map entries. @@ -975,8 +1063,9 @@ typedef struct tdVMMDLL_MAP_SERVICE { * -- fIdentifyModules = try identify modules as well (= slower) * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetPte(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbPteMap) PVMMDLL_MAP_PTE pPteMap, _Inout_ PDWORD pcbPteMap, _In_ BOOL fIdentifyModules); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetPteU(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbPteMap) PVMMDLL_MAP_PTE pPteMap, _Inout_ PDWORD pcbPteMap, _In_ BOOL fIdentifyModules); +_Success_(return) BOOL VMMDLL_Map_GetPteW(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbPteMap) PVMMDLL_MAP_PTE pPteMap, _Inout_ PDWORD pcbPteMap, _In_ BOOL fIdentifyModules); /* * Retrieve memory map entries based on virtual address descriptor (VAD) for @@ -989,8 +1078,9 @@ BOOL VMMDLL_Map_GetPte(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbPteMap) PVMM * -- fIdentifyModules = try identify modules as well (= slower) * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetVad(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbVadMap) PVMMDLL_MAP_VAD pVadMap, _Inout_ PDWORD pcbVadMap, _In_ BOOL fIdentifyModules); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetVadU(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbVadMap) PVMMDLL_MAP_VAD pVadMap, _Inout_ PDWORD pcbVadMap, _In_ BOOL fIdentifyModules); +_Success_(return) BOOL VMMDLL_Map_GetVadW(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbVadMap) PVMMDLL_MAP_VAD pVadMap, _Inout_ PDWORD pcbVadMap, _In_ BOOL fIdentifyModules); /* * Retrieve extended memory map information about a select sub-set of the memory @@ -1003,7 +1093,7 @@ BOOL VMMDLL_Map_GetVad(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbVadMap) PVMM * -- cPage = number of pages to process from oPages base. * -- return = success/fail. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_Map_GetVadEx(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbVadExMap) PVMMDLL_MAP_VADEX pVadExMap, _Inout_ PDWORD pcbVadExMap, _In_ DWORD oPage, _In_ DWORD cPage); /* @@ -1014,8 +1104,9 @@ BOOL VMMDLL_Map_GetVadEx(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbVadExMap) * -- pcbModuleMap = pointer to byte count of pModuleMap buffer. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetModule(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbModuleMap) PVMMDLL_MAP_MODULE pModuleMap, _Inout_ PDWORD pcbModuleMap); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetModuleU(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbModuleMap) PVMMDLL_MAP_MODULE pModuleMap, _Inout_ PDWORD pcbModuleMap); +_Success_(return) BOOL VMMDLL_Map_GetModuleW(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbModuleMap) PVMMDLL_MAP_MODULE pModuleMap, _Inout_ PDWORD pcbModuleMap); /* * Retrieve a module (.dll) entry given a process and module name. @@ -1024,13 +1115,14 @@ BOOL VMMDLL_Map_GetModule(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbModuleMap * If pcbModuleMapEntry is set to NULL the pModuleMapEntry is assumed to be of * size sizeof(VMMDLL_MAP_MODULEENTRY) and data without names will be copied. * -- dwPID -* -- szModuleName +* -- [uw]szModuleName * -- pModuleMapEntry = buffer of minimum byte length *pcbModuleMapEntry or NULL. * -- pcbModuleMapEntry = pointer to byte count of pModuleMapEntry buffer or NULL. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetModuleFromName(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName, _Out_writes_bytes_opt_(*pcbModuleMapEntry) PVMMDLL_MAP_MODULEENTRY pModuleMapEntry, _Inout_opt_ PDWORD pcbModuleMapEntry); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetModuleFromNameU(_In_ DWORD dwPID, _In_ LPSTR uszModuleName, _Out_writes_bytes_opt_(*pcbModuleMapEntry) PVMMDLL_MAP_MODULEENTRY pModuleMapEntry, _Inout_opt_ PDWORD pcbModuleMapEntry); +_Success_(return) BOOL VMMDLL_Map_GetModuleFromNameW(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName, _Out_writes_bytes_opt_(*pcbModuleMapEntry) PVMMDLL_MAP_MODULEENTRY pModuleMapEntry, _Inout_opt_ PDWORD pcbModuleMapEntry); /* * Retrieve the unloaded modules (.dll/.sys) for the specified process. If @@ -1041,33 +1133,37 @@ BOOL VMMDLL_Map_GetModuleFromName(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName, _ * -- pcbUnloadedModuleMap = pointer to byte count of pUnloadedModuleMap buffer. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetUnloadedModule(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbUnloadedModuleMap) PVMMDLL_MAP_UNLOADEDMODULE pUnloadedModuleMap, _Inout_ PDWORD pcbUnloadedModuleMap); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetUnloadedModuleU(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbUnloadedModuleMap) PVMMDLL_MAP_UNLOADEDMODULE pUnloadedModuleMap, _Inout_ PDWORD pcbUnloadedModuleMap); +_Success_(return) BOOL VMMDLL_Map_GetUnloadedModuleW(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbUnloadedModuleMap) PVMMDLL_MAP_UNLOADEDMODULE pUnloadedModuleMap, _Inout_ PDWORD pcbUnloadedModuleMap); /* * Retrieve the module exported functions from the export address table (EAT). * If pEatMap is set to NULL the number of bytes required will be returned in * parameter pcbEatMap. * -- dwPID -* -- wszModuleName +* -- [uw]szModuleName * -- pEatMap = buffer of minimum byte length *pcbEatMap or NULL. * -- pcbEatMap = pointer to byte count of pEatMap buffer. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetEAT(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName, _Out_writes_bytes_opt_(*pcbEatMap) PVMMDLL_MAP_EAT pEatMap, _Inout_ PDWORD pcbEatMap); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetEATU(_In_ DWORD dwPID, _In_ LPSTR uszModuleName, _Out_writes_bytes_opt_(*pcbEatMap) PVMMDLL_MAP_EAT pEatMap, _Inout_ PDWORD pcbEatMap); +_Success_(return) BOOL VMMDLL_Map_GetEATW(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName, _Out_writes_bytes_opt_(*pcbEatMap) PVMMDLL_MAP_EAT pEatMap, _Inout_ PDWORD pcbEatMap); /* * Retrieve the module imported functions from the import address table (IAT). * If pIatMap is set to NULL the number of bytes required will be returned in * parameter pcbIatMap. * -- dwPID +* -- [uw]szModuleName * -- pIatMap = buffer of minimum byte length *pcbIatMap or NULL. * -- pcbIatMap = pointer to byte count of pIatMap buffer. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetIAT(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName, _Out_writes_bytes_opt_(*pcbIatMap) PVMMDLL_MAP_IAT pIatMap, _Inout_ PDWORD pcbIatMap); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetIATU(_In_ DWORD dwPID, _In_ LPSTR uszModuleName, _Out_writes_bytes_opt_(*pcbIatMap) PVMMDLL_MAP_IAT pIatMap, _Inout_ PDWORD pcbIatMap); +_Success_(return) BOOL VMMDLL_Map_GetIATW(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName, _Out_writes_bytes_opt_(*pcbIatMap) PVMMDLL_MAP_IAT pIatMap, _Inout_ PDWORD pcbIatMap); /* * Retrieve the heaps for the specified process. If pHeapMap is set to NULL @@ -1077,8 +1173,8 @@ BOOL VMMDLL_Map_GetIAT(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName, _Out_writes_ * -- pcbHeapMap = pointer to byte count of pHeapMap buffer. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetHeap(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbHeapMap) PVMMDLL_MAP_HEAP pHeapMap, _Inout_ PDWORD pcbHeapMap); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetHeap(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbHeapMap) PVMMDLL_MAP_HEAP pHeapMap, _Inout_ PDWORD pcbHeapMap); /* * Retrieve the threads for the specified process. If pThreadMap is set to NULL @@ -1089,8 +1185,8 @@ BOOL VMMDLL_Map_GetHeap(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbHeapMap) PV * -- pcbThreadMap = pointer to byte count of pThreadMap buffer. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetThread(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbThreadMap) PVMMDLL_MAP_THREAD pThreadMap, _Inout_ PDWORD pcbThreadMap); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetThread(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbThreadMap) PVMMDLL_MAP_THREAD pThreadMap, _Inout_ PDWORD pcbThreadMap); /* * Retrieve the handles for the specified process. If pHandleMap is set to NULL @@ -1101,8 +1197,9 @@ BOOL VMMDLL_Map_GetThread(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbThreadMap * -- pcbHandleMap = pointer to byte count of pHandleMap buffer. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetHandle(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbHandleMap) PVMMDLL_MAP_HANDLE pHandleMap, _Inout_ PDWORD pcbHandleMap); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetHandleU(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbHandleMap) PVMMDLL_MAP_HANDLE pHandleMap, _Inout_ PDWORD pcbHandleMap); +_Success_(return) BOOL VMMDLL_Map_GetHandleW(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbHandleMap) PVMMDLL_MAP_HANDLE pHandleMap, _Inout_ PDWORD pcbHandleMap); /* * Retrieve the physical memory ranges from the physical memory map that Windows @@ -1111,8 +1208,8 @@ BOOL VMMDLL_Map_GetHandle(_In_ DWORD dwPID, _Out_writes_bytes_opt_(*pcbHandleMap * -- pcbPhysMemMap = pointer to byte count of pPhysMemMap buffer. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetPhysMem(_Out_writes_bytes_opt_(*pcbPhysMemMap) PVMMDLL_MAP_PHYSMEM pPhysMemMap, _Inout_ PDWORD pcbPhysMemMap); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetPhysMem(_Out_writes_bytes_opt_(*pcbPhysMemMap) PVMMDLL_MAP_PHYSMEM pPhysMemMap, _Inout_ PDWORD pcbPhysMemMap); /* * Retrieve the network connection map - consisting of active network connections, @@ -1121,8 +1218,9 @@ BOOL VMMDLL_Map_GetPhysMem(_Out_writes_bytes_opt_(*pcbPhysMemMap) PVMMDLL_MAP_PH * -- pcbNetMap = pointer to byte count of pNetrMap buffer. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetNet(_Out_writes_bytes_opt_(*pcbNetMap) PVMMDLL_MAP_NET pNetMap, _Inout_ PDWORD pcbNetMap); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetNetU(_Out_writes_bytes_opt_(*pcbNetMap) PVMMDLL_MAP_NET pNetMap, _Inout_ PDWORD pcbNetMap); +_Success_(return) BOOL VMMDLL_Map_GetNetW(_Out_writes_bytes_opt_(*pcbNetMap) PVMMDLL_MAP_NET pNetMap, _Inout_ PDWORD pcbNetMap); /* * Retrieve the non well known users that are detected in the target system. @@ -1133,8 +1231,9 @@ BOOL VMMDLL_Map_GetNet(_Out_writes_bytes_opt_(*pcbNetMap) PVMMDLL_MAP_NET pNetMa * -- pcbUserMap = pointer to byte count of pUserMap buffer. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetUsers(_Out_writes_bytes_opt_(*pcbUserMap) PVMMDLL_MAP_USER pUserMap, _Inout_ PDWORD pcbUserMap); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetUsersU(_Out_writes_bytes_opt_(*pcbUserMap) PVMMDLL_MAP_USER pUserMap, _Inout_ PDWORD pcbUserMap); +_Success_(return) BOOL VMMDLL_Map_GetUsersW(_Out_writes_bytes_opt_(*pcbUserMap) PVMMDLL_MAP_USER pUserMap, _Inout_ PDWORD pcbUserMap); /* * Retrieve the services currently known by the service control manager (SCM). @@ -1142,8 +1241,9 @@ BOOL VMMDLL_Map_GetUsers(_Out_writes_bytes_opt_(*pcbUserMap) PVMMDLL_MAP_USER pU * -- pcbServiceMap = pointer to byte count of pServiceMap buffer. * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_Map_GetServices(_Out_writes_bytes_opt_(*pcbServiceMap) PVMMDLL_MAP_SERVICE pServiceMap, _Inout_ PDWORD pcbServiceMap); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_Map_GetServicesU(_Out_writes_bytes_opt_(*pcbServiceMap) PVMMDLL_MAP_SERVICE pServiceMap, _Inout_ PDWORD pcbServiceMap); +_Success_(return) BOOL VMMDLL_Map_GetServicesW(_Out_writes_bytes_opt_(*pcbServiceMap) PVMMDLL_MAP_SERVICE pServiceMap, _Inout_ PDWORD pcbServiceMap); @@ -1237,7 +1337,7 @@ typedef struct tdVMMDLL_MAP_PFN { * -- pcbPfnMap = pointer to byte count of pPhysMemMap buffer. * -- return = success/fail. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_Map_GetPfn(_In_ DWORD pPfns[], _In_ DWORD cPfns, _Out_writes_bytes_opt_(*pcbPfnMap) PVMMDLL_MAP_PFN pPfnMap, _Inout_ PDWORD pcbPfnMap); @@ -1256,7 +1356,7 @@ BOOL VMMDLL_Map_GetPfn(_In_ DWORD pPfns[], _In_ DWORD cPfns, _Out_writes_bytes_o * -- pdwPID = pointer that will receive PID on success. * -- return */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID); /* @@ -1265,7 +1365,7 @@ BOOL VMMDLL_PidGetFromName(_In_ LPSTR szProcName, _Out_ PDWORD pdwPID); * -- pcPIDs = size of (in number of DWORDs) pPIDs array on entry, number of PIDs in system on exit. * -- return = success/fail. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_PidList(_Out_writes_opt_(*pcPIDs) PDWORD pPIDs, _Inout_ PULONG64 pcPIDs); #define VMMDLL_PROCESS_INFORMATION_MAGIC 0xc0ffee663df9301e @@ -1305,7 +1405,7 @@ typedef struct tdVMMDLL_PROCESS_INFORMATION { * -- pcbProcessInformation = size of pProcessInfo (in bytes) on entry and exit * -- return = success/fail. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_INFORMATION pProcessInformation, _In_ PSIZE_T pcbProcessInformation); #define VMMDLL_PROCESS_INFORMATION_OPT_STRING_PATH_KERNEL 1 @@ -1322,6 +1422,7 @@ BOOL VMMDLL_ProcessGetInformation(_In_ DWORD dwPID, _Inout_opt_ PVMMDLL_PROCESS_ * -- fOptionString = string value to retrieve as given by VMMDLL_PROCESS_INFORMATION_OPT_STRING_* * -- return - fail: NULL, success: the string - NB! must be VMMDLL_MemFree'd by caller! */ +EXPORTED_FUNCTION LPSTR VMMDLL_ProcessGetInformationString(_In_ DWORD dwPID, _In_ DWORD fOptionString); /* @@ -1330,33 +1431,39 @@ LPSTR VMMDLL_ProcessGetInformationString(_In_ DWORD dwPID, _In_ DWORD fOptionStr * If the pData == NULL upon entry the number of entries of the pData array must * have in order to be able to hold the data is returned. * -- dwPID -* -- wszModule +* -- [uw]szModule * -- pData * -- cData * -- pcData * -- return = success/fail. */ -_Success_(return) -BOOL VMMDLL_ProcessGetDirectories(_In_ DWORD dwPID, _In_ LPWSTR wszModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData); -_Success_(return) -BOOL VMMDLL_ProcessGetSections(_In_ DWORD dwPID, _In_ LPWSTR wszModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_ProcessGetDirectoriesU(_In_ DWORD dwPID, _In_ LPSTR uszModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData); +_Success_(return) BOOL VMMDLL_ProcessGetDirectoriesW(_In_ DWORD dwPID, _In_ LPWSTR wszModule, _Out_writes_(16) PIMAGE_DATA_DIRECTORY pData, _In_ DWORD cData, _Out_ PDWORD pcData); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_ProcessGetSectionsU(_In_ DWORD dwPID, _In_ LPSTR uszModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData); +_Success_(return) BOOL VMMDLL_ProcessGetSectionsW(_In_ DWORD dwPID, _In_ LPWSTR wszModule, _Out_opt_ PIMAGE_SECTION_HEADER pData, _In_ DWORD cData, _Out_ PDWORD pcData); /* * Retrieve the virtual address of a given function inside a process/module. * -- dwPID -* -- wszModuleName +* -- [uw]szModuleName * -- szFunctionName * -- return = virtual address of function, zero on fail. */ -ULONG64 VMMDLL_ProcessGetProcAddress(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName, _In_ LPSTR szFunctionName); +EXPORTED_FUNCTION +ULONG64 VMMDLL_ProcessGetProcAddressU(_In_ DWORD dwPID, _In_ LPSTR uszModuleName, _In_ LPSTR szFunctionName); +ULONG64 VMMDLL_ProcessGetProcAddressW(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName, _In_ LPSTR szFunctionName); /* * Retrieve the base address of a given module. * -- dwPID -* -- wszModuleName +* -- [uw]szModuleName * -- return = virtual address of module base, zero on fail. */ -ULONG64 VMMDLL_ProcessGetModuleBase(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName); +EXPORTED_FUNCTION +ULONG64 VMMDLL_ProcessGetModuleBaseU(_In_ DWORD dwPID, _In_ LPSTR uszModuleName); +ULONG64 VMMDLL_ProcessGetModuleBaseW(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName); @@ -1371,7 +1478,7 @@ ULONG64 VMMDLL_ProcessGetModuleBase(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName) * -- szModuleName = buffer to receive module name upon success. * -- return */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_PdbLoad(_In_ DWORD dwPID, _In_ ULONG64 vaModuleBase, _Out_writes_(MAX_PATH) LPSTR szModuleName); /* @@ -1384,7 +1491,7 @@ BOOL VMMDLL_PdbLoad(_In_ DWORD dwPID, _In_ ULONG64 vaModuleBase, _Out_writes_(MA * -- pdwSymbolDisplacement = displacement from the beginning of the symbol. * -- return */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_PdbSymbolName(_In_ LPSTR szModule, _In_ QWORD cbSymbolAddressOrOffset, _Out_writes_(MAX_PATH) LPSTR szSymbolName, _Out_opt_ PDWORD pdwSymbolDisplacement); /* @@ -1396,7 +1503,7 @@ BOOL VMMDLL_PdbSymbolName(_In_ LPSTR szModule, _In_ QWORD cbSymbolAddressOrOffse * -- pvaSymbolAddress * -- return */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_PdbSymbolAddress(_In_ LPSTR szModule, _In_ LPSTR szSymbolName, _Out_ PULONG64 pvaSymbolAddress); /* @@ -1408,7 +1515,7 @@ BOOL VMMDLL_PdbSymbolAddress(_In_ LPSTR szModule, _In_ LPSTR szSymbolName, _Out_ * -- pcbTypeSize * -- return */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_PdbTypeSize(_In_ LPSTR szModule, _In_ LPSTR szTypeName, _Out_ PDWORD pcbTypeSize); /* @@ -1416,13 +1523,13 @@ BOOL VMMDLL_PdbTypeSize(_In_ LPSTR szModule, _In_ LPSTR szTypeName, _Out_ PDWORD * NB! not all modules may exist - initially only module "nt" is available. * NB! if multiple modules have the same name the 1st to be added will be used. * -- szModule -* -- szTypeName -* -- wszTypeChildName +* -- uszTypeName +* -- uszTypeChildName * -- pcbTypeChildOffset * -- return */ -_Success_(return) -BOOL VMMDLL_PdbTypeChildOffset(_In_ LPSTR szModule, _In_ LPSTR szTypeName, _In_ LPWSTR wszTypeChildName, _Out_ PDWORD pcbTypeChildOffset); +EXPORTED_FUNCTION _Success_(return) +BOOL VMMDLL_PdbTypeChildOffset(_In_ LPSTR szModule, _In_ LPSTR uszTypeName, _In_ LPSTR uszTypeChildName, _Out_ PDWORD pcbTypeChildOffset); @@ -1431,7 +1538,7 @@ BOOL VMMDLL_PdbTypeChildOffset(_In_ LPSTR szModule, _In_ LPSTR szTypeName, _In_ //----------------------------------------------------------------------------- #define VMMDLL_REGISTRY_HIVE_INFORMATION_MAGIC 0xc0ffee653df8d01e -#define VMMDLL_REGISTRY_HIVE_INFORMATION_VERSION 2 +#define VMMDLL_REGISTRY_HIVE_INFORMATION_VERSION 3 typedef struct td_VMMDLL_REGISTRY_HIVE_INFORMATION { ULONG64 magic; @@ -1441,9 +1548,9 @@ typedef struct td_VMMDLL_REGISTRY_HIVE_INFORMATION { ULONG64 vaCMHIVE; ULONG64 vaHBASE_BLOCK; DWORD cbLength; - CHAR szName[128]; - WCHAR wszNameShort[32 + 1]; - WCHAR wszHiveRootPath[MAX_PATH]; + CHAR uszName[128]; + CHAR uszNameShort[32 + 1]; + CHAR uszHiveRootPath[MAX_PATH]; QWORD _FutureReserved[0x10]; } VMMDLL_REGISTRY_HIVE_INFORMATION, *PVMMDLL_REGISTRY_HIVE_INFORMATION; @@ -1454,7 +1561,7 @@ typedef struct td_VMMDLL_REGISTRY_HIVE_INFORMATION { * -- pcHives = if pHives == NULL: # total hives. if pHives: # read hives. * -- return */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_WinReg_HiveList(_Out_writes_(cHives) PVMMDLL_REGISTRY_HIVE_INFORMATION pHives, _In_ DWORD cHives, _Out_ PDWORD pcHives); /* @@ -1470,7 +1577,7 @@ BOOL VMMDLL_WinReg_HiveList(_Out_writes_(cHives) PVMMDLL_REGISTRY_HIVE_INFORMATI * -- return = success/fail. NB! reads may report as success even if 0 bytes are * read - it's recommended to verify pcbReadOpt parameter. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_WinReg_HiveReadEx(_In_ ULONG64 vaCMHive, _In_ DWORD ra, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags); /* @@ -1482,9 +1589,85 @@ BOOL VMMDLL_WinReg_HiveReadEx(_In_ ULONG64 vaCMHive, _In_ DWORD ra, _Out_ PBYTE * -- cb * -- return = TRUE on success, FALSE on partial or zero write. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_WinReg_HiveWrite(_In_ ULONG64 vaCMHive, _In_ DWORD ra, _In_ PBYTE pb, _In_ DWORD cb); +/* +* Enumerate registry sub keys - similar to WINAPI function 'RegEnumKeyExW.' +* Please consult WINAPI function documentation for information. +* May be called with HKLM base or virtual address of CMHIVE base examples: +* 1) 'HKLM\SOFTWARE\Key\SubKey' +* 2) 'HKLM\ORPHAN\SAM\Key\SubKey' (orphan key) +* 3) '0x\ROOT\Key\SubKey' +* 4) '0x\ORPHAN\Key\SubKey' (orphan key) +* -- uszFullPathKey +* -- dwIndex = sub-key index 0..N (-1 for key). +* -- lpName +* -- lpcchName +* -- lpftLastWriteTime +* -- return +*/ +EXPORTED_FUNCTION _Success_(return) +BOOL VMMDLL_WinReg_EnumKeyExU( + _In_ LPSTR uszFullPathKey, + _In_ DWORD dwIndex, + _Out_writes_opt_(*lpcchName) LPSTR lpName, + _Inout_ LPDWORD lpcchName, + _Out_opt_ PFILETIME lpftLastWriteTime +); + +/* +* Enumerate registry values given a registry key - similar to WINAPI function +* 'EnumValueW'. Please consult WINAPI function documentation for information. +* May be called in two ways: +* May be called with HKLM base or virtual address of CMHIVE base examples: +* 1) 'HKLM\SOFTWARE\Key\SubKey' +* 2) 'HKLM\ORPHAN\SAM\Key\SubKey' (orphan key) +* 3) '0x\ROOT\Key\SubKey' +* 4) '0x\ORPHAN\Key\SubKey' (orphan key) +* -- uszFullPathKey +* -- dwIndex +* -- lpValueName +* -- lpcchValueName +* -- lpType +* -- lpData +* -- lpcbData +* -- return +*/ +EXPORTED_FUNCTION _Success_(return) +BOOL VMMDLL_WinReg_EnumValueU( + _In_ LPSTR uszFullPathKey, + _In_ DWORD dwIndex, + _Out_writes_opt_(*lpcchValueName) LPSTR lpValueName, + _Inout_ LPDWORD lpcchValueName, + _Out_opt_ LPDWORD lpType, + _Out_writes_opt_(*lpcbData) LPBYTE lpData, + _Inout_opt_ LPDWORD lpcbData +); + +/* +* Query a registry value given a registry key/value path - similar to WINAPI +* function 'RegQueryValueEx'. +* Please consult WINAPI function documentation for information. +* May be called with HKLM base or virtual address of CMHIVE base examples: +* 1) 'HKLM\SOFTWARE\Key\SubKey\Value' +* 2) 'HKLM\ORPHAN\SAM\Key\SubKey\' (orphan key and default value) +* 3) '0x\ROOT\Key\SubKey\Value' +* 4) '0x\ORPHAN\Key\SubKey\Value' (orphan key value) +* -- uszFullPathKeyValue +* -- lpType +* -- lpData +* -- lpcbData +* -- return +*/ +EXPORTED_FUNCTION _Success_(return) +BOOL VMMDLL_WinReg_QueryValueExU( + _In_ LPSTR uszFullPathKeyValue, + _Out_opt_ LPDWORD lpType, + _Out_writes_opt_(*lpcbData) LPBYTE lpData, + _When_(lpData == NULL, _Out_opt_) _When_(lpData != NULL, _Inout_opt_) LPDWORD lpcbData +); + /* * Enumerate registry sub keys - similar to WINAPI function 'RegEnumKeyExW.' * Please consult WINAPI function documentation for information. @@ -1581,20 +1764,15 @@ typedef struct tdVMMDLL_WIN_THUNKINFO_IAT { * function. This includes the virtual address of the IAT thunk which is useful * for hooking. * -- dwPID -* -- wszModuleName +* -- [uw]szModuleName * -- szImportModuleName * -- szImportFunctionName * -- pThunkIAT * -- return */ -_Success_(return) -BOOL VMMDLL_WinGetThunkInfoIAT( - _In_ DWORD dwPID, - _In_ LPWSTR wszModuleName, - _In_ LPSTR szImportModuleName, - _In_ LPSTR szImportFunctionName, - _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT -); +EXPORTED_FUNCTION +_Success_(return) BOOL VMMDLL_WinGetThunkInfoIATU(_In_ DWORD dwPID, _In_ LPSTR uszModuleName, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT); +_Success_(return) BOOL VMMDLL_WinGetThunkInfoIATW(_In_ DWORD dwPID, _In_ LPWSTR wszModuleName, _In_ LPSTR szImportModuleName, _In_ LPSTR szImportFunctionName, _Out_ PVMMDLL_WIN_THUNKINFO_IAT pThunkInfoIAT); @@ -1611,7 +1789,7 @@ BOOL VMMDLL_WinGetThunkInfoIAT( * -- pcsz = IF sz==NULL :: size of buffer (including space for terminating NULL) on exit * IF sz!=NULL :: size of buffer on entry, size of characters (excluding terminating NULL) on exit. */ -_Success_(return) +EXPORTED_FUNCTION _Success_(return) BOOL VMMDLL_UtilFillHexAscii( _In_reads_opt_(cb) PBYTE pb, _In_ DWORD cb, @@ -1620,6 +1798,34 @@ BOOL VMMDLL_UtilFillHexAscii( _Inout_ PDWORD pcsz ); + + +//----------------------------------------------------------------------------- +// DEFAULT (WINDOWS ONLY) COMPATIBILITY FUNCTION DEFINITIONS BELOW: +//----------------------------------------------------------------------------- + +#ifdef _WIN32 +#define VMMDLL_VfsList VMMDLL_VfsListW +#define VMMDLL_VfsRead VMMDLL_VfsReadW +#define VMMDLL_VfsWrite VMMDLL_VfsWriteW +#define VMMDLL_ProcessGetDirectories VMMDLL_ProcessGetDirectoriesW +#define VMMDLL_ProcessGetSections VMMDLL_ProcessGetSectionsW +#define VMMDLL_ProcessGetProcAddress VMMDLL_ProcessGetProcAddressW +#define VMMDLL_ProcessGetModuleBase VMMDLL_ProcessGetModuleBaseW +#define VMMDLL_Map_GetPte VMMDLL_Map_GetPteW +#define VMMDLL_Map_GetVad VMMDLL_Map_GetVadW +#define VMMDLL_Map_GetModule VMMDLL_Map_GetModuleW +#define VMMDLL_Map_GetModuleFromName VMMDLL_Map_GetModuleFromNameW +#define VMMDLL_Map_GetUnloadedModule VMMDLL_Map_GetUnloadedModuleW +#define VMMDLL_Map_GetEAT VMMDLL_Map_GetEATW +#define VMMDLL_Map_GetIAT VMMDLL_Map_GetIATW +#define VMMDLL_Map_GetHandle VMMDLL_Map_GetHandleW +#define VMMDLL_Map_GetNet VMMDLL_Map_GetNetW +#define VMMDLL_Map_GetUsers VMMDLL_Map_GetUsersW +#define VMMDLL_Map_GetServices VMMDLL_Map_GetServicesW +#define VMMDLL_WinGetThunkInfoIAT VMMDLL_WinGetThunkInfoIATW +#endif /* _WIN32 */ + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/pcileech/Makefile b/pcileech/Makefile index e154274..8e6d36f 100644 --- a/pcileech/Makefile +++ b/pcileech/Makefile @@ -1,6 +1,6 @@ CC=gcc -CFLAGS=-I. -I../includes -D LINUX -L. -l:leechcore.so -pthread -LDFLAGS=-Wl,-rpath,'$$ORIGIN' -ldl +CFLAGS +=-I. -I../includes -D LINUX -L. -l:leechcore.so -l:vmm.so -pthread +LDFLAGS +=-Wl,-rpath,'$$ORIGIN' -ldl DEPS = pcileech.h OBJ = oscompatibility.o device.o pcileech.o executor.o extra.o help.o kmd.o memdump.o mempatch.o statistics.o umd.o util.o vfs.o vmmx.o @@ -8,12 +8,16 @@ OBJ = oscompatibility.o device.o pcileech.o executor.o extra.o help.o kmd.o memd $(CC) -c -o $@ $< $(CFLAGS) pcileech: $(OBJ) - cp ../files/leechcore.so . |true + cp ../files/vmm.so . || cp ../../MemProcFS*/files/vmm.so . || true + cp ../files/leechcore.so . || cp ../../LeechCore*/files/leechcore.so . || true $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) - rm *.o mv pcileech ../files/ |true + mv vmm.so ../files/ |true mv leechcore.so ../files/ |true + rm -f *.o || true + rm -f *.so || true + true clean: - rm -f *.o - rm -f *.so + rm -f *.o || true + rm -f *.so || true diff --git a/pcileech/executor.c b/pcileech/executor.c index 8d953d8..067d7aa 100644 --- a/pcileech/executor.c +++ b/pcileech/executor.c @@ -91,7 +91,7 @@ BOOL Exec_ConsoleRedirect_Initialize(_In_ QWORD ConsoleBufferAddr_InputStream, _ pd->pInfoOS = (PEXEC_IO)pd->pbDataOSConsoleBuffer; // read initial buffer and check validity result = dwPID ? - Vmmx_MemReadEx(dwPID, ConsoleBufferAddr_OutputStream, pd->pbDataOSConsoleBuffer, 0x1000, NULL, VMMDLL_FLAG_NOCACHE) : + VMMDLL_MemReadEx(dwPID, ConsoleBufferAddr_OutputStream, pd->pbDataOSConsoleBuffer, 0x1000, NULL, VMMDLL_FLAG_NOCACHE) : DeviceReadMEM(ConsoleBufferAddr_OutputStream, 0x1000, pd->pbDataOSConsoleBuffer, FALSE); if(!result || (pd->pInfoOS->magic != EXEC_IO_MAGIC)) { return FALSE; @@ -122,14 +122,14 @@ VOID Exec_ConsoleRedirect(_In_ QWORD ConsoleBufferAddr_InputStream, _In_ QWORD C while(TRUE) { SwitchToThread(); result = dwPID ? - Vmmx_MemReadEx(dwPID, ConsoleBufferAddr_OutputStream, pd->pbDataOSConsoleBuffer, 0x1000, NULL, VMMDLL_FLAG_NOCACHE) : + VMMDLL_MemReadEx(dwPID, ConsoleBufferAddr_OutputStream, pd->pbDataOSConsoleBuffer, 0x1000, NULL, VMMDLL_FLAG_NOCACHE) : DeviceReadMEM(ConsoleBufferAddr_OutputStream, 0x1000, pd->pbDataOSConsoleBuffer, FALSE); if(!result || pd->pInfoOS->magic != EXEC_IO_MAGIC) { printf("\nCONSOLE_REDIRECT: Error: Address 0x%016llX does not\ncontain a valid console buffer.\n", ConsoleBufferAddr_OutputStream); goto fail; } if(dwPID) { - Vmmx_MemWrite(dwPID, ConsoleBufferAddr_InputStream, pd->pbDataISConsoleBuffer, 0x1000); + VMMDLL_MemWrite(dwPID, ConsoleBufferAddr_InputStream, pd->pbDataISConsoleBuffer, 0x1000); } else { DeviceWriteMEM(ConsoleBufferAddr_InputStream, 0x1000, pd->pbDataISConsoleBuffer, FALSE); } diff --git a/pcileech/extra.c b/pcileech/extra.c index fdaf30a..9e363b9 100644 --- a/pcileech/extra.c +++ b/pcileech/extra.c @@ -59,7 +59,12 @@ BOOL Extra_MacFVRecover_Analyze(_In_ PBYTE pb512M) isFound = TRUE; if(memcmp(pbLast, pb + dwCandidate, 32)) { // duplicate removal memcpy(pbLast, pb + dwCandidate, 32); +#ifdef _WIN32 printf("MAC_FVRECOVER: PASSWORD CANDIDATE: %S\n", (LPWSTR)(pb + dwCandidate)); +#endif /* _WIN32 */ +#ifdef LINUX + printf("MAC_FVRECOVER: PASSWORD CANDIDATE (hex8): %llx\n", *(PQWORD)(pb + dwCandidate)); +#endif /* LINUX */ } break; } diff --git a/pcileech/help.c b/pcileech/help.c index 89e6780..641eddd 100644 --- a/pcileech/help.c +++ b/pcileech/help.c @@ -65,8 +65,8 @@ VOID Help_ShowGeneral() " tlploop NATIVE [ in ] (FPGA) \n" \ " probe NATIVE [ min, max ] (FPGA) \n" \ " regcfg NATIVE [ in, out, min, max] (FPGA) \n" \ - " pslist NATIVE (Windows) \n" \ - " psvirt2phys NATIVE [ 0, 1 ] (Windows) \n" \ + " pslist NATIVE \n" \ + " psvirt2phys NATIVE [ 0, 1 ] \n" \ " agent-execpy NATIVE [ in, out ] (Remote LeechAgent) \n" \ " System specific commands and valid MODEs [ and options ]: \n" \ " mac_fvrecover NATIVE (USB3380) \n" \ @@ -132,10 +132,10 @@ VOID Help_ShowGeneral() " ALTERNATIVELY \n" \ " kernel module to use, see list below for choices: \n" \ " WIN10_X64 \n" \ - " WIN10_X64_2 (Requires: FPGA & Windows) \n" \ - " WIN10_X64_3 (Requires: FPGA & Windows) \n" \ + " WIN10_X64_2 \n" \ + " WIN10_X64_3 \n" \ " LINUX_X64_46 (NB! Kernels 2.6.33 - 4.6) \n" \ - " LINUX_X64_48 (NB! Kernels 4.8+, FPGA only) \n" \ + " LINUX_X64_48 (NB! Kernels 4.8+) \n" \ " LINUX_X64_EFI (NB! UEFI booted systems only) \n" \ " FREEBSD_X64 \n" \ " MACOS \n" \ @@ -146,7 +146,7 @@ VOID Help_ShowGeneral() " -sig : available patches - including operating system unlock patches: \n"); ShowListFiles("*.sig", 13, 0, 4); printf( - " User-Mode implants: EXPERIMENTAL! (Requires: Windows) \n" \ + " User-Mode implants: EXPERIMENTAL! \n" \ " UMD_WINX64_IAT_PSEXEC \n" \ " Kernel-mode implants: \n"); ShowListFiles("*.ksh", 13, 0, 4); @@ -161,7 +161,7 @@ VOID Help_ShowInfo() " Version: " \ VER_FILE_VERSION_STR "\n" \ " \n" \ - " License: GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 \n" \ + " License: GNU Affero General Public License v3.0 \n" \ " Contact information: pcileech@frizk.net \n" \ " System requirements: 64-bit Windows 7, 10 or Linux. \n" \ " Other project references: \n" \ @@ -174,7 +174,7 @@ VOID Help_ShowInfo() " PCIe Injector - https://github.com/enjoy-digital/pcie_injector \n" \ " Dokany - https://github.com/dokan-dev/dokany/releases/latest \n" \ " ---------------- \n" \ - " MemProcFS is free open source software. If you find it useful please \n" \ + " PCILeech is free open source software. If you find it useful please \n" \ " become a sponsor at: https://github.com/sponsors/ufrisk Thank You :) \n" \ " ---------------- \n" \ " Use with memory dump files, DumpIt, WinPmem in read-only mode. \n" \ @@ -578,9 +578,8 @@ VOID Help_ShowDetailed() printf( " LIST PROCESSES OF THE TARGET SYSTEM \n" \ " MODES : NATIVE \n" \ - " REQUIRE : Windows \n" \ " OPTIONS : \n" \ - " List the process names and pids of the targeted system. \n" \ + " List the process names and pids of the targeted Windows system. \n" \ " EXAMPLEs: \n" \ " 1) List devices using 'fpga' or 'usb3380' hardware device. \n" \ " pcileech pslist \n" \ @@ -591,9 +590,8 @@ VOID Help_ShowDetailed() printf( " TRANSLATE A VIRTUAL MEMORY ADDRESS INTO PHYSICAL MEMORY ADDRESS FOR GIVEN PID \n" \ " MODES : NATIVE \n" \ - " REQUIRE : Windows \n" \ " OPTIONS : -0, -1 \n" \ - " Translate a process virtual address into a physical address \n" \ + " Translate a Windows process virtual address into a physical address \n" \ " EXAMPLEs: \n" \ " 1) Translate a virtual address of pid 638 into its physical address \n" \ " pcileech psvirt2phys -0 638 -1 0x7ffc8b41a000 \n"); @@ -602,7 +600,6 @@ VOID Help_ShowDetailed() printf( " EXECUTE A USER MODE SHELLCODE (EXPERIMENTAL) \n" \ " MODES : NATIVE \n" \ - " REQUIRE : Windows \n" \ " OPTIONS : -0, -1 -hook -s \n" \ " Hook a user mode application (currently supported method is hooking the import\n" \ " address table - IAT). If the hook is successful the shellcode will be executed\n" \ diff --git a/pcileech/kmd.c b/pcileech/kmd.c index f39c5c7..5fa9274 100644 --- a/pcileech/kmd.c +++ b/pcileech/kmd.c @@ -758,8 +758,6 @@ BOOL KMDOpen_UEFI(_In_ BYTE bOffsetHookBootServices) return KMD_SetupStage3((DWORD)qwAddrKMDDATA, pb + 0x1000, 0x1000); } -#ifdef WIN32 - /* * Load a kernel module (KMD) into a Windows 10 system on which not both of * Vt-d and Virtualization Based Security is enabled. This technique relies @@ -804,20 +802,20 @@ BOOL KMDOpen_WINX64_2_VMM() // hal.dll!HalBugCheckSystem (used for 'hook' to provide valid landing // site for PsCreateSystemThread -> no security bugchecks...) // ------------------------------------------------------------------------ - vaBaseKdCom = VMMDLL_ProcessGetModuleBase(4, L"kdcom.dll"); - vaBaseNtoskrnl = VMMDLL_ProcessGetModuleBase(4, L"ntoskrnl.exe"); - vaHalBugCheckSystem = VMMDLL_ProcessGetProcAddress(4, L"hal.dll", "HalBugCheckSystem"); + vaBaseKdCom = VMMDLL_ProcessGetModuleBaseU(4, "kdcom.dll"); + vaBaseNtoskrnl = VMMDLL_ProcessGetModuleBaseU(4, "ntoskrnl.exe"); + vaHalBugCheckSystem = VMMDLL_ProcessGetProcAddressU(4, "hal.dll", "HalBugCheckSystem"); if(!vaBaseKdCom || !vaBaseNtoskrnl || !vaHalBugCheckSystem) { printf("KMD: Failed vmm.dll!ProcessGetModuleBase (kdcom.dll/ntoskrnl.exe)\n"); goto fail; } - if(!VMMDLL_ProcessGetSections(4, L"kdcom.dll", NULL, 0, &cSections) || !cSections) { + if(!VMMDLL_ProcessGetSectionsU(4, "kdcom.dll", NULL, 0, &cSections) || !cSections) { printf("KMD: Failed vmm.dll!ProcessGetSections (kdcom.dll) #1\n"); goto fail; } pSections = LocalAlloc(LMEM_ZEROINIT, cSections * sizeof(IMAGE_SECTION_HEADER)); if(!pSections) { goto fail; } - if(!VMMDLL_ProcessGetSections(4, L"kdcom.dll", pSections, cSections, &cSections)) { + if(!VMMDLL_ProcessGetSectionsU(4, "kdcom.dll", pSections, cSections, &cSections)) { printf("KMD: Failed vmm.dll!ProcessGetSections (kdcom.dll) #2\n"); goto fail; } @@ -843,13 +841,13 @@ BOOL KMDOpen_WINX64_2_VMM() // i.e. function table in hal.dll heap. Result is address of function pointer to // place hook upon. // ------------------------------------------------------------------------ - if(!VMMDLL_Map_GetPte(4, NULL, &cbMemMap, FALSE) || !cbMemMap) { + if(!VMMDLL_Map_GetPteU(4, NULL, &cbMemMap, FALSE) || !cbMemMap) { printf("KMD: Failed vmm.dll!Map_GetPte #1.\n"); goto fail; } pMemMap = LocalAlloc(LMEM_ZEROINIT, cbMemMap); if(!pMemMap) { goto fail; } - if(!VMMDLL_Map_GetPte(4, pMemMap, &cbMemMap, FALSE)) { + if(!VMMDLL_Map_GetPteU(4, pMemMap, &cbMemMap, FALSE)) { printf("KMD: Failed vmm.dll!Map_GetPte #2.\n"); goto fail; } @@ -883,10 +881,10 @@ BOOL KMDOpen_WINX64_2_VMM() *(PQWORD)(pbExec + 0x18) = vaData + 0x10; // DEBUG data address *(PQWORD)(pbExec + 0x20) = vaData; // KMDDATA physical address *(PQWORD)(pbExec + 0x28) = vaBaseNtoskrnl; // NTOSKRNL.EXE virtual address - *(PQWORD)(pbExec + 0x30) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "MmAllocateContiguousMemory"); - *(PQWORD)(pbExec + 0x38) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "PsCreateSystemThread"); - *(PQWORD)(pbExec + 0x40) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "MmGetPhysicalAddress"); - *(PQWORD)(pbExec + 0x48) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "KeGetCurrentIrql"); + *(PQWORD)(pbExec + 0x30) = VMMDLL_ProcessGetProcAddressU(4, "ntoskrnl.exe", "MmAllocateContiguousMemory"); + *(PQWORD)(pbExec + 0x38) = VMMDLL_ProcessGetProcAddressU(4, "ntoskrnl.exe", "PsCreateSystemThread"); + *(PQWORD)(pbExec + 0x40) = VMMDLL_ProcessGetProcAddressU(4, "ntoskrnl.exe", "MmGetPhysicalAddress"); + *(PQWORD)(pbExec + 0x48) = VMMDLL_ProcessGetProcAddressU(4, "ntoskrnl.exe", "KeGetCurrentIrql"); *(PQWORD)(pbExec + 0x50) = vaHalBugCheckSystem; // ------------------------------------------------------------------------ // 6: hook and watch for execution & restore @@ -985,11 +983,11 @@ BOOL KMDOpen_WINX64_3_VMM() // data: (CI.dll '.data' section) // hook: (nt!PsGetCurrentProcessId) // ------------------------------------------------------------------------ - f = (vaCI = VMMDLL_ProcessGetModuleBase(4, L"CI.dll")) && - VMMDLL_ProcessGetSections(4, L"CI.dll", NULL, 0, &cSections) && + f = (vaCI = VMMDLL_ProcessGetModuleBaseU(4, "CI.dll")) && + VMMDLL_ProcessGetSectionsU(4, "CI.dll", NULL, 0, &cSections) && cSections && (pSections = LocalAlloc(LMEM_ZEROINIT, cSections * sizeof(IMAGE_SECTION_HEADER))) && - VMMDLL_ProcessGetSections(4, L"CI.dll", pSections, cSections, &cSections); + VMMDLL_ProcessGetSectionsU(4, "CI.dll", pSections, cSections, &cSections); for(i = 0; f && (i < cSections); i++) { if(!strcmp("INIT", pSections[i].Name)) { vaExec = vaCI + pSections[i].VirtualAddress + 0x400; @@ -1002,7 +1000,7 @@ BOOL KMDOpen_WINX64_3_VMM() printf("KMD: Failed get code cave (CI.dll) #2\n"); goto fail; } - f = (vaHook = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "PsGetCurrentProcessId")) && + f = (vaHook = VMMDLL_ProcessGetProcAddressU(4, "ntoskrnl.exe", "PsGetCurrentProcessId")) && VMMDLL_MemRead(4, vaHook, pbHookOriginalData, sizeof(pbHookOriginalData)); if(!f) { printf("KMD: Failed get hook (ntoskrnl.exe) #3\n"); @@ -1015,12 +1013,12 @@ BOOL KMDOpen_WINX64_3_VMM() // ------------------------------------------------------------------------ // 4: Prepare and Inject! // ------------------------------------------------------------------------ - f = (*(PQWORD)(pbShellcode + 0x020) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "KeGetCurrentIrql")) && - (*(PQWORD)(pbShellcode + 0x028) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "PsCreateSystemThread")) && - (*(PQWORD)(pbShellcode + 0x030) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "ZwClose")) && - (*(PQWORD)(pbShellcode + 0x038) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "MmAllocateContiguousMemory")) && - (*(PQWORD)(pbShellcode + 0x040) = VMMDLL_ProcessGetProcAddress(4, L"ntoskrnl.exe", "MmGetPhysicalAddress")) && - (*(PQWORD)(pbShellcode + 0x048) = VMMDLL_ProcessGetModuleBase(4, L"ntoskrnl.exe")); + f = (*(PQWORD)(pbShellcode + 0x020) = VMMDLL_ProcessGetProcAddressU(4, "ntoskrnl.exe", "KeGetCurrentIrql")) && + (*(PQWORD)(pbShellcode + 0x028) = VMMDLL_ProcessGetProcAddressU(4, "ntoskrnl.exe", "PsCreateSystemThread")) && + (*(PQWORD)(pbShellcode + 0x030) = VMMDLL_ProcessGetProcAddressU(4, "ntoskrnl.exe", "ZwClose")) && + (*(PQWORD)(pbShellcode + 0x038) = VMMDLL_ProcessGetProcAddressU(4, "ntoskrnl.exe", "MmAllocateContiguousMemory")) && + (*(PQWORD)(pbShellcode + 0x040) = VMMDLL_ProcessGetProcAddressU(4, "ntoskrnl.exe", "MmGetPhysicalAddress")) && + (*(PQWORD)(pbShellcode + 0x048) = VMMDLL_ProcessGetModuleBaseU(4, "ntoskrnl.exe")); if(!f) { printf("KMD: Failed get functions (ntoskrnl.exe) #5\n"); goto fail; @@ -1096,22 +1094,6 @@ BOOL KMDOpen_WINX64_3_VMM() return fResult; } -#endif /* WIN32 */ -#ifdef LINUX - -BOOL KMDOpen_WINX64_2_VMM() -{ - printf("KMD: Failed. Not supported on Linux.\n"); - return FALSE; -} -BOOL KMDOpen_WINX64_3_VMM() -{ - printf("KMD: Failed. Not supported on Linux.\n"); - return FALSE; -} - -#endif /* LINUX */ - // https://blog.coresecurity.com/2016/08/25/getting-physical-extreme-abuse-of-intel-based-paging-systems-part-3-windows-hals-heap/ // HAL is statically located at: ffffffffffd00000 (win8.1/win10 pre 1703) // HAL is randomized between: fffff78000000000:fffff7ffc0000000 (win10 1703) [512 possible positions in PDPT] diff --git a/pcileech/oscompatibility.h b/pcileech/oscompatibility.h index 5ce310a..f750364 100644 --- a/pcileech/oscompatibility.h +++ b/pcileech/oscompatibility.h @@ -45,20 +45,18 @@ VOID usleep(_In_ DWORD us); #include typedef void VOID, *PVOID; -typedef void *HANDLE, **PHANDLE; -typedef void *HMODULE, *FARPROC; +typedef void *HANDLE, **PHANDLE, *HMODULE, *FARPROC; typedef uint32_t BOOL, *PBOOL; typedef uint8_t BYTE, *PBYTE; typedef uint8_t UCHAR, *PUCHAR; typedef char CHAR, *PCHAR, *PSTR, *LPSTR; typedef uint16_t WORD, *PWORD, USHORT, *PUSHORT; -typedef wchar_t WCHAR, *PWCHAR, *LPWSTR; -typedef uint32_t DWORD, *PDWORD; -typedef uint32_t ULONG, *PULONG; +typedef uint16_t WCHAR, *PWCHAR, *LPWSTR, *LPCWSTR; +typedef uint32_t DWORD, *PDWORD, ULONG, *PULONG; typedef long long unsigned int QWORD, *PQWORD, ULONG64, *PULONG64; -typedef long long unsigned int LARGE_INTEGER, *PLARGE_INTEGER, FILETIME; +typedef uint64_t LARGE_INTEGER, *PLARGE_INTEGER, FILETIME; typedef uint64_t SIZE_T, *PSIZE_T; -typedef void *LPOVERLAPPED; +typedef void *OVERLAPPED, *LPOVERLAPPED; typedef struct tdEXCEPTION_RECORD32 { CHAR sz[80]; } EXCEPTION_RECORD32; typedef struct tdEXCEPTION_RECORD64 { CHAR sz[152]; } EXCEPTION_RECORD64; #define TRUE 1 @@ -79,6 +77,8 @@ typedef struct tdEXCEPTION_RECORD64 { CHAR sz[152]; } EXCEPTION_RECORD64 #define CRYPT_STRING_HEXASCIIADDR (0x00000008L) #define STILL_ACTIVE (0x00000103L) #define INVALID_FILE_SIZE (0xffffffffL) +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 #define _TRUNCATE ((SIZE_T)-1LL) #define LPTHREAD_START_ROUTINE PVOID #define WINUSB_INTERFACE_HANDLE libusb_device_handle* @@ -105,14 +105,17 @@ typedef struct tdEXCEPTION_RECORD64 { CHAR sz[152]; } EXCEPTION_RECORD64 #define _byteswap_ulong(v) (bswap_32(v)) #define _byteswap_uint64(v) (bswap_64(v)) #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) +#define sprintf_s(s, maxcount, ...) (snprintf(s, maxcount, __VA_ARGS__)) #define strnlen_s(s, maxcount) (strnlen(s, maxcount)) -#define strcat_s(dst, len, src) (strncat(dst, src, len-strlen(dst))) #define strcpy_s(dst, len, src) (strncpy(dst, src, len)) -#define strncpy_s(dst, len, src, srclen) (strncpy(dst, src, len)) +#define strncpy_s(dst, len, src, srclen) (strncpy(dst, src, min((QWORD)(max(1, len)) - 1, (QWORD)(srclen)))) +#define strncat_s(dst, dstlen, src, srclen) (strncat(dst, src, min((((strlen(dst) + 1 >= (QWORD)(dstlen)) || ((QWORD)(dstlen) == 0)) ? 0 : ((QWORD)(dstlen) - strlen(dst) - 1)), (QWORD)(srclen)))) +#define strcat_s(dst, dstlen, src) (strncat_s(dst, dstlen, src, _TRUNCATE)) +#define _vsnprintf_s(dst, len, cnt, fmt, a) (vsnprintf(dst, min((QWORD)(len), (QWORD)(cnt)), fmt, a)) #define _stricmp(s1, s2) (strcasecmp(s1, s2)) #define _strnicmp(s1, s2, maxcount) (strncasecmp(s1, s2, maxcount)) #define strtok_s(s, d, c) (strtok_r(s, d, c)) -#define _snprintf_s(s, l, _l, f, ...) (snprintf(s, l, f, __VA_ARGS__)) +#define _snprintf_s(s,l,c,...) (snprintf(s,min((QWORD)(l), (QWORD)(c)),__VA_ARGS__)) #define sscanf_s(s, f, ...) (sscanf(s, f, __VA_ARGS__)) #define SwitchToThread() (sched_yield()) #define ExitThread(dwExitCode) (pthread_exit(dwExitCode)) diff --git a/pcileech/umd.c b/pcileech/umd.c index 769b51a..eb82fcd 100644 --- a/pcileech/umd.c +++ b/pcileech/umd.c @@ -6,7 +6,6 @@ // #include "umd.h" #include -#ifdef WIN32 #include "executor.h" #include "util.h" #include @@ -42,7 +41,7 @@ VOID Action_UmdPsList() pProcInfo->magic = VMMDLL_PROCESS_INFORMATION_MAGIC; pProcInfo->wVersion = VMMDLL_PROCESS_INFORMATION_VERSION; cbProcInfo = sizeof(VMMDLL_PROCESS_INFORMATION); - if(VMMDLL_ProcessGetInformation(pdwPIDs[i], pProcInfo, &cbProcInfo)) { + if(VMMDLL_ProcessGetInformation(pdwPIDs[i], pProcInfo, (PSIZE_T)&cbProcInfo)) { printf(" %6i %s %s\n", pProcInfo->dwPID, pProcInfo->win.fWow64 ? "32" : " ", pProcInfo->szName); } } @@ -70,7 +69,7 @@ VOID Action_UmdPsVirt2Phys() oProcInfo.magic = VMMDLL_PROCESS_INFORMATION_MAGIC; oProcInfo.wVersion = VMMDLL_PROCESS_INFORMATION_VERSION; cbProcInfo = sizeof(VMMDLL_PROCESS_INFORMATION); - if(!VMMDLL_ProcessGetInformation((DWORD)ctxMain->cfg.qwDataIn[0], &oProcInfo, &cbProcInfo)) { + if(!VMMDLL_ProcessGetInformation((DWORD)ctxMain->cfg.qwDataIn[0], &oProcInfo, (PSIZE_T)&cbProcInfo)) { printf("UMD: Failed retrieving information for PID: %lli\n", ctxMain->cfg.qwDataIn[0]); printf(" SYNTAX: pcileech psvirt2phys -0 -1 \n"); goto fail; @@ -127,7 +126,7 @@ typedef struct tdUMD_EXEC_CONTEXT_LIMITED { VOID UmdWinExec() { BOOL result; - WCHAR wszModuleName[16]; + LPSTR szModuleName; DWORD cbExec = 0; BYTE pbExec[0x500], pbPage[0x1000] = { 0 }; DWORD i, dwPID, cSections; @@ -164,10 +163,8 @@ VOID UmdWinExec() printf("UMD: EXEC: Could not retrieve process for PID: %i\n", dwPID); return; } - for(i = 0; i < 16; i++) { - wszModuleName[i] = oProcessInformation.szName[i]; - } - result = VMMDLL_WinGetThunkInfoIAT(dwPID, wszModuleName, szHookModule, szHookFunction, &oThunkInfoIAT); + szModuleName = oProcessInformation.szName; + result = VMMDLL_WinGetThunkInfoIATU(dwPID, szModuleName, szHookModule, szHookFunction, &oThunkInfoIAT); if(!result) { printf("UMD: EXEC: Could not retrieve hook for %s!%s in '%s'\n", szHookModule, szHookFunction, oProcessInformation.szName); return; @@ -176,24 +173,24 @@ VOID UmdWinExec() printf("UMD: EXEC: Could not retrieve valid hook in 64-bit process.\n"); return; } - if(!VMMDLL_ProcessGetSections(dwPID, wszModuleName, NULL, 0, &cSections) || !cSections) { - printf("UMD: EXEC: Could not retrieve sections #1 for '%S'\n", wszModuleName); + if(!VMMDLL_ProcessGetSectionsU(dwPID, szModuleName, NULL, 0, &cSections) || !cSections) { + printf("UMD: EXEC: Could not retrieve sections #1 for '%s'\n", szModuleName); return; } pSections = (PIMAGE_SECTION_HEADER)LocalAlloc(LMEM_ZEROINIT, cSections * sizeof(IMAGE_SECTION_HEADER)); - if(!pSections || !VMMDLL_ProcessGetSections(dwPID, wszModuleName, pSections, cSections, &cSections) || !cSections) { - printf("UMD: EXEC: Could not retrieve sections #2 for '%S'\n", wszModuleName); + if(!pSections || !VMMDLL_ProcessGetSectionsU(dwPID, szModuleName, pSections, cSections, &cSections) || !cSections) { + printf("UMD: EXEC: Could not retrieve sections #2 for '%s'\n", szModuleName); return; } for(i = 0; i < cSections; i++) { if(!vaCodeCave && (pSections[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && ((pSections[i].Misc.VirtualSize & 0xfff) < (0x1000 - sizeof(pbExec)))) { - vaCodeCave = VMMDLL_ProcessGetModuleBase(dwPID, wszModuleName) + ((pSections[i].VirtualAddress + pSections[i].Misc.VirtualSize + 0xfff) & ~0xfff) - sizeof(pbExec); + vaCodeCave = VMMDLL_ProcessGetModuleBaseU(dwPID, szModuleName) + ((pSections[i].VirtualAddress + pSections[i].Misc.VirtualSize + 0xfff) & ~0xfff) - sizeof(pbExec); if(!VMMDLL_MemReadPage(dwPID, vaCodeCave & ~0xfff, pbPage)) { vaCodeCave = 0; // read test failed! } } if(!vaWriteCave && (pSections[i].Characteristics & IMAGE_SCN_MEM_WRITE) && ((pSections[i].Misc.VirtualSize & 0xfff) < (0x1000 - sizeof(ctx)))) { - vaWriteCave += VMMDLL_ProcessGetModuleBase(dwPID, wszModuleName) + ((pSections[i].VirtualAddress + pSections[i].Misc.VirtualSize + 0xfff) & ~0xfff) - sizeof(ctx); + vaWriteCave += VMMDLL_ProcessGetModuleBaseU(dwPID, szModuleName) + ((pSections[i].VirtualAddress + pSections[i].Misc.VirtualSize + 0xfff) & ~0xfff) - sizeof(ctx); if(!VMMDLL_MemReadPage(dwPID, vaWriteCave & ~0xfff, pbPage)) { vaWriteCave = 0; // read test failed! } @@ -201,10 +198,10 @@ VOID UmdWinExec() } if(!vaCodeCave || !vaWriteCave) { if(!vaCodeCave) { - printf("UMD: EXEC: Could not locate suitable code cave in '%S'\n", wszModuleName); + printf("UMD: EXEC: Could not locate suitable code cave in '%s'\n", szModuleName); } if(!vaWriteCave) { - printf("UMD: EXEC: Could not locate suitable write cave in '%S'\n", wszModuleName); + printf("UMD: EXEC: Could not locate suitable write cave in '%s'\n", szModuleName); } return; } @@ -217,22 +214,22 @@ VOID UmdWinExec() *(PQWORD)(pbExec + 0x10) = oThunkInfoIAT.vaFunction; // prepare configuration data (goes into rw- section) ctx.qwDEBUG = 0; - ctx.fn.CloseHandle = VMMDLL_ProcessGetProcAddress(dwPID, L"kernel32.dll", "CloseHandle"); - ctx.fn.CreatePipe = VMMDLL_ProcessGetProcAddress(dwPID, L"kernel32.dll", "CreatePipe"); - ctx.fn.CreateProcessA = VMMDLL_ProcessGetProcAddress(dwPID, L"kernel32.dll", "CreateProcessA"); - ctx.fn.CreateThread = VMMDLL_ProcessGetProcAddress(dwPID, L"kernel32.dll", "CreateThread"); - ctx.fn.GetExitCodeProcess = VMMDLL_ProcessGetProcAddress(dwPID, L"kernel32.dll", "GetExitCodeProcess"); - ctx.fn.LocalAlloc = VMMDLL_ProcessGetProcAddress(dwPID, L"kernel32.dll", "LocalAlloc"); - ctx.fn.ReadFile = VMMDLL_ProcessGetProcAddress(dwPID, L"kernel32.dll", "ReadFile"); - ctx.fn.Sleep = VMMDLL_ProcessGetProcAddress(dwPID, L"kernel32.dll", "Sleep"); - ctx.fn.WriteFile = VMMDLL_ProcessGetProcAddress(dwPID, L"kernel32.dll", "WriteFile"); + ctx.fn.CloseHandle = VMMDLL_ProcessGetProcAddressU(dwPID, "kernel32.dll", "CloseHandle"); + ctx.fn.CreatePipe = VMMDLL_ProcessGetProcAddressU(dwPID, "kernel32.dll", "CreatePipe"); + ctx.fn.CreateProcessA = VMMDLL_ProcessGetProcAddressU(dwPID, "kernel32.dll", "CreateProcessA"); + ctx.fn.CreateThread = VMMDLL_ProcessGetProcAddressU(dwPID, "kernel32.dll", "CreateThread"); + ctx.fn.GetExitCodeProcess = VMMDLL_ProcessGetProcAddressU(dwPID, "kernel32.dll", "GetExitCodeProcess"); + ctx.fn.LocalAlloc = VMMDLL_ProcessGetProcAddressU(dwPID, "kernel32.dll", "LocalAlloc"); + ctx.fn.ReadFile = VMMDLL_ProcessGetProcAddressU(dwPID, "kernel32.dll", "ReadFile"); + ctx.fn.Sleep = VMMDLL_ProcessGetProcAddressU(dwPID, "kernel32.dll", "Sleep"); + ctx.fn.WriteFile = VMMDLL_ProcessGetProcAddressU(dwPID, "kernel32.dll", "WriteFile"); strcpy_s(ctx.szProcToStart, MAX_PATH - 1, ctxMain->cfg.szInS); ctx.dwFlagsCreateProcessA = (DWORD)ctxMain->cfg.qwDataIn[1]; ctx.fEnableConsoleRedirect = ctxMain->cfg.qwDataIn[2] ? 1 : 0; //------------------------------------------------ // 4: Inject & Hook //------------------------------------------------ - printf("UMD: EXEC: Injecting code and configuration data into process %S\n", wszModuleName); + printf("UMD: EXEC: Injecting code and configuration data into process %s\n", szModuleName); printf(" IAT Hook : %s!%s at 0x%llx [0x%llx]\n", szHookModule, szHookFunction, oThunkInfoIAT.vaThunk, oThunkInfoIAT.vaFunction); VMMDLL_MemWrite(dwPID, vaWriteCave, (PBYTE)&ctx, sizeof(UMD_EXEC_CONTEXT_LIMITED)); VMMDLL_MemWrite(dwPID, vaCodeCave, pbExec, sizeof(pbExec)); @@ -285,23 +282,3 @@ VOID ActionExecUserMode() } Vmmx_Close(); } - -#endif /* WIN32 */ -#ifdef LINUX - -VOID Action_UmdPsList() -{ - printf("UMD: Not supported on Linux - require: Windows-only MemProcFS/vmm.dll\n"); -} - -VOID Action_UmdPsVirt2Phys() -{ - printf("UMD: Not supported on Linux - require: Windows-only MemProcFS/vmm.dll\n"); -} - -VOID ActionExecUserMode() -{ - printf("UMD: Not supported on Linux - require: Windows-only MemProcFS/vmm.dll\n"); -} - -#endif /* LINUX */ diff --git a/pcileech/version.h b/pcileech/version.h index b3a92c4..989065a 100644 --- a/pcileech/version.h +++ b/pcileech/version.h @@ -2,9 +2,9 @@ #define STRINGIZE(s) STRINGIZE2(s) #define VERSION_MAJOR 4 -#define VERSION_MINOR 9 +#define VERSION_MINOR 10 #define VERSION_REVISION 0 -#define VERSION_BUILD 23 +#define VERSION_BUILD 24 #define VER_FILE_DESCRIPTION_STR "The PCILeech Direct Memory Access Attack Toolkit" #define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD diff --git a/pcileech/vmmx.c b/pcileech/vmmx.c index 7d9a298..a0d853b 100644 --- a/pcileech/vmmx.c +++ b/pcileech/vmmx.c @@ -1,10 +1,8 @@ -// vmmx.h : implementation of external VMM/MemProcFS functionality with linux compatible dummy functions. +// vmmx.h : implementation of external memory process file system functionality. // // (c) Ulf Frisk, 2020-2021 // Author: Ulf Frisk, pcileech@frizk.net // -#ifdef WIN32 - #include #include #include "vmmx.h" @@ -49,17 +47,3 @@ BOOL Vmmx_Initialize(_In_ BOOL fRefresh, _In_ BOOL fMemMapAuto) } return ctxMain->fVmmInitialized; } - -#endif /* WIN32 */ -#ifdef LINUX - -#include "vmmx.h" - -#define VMMDLL_FLAG_NOCACHE 0x0001 - -BOOL Vmmx_Initialize(_In_ BOOL fRefresh, _In_ BOOL fMemMapAuto) { return FALSE; } -VOID Vmmx_Close() { return; } -BOOL Vmmx_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags) { return FALSE; } -BOOL Vmmx_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb) { return FALSE; } - -#endif /* LINUX */ diff --git a/pcileech/vmmx.h b/pcileech/vmmx.h index 9a5f507..4b09449 100644 --- a/pcileech/vmmx.h +++ b/pcileech/vmmx.h @@ -1,14 +1,13 @@ -// vmmx.h : definitions related to memory process file system functionality. +// vmmx.h : definitions related to external memory process file system functionality. // // (c) Ulf Frisk, 2020-2021 // Author: Ulf Frisk, pcileech@frizk.net // #ifndef __VMMX_H__ #define __VMMX_H__ -#include "pcileech.h" - -#ifdef WIN32 #include +#include "pcileech.h" +#include "oscompatibility.h" /* * Load the memory process file system mode using the default LeechCore device. @@ -27,37 +26,4 @@ BOOL Vmmx_Initialize(_In_ BOOL fRefresh, _In_ BOOL fMemMapAuto); */ VOID Vmmx_Close(); - - -//------------------------------------------------------------------------------- -// Functions below are wrapper functions around VMM.DLL functions and -// exists primarily for Linux compatibility reasons (dummy functions). -//------------------------------------------------------------------------------- - -_Success_(return) -inline BOOL Vmmx_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags) -{ - return VMMDLL_MemReadEx(dwPID, qwVA, pb, cb, pcbReadOpt, flags); -} - -_Success_(return) -inline BOOL Vmmx_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwA, _In_reads_(cb) PBYTE pb, _In_ DWORD cb) -{ - return VMMDLL_MemWrite(dwPID, qwA, pb, cb); -} - -#endif /* WIN32 */ -#ifdef LINUX - -#include "pcileech.h" -#include "oscompatibility.h" -#define VMMDLL_FLAG_NOCACHE 0x0001 - -BOOL Vmmx_Initialize(_In_ BOOL fRefresh, _In_ BOOL fMemMapAuto); -VOID Vmmx_Close(); -BOOL Vmmx_MemReadEx(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _Out_ PBYTE pb, _In_ DWORD cb, _Out_opt_ PDWORD pcbReadOpt, _In_ ULONG64 flags); -BOOL Vmmx_MemWrite(_In_ DWORD dwPID, _In_ ULONG64 qwVA, _In_ PBYTE pb, _In_ DWORD cb); -BOOL Vmmx_PhysMemMapAsText(_Out_writes_bytes_(0x01000000) LPSTR sz); - -#endif /* LINUX */ #endif /* __VMMX_H__ */ diff --git a/pcileech_gensig/pcileech_gensig.c b/pcileech_gensig/pcileech_gensig.c deleted file mode 100644 index 7ce3e91..0000000 --- a/pcileech_gensig/pcileech_gensig.c +++ /dev/null @@ -1,251 +0,0 @@ -// pcileech_gensig.c : kernel module signature generator for PCILeech -// -// PCILeech require code pages from the ntfs.sys kernel driver to hi-jack the -// execution flow in Windows 10. To avoid copyright infringement the end user -// must create the kmd signature files together with supported ntfs.sys files -// -// (c) Ulf Frisk, 2016, 2017 -// Author: Ulf Frisk, pcileech@frizk.net -// Github: github.com/ufrisk/pcileech -// -#include -#include -#include - -#pragma comment (lib, "crypt32.lib") -#pragma comment (lib, "bcrypt.lib") - -typedef struct tdSIGNATURE{ - DWORD dwOffset1; - DWORD dwOffset2; - LPSTR szHash1; - LPSTR szHash2; - LPSTR szFileName; - LPSTR szSignatureInfoDisplay; - LPSTR szSignatureInfo; - LPSTR szSignatureData; -} SIGNATURE, *PSIGNATURE; - -#define MAX_SIGNATURES 64 - -VOID Util_GetFileInDirectory(_Out_ CHAR szPath[MAX_PATH], _In_ LPSTR szFileName) -{ - SIZE_T i, cchFileName = strlen(szFileName); - GetModuleFileNameA(NULL, (LPSTR)szPath, (DWORD)(MAX_PATH - cchFileName - 4)); - for(i = strlen(szPath) - 1; i > 0; i--) { - if(szPath[i] == '/' || szPath[i] == '\\') { - strcpy_s(&szPath[i + 1], MAX_PATH - i - 5, szFileName); - return; - } - } -} - -_Success_(return) BOOL Util_ParseSignatureLine(_In_ PSTR szLine, _In_ PSIGNATURE pSignature) { - LPSTR szToken, szContext = NULL; - SIZE_T i; - if(!szLine || !strlen(szLine) || szLine[0] == '#') { return FALSE; } - szToken = strtok_s(szLine, ";", &szContext); - for(i = 0; i < 8; i++) { - if(!szToken) { return FALSE; } - switch(i) { - case 0: - pSignature->szSignatureInfoDisplay = szToken; - break; - case 1: - pSignature->szFileName = szToken; - break; - case 2: - pSignature->szSignatureInfo = szToken; - break; - case 3: - pSignature->dwOffset1 = strtoul(szToken, NULL, 16); - break; - case 4: - pSignature->dwOffset2 = strtoul(szToken, NULL, 16); - break; - case 5: - pSignature->szHash1 = szToken; - break; - case 6: - pSignature->szHash2 = szToken; - break; - case 7: - pSignature->szSignatureData = szToken; - break; - } - szToken = strtok_s(NULL, ";", &szContext); - } - return (i == 8); -} - -VOID GetSignaturesFromConfigFile(_Out_ PSIGNATURE pSignatures, _Out_ PDWORD pcSignatures) -{ - PBYTE pbFile; - DWORD cbFile; - FILE *pFile; - CHAR szFile[MAX_PATH]; - LPSTR szContext = NULL, szLine; - *pcSignatures = 0; - // 1: Open configuration file containing signatures - pbFile = LocalAlloc(LMEM_ZEROINIT, 0x00100000); - if(!pbFile) { return; } - Util_GetFileInDirectory(szFile, "pcileech_gensig.cfg"); - if(fopen_s(&pFile, szFile, "rb") || !pFile) { goto error; } - cbFile = (DWORD)fread(pbFile, 1, 0x00100000, pFile); - fclose(pFile); - if(!cbFile || (cbFile == 0x00100000)) { goto error; } - // 2: Parse signature file on a per-line level - szLine = strtok_s(pbFile, "\r\n", &szContext); - while(szLine && (*pcSignatures < MAX_SIGNATURES)) { - if(Util_ParseSignatureLine(szLine, &pSignatures[*pcSignatures])) { - *pcSignatures = *pcSignatures + 1; - } - szLine = strtok_s(NULL, "\r\n", &szContext); - } -error: - ; - //LocalFree(pbFile); // buffer is leaked (is used by the tokenized fragments) -} - -const LPSTR SIGNATURE_FILE_HEADER = \ -"# PCILeech kernel module signature \r\n" \ -"# syntax(exactly one signature is only allowed) : \r\n" \ -"# \r\n" \ -"# chunk[0] = , \r\n" \ -"# chunk[1] = , \r\n" \ -"# chunk[2] = , \r\n" \ -"# chunk[3] = , \r\n" \ -"# chunk[4] = , \r\n" \ -"# chunk[5] = , \r\n" \ -"# *) shellcode can be given as hexascii, internal reference or file name. \r\n" \ -"# \r\n"; - -VOID Util_SHA256(_In_ PBYTE pb, _In_ DWORD cb, _Out_ __bcount(32) PBYTE pbHash) -{ - BCRYPT_ALG_HANDLE hAlg = NULL; - BCRYPT_HASH_HANDLE hHash = NULL; - BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA256_ALGORITHM, NULL, 0); - BCryptCreateHash(hAlg, &hHash, NULL, 0, NULL, 0, 0); - BCryptHashData(hHash, pb, cb, 0); - BCryptFinishHash(hHash, pbHash, 32, 0); - BCryptDestroyHash(hHash); - BCryptCloseAlgorithmProvider(hAlg, 0); -} - -_Success_(return) BOOL Util_SHA256CMP(_In_ __bcount(4096) PBYTE pb, _In_ LPSTR szHash) -{ - BYTE pbHash1[32], pbHash2[32]; - DWORD cb = 32; - Util_SHA256(pb, 4096, pbHash1); - CryptStringToBinaryA(szHash, 0, CRYPT_STRING_HEXRAW, pbHash2, &cb, NULL, NULL); - return 0 == memcmp(pbHash1, pbHash2, 32); -} - -DWORD PEGetImageSize(_In_ HMODULE hModule) -{ - PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule; - if(!dosHeader || dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return 0; } - PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)hModule + dosHeader->e_lfanew); - if(!ntHeader || ntHeader->Signature != IMAGE_NT_SIGNATURE) { return 0; } - return ntHeader->OptionalHeader.SizeOfImage; -} - -_Success_(return) BOOL WriteSignatureFile(_In_ PSIGNATURE pSignature, _In_ __bcount(4096) PBYTE pb1, _In_ __bcount(4096) PBYTE pb2) -{ - DWORD cbWritten, csz1 = 0x2001, csz2 = 0x2001; - HANDLE hFile; - BOOL result; - CHAR sz[0x2001]; - hFile = CreateFileA( - pSignature->szFileName, - GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - CREATE_NEW, - FILE_ATTRIBUTE_NORMAL, - NULL); - if(!hFile) { return FALSE; } - HRESULT hr = GetLastError(); - result = - WriteFile(hFile, SIGNATURE_FILE_HEADER, (DWORD)strlen(SIGNATURE_FILE_HEADER), &cbWritten, NULL) && - WriteFile(hFile, pSignature->szSignatureInfo, (DWORD)strlen(pSignature->szSignatureInfo), &cbWritten, NULL) && - WriteFile(hFile, "\r\n0,", 4, &cbWritten, NULL) && - CryptBinaryToStringA(pb1, 4096, CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, sz, &csz1) && - WriteFile(hFile, sz, 8192, &cbWritten, NULL) && - WriteFile(hFile, ",0,", 3, &cbWritten, NULL) && - CryptBinaryToStringA(pb2, 4096, CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, sz, &csz2) && - WriteFile(hFile, sz, 8192, &cbWritten, NULL) && - WriteFile(hFile, pSignature->szSignatureData, (DWORD)strlen(pSignature->szSignatureData), &cbWritten, NULL); - CloseHandle(hFile); - return result; -} - -VOID ShowInfo(_In_ PSIGNATURE pS, _In_ DWORD cS) -{ - printf( - "The PCILeech signature generator - generate Windows kernel module signatures \n" \ - "===============================================================================\n" \ - "Syntax: pcileech_gensig \n" \ - " \n" \ - "Some Windows kernel module signatures must be generated since they contain 8192\n" \ - "bytes of microsoft copyrighted code. In order to avoid copyright issues one has\n" \ - "to generate the signatures by themselves. Please start pcileech_gensig with the\n" \ - "path to the ntfs.sys file to generate the signature for. The ntfs.sys file is\n" \ - "generally found at c:\\Windows\\System32\\drivers\\ntfs.sys. In order to generate a\n" \ - "a signature please run: 'pcileech_gensig.exe c:\\path_to_ntfs_sys\\ntfs.sys' and\n" \ - "a .kmd signature file will be created on success. \n" \ - "Supported ntfs.sys file versions: \n" \ - "================================= \n"); - for(DWORD i = 0; i < cS; i++) { - printf("%s\n", pS[i].szSignatureInfoDisplay); - } - printf("\n"); -} - -int main(_In_ int argc, _In_ char* argv[]) -{ - BOOL result; - SIGNATURE pS[MAX_SIGNATURES]; - HMODULE hModule; - DWORD i, dwSizeMax, cS; - GetSignaturesFromConfigFile(pS, &cS); - if(!cS) { - printf("pcileech_gensig: failed! cannot load signatures from configuration file: pcileech_gensig.cfg\n\n"); - return 1; - } - if(argc != 2) { - ShowInfo(pS, cS); - return 1; - } - hModule = LoadLibraryA(argv[1]); - if(!hModule) { - printf("pcileech_gensig: failed! cannot load the file: %s\n\n", argv[1]); - return 1; - } - dwSizeMax = PEGetImageSize(hModule); - if(!dwSizeMax) { - printf("pcileech_gensig: failed! cannot interpret the file: %s\n\n", argv[1]); - return 1; - } - for(i = 0; i < cS; i++) { - if(pS[i].dwOffset1 > dwSizeMax || pS[i].dwOffset2 > dwSizeMax) { - continue; - } - if(!Util_SHA256CMP((PBYTE)hModule + pS[i].dwOffset1, pS[i].szHash1)) { - continue; - } - if(!Util_SHA256CMP((PBYTE)hModule + pS[i].dwOffset2, pS[i].szHash2)) { - continue; - } - result = WriteSignatureFile(&pS[i], (PBYTE)hModule + pS[i].dwOffset1, (PBYTE)hModule + pS[i].dwOffset2); - if(result) { - printf("pcileech_gensig: successfully wrote signatute to file: %s\n\n", pS[i].szFileName); - return 0; - } else { - printf("pcileech_gensig: failed! failed writing to file: %s\n\n", pS[i].szFileName); - return 1; - } - } - printf("pcileech_gensig: failed! no signature matches file: %s\n\n", argv[1]); - return 1; -} diff --git a/pcileech_gensig/pcileech_gensig.vcxproj b/pcileech_gensig/pcileech_gensig.vcxproj deleted file mode 100644 index 8f851e3..0000000 --- a/pcileech_gensig/pcileech_gensig.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - x64 - - - ReleaseMT - x64 - - - Release - x64 - - - - {C55314C6-71A0-4AE2-A4F0-E5E531A5E065} - pcileech_gensig - 10.0 - - - - Application - true - v142 - Unicode - - - false - - - Application - false - v142 - false - Unicode - false - - - Application - false - v142 - false - Unicode - false - - - - - - - - - - - - - - - - - - $(SolutionDir)\files\ - $(SolutionDir)\files\temp\$(ProjectName)\ - - - $(SolutionDir)\files\ - $(SolutionDir)\files\temp\$(ProjectName)\ - - - $(SolutionDir)\files\ - $(SolutionDir)\files\temp\$(ProjectName)\ - false - - - - Level3 - Disabled - true - - - Debug - - - - - Level3 - MaxSpeed - true - true - true - ProgramDatabase - - - true - true - No - - - - - Level3 - MaxSpeed - true - true - true - ProgramDatabase - MultiThreaded - - - true - true - No - - - - - - - - - \ No newline at end of file diff --git a/pcileech_gensig/pcileech_gensig.vcxproj.filters b/pcileech_gensig/pcileech_gensig.vcxproj.filters deleted file mode 100644 index 5f7f0b4..0000000 --- a/pcileech_gensig/pcileech_gensig.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/pcileech_gensig/pcileech_gensig.vcxproj.user b/pcileech_gensig/pcileech_gensig.vcxproj.user deleted file mode 100644 index abe8dd8..0000000 --- a/pcileech_gensig/pcileech_gensig.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/readme.md b/readme.md index 1456095..0bd8bd6 100644 --- a/readme.md +++ b/readme.md @@ -6,7 +6,7 @@ PCILeech uses PCIe hardware devices to read and write target system memory. This PCILeech supports multiple memory acquisition devices. Both hardware and software based. USB3380 based hardware is only able to read 4GB of memory natively, but is able to read all memory if a kernel module (KMD) is first inserted into the target system kernel. FPGA based hardware, and software based methods, are able to read all memory. -PCILeech is capable of inserting a wide range of kernel implants into the targeted kernels - allowing for easy access to live ram and the file system via a "mounted drive". It is also possible to remove the logon password requirement, loading unsigned drivers, executing code and spawn system shells. PCIleech runs on Windows and Linux. Supported target systems are currently the x64 versions of: UEFI, Linux, FreeBSD, macOS and Windows. This requires write access to memory (USB3380 hardware, FPGA hardware or CVE-2018-1038 "Total Meltdown"). +PCILeech is capable of inserting a wide range of kernel implants into the targeted kernels - allowing for easy access to live ram and the file system via a "mounted drive". It is also possible to remove the logon password requirement, loading unsigned drivers, executing code and spawn system shells. PCIleech runs on Windows and Linux. Supported target systems are currently the x64 versions of: UEFI, Linux, FreeBSD and Windows. This requires write access to memory (USB3380 hardware, FPGA hardware, LiveCloudKd or CVE-2018-1038 "Total Meltdown"). To get going clone the sources in the repository or download the latest [binaries, modules and configuration files](https://github.com/ufrisk/pcileech/releases/latest). @@ -139,27 +139,17 @@ Dump memory using the the reported "TotalMeltdown" [Windows 7/2008R2 x64 PML4 pa Insert a kernel module into a running Linux system remotely via a [DMA patched HP iLO](https://www.synacktiv.com/posts/exploit/using-your-bmc-as-a-dma-device-plugging-pcileech-to-hpe-ilo-4.html). * ` pcileech.exe kmdload -vvv -device -device RawTCP://127.0.0.1:8888 -kmd LINUX_X64_48 ` -Generating Signatures: -====================== -PCILeech comes with built in signatures for Windows, Linux, FreeBSD and macOS. There is also an optional, now obsoleted method of generating signatures by using the pcileech_gensig.exe program. - Limitations/Known Issues: ========================= -* Read and write errors on some hardware with the USB3380. Try `pcileech.exe testmemreadwrite -min 0x1000` to test memory reads and writes against the physical address 0x1000 (or any other address) in order to confirm. If issues exists downgrading to USB2 may help. * Does not work if the OS uses the IOMMU/VT-d. This is the default on macOS (unless disabled in recovery mode). Windows 10 with Virtualization based security features enabled does not work fully - this is however not the default setting in Windows 10 or Linux. * Some Linux kernels does not work. Sometimes a required symbol is not exported in the kernel and PCILeech fails. -* Linux based on the 4.8 kernel and later might not work with the USB3380 hardware. -* File system mount support only exists for Windows. +* File system mount support only exists for Windows (Linux version is planned). * Remote connectivity support only exists for Windows. Building: ========= The binaries are found in the [releases section](https://github.com/ufrisk/pcileech/releases/latest) of this repository. If one wish to build an own version it is possible to do so. Please see the [PCILeech on Windows](https://github.com/ufrisk/pcileech/wiki/PCILeech-on-Windows) or [PCILeech on Linux](https://github.com/ufrisk/pcileech/wiki/PCILeech-on-Linux) for more information about building PCILeech. PCILeech is also dependant on LeechCore and optionally (for some extra functionality) on The Memory Process File System which must both be built separately. -License: -====== -The project source code is released under GPLv3. Some bundled Microsoft redistributable binaries are released under separate licenses. - Contributing: ============= PCILeech, MemProcFS and LeechCore are open source but not open contribution. PCILeech, MemProcFS and LeechCore offers a highly flexible plugin architecture that will allow for contributions in the form of plugins. If you wish to make a contribution, other than a plugin, to the core projects please contact me before starting to develop. @@ -178,11 +168,13 @@ Links: Support PCILeech/MemProcFS development: ======================================= -PCILeech and MemProcFS are hobby projects of mine. I put a lot of time and energy into my projects. The time being most of my spare time. Since some aspects also relate to hardware I also put quite some of money into my projects. If you think PCILeech and/or MemProcFS are awesome tools and/or if you had a use for them it's now possible to contribute. It's possible to sponsor via Github Sponsors. +PCILeech and MemProcFS is free and open source! - - Github Sponsors: [`https://github.com/sponsors/ufrisk`](https://github.com/sponsors/ufrisk) +I put a lot of time and energy into PCILeech and MemProcFS and related research to make this happen. Some aspects of the projects relate to hardware and I put quite some money into my projects and related research. If you think PCILeech and/or MemProcFS are awesome tools and/or if you had a use for them it's now possible to contribute by becoming a sponsor! -To all my sponsors, Thank You :sparkling_heart: +If you like what I've created with PCIleech and MemProcFS with regards to DMA, Memory Analysis and Memory Forensics and would like to give something back to support future development please consider becoming a sponsor at: [`https://github.com/sponsors/ufrisk`](https://github.com/sponsors/ufrisk) + +To all my sponsors, Thank You 💖 All sponsorships are welcome, no matter how large or small. I especially wish to thank my **bronze sponsors**: [grandprixgp](https://github.com/grandprixgp). @@ -241,10 +233,15 @@ v4.1 [v4.8](https://github.com/ufrisk/pcileech/releases/tag/v4.8) * Bug fixes. * Better support for recent x64 Linux kernels. - [v4.9](https://github.com/ufrisk/pcileech/releases/tag/v4.9) * Bug fixes. * Signature updates. * Better support for recent x64 Linux kernels (Ubuntu 21.04). * Unmount of monted driver when CTRL+C pressed. + + +[v4.10](https://github.com/ufrisk/pcileech/releases/tag/v4.10) +* Linux support for Windows 10 built-in signatures (dependency on MemProcFS v4.0). +* Separate releases for Windows and Linux. +* General cleanup.