From 95f332cacda930e3767a186876098a69fca3bce0 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Sun, 12 Apr 2026 13:13:31 +0200 Subject: [PATCH] Vendor distorm and scylla_wrapper --- .gitmodules | 3 - TitanEngine.sln | 34 +- TitanEngine/TitanEngine.Debugger.cpp | 12 +- TitanEngine/TitanEngine.cbp | 158 - TitanEngine/TitanEngine.vcproj | 521 - TitanEngine/TitanEngine.vcxproj | 50 +- TitanEngine/TitanEngine.vcxproj.filters | 3 - TitanEngine/aplib.h | 4 +- TitanEngine/aplib_x64.lib | Bin 11928 -> 0 bytes TitanEngine/aplib_x86.lib | Bin 10552 -> 0 bytes TitanEngine/ntdll.h | 2587 ++- TitanEngine/scylla_wrapper.h | 6 - distorm/COPYING | 26 + distorm/distorm.vcxproj | 157 + distorm/distorm.vcxproj.filters | 30 + {TitanEngine => distorm/include}/distorm.h | 166 +- distorm/include/mnemonics.h | 305 + distorm/src/distorm.c | 13911 ++++++++++++++++ release.bat | 15 +- scylla_wrapper/ApiReader.cpp | 1218 ++ scylla_wrapper/ApiReader.h | 74 + scylla_wrapper/Architecture.cpp | 24 + scylla_wrapper/Architecture.h | 27 + scylla_wrapper/DeviceNameResolver.cpp | 102 + scylla_wrapper/DeviceNameResolver.h | 31 + scylla_wrapper/IATReferenceScan.cpp | 738 + scylla_wrapper/IATReferenceScan.h | 126 + scylla_wrapper/IATSearch.cpp | 547 + scylla_wrapper/IATSearch.h | 34 + scylla_wrapper/ImportRebuilder.cpp | 550 + scylla_wrapper/ImportRebuilder.h | 101 + scylla_wrapper/NativeWinApi.cpp | 84 + scylla_wrapper/NativeWinApi.h | 502 + scylla_wrapper/PeParser.cpp | 1378 ++ scylla_wrapper/PeParser.h | 167 + scylla_wrapper/ProcessAccessHelp.cpp | 963 ++ scylla_wrapper/ProcessAccessHelp.h | 230 + scylla_wrapper/ProcessLister.cpp | 291 + scylla_wrapper/ProcessLister.h | 72 + scylla_wrapper/README.md | 122 + scylla_wrapper/StringConversion.cpp | 27 + scylla_wrapper/StringConversion.h | 9 + scylla_wrapper/SystemInformation.cpp | 77 + scylla_wrapper/SystemInformation.h | 26 + scylla_wrapper/Thunks.cpp | 40 + scylla_wrapper/Thunks.h | 36 + .../distorm_x64.lib | Bin .../distorm_x86.lib | Bin scylla_wrapper/dllmain.cpp | 18 + scylla_wrapper/mnemonics.h | 316 + scylla_wrapper/scylla_wrapper.cpp | 660 + scylla_wrapper/scylla_wrapper.h | 66 + scylla_wrapper/scylla_wrapper.vcxproj | 229 + scylla_wrapper/scylla_wrapper.vcxproj.filters | 123 + scylla_wrapper/stdafx.cpp | 8 + scylla_wrapper/stdafx.h | 8 + scylla_wrapper/targetver.h | 8 + scylla_wrapper_dll | 1 - 58 files changed, 25862 insertions(+), 1159 deletions(-) delete mode 100644 .gitmodules delete mode 100644 TitanEngine/TitanEngine.cbp delete mode 100644 TitanEngine/TitanEngine.vcproj delete mode 100644 TitanEngine/aplib_x64.lib delete mode 100644 TitanEngine/aplib_x86.lib create mode 100644 distorm/COPYING create mode 100644 distorm/distorm.vcxproj create mode 100644 distorm/distorm.vcxproj.filters rename {TitanEngine => distorm/include}/distorm.h (78%) create mode 100644 distorm/include/mnemonics.h create mode 100644 distorm/src/distorm.c create mode 100644 scylla_wrapper/ApiReader.cpp create mode 100644 scylla_wrapper/ApiReader.h create mode 100644 scylla_wrapper/Architecture.cpp create mode 100644 scylla_wrapper/Architecture.h create mode 100644 scylla_wrapper/DeviceNameResolver.cpp create mode 100644 scylla_wrapper/DeviceNameResolver.h create mode 100644 scylla_wrapper/IATReferenceScan.cpp create mode 100644 scylla_wrapper/IATReferenceScan.h create mode 100644 scylla_wrapper/IATSearch.cpp create mode 100644 scylla_wrapper/IATSearch.h create mode 100644 scylla_wrapper/ImportRebuilder.cpp create mode 100644 scylla_wrapper/ImportRebuilder.h create mode 100644 scylla_wrapper/NativeWinApi.cpp create mode 100644 scylla_wrapper/NativeWinApi.h create mode 100644 scylla_wrapper/PeParser.cpp create mode 100644 scylla_wrapper/PeParser.h create mode 100644 scylla_wrapper/ProcessAccessHelp.cpp create mode 100644 scylla_wrapper/ProcessAccessHelp.h create mode 100644 scylla_wrapper/ProcessLister.cpp create mode 100644 scylla_wrapper/ProcessLister.h create mode 100644 scylla_wrapper/README.md create mode 100644 scylla_wrapper/StringConversion.cpp create mode 100644 scylla_wrapper/StringConversion.h create mode 100644 scylla_wrapper/SystemInformation.cpp create mode 100644 scylla_wrapper/SystemInformation.h create mode 100644 scylla_wrapper/Thunks.cpp create mode 100644 scylla_wrapper/Thunks.h rename {TitanEngine => scylla_wrapper}/distorm_x64.lib (100%) rename {TitanEngine => scylla_wrapper}/distorm_x86.lib (100%) create mode 100644 scylla_wrapper/dllmain.cpp create mode 100644 scylla_wrapper/mnemonics.h create mode 100644 scylla_wrapper/scylla_wrapper.cpp create mode 100644 scylla_wrapper/scylla_wrapper.h create mode 100644 scylla_wrapper/scylla_wrapper.vcxproj create mode 100644 scylla_wrapper/scylla_wrapper.vcxproj.filters create mode 100644 scylla_wrapper/stdafx.cpp create mode 100644 scylla_wrapper/stdafx.h create mode 100644 scylla_wrapper/targetver.h delete mode 160000 scylla_wrapper_dll diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 6db9806..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "scylla_wrapper_dll"] - path = scylla_wrapper_dll - url = https://bitbucket.org/cypherpunk/scylla_wrapper_dll diff --git a/TitanEngine.sln b/TitanEngine.sln index 20ab757..12584cd 100644 --- a/TitanEngine.sln +++ b/TitanEngine.sln @@ -1,12 +1,16 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36915.13 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TitanEngine", "TitanEngine\TitanEngine.vcxproj", "{9C7B8246-FDDA-48C7-9634-044969701E40}" ProjectSection(ProjectDependencies) = postProject {F874B1B3-8EF7-4DF1-9889-57098E08A51C} = {F874B1B3-8EF7-4DF1-9889-57098E08A51C} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scylla_wrapper", "scylla_wrapper_dll\scylla_wrapper\scylla_wrapper.vcxproj", "{F874B1B3-8EF7-4DF1-9889-57098E08A51C}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scylla_wrapper", "scylla_wrapper\scylla_wrapper.vcxproj", "{F874B1B3-8EF7-4DF1-9889-57098E08A51C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "distorm", "distorm\distorm.vcxproj", "{25FF4A19-7088-4687-AA32-76E61BD62E51}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -24,14 +28,22 @@ Global {9C7B8246-FDDA-48C7-9634-044969701E40}.Release|Win32.Build.0 = Release|Win32 {9C7B8246-FDDA-48C7-9634-044969701E40}.Release|x64.ActiveCfg = Release|x64 {9C7B8246-FDDA-48C7-9634-044969701E40}.Release|x64.Build.0 = Release|x64 - {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Debug|Win32.ActiveCfg = Release-Lib|Win32 - {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Debug|Win32.Build.0 = Release-Lib|Win32 - {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Debug|x64.ActiveCfg = Release-Lib|x64 - {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Debug|x64.Build.0 = Release-Lib|x64 - {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Release|Win32.ActiveCfg = Release-Lib|Win32 - {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Release|Win32.Build.0 = Release-Lib|Win32 - {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Release|x64.ActiveCfg = Release-Lib|x64 - {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Release|x64.Build.0 = Release-Lib|x64 + {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Debug|Win32.ActiveCfg = Debug|Win32 + {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Debug|Win32.Build.0 = Debug|Win32 + {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Debug|x64.ActiveCfg = Debug|x64 + {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Debug|x64.Build.0 = Debug|x64 + {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Release|Win32.ActiveCfg = Release|Win32 + {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Release|Win32.Build.0 = Release|Win32 + {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Release|x64.ActiveCfg = Release|x64 + {F874B1B3-8EF7-4DF1-9889-57098E08A51C}.Release|x64.Build.0 = Release|x64 + {25FF4A19-7088-4687-AA32-76E61BD62E51}.Debug|Win32.ActiveCfg = Debug|Win32 + {25FF4A19-7088-4687-AA32-76E61BD62E51}.Debug|Win32.Build.0 = Debug|Win32 + {25FF4A19-7088-4687-AA32-76E61BD62E51}.Debug|x64.ActiveCfg = Debug|x64 + {25FF4A19-7088-4687-AA32-76E61BD62E51}.Debug|x64.Build.0 = Debug|x64 + {25FF4A19-7088-4687-AA32-76E61BD62E51}.Release|Win32.ActiveCfg = Release|Win32 + {25FF4A19-7088-4687-AA32-76E61BD62E51}.Release|Win32.Build.0 = Release|Win32 + {25FF4A19-7088-4687-AA32-76E61BD62E51}.Release|x64.ActiveCfg = Release|x64 + {25FF4A19-7088-4687-AA32-76E61BD62E51}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/TitanEngine/TitanEngine.Debugger.cpp b/TitanEngine/TitanEngine.Debugger.cpp index cc439f5..d01a5a2 100644 --- a/TitanEngine/TitanEngine.Debugger.cpp +++ b/TitanEngine/TitanEngine.Debugger.cpp @@ -482,10 +482,10 @@ __declspec(dllexport) void* TITCALL InitNativeDebugW(wchar_t* szFileName, wchar_ RtlZeroMemory(&CreateInfo, sizeof(CreateInfo)); CreateInfo.Size = sizeof(CreateInfo); CreateInfo.State = PsCreateInitialState; - CreateInfo.InitState.u1.s1.WriteOutputOnExit = TRUE; - CreateInfo.InitState.u1.s1.DetectManifest = TRUE; - CreateInfo.InitState.u1.s1.ProhibitedImageCharacteristics = 0; // Normally: IMAGE_FILE_DLL (disallow executing DLLs) - CreateInfo.InitState.AdditionalFileAccess = FILE_READ_ATTRIBUTES | FILE_READ_DATA; + CreateInfo.u1.InitState.u2.s1.WriteOutputOnExit = TRUE; + CreateInfo.u1.InitState.u2.s1.DetectManifest = TRUE; + CreateInfo.u1.InitState.u2.s1.ProhibitedImageCharacteristics = 0; // Normally: IMAGE_FILE_DLL (disallow executing DLLs) + CreateInfo.u1.InitState.AdditionalFileAccess = FILE_READ_ATTRIBUTES | FILE_READ_DATA; // Initialize the PS_ATTRIBUTE_LIST that contains the process creation attributes const SIZE_T NumAttributes = 3; @@ -554,8 +554,8 @@ finished: if(ProcessHandle != NULL) { // Close the file and section handles we got back from the kernel - NtClose(CreateInfo.SuccessState.FileHandle); - NtClose(CreateInfo.SuccessState.SectionHandle); + NtClose(CreateInfo.u1.SuccessState.FileHandle); + NtClose(CreateInfo.u1.SuccessState.SectionHandle); // If we failed, terminate the process if(!NT_SUCCESS(Status)) diff --git a/TitanEngine/TitanEngine.cbp b/TitanEngine/TitanEngine.cbp deleted file mode 100644 index 18beb3e..0000000 --- a/TitanEngine/TitanEngine.cbp +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - diff --git a/TitanEngine/TitanEngine.vcproj b/TitanEngine/TitanEngine.vcproj deleted file mode 100644 index e579a7e..0000000 --- a/TitanEngine/TitanEngine.vcproj +++ /dev/null @@ -1,521 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TitanEngine/TitanEngine.vcxproj b/TitanEngine/TitanEngine.vcxproj index 7ced7b6..8b2ff34 100644 --- a/TitanEngine/TitanEngine.vcxproj +++ b/TitanEngine/TitanEngine.vcxproj @@ -22,7 +22,7 @@ {9C7B8246-FDDA-48C7-9634-044969701E40} TitanEngine Win32Proj - 10.0 + 7.0 @@ -67,14 +67,14 @@ <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)$(IntDir)x32\ - $(SolutionDir)\$(IntDir)x32\ - $(Configuration)\x32\ - $(Configuration)\x32\ - $(SolutionDir)$(Configuration)\x64\ - $(SolutionDir)\$(Configuration)\x64\ - $(Configuration)\x64\ - $(Configuration)\x64\ + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ false false AllRules.ruleset @@ -92,6 +92,18 @@ false false + + $(SolutionDir)distorm\include;$(IncludePath) + + + $(SolutionDir)distorm\include;$(IncludePath) + + + $(SolutionDir)distorm\include;$(IncludePath) + + + $(SolutionDir)distorm\include;$(IncludePath) + Full @@ -113,11 +125,12 @@ /Zc:threadSafeInit- %(AdditionalOptions) - $(ProjectDir)ntdll_x86.lib;$(SolutionDir)$(Platform)\Release-Lib\scylla_wrapper_x86.lib;$(ProjectDir)distorm_x86.lib;Imagehlp.lib;psapi.lib;%(AdditionalDependencies) + $(ProjectDir)ntdll_x86.lib;Imagehlp.lib;psapi.lib;%(AdditionalDependencies) $(ProjectDir)TitanEngine.def true UseLinkTimeCodeGeneration /ignore:4197 /PDBALTPATH:%_PDB% %(AdditionalOptions) + Windows manifest.xml @@ -128,7 +141,7 @@ Disabled true WINVER=0x0501;_WIN32_WINNT=0x0501;NTDDI_VERSION=0x05010000;WIN32;NDEBUG;_WINDOWS;_USRDLL;UNPACKERENGINE_EXPORTS;%(PreprocessorDefinitions) - MultiThreaded + MultiThreadedDebug Default false Use @@ -143,11 +156,12 @@ /Zc:threadSafeInit- %(AdditionalOptions) - $(ProjectDir)ntdll_x86.lib;$(SolutionDir)$(Platform)\Release-Lib\scylla_wrapper_x86.lib;$(ProjectDir)distorm_x86.lib;Imagehlp.lib;psapi.lib;%(AdditionalDependencies) + $(ProjectDir)ntdll_x86.lib;Imagehlp.lib;psapi.lib;%(AdditionalDependencies) $(ProjectDir)TitanEngine.def true UseLinkTimeCodeGeneration /ignore:4197 /PDBALTPATH:%_PDB% %(AdditionalOptions) + Windows manifest.xml @@ -173,7 +187,7 @@ /Zc:threadSafeInit- %(AdditionalOptions) - $(ProjectDir)ntdll_x64.lib;$(SolutionDir)$(Platform)\Release-Lib\scylla_wrapper_x64.lib;$(ProjectDir)distorm_x64.lib;Imagehlp.lib;psapi.lib;%(AdditionalDependencies) + $(ProjectDir)ntdll_x64.lib;Imagehlp.lib;psapi.lib;%(AdditionalDependencies) $(OutDir)TitanEngine.dll false $(ProjectDir)TitanEngine.def @@ -200,7 +214,7 @@ Disabled WINVER=0x0502;_WIN32_WINNT=0x0502;NTDDI_VERSION=0x05020000;_AMD64_;_WIN64;NDEBUG;_WINDOWS;_USRDLL;UNPACKERENGINE_EXPORTS;%(PreprocessorDefinitions) - MultiThreaded + MultiThreadedDebug Default true Use @@ -212,7 +226,7 @@ /Zc:threadSafeInit- %(AdditionalOptions) - $(ProjectDir)ntdll_x64.lib;$(SolutionDir)$(Platform)\Release-Lib\scylla_wrapper_x64.lib;$(ProjectDir)distorm_x64.lib;Imagehlp.lib;psapi.lib;%(AdditionalDependencies) + $(ProjectDir)ntdll_x64.lib;Imagehlp.lib;psapi.lib;%(AdditionalDependencies) $(OutDir)TitanEngine.dll false $(ProjectDir)TitanEngine.def @@ -300,7 +314,6 @@ - @@ -350,7 +363,10 @@ - + + {25ff4a19-7088-4687-aa32-76e61bd62e51} + + {f874b1b3-8ef7-4df1-9889-57098e08a51c} diff --git a/TitanEngine/TitanEngine.vcxproj.filters b/TitanEngine/TitanEngine.vcxproj.filters index f08922a..6304c3c 100644 --- a/TitanEngine/TitanEngine.vcxproj.filters +++ b/TitanEngine/TitanEngine.vcxproj.filters @@ -296,9 +296,6 @@ Header Files\ThirdParty - - Header Files\ThirdParty - Header Files\ThirdParty diff --git a/TitanEngine/aplib.h b/TitanEngine/aplib.h index 39cd91a..e621461 100644 --- a/TitanEngine/aplib.h +++ b/TitanEngine/aplib.h @@ -42,7 +42,7 @@ inline unsigned int APLIB_CONVENTION aP_depack_asm_safe(const void* source, void* destination, unsigned int dstlen) { - return 0; + return APLIB_ERROR; } unsigned int APLIB_CONVENTION aP_crc32(const void* source, unsigned int length); @@ -63,7 +63,7 @@ inline unsigned int APLIB_CONVENTION aPsafe_depack(const void* source, void* destination, unsigned int dstlen) { - return 0; + return APLIB_ERROR; } #ifdef __cplusplus diff --git a/TitanEngine/aplib_x64.lib b/TitanEngine/aplib_x64.lib deleted file mode 100644 index 8bf669526029b557b05525511f8b3aeb1e28e45a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11928 zcmcgy30zZG)_+-qh~kUZT3Txx+i1m91hE#3wmeDX#fBEG+gK_fpr|OCMXbdZ3@Gs$ zYsW5jX6kfm+i}{CqoNe|grI;c;0Eqv^)nb-t!)(@>-)}m?*$UUW&HK~o|4?<+;h+J zzvrHJZ+Z?%Go@#}6w+T6_(Vm=Mh+S@AU0+|V0)xk9T4T~NDZMVsslwy2UC=6KSjw` zQdH0|iV7YM%{qz-g*G~pq8@GjOG`4RP0mc2m6kr863bIEEh#yssZ&zSQ|D#+8Z$Ee zNz$`2dHNKgIVH_JBL(>YwSUv(G_xhJ32W)5^ymRtn2|P@pExtaHOlnAbFvwsjMeUbS)Ji!;4GW^E;lUK811s$hrKm_6{vPFxMk%OZDu`-F zwdeoIDH$cDBmok)s2iwON^4D3~> zAPrKfq6ZEXv6C8-u~0${Km7eDP?Z7$!BZ%Suw>4)@MYoSEBG1$e`m!uFeasMU~-i=39(o0+8O0rtl>hrw|B zIJwbYZXc)gAWwTjS0fp%PBoHbbrwsE>NpmvtdZ!{Nk*uSH^L+;qdi&OhqaZ5@ndXF zoaHHdf&$4|)?UuqTtbIEp(BB2n=_2HRYaz^^)LZI0JM7xK0!?={js?X3ZmXZpA=oo zTNQio;addM3JuWWZz1F;qm=OJznaY8E`+boE%)8`D83VJ5Ji#Cr>~t`o#Z1 zpODUI`GT8hYikEGQf|8$W|9#`=|)Py!#+)0Yw69N%mNsF>ZtCgPxK41t@OFs zEJ161K7&5g=LG!Wb3cr!So;CQmldHki$yJ`k>H`c+G!*~ZfgoN{ecZHH;s-Rr^tPc zmAJ?_1rHo;LPzV%h$@zhQyOD;=MDgJL{TJAAmrkJn5Tq(Hnzsvg-4_~wkt_cTI4*s zZ565%_p2bQfUdbv6414{xeW?;*c@BB;D`7;7`l1^wdj}Tpx_^B`RE&B=A%cmi|*^A z0g)|{(iaB`U?#METbR>AEBYuGyWv4?5p%faeg07UoX}l#!XtsEzr%c}m|!$y7zoei z%>ujNX=~YahW3EaDVWFHY=ryaGTFAb+^mSJE-QKe+Kl>ww<5=8|7>vSaJtJU*z08 zd}cr|+u3j6>v!*pxqDZSJG(4T;PO%>hSwWoo%EvL!0`rqlOf#6ET#m#FG5p*-iH&k0}0HV?h)*?l-E}sVwn0B(^^G;}edi|V@|*n#_BA^krKOh8rZkBNDXUs2&3vh!4VQZ%IIf`s4>*{V&9}j)0EW8eV>}8y}^FN5bk0Yix3oN_vW`Oq_$a^&Ktw4fEp*a#5$*tSF|gU4_hi8EWQjZl# z&DWx;J=s|35#{uxV?kXao(9?UY8PV;rE?rZNsz82nKReD~5X7BUg)_N@CI#+vp zyw6pEE5G#&gl0a#m_zb!wKE6Xn%>Qob1u%sEYsPYC6ckM{WcrE>*p^fdKda(#T`}6 zxjbG#MdxbIIruVNbx&Z!kAD213m$W(fCW$SDS3;5TPz$UCZ6J#@2v+iYQR$*d;8ml&4&V3gsnhq@YxsrrQDkuL^J$%a+&r@V zCy!Um2!8LEX|rDVGQDxthZ!pe6d&*OMcIkBo@zXNrnsT*V~w%2{kFVy?*#WNyYPOG z9m_J5-}ShvT04!Mz3Jyu%=W_hhmJkrJ$G`($c=}7sVq8Z8@nR=5$EdZ8S`#T`t4G6 z=Hl0qC0!e`gVNK7(l>t%RXD0tGqn?yQ;p}C)WfFPQ$DXfCmWJ*NdC%iMWJ=mH->z9 zbM?j-vRAAhcBFdC@wgjXzx_VDetRAek33q{Ev;t9 z#$Pt{e72%w>?a>?K0trDt!!nPw2z{=UCR1~j=R*29o8+%%jw_Qm^J>J9%-(j{U(<# zV@}KontfcdRaLj5uk!F^d(pbtPj4&@`tsb4zeXP_^L$<%Ja^y?ie9?9{YPOdI{kY~ z=(KnH4V|I*I6LEgNpkxC{4#R-^hs&iPu53f7QISMy86S1LD_GADe3O|MX_L91^w%; zhP9bVjo)>-Shk(y6>qwAy2r^$hJME${W#DPnTMjW_ zo*r@Z!}_5!Dr&#@&o4&~PHUVRf2(2Uz~RMH{#jF&dd%EUt~=jD7M)@Y`MNqU^yHA) z?UKG`q|Ygp9kwr2b*%2SF>72&QI4wpp~;*6dM<5$ryHjxuBdJZe`ZC^+6}9ZRz5bg z<=QWQZVeT(Ze{R%-E#U$-73YRtgDizZkGp5eRJHT z>wBhT=Fc9K{rH8T=`-haKXm(y=AeDTykp9}BTi1qIlbw|jmz7Y#&7@bvBOK(rg~N# zIr7f(+P_tl*T;;ydiu4WrfjL5GH&ZvCxbS={K}y9>@iJfy|H`9zpjmt4N9FSXWW-l zPmei0W%cEyGo#+xK6Ut#lC(Wf*d}lNtS+b5ptD({KFsa7SC-IW%cgG9XZrVUH)gwb z^UgjUwypo;gbf<`w36h%b4Sag4%BQUD;u8gvF6kpYs)kK-1}%6kFYc%WLj_F?7@y|=^{usLb@cHj9pUCTZ`gn&! zbq5y?JA3G-rjnCcGi}G7-q&q=!5h6dUHfpriZ3$DJCzV@kub5%VUOl#NKMkao{{^8-yz-xs%c*zmWd9o^kex0~R&EbWJp z4|g^>#`Na16%3+nz2x~vTpT6i)5Ek`*;6OA5&vI!L5T9cPhb2WG;mc@PSJj2pI@Xb)rbv11MTRT4oskT8bc6#JN$w8}x7#v} z;n*8d5ZKJ3-%u_6}ess?f z4?hzM<7VM-5ne^|)XFkA6Q=ah)jD!aTVo`(j=4=bI-%Z>ew@92oS{p*6xLaKGGvdz zA%7x9X$b~RxoYdLMb%|^+Dz*!b+Rh2OeZ^F;K~`U%DR_@Q%yLg1lA03xho5d=w*0x zz{^Og^@WfTYyj-@6SHKuPV0mTorZKLtEpP1i|K5MWg));RzEZ7c(64CwieK05YPf& z3TOsR48)+IOQppU1IH-bdN>{1eVJ!OG$@`oHJeaLYV zx=;yT3Xt{Q3(-%hdnyya@^_=WuMHo-%nwZBF1VQwkTyTX*qY?#Fzx#+fZXzS8K%IS z;If5+v{&zPi|y$mbr557-u8AYxQXW!rcMBHD8k`|Nd`sNMFk(0Y~?cBP3e3&sq%J? zuCBdk>A*S+l+7iry=c7w(@FE_XeR^jDGG>O@NI2!=p-R-?3v$Q;NX-)YzrW%wJ;Q>d|zl(J7 zO0a*8%2qCIJO~;KQ42R{(RI^!M`wr*P4+Cg0dLP_kEam6A4r`zx^!17eMMn$yzL!daGS?w5_bSf2+iT#0q?N;Xjr4V zF9A6U^WWjQMtc*-ITlb^5=vXp2Ru6`j1vkPQnu1emJdrRW*#r^X>BY@8~8AkuO}}?e8

a$RkD{4Pk7YgkD$-nIP=OLGbsg1UGKDGt}+sLxvRN5ql=|8p+Byl*IlQbun<+0yn(W z2uH`Kp^jV)+Wn>>MVuwZv52=gFK4qEn&!wgO<;zmf=ba00Po={GNcSyz*uvIPP-fS z>D^!-yq&~ZFTeu9AYLHvrO;3K@h8e9+ z)2JioW8|GJp*rmv76he>h9Z&nvRQ3#jFlQR`(aa$k%w4Axt#{Cf`!~dd)eg0dr}pY z=)$o)xo6JXI@cIPF+F*A8N8voW=+8?|BYX{J>Xdp z80cV&68u?YfFnU~5Nb@|j2j&ZA8;)V&SgPLL>16@zVpheBX2vjM@&1hTB__Fn)WcNdh@Sk!k{h1CLp;!t zXUQ9IKY2h;D#$?{@p#^cR#@nI2P*-qX;0-n%aDDVs$ z^u*;2V*nKz_b0ZqGFiE+Ny^A7v>rWebm@z(Svu;p=ktQ~+LPFTF$oj`J#kA(LjA@w z#EDxAGm&|dNqz`DPG4_Jk7{TQ(4%`>LeB4n@~Z?D8$TxztyO$TJ#_ec1^$-{d?0hhHC{<@*13GbkPFp?$e8lXvp zTj?{beXDvcRE+j71eiF6!Qq&&Y>ak;inVt(0tn_B3S42IwS%Bh5C@Ci2#}a%gjAk& zjO-K5F`Mzw(HqP<{tT?3Hw0k7l;uMiQy`W|;Ve*L;HvC-3P=m2_B_cgYa_74_hUGe zgRb4yYL@6B6mC`5!!V`{7{Y8t7-ykFRau0=2Er|;vln5Awr|5-zz+D<13{v~z74Y? zx|AYEb>u>^gyr-K_@f;0oRM6Iz?WR9Q>O|H^kI79f$b-Y(K_jcXW_RtfS}Q^Hh2^z zfxeN@J3bMD?m(^_$6kknL%3?_O~ybl(ZlWg67?AnQ1gKr77wM@xXB)dJ6hzV3#a3+ zcC^{*RBLC5SEF@=16##_2Zwlj8$nj$W*wu|F^p!Xp6p}EKA1@5Y2eon(7}))ux&`` zCCOkK!Yi$2Td1GFe!_jIf*b*c5IMtsLb~QdNt3_JbQP@J~tH>4aldzusgMqA4r)}bqK^w2=i_Te;jF!s_(rfF5 zx^*bj=f{v*K?0AGmnu<26Icvvv-Ju{G@2J3gmff_Nj!}|gSqP8RlwbMQ3>wW=zyh# zU?bjP$?6QfBT?#zzl~;K4UoP2?9dY;gVCXb5QIL}6L^K*=PCLR#{m+GvIJJLcZMPx zNBnQVMaHuLD&QjHU4QCY8!U#2EP4S8(OsY}U6_K7=b;dfC9)R+5zmp)>`NrOWP2Fx zUWQKC%V;VvX6Q(jAZeT@7pB38$uim#rbsY=5%7Z2Ub@QLBT}f6E1u)fpxyOOM_3N{ zL#FW{CDO+UX!GP<4xq31e1r4=wvWJGFlLCB2dy>1kt6|l;1u>dr@@I8L$9gu^n$4j+%AUOYrWv@qIc*yq0iG1I`q-!!1*%zy#=5QL=_4I0@!#K z{Rm211iXuDYy&Jgt^3{Qv>P!nS({~hO>=Y7k6O3yWz(2pcB{WMQyl)OoKUjuYldmy=ySbd1WFs6gx zGoIlpyy1RBvHmzNpLSTHSqN&PI0{i59&A^@20CqqdOTfp9*TfAJ^8IIwCOds5N&#L z096X*7oCW-L4HVEAgsI=q|Jr~Kw2jdO+Xq5?3JUS;6;WUh2Z81{UIQ-y@W&D^IyKx z>QA;<9U!3+t&RYZS-K!5&}*I&7!584<^2)y2u$Ha1jFsb;GJbwiJk!YlYN_#5!#$! ziN^0CBjinlTP?1~Id2Dq-FYSk6 z7CKn6f!~yTQj3b{v|e*hR=DYFark360Px4_?KPd}68VDwy`oYt9t7xxg8zlB=$J26y0RaKiQ>i&3ZnxHU_{)r7 z9L#DejR2jwMj|FJL`-O43O>Ps-D#FzDg-Ii3Rt*s?r06+(esm@-vUXHL#B%}BFM&6zn^m1VKa8r;8sZf63rYbMFkvyaS|I`=%A#4Ib$l^jQm@_8h0^{e*-?22Yp}77`rXyWLR@4GpssGCc``@FEC)3PA|=5QOke zf)I@%2={P;@ce)vB<~Z1_Z@;5e9-Zqp;H@l^K&v5>#`ORj!JHhF{4PImz!b8Tbko+ z&Cco7DQiIvHzb22Watb98ORFm#uUz&f;Fj*W;u16F%B`ui_MMd)Sj*q%VfDZmh{s#g~DhsEa5{;g-;$^dcoNS z1-k|ujnA5kMF>go;8=nf$bNDke8N>%7X}j!?+pyx7wKWhfc-F}L&iVl z^h*cQ8Ni>Dq(9P601c6LeORPvBT3RD0pyi;5m}QLJy%HGmFop`oQwkphj0dTsNY|; zVbI5+T5pH)G;sdrP)zYK&BDSW`)PL8DMEkERsan(gLK6{P9I`5OC-2yQeSBoHxMVW#C#G2JbP-jY#59ghB!eT9WhG-YS{Is36(=(d zHaDrY4u4X``Iyfb1%M<68_LA_)GR1*K9%QeLs5H!iY<^loDXNoKRWBktv~P~Kz9J& z6WFfl)0t8op2lVar#T*KkI)duI+5w=@U#^$E8={=n2v&0)V&zV@Sx^SPXjynJK-N` zhu^m!>fn1WNIq`o;)Cq&gW4dro%^^SMt(qYVB}1N_Q2yXGdSURn0H2mhW7K$J76l# zTK&DV4hV>b>*GX&j^(@)T}-VhzbP%Ng6`#vv}`rJsUyrUA?;K?Ddb64nV_LkL>=T& zfh1JtL$$)4YUb5KfgsvVgY5m1u%B-n(SEPdu-~P9d{4WS!gL!_??N5wN*078 zs&i?&!7xk> zG`Nbiz?GGB)pJPh5qMe;Rew0(Of6DPS-bG%(u?frHLyjxY6y~hc!+wa`okKq&qQS+ zDU3YwoOF#1ItEBc>8guRm}$Nj@Z(P#=XSkxk6{u%f)++v-U6?NFU59?)IzON6lXrr zSAzGEz?ljqSPNAb3Cen?`ooimW#A7T%p}-RurP_!|_IHnjhn_1*0_pS#DA_@j ztn*ifVMWo0gBT$#^;VuSlxpLf5A+%}6h{qmjAB9S+K5Bd~g-#Gmxhm-m{T*Tg|#W|z? zlGD>>KtLpbd-d|E`wV!P&p1robq`$E=@~;=&v4Khp#;m z;r(p?Eg0fKw#NW`nC(N(ZLH>73!tarW=M-Q8w-9R_14)~c%qsgvqff|0cBae;g;!{ zk8LNcNl**uFv+Zwpw9RTv8rWj9kTL*D+klnCl{4n>d^++)Sy_{$cYgL3TMj7-RdZ!| ziQmLzp42bNeZTD+!Nm9z!s)-3d$%vz;koI~hdajSzqM`hsg~Mv(cODK{W||lsA*2; zv&Xzoeev9+wog6{?idqAT+po0oId2MYu&fw#`e)q?602r_PX82q?`8Etgqqwi!0nR zwslAjl3iX~*OV5G8<@CY)+Zx$4U@*s-}ze17sa9_=XiS*?QcCPJ9))izIDl{9Xmyv zzS;L)*ohkJ`z`J-hIbRvst-Nhl)p9Lt6J}cFOQv6ApT2!_UpVkS>N5zELt>Am+yBb zIHx?Bn0Nj1I#K?gHt~ix+z_wQ?w9_2uwzS(y6dw+mul+h(u!TbbdESbZ|c~yLw+hf z{z^{biMz9O+meoIc0?J8JsU0t*Pe*k)H&_+x-*js_P1@kd*jscgixeIw=I?s% z8{N?X-52J*)zT60_*<=8wtslKdFZ6-=T>@e4^qw9``N$pch@VZn#((@_q`*zxKr>> z`&MIQ{K-rIE@}VUkTK_kl) zz5BA*wbHBY8^miCT<49v*C@(+K|Al(=eap6mQ2Wh?0eCo!s6j4?tQ5|Zhn60S=oQ4 zozE@m+|}KErLJm9-Dg8jR&B|&Za8&n`P#OB>~B01k#fCr#(we|+2+xAZ#I?gRc_d$;}h`Rz*K!sFCaLUMJd*ubzDI#I@Vi=NA-GXGb0Jty?*J%&wbXm24?0iT_Og z-Sgs##S5j(VU=k9953ELW_`}9d7J0mKF%!CJ$o$Q_r;5zfB&)F`*a#5Om3_eMC!)m z{_~b^W@}P>-qdp?g-=gg*tYqL=TCLa_v(zksyg#j>gGKk9avv`;pJo7;=7m~!G72G z?yYRxeK>e+b?OHjwv%oXT6eD%ojwwvy^yvqx8sSRrSq$6rs?+chc9^H4Q0`jPt|#C z|3{UiX?UmG^Oh_8v3O~QD-v7>!2>CfeJ~B)?=<3?GjWuF7yzG`(76MeZgGCzy#Bd7 z_$kMM-@YO`?p(%)huRO!n9BvkCb)B%1xF>63Ln><8P@**>&GitaCsDjIy0zGDt93} zi_wI--c^1iY=HmmxF)$g&@Y;qDlrYDV}#}yaddNxL=0qejF2iNg#+B&-Ffiwq`CK|TqR5yQ_s0P=mrm*_9E~7hD&u{B8bvMB|OGu}Y z!t|Niu$z{t1bv(Op4VoLv-oJK+q{yi$$McPW-QA*jLE5%Y?9#RNle~$(akSOKx{fj ze6x{f^sJQg&)sXPklXmJiu?BBI<#F%u8^B*X5Y69$4JJ9BU***0gO=VjJYoWEUD>q zJ}H|SRGYTh9HQf$thn4k> zMoX;P-6o*w-Q(k!MAFaH3S4J5rOwm>4_Wg{f4jF<4lQe!mdyd5g_YWex+g96sKc4e zP@|ib2P0(0NTei3V@vr>(~l1@NsPEvQRz-=gc)-y_)Ls&cB7a8oBI&PqtsD`w?tx@ z>CuC&#*VE6R-pf163fy^pFTG0H^I$V(g)4^DE;`4*pCNZD=j+!_*L>U(97pm@K_-J z-w^;W?WZv)@q3y%S48pcVI*cxorYo59id@}Y9+)oVKm)3GrXSqQbg6eK}UOICfCu8 zy2Q81*rTi7V;Z|t*7K&p?vAP#P`CNZ+;?Hf+PuSBU}No0HSpW4rf%vEf0=}hWlJp2 z6L>;IU*aPAlBwI?hMm0FPE@_HZy&BH748|t=`-nTR2}QU^DDRoErTr}5YT zj-|G`qe#iZipPEnmNZh15T5Jq3ya1DmS|M9?bbWwr9?%R65Ia{<4+9J+%WDK& zXQ^KI0fdVmqs@NsRy7p6DH|a9D;wO93Z<}m_@I7}vCDyCX4pCUn$|prl)=AGCUMAvBSC9=tD|&mX+N&Yq5KRc{NUI zmvL1dI0&d6yqm}cts9F)<}@s5EaZ%GoPPqeNAO zF)S^|ueQLf!K$-{(Uv4WZB^!z{*|%bL=?{?ni8WrtG|w;U;+16ot2h-1>IF(v*P$v zjKzPUg93lx;G+RAq^;I>ph;;JT&|h%!~W!3mvLaj9X{RIU>zlB6vUD;)tTa1$P%RV zu}$OTFvYR#<|4Z^U}ptru zz~F|Kb3Wv7zcxW zac`m^iU&sKlYXUMY^G2dNm;27hRHEeKG!HA?jzf^+YgfMG*EiUHn5KbHq5Y`uwC!d zK`z4nH?mPbgu|wmp|3@jk_jfyjIjE-)c){BIl61K>X^wZ11@hJO=)DT>a_7P2$ZO5 zHhya!Fg4Z829|jyEO|0ZvXA98`QP1$TFmw7Y)F^~LUsr+m%0(Ko=(EUjs7atAY9pq z#p$Lm=>hai8GB8LUwo~`xG=NXz`UN#6LlE;<|ynYG_y-^r3V<*4`fhRc=F~7c_S0x zUNH^+<>t8(OlPVl>FQRPoZHWW9<$*7Wda%`8b-=LVqjxx8UwyH2UZy+=#oPFD$~eB zHFTMkqGsB_%gXDeWwU?>gqxpf5b&4?{iDHuNbq)l+fbaI9-wSer)n$^z_Q4D0KY)l9F5bRc9jpal#jc(E^o7Ebt_6A;*OSI|qQ54bI zev@HT;CNCCZZ_xx?B=J`gJSs7GCycxH$hkzNXsM~U$xR^NoP_lQ+R4x6s@)-k_nI` z%=x6k>IRZQyA~ux1QaQjSTYdfyZIN^3l-&zDFMVGBSFt)PlKitLBD7=1tfqZ^nist zND)@+mY<*k>Vl}2d^gCkq(9r~2^7}~%E?~#Vgo{2{t_HbSu~ax(IQLIJ&h%mp91G8 z6f7FE*J6l4lqkX}%}J03a4&z_K2)$goc5&-{F-i=F3?bo0_+%#VvlEsCXx||eIR20 zj(w;AhT_*>X@Cg}dL)9=tZahNP^+4Y`E)bLpQfg5$}8y(ek?{`LD)eEgzLirhzKo8 znDjHJt(MEJPeWC80F_*hDJ25>g#((w;1q$#RGXe+ef2tPM>d59Yf)A)J4$L<2e|_A zQn7Af(!jQoOl7tC4r~v+f^km3_%v1_4QmCMhru7MQNR=@1Jp55!<_!st=u35u<;Qb zQXN?y0iA>G%suRTRim8q8#nM9<513Lpe!(Yv7(Iz(QHakD2+a@Je>l*XC+~(XJ?qM z03>NPbo(^R6h@6;cmf5|L_SGUzY3(UmZLhp>8UB!zg}}nm+p{mFh~dPt9bcI7nPk- zJ;h1o&bo)uos;WvWLxVxrLIdG00f0-3x4}|l6vW%S=mG4i7s}3qK7-%GtKb_dX*u3j z179_LT6tX1Xm=aHf^!>mx@ZuQb(@dD^X+Z}F2Ta;i$T(3Pj{#~-3Htp7>C=X2}FRk z=^E>-tE|l@VhZ4#tqtH-9at6xy?@iHkGWXYo1K0-%ooPkMxb5UJzNuH7_@ByOyaOD zYBwc;O_pb*t2!V*AOd*)XQO5n0st;ef38&?)1+8yuJm>55LUjIpM98oq>FrVR=!VQ zq%Hh~*{A(oV^{2>rlweotC`^x=TYNB5uW8qD|K}N$% z166#dKz$_Vo7DsT1?&DT+gaLW1DO7Go6(;d-&hh6AXMiBj|Oj2sxS%@bF%-_v3n_2#Fo~^rmCY z^)?Z|021) #include -#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) -#define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3) +#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) +#define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3) +#ifndef FASTCALL #define FASTCALL __fastcall +#endif #ifndef _Reserved_ #define _Reserved_ #endif +#if (defined(_MSC_VER) && !defined(__clang__)) +#define BUILTIN_OFFSETOF_REQUIRES_CPP (_MSC_VER < 9999 ? 1 : 0) // Update this number if/when MS ever fix this +#else +#define BUILTIN_OFFSETOF_REQUIRES_CPP 0 +#endif + +#if ((!BUILTIN_OFFSETOF_REQUIRES_CPP || defined(__cplusplus)) && \ + ((defined(_MSC_VER) && (_MSC_VER >= 1910)) || \ + defined(__clang__)) && \ + (!defined(__RESHARPER__) && !defined(__INTELLISENSE__))) +#undef FIELD_OFFSET +#undef UFIELD_OFFSET +#define FIELD_OFFSET(type, field) ((LONG)(LONG_PTR)__builtin_offsetof(type, field)) +#define UFIELD_OFFSET(type, field) ((ULONG)(LONG_PTR)__builtin_offsetof(type, field)) + +#undef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (PCHAR)(address) - \ + (ULONG_PTR)(__builtin_offsetof(type, field)))) +#endif + +#define PAGE_SIZE 0x1000 + #define ALIGN_DOWN(length, type) \ - ((ULONG)(length) & ~(sizeof(type) - 1)) + ((ULONG_PTR)(length) & ~(sizeof(type) - 1)) #define ALIGN_UP(length, type) \ - (ALIGN_DOWN(((ULONG)(length) + sizeof(type) - 1), type)) + (ALIGN_DOWN(((ULONG_PTR)(length) + sizeof(type) - 1), type)) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) -typedef LONG NTSTATUS, *PNTSTATUS; +typedef _Return_type_success_(return >= 0) LONG NTSTATUS, *PNTSTATUS; typedef LONG KPRIORITY, *PKPRIORITY; typedef ULONG LOGICAL, *PLOGICAL; +typedef enum _NT_PRODUCT_TYPE +{ + NtProductWinNt = 1, + NtProductLanManNt, + NtProductServer +} NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE; + +typedef enum _SUITE_TYPE +{ + SmallBusiness, + Enterprise, + BackOffice, + CommunicationServer, + TerminalServer, + SmallBusinessRestricted, + EmbeddedNT, + DataCenter, + SingleUserTS, + Personal, + Blade, + EmbeddedRestricted, + SecurityAppliance, + StorageServer, + ComputeServer, + WHServer, + PhoneNT, + MaxSuiteType +} SUITE_TYPE; + typedef struct _CLIENT_ID { HANDLE UniqueProcess; @@ -105,6 +175,7 @@ typedef enum _KWAIT_REASON WrRundown, WrAlertByThreadId, WrDeferredPreempt, + WrPhysicalFault, MaximumWaitReason } KWAIT_REASON; @@ -186,15 +257,21 @@ __pragma(warning(disable:4221)) __pragma(warning(disable:4204)) \ static UNICODE_STRING _var = { 0, (_size) * sizeof(WCHAR) , _var ## _buffer } \ __pragma(warning(pop)) -#if defined(__clang__) -#define RTL_CONSTANT_STRING(s) \ -__pragma(clang diagnostic push) \ -__pragma(clang diagnostic ignored "-Wwritable-strings") \ -{ sizeof(s) - sizeof((s)[0]), sizeof(s), s } \ -__pragma(clang diagnostic pop) +#if !defined(__cplusplus) +#define RTL_CONSTANT_STRING(s) { sizeof(s) - sizeof(*(s)), sizeof(s), (PWSTR)(s) } +#define RTL_CONSTANT_ANSI_STRING(s) { sizeof(s) - sizeof(*(s)), sizeof(s), (PSTR)(s) } #else -#define RTL_CONSTANT_STRING(s) { sizeof(s) - sizeof((s)[0]), sizeof(s), (PWSTR)s } -#define RTL_CONSTANT_ANSI_STRING(s) { sizeof(s) - sizeof((s)[0]), sizeof(s), (PSTR)s } +extern "C++" +{ + template struct remove_constref { typedef T type; }; + template struct remove_constref { typedef T type; }; + template struct remove_constref { typedef T type; }; + template struct remove_constref { typedef T type; }; + template struct remove_constref < T && > { typedef T type; }; + template struct remove_constref < const T && > { typedef T type; }; +} +#define RTL_CONSTANT_STRING(s) { sizeof(s) - sizeof(*(s)), sizeof(s), (remove_constref::type*)(s) } +#define RTL_CONSTANT_ANSI_STRING(s) RTL_CONSTANT_STRING(s) #endif FORCEINLINE @@ -214,7 +291,7 @@ typedef struct _STRING USHORT Length; USHORT MaximumLength; PCHAR Buffer; -} ANSI_STRING, *PANSI_STRING; +} STRING, *PSTRING, ANSI_STRING, *PANSI_STRING, OEM_STRING, *POEM_STRING; typedef struct _SYSTEM_SESSION_PROCESS_INFORMATION { @@ -262,10 +339,119 @@ typedef struct _SYSTEM_THREAD_INFORMATION KPRIORITY Priority; LONG BasePriority; ULONG ContextSwitches; - ULONG ThreadState; + KTHREAD_STATE ThreadState; KWAIT_REASON WaitReason; } SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; +typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION +{ + SYSTEM_THREAD_INFORMATION ThreadInfo; + PVOID StackBase; + PVOID StackLimit; + PVOID Win32StartAddress; + _TEB* TebBase; // since Vista + ULONG_PTR Reserved2; + ULONG_PTR Reserved3; + ULONG_PTR Reserved4; +} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION; + +typedef union _ENERGY_STATE_DURATION +{ + ULONGLONG Value; + struct + { + ULONG LastChangeTime; + ULONG Duration : 31; + ULONG IsInState : 1; + } s; +} ENERGY_STATE_DURATION, *PENERGY_STATE_DURATION; + +typedef struct _PROCESS_ENERGY_VALUES +{ + ULONGLONG Cycles[4][2]; + ULONGLONG DiskEnergy; + ULONGLONG NetworkTailEnergy; + ULONGLONG MBBTailEnergy; + ULONGLONG NetworkTxRxBytes; + ULONGLONG MBBTxRxBytes; + union + { + ENERGY_STATE_DURATION Durations[3]; + struct + { + ENERGY_STATE_DURATION ForegroundDuration; + ENERGY_STATE_DURATION DesktopVisibleDuration; + ENERGY_STATE_DURATION PSMForegroundDuration; + } s; + } u; + ULONG CompositionRendered; + ULONG CompositionDirtyGenerated; + ULONG CompositionDirtyPropagated; + ULONG Reserved1; + ULONGLONG AttributedCycles[4][2]; + ULONGLONG WorkOnBehalfCycles[4][2]; +} PROCESS_ENERGY_VALUES, *PPROCESS_ENERGY_VALUES; + +typedef struct _PROCESS_DISK_COUNTERS +{ + ULONGLONG BytesRead; + ULONGLONG BytesWritten; + ULONGLONG ReadOperationCount; + ULONGLONG WriteOperationCount; + ULONGLONG FlushOperationCount; +} PROCESS_DISK_COUNTERS, *PPROCESS_DISK_COUNTERS; + +typedef enum _SYSTEM_PROCESS_CLASSIFICATION +{ + SystemProcessClassificationNormal, + SystemProcessClassificationSystem, + SystemProcessClassificationSecureSystem, + SystemProcessClassificationMemCompression, + SystemProcessClassificationRegistry, + SystemProcessClassificationMaximum +} SYSTEM_PROCESS_CLASSIFICATION; + +typedef struct _SYSTEM_PROCESS_INFORMATION_EXTENSION +{ + PROCESS_DISK_COUNTERS DiskCounters; + ULONGLONG ContextSwitches; + union + { + ULONG Flags; + struct + { + ULONG HasStrongId : 1; + ULONG Classification : 4; // SYSTEM_PROCESS_CLASSIFICATION + ULONG BackgroundActivityModerated : 1; + ULONG Spare : 26; + } s; + } u; + ULONG UserSidOffset; + ULONG PackageFullNameOffset; + PROCESS_ENERGY_VALUES EnergyValues; + ULONG AppIdOffset; + SIZE_T SharedCommitCharge; + ULONG JobObjectId; + ULONG SpareUlong; + ULONGLONG ProcessSequenceNumber; +} SYSTEM_PROCESS_INFORMATION_EXTENSION, *PSYSTEM_PROCESS_INFORMATION_EXTENSION; + +typedef struct _HV_DETAILS +{ + ULONG Data[4]; +} HV_DETAILS, *PHV_DETAILS; + +typedef struct _SYSTEM_HYPERVISOR_DETAIL_INFORMATION +{ + HV_DETAILS HvVendorAndMaxFunction; + HV_DETAILS HypervisorInterface; + HV_DETAILS HypervisorVersion; + HV_DETAILS HvFeatures; + HV_DETAILS HwFeatures; + HV_DETAILS EnlightenmentInfo; + HV_DETAILS ImplementationLimits; +} SYSTEM_HYPERVISOR_DETAIL_INFORMATION, *PSYSTEM_HYPERVISOR_DETAIL_INFORMATION; + typedef struct _SYSTEM_PROCESS_INFORMATION { ULONG NextEntryOffset; @@ -302,7 +488,9 @@ typedef struct _SYSTEM_PROCESS_INFORMATION LARGE_INTEGER ReadTransferCount; LARGE_INTEGER WriteTransferCount; LARGE_INTEGER OtherTransferCount; - SYSTEM_THREAD_INFORMATION Threads[1]; + SYSTEM_THREAD_INFORMATION Threads[1]; // SystemProcessInformation + // SYSTEM_EXTENDED_THREAD_INFORMATION Threads[1]; // SystemExtendedProcessinformation + // SYSTEM_EXTENDED_THREAD_INFORMATION + SYSTEM_PROCESS_INFORMATION_EXTENSION // SystemFullProcessInformation } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; typedef struct _PROCESS_SESSION_INFORMATION @@ -446,11 +634,213 @@ typedef struct _FILE_STANDARD_INFORMATION BOOLEAN Directory; } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; +typedef struct _FILE_STANDARD_INFORMATION_EX +{ + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + BOOLEAN DeletePending; + BOOLEAN Directory; + BOOLEAN AlternateStream; + BOOLEAN MetadataAttribute; +} FILE_STANDARD_INFORMATION_EX, *PFILE_STANDARD_INFORMATION_EX; + +typedef struct _FILE_INTERNAL_INFORMATION +{ + union + { + LARGE_INTEGER IndexNumber; + struct + { + LONGLONG MftRecordIndex : 48; + LONGLONG SequenceNumber : 16; + } s; + } u; +} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; + +typedef struct _FILE_EA_INFORMATION +{ + ULONG EaSize; +} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; + +typedef struct _FILE_ACCESS_INFORMATION +{ + ACCESS_MASK AccessFlags; +} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; + typedef struct _FILE_POSITION_INFORMATION { LARGE_INTEGER CurrentByteOffset; } FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; +typedef struct _FILE_MODE_INFORMATION +{ + ULONG Mode; +} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; + +typedef struct _FILE_ALIGNMENT_INFORMATION +{ + ULONG AlignmentRequirement; +} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; + +typedef struct _FILE_NAME_INFORMATION +{ + ULONG FileNameLength; + _Field_size_bytes_(FileNameLength) WCHAR FileName[1]; +} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; + +typedef struct _FILE_ALL_INFORMATION +{ + FILE_BASIC_INFORMATION BasicInformation; + FILE_STANDARD_INFORMATION StandardInformation; + FILE_INTERNAL_INFORMATION InternalInformation; + FILE_EA_INFORMATION EaInformation; + FILE_ACCESS_INFORMATION AccessInformation; + FILE_POSITION_INFORMATION PositionInformation; + FILE_MODE_INFORMATION ModeInformation; + FILE_ALIGNMENT_INFORMATION AlignmentInformation; + FILE_NAME_INFORMATION NameInformation; +} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; + +typedef struct _FILE_NETWORK_OPEN_INFORMATION +{ + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; +} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION; + +typedef struct _FILE_ATTRIBUTE_TAG_INFORMATION +{ + ULONG FileAttributes; + ULONG ReparseTag; +} FILE_ATTRIBUTE_TAG_INFORMATION, *PFILE_ATTRIBUTE_TAG_INFORMATION; + +typedef struct _FILE_ALLOCATION_INFORMATION +{ + LARGE_INTEGER AllocationSize; +} FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION; + +typedef struct _FILE_COMPRESSION_INFORMATION +{ + LARGE_INTEGER CompressedFileSize; + USHORT CompressionFormat; + UCHAR CompressionUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + UCHAR Reserved[3]; +} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION; + +typedef struct _FILE_DISPOSITION_INFORMATION +{ + BOOLEAN DeleteFile; +} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; + +typedef struct _FILE_END_OF_FILE_INFORMATION +{ + LARGE_INTEGER EndOfFile; +} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; + +typedef struct _FILE_VALID_DATA_LENGTH_INFORMATION +{ + LARGE_INTEGER ValidDataLength; +} FILE_VALID_DATA_LENGTH_INFORMATION, *PFILE_VALID_DATA_LENGTH_INFORMATION; + +#define FILE_LINK_REPLACE_IF_EXISTS 0x00000001 // since RS5 +#define FILE_LINK_POSIX_SEMANTICS 0x00000002 + +#define FILE_LINK_SUPPRESS_STORAGE_RESERVE_INHERITANCE 0x00000008 +#define FILE_LINK_NO_INCREASE_AVAILABLE_SPACE 0x00000010 +#define FILE_LINK_NO_DECREASE_AVAILABLE_SPACE 0x00000020 +#define FILE_LINK_PRESERVE_AVAILABLE_SPACE 0x00000030 +#define FILE_LINK_IGNORE_READONLY_ATTRIBUTE 0x00000040 +#define FILE_LINK_FORCE_RESIZE_TARGET_SR 0x00000080 // since 19H1 +#define FILE_LINK_FORCE_RESIZE_SOURCE_SR 0x00000100 +#define FILE_LINK_FORCE_RESIZE_SR 0x00000180 + +typedef struct _FILE_LINK_INFORMATION +{ + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + _Field_size_bytes_(FileNameLength) WCHAR FileName[1]; +} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION; + +typedef struct _FILE_LINK_INFORMATION_EX +{ + ULONG Flags; + HANDLE RootDirectory; + ULONG FileNameLength; + _Field_size_bytes_(FileNameLength) WCHAR FileName[1]; +} FILE_LINK_INFORMATION_EX, *PFILE_LINK_INFORMATION_EX; + +typedef struct _FILE_MOVE_CLUSTER_INFORMATION +{ + ULONG ClusterCount; + HANDLE RootDirectory; + ULONG FileNameLength; + _Field_size_bytes_(FileNameLength) WCHAR FileName[1]; +} FILE_MOVE_CLUSTER_INFORMATION, *PFILE_MOVE_CLUSTER_INFORMATION; + +typedef struct _FILE_RENAME_INFORMATION +{ + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + _Field_size_bytes_(FileNameLength) WCHAR FileName[1]; +} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; + +#define FILE_RENAME_REPLACE_IF_EXISTS 0x00000001 // since REDSTONE +#define FILE_RENAME_POSIX_SEMANTICS 0x00000002 +#define FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE 0x00000004 // since REDSTONE3 +#define FILE_RENAME_SUPPRESS_STORAGE_RESERVE_INHERITANCE 0x00000008 // since REDSTONE5 +#define FILE_RENAME_NO_INCREASE_AVAILABLE_SPACE 0x00000010 +#define FILE_RENAME_NO_DECREASE_AVAILABLE_SPACE 0x00000020 +#define FILE_RENAME_PRESERVE_AVAILABLE_SPACE 0x00000030 +#define FILE_RENAME_IGNORE_READONLY_ATTRIBUTE 0x00000040 +#define FILE_RENAME_FORCE_RESIZE_TARGET_SR 0x00000080 // since 19H1 +#define FILE_RENAME_FORCE_RESIZE_SOURCE_SR 0x00000100 +#define FILE_RENAME_FORCE_RESIZE_SR 0x00000180 + +typedef struct _FILE_RENAME_INFORMATION_EX +{ + ULONG Flags; + HANDLE RootDirectory; + ULONG FileNameLength; + _Field_size_bytes_(FileNameLength) WCHAR FileName[1]; +} FILE_RENAME_INFORMATION_EX, *PFILE_RENAME_INFORMATION_EX; + +typedef struct _FILE_STREAM_INFORMATION +{ + ULONG NextEntryOffset; + ULONG StreamNameLength; + LARGE_INTEGER StreamSize; + LARGE_INTEGER StreamAllocationSize; + _Field_size_bytes_(StreamNameLength) WCHAR StreamName[1]; +} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION; + +typedef struct _FILE_TRACKING_INFORMATION +{ + HANDLE DestinationFile; + ULONG ObjectInformationLength; + _Field_size_bytes_(ObjectInformationLength) CHAR ObjectInformation[1]; +} FILE_TRACKING_INFORMATION, *PFILE_TRACKING_INFORMATION; + +typedef struct _FILE_COMPLETION_INFORMATION +{ + HANDLE Port; + PVOID Key; +} FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION; + +typedef struct _FILE_PROCESS_IDS_USING_FILE_INFORMATION +{ + ULONG NumberOfProcessIdsInList; + ULONG_PTR ProcessIdList[1]; +} FILE_PROCESS_IDS_USING_FILE_INFORMATION, *PFILE_PROCESS_IDS_USING_FILE_INFORMATION; + // Privileges #define SE_MIN_WELL_KNOWN_PRIVILEGE (2L) #define SE_CREATE_TOKEN_PRIVILEGE (2L) @@ -514,13 +904,32 @@ typedef struct _MEMORY_REGION_INFORMATION ULONG MappedPageFile : 1; ULONG MappedPhysical : 1; ULONG DirectMapped : 1; - ULONG Reserved : 26; + ULONG SoftwareEnclave : 1; //REDSTONE3 + ULONG PageSize64K : 1; + ULONG Reserved : 24; } s; } u; SIZE_T RegionSize; SIZE_T CommitSize; } MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION; +typedef struct _MEMORY_IMAGE_INFORMATION +{ + PVOID ImageBase; + SIZE_T SizeOfImage; + union + { + ULONG ImageFlags; + struct + { + ULONG ImagePartialMap : 1; + ULONG ImageNotExecutable : 1; + ULONG ImageSigningLevel : 1; // REDSTONE3 + ULONG Reserved : 30; + } s1; + } u1; +} MEMORY_IMAGE_INFORMATION, *PMEMORY_IMAGE_INFORMATION; + typedef struct _SECTION_BASIC_INFORMATION { PVOID BaseAddress; @@ -584,14 +993,55 @@ typedef struct _SECTION_INTERNAL_IMAGE_INFORMATION ULONG ExtendedFlags; struct { - ULONG ImageReturnFlowGuardEnabled : 1; - ULONG ImageReturnFlowGuardStrict : 1; ULONG ImageExportSuppressionEnabled : 1; - ULONG Reserved : 29; + ULONG Reserved : 31; } s; } u; } SECTION_INTERNAL_IMAGE_INFORMATION, *PSECTION_INTERNAL_IMAGE_INFORMATION; +typedef struct _IMAGE_INFO +{ + union + { + ULONG Properties; + struct + { + ULONG ImageAddressingMode : 8; // Code addressing mode + ULONG SystemModeImage : 1; // System mode image + ULONG ImageMappedToAllPids : 1; // Image mapped into all processes + ULONG ExtendedInfoPresent : 1; // IMAGE_INFO_EX available + ULONG MachineTypeMismatch : 1; // Architecture type mismatch + ULONG ImageSignatureLevel : 4; // Signature level + ULONG ImageSignatureType : 3; // Signature type + ULONG ImagePartialMap : 1; // Nonzero if entire image is not mapped + ULONG Reserved : 12; + } s1; + } u1; + PVOID ImageBase; + ULONG ImageSelector; + SIZE_T ImageSize; + ULONG ImageSectionNumber; +} IMAGE_INFO, *PIMAGE_INFO; + +typedef struct _PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION +{ + ULONG Version; // Set to 0 for x64, 1 for native x86, and use as PVOID Callback on WOW64 + ULONG Reserved; + PVOID Callback; +} PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION, *PPROCESS_INSTRUMENTATION_CALLBACK_INFORMATION; + +typedef struct _THREAD_LAST_SYSCALL_INFORMATION +{ + PVOID FirstArgument; + USHORT SystemCallNumber; +#ifdef _WIN64 + USHORT Pad[0x3]; +#else + USHORT Pad[0x1]; +#endif + ULONG64 WaitTime; // may be omitted +} THREAD_LAST_SYSCALL_INFORMATION, *PTHREAD_LAST_SYSCALL_INFORMATION; + typedef struct _OBJECT_ATTRIBUTES { ULONG Length; @@ -684,6 +1134,379 @@ typedef struct _RTL_PROCESS_MODULE_INFORMATION_EX PVOID DefaultBase; } RTL_PROCESS_MODULE_INFORMATION_EX, *PRTL_PROCESS_MODULE_INFORMATION_EX; +typedef struct _SYSTEM_PROCESS_ID_INFORMATION +{ + HANDLE ProcessId; + UNICODE_STRING ImageName; +} SYSTEM_PROCESS_ID_INFORMATION, *PSYSTEM_PROCESS_ID_INFORMATION; + +typedef struct _SYSTEM_HYPERVISOR_QUERY_INFORMATION +{ + BOOLEAN HypervisorConnected; + BOOLEAN HypervisorDebuggingEnabled; + BOOLEAN HypervisorPresent; + BOOLEAN Spare0[5]; + ULONGLONG EnabledEnlightenments; +} SYSTEM_HYPERVISOR_QUERY_INFORMATION, *PSYSTEM_HYPERVISOR_QUERY_INFORMATION; + +typedef struct _SYSTEM_CODEINTEGRITY_INFORMATION +{ + ULONG Length; + ULONG CodeIntegrityOptions; +} SYSTEM_CODEINTEGRITY_INFORMATION, *PSYSTEM_CODEINTEGRITY_INFORMATION; + +#define CODEINTEGRITY_OPTION_ENABLED 0x01 +#define CODEINTEGRITY_OPTION_TESTSIGN 0x02 +#define CODEINTEGRITY_OPTION_UMCI_ENABLED 0x04 +#define CODEINTEGRITY_OPTION_UMCI_AUDITMODE_ENABLED 0x08 +#define CODEINTEGRITY_OPTION_UMCI_EXCLUSIONPATHS_ENABLED 0x10 +#define CODEINTEGRITY_OPTION_TEST_BUILD 0x20 +#define CODEINTEGRITY_OPTION_PREPRODUCTION_BUILD 0x40 +#define CODEINTEGRITY_OPTION_DEBUGMODE_ENABLED 0x80 +#define CODEINTEGRITY_OPTION_FLIGHT_BUILD 0x100 +#define CODEINTEGRITY_OPTION_FLIGHTING_ENABLED 0x200 +#define CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED 0x400 +#define CODEINTEGRITY_OPTION_HVCI_KMCI_AUDITMODE_ENABLED 0x800 +#define CODEINTEGRITY_OPTION_HVCI_KMCI_STRICTMODE_ENABLED 0x1000 +#define CODEINTEGRITY_OPTION_HVCI_IUM_ENABLED 0x2000 +#define CODEINTEGRITY_OPTION_WHQL_ENFORCEMENT_ENABLED 0x4000 +#define CODEINTEGRITY_OPTION_WHQL_AUDITMODE_ENABLED 0x8000 + +typedef struct _SYSTEM_SECUREBOOT_POLICY_INFORMATION +{ + GUID PolicyPublisher; + ULONG PolicyVersion; + ULONG PolicyOptions; +} SYSTEM_SECUREBOOT_POLICY_INFORMATION, *PSYSTEM_SECUREBOOT_POLICY_INFORMATION; + +typedef struct _SYSTEM_SECUREBOOT_POLICY_FULL_INFORMATION +{ + SYSTEM_SECUREBOOT_POLICY_INFORMATION PolicyInformation; + ULONG PolicySize; + UCHAR Policy[1]; +} SYSTEM_SECUREBOOT_POLICY_FULL_INFORMATION, *PSYSTEM_SECUREBOOT_POLICY_FULL_INFORMATION; + +typedef struct _SYSTEM_ISOLATED_USER_MODE_INFORMATION +{ + BOOLEAN SecureKernelRunning : 1; + BOOLEAN HvciEnabled : 1; + BOOLEAN HvciStrictMode : 1; + BOOLEAN DebugEnabled : 1; + BOOLEAN FirmwarePageProtection : 1; + BOOLEAN EncryptionKeyAvailable : 1; + BOOLEAN SpareFlags : 2; + BOOLEAN TrustletRunning : 1; + BOOLEAN HvciDisableAllowed : 1; + BOOLEAN SpareFlags2 : 6; + BOOLEAN Spare0[6]; + ULONGLONG Spare1; +} SYSTEM_ISOLATED_USER_MODE_INFORMATION, *PSYSTEM_ISOLATED_USER_MODE_INFORMATION; + +typedef struct _SYSTEM_TPM_INFORMATION +{ + ULONG Flags; +} SYSTEM_TPM_INFORMATION, *PSYSTEM_TPM_INFORMATION; + +typedef struct _SYSTEM_VSM_PROTECTION_INFORMATION +{ + BOOLEAN DmaProtectionsAvailable; + BOOLEAN DmaProtectionsInUse; + BOOLEAN HardwareMbecAvailable; + BOOLEAN ApicVirtualizationAvailable; +} SYSTEM_VSM_PROTECTION_INFORMATION, *PSYSTEM_VSM_PROTECTION_INFORMATION; + +typedef struct _SYSTEM_KERNEL_DEBUGGER_FLAGS +{ + BOOLEAN KernelDebuggerIgnoreUmExceptions; +} SYSTEM_KERNEL_DEBUGGER_FLAGS, *PSYSTEM_KERNEL_DEBUGGER_FLAGS; + +typedef struct _SYSTEM_SINGLE_MODULE_INFORMATION +{ + PVOID TargetModuleAddress; + RTL_PROCESS_MODULE_INFORMATION_EX ExInfo; +} SYSTEM_SINGLE_MODULE_INFORMATION, *PSYSTEM_SINGLE_MODULE_INFORMATION; + +// SYSTEM_CODEINTEGRITYPOLICY_INFORMATION Options +#define CODEINTEGRITYPOLICY_OPTION_ENABLED 0x01 +#define CODEINTEGRITYPOLICY_OPTION_AUDIT 0x02 +#define CODEINTEGRITYPOLICY_OPTION_REQUIRE_WHQL 0x04 +#define CODEINTEGRITYPOLICY_OPTION_DISABLED_FLIGHTSIGNING 0x08 +#define CODEINTEGRITYPOLICY_OPTION_ENABLED_UMCI 0x10 +#define CODEINTEGRITYPOLICY_OPTION_ENABLED_UPDATE_POLICY_NOREBOOT 0x20 +#define CODEINTEGRITYPOLICY_OPTION_ENABLED_SECURE_SETTING_POLICY 0x40 +#define CODEINTEGRITYPOLICY_OPTION_ENABLED_UNSIGNED_SYSTEMINTEGRITY_POLICY 0x80 +#define CODEINTEGRITYPOLICY_OPTION_DYNAMIC_CODE_POLICY_ENABLED 0x100 +#define CODEINTEGRITYPOLICY_OPTION_RELOAD_POLICY_NO_REBOOT 0x10000000 // NtSetSystemInformation reloads SiPolicy.p7b +#define CODEINTEGRITYPOLICY_OPTION_CONDITIONAL_LOCKDOWN 0x20000000 +#define CODEINTEGRITYPOLICY_OPTION_NOLOCKDOWN 0x40000000 +#define CODEINTEGRITYPOLICY_OPTION_LOCKDOWN 0x80000000 + +// SYSTEM_CODEINTEGRITYPOLICY_INFORMATION HVCIOptions +#define CODEINTEGRITYPOLICY_HVCIOPTION_ENABLED 0x01 +#define CODEINTEGRITYPOLICY_HVCIOPTION_STRICT 0x02 +#define CODEINTEGRITYPOLICY_HVCIOPTION_DEBUG 0x04 + +typedef struct _SYSTEM_CODEINTEGRITYPOLICY_INFORMATION +{ + ULONG Options; + ULONG HVCIOptions; + ULONGLONG Version; + GUID PolicyGuid; +} SYSTEM_CODEINTEGRITYPOLICY_INFORMATION, *PSYSTEM_CODEINTEGRITYPOLICY_INFORMATION; + +typedef struct _SYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION +{ + HANDLE ImageFile; +} SYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION, *PSYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION; + +typedef struct _SYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION +{ + union + { + ULONG Flags; + struct + { + ULONG Locked : 1; + ULONG UnlockApplied : 1; // Unlockable field removed 19H1 + ULONG UnlockIdValid : 1; + ULONG Reserved : 29; + } s1; + } u1; + UCHAR UnlockId[32]; // REDSTONE4 +} SYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION, *PSYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION; + +typedef struct _SYSTEM_CODEINTEGRITYVERIFICATION_INFORMATION +{ + HANDLE FileHandle; + ULONG ImageSize; + PVOID Image; +} SYSTEM_CODEINTEGRITYVERIFICATION_INFORMATION, *PSYSTEM_CODEINTEGRITYVERIFICATION_INFORMATION; + +typedef struct _SYSTEM_SECURE_KERNEL_HYPERGUARD_PROFILE_INFORMATION +{ + ULONG ExtentCount; + ULONG ValidStructureSize; + ULONG NextExtentIndex; + ULONG ExtentRestart; + ULONG CycleCount; + ULONG TimeoutCount; + ULONGLONG CycleTime; + ULONGLONG CycleTimeMax; + ULONGLONG ExtentTime; + ULONG ExtentTimeIndex; + ULONG ExtentTimeMaxIndex; + ULONGLONG ExtentTimeMax; + ULONGLONG HyperFlushTimeMax; + ULONGLONG TranslateVaTimeMax; + ULONGLONG DebugExemptionCount; + ULONGLONG TbHitCount; + ULONGLONG TbMissCount; + ULONGLONG VinaPendingYield; + ULONGLONG HashCycles; + ULONG HistogramOffset; + ULONG HistogramBuckets; + ULONG HistogramShift; + ULONG Reserved1; + ULONGLONG PageNotPresentCount; +} SYSTEM_SECURE_KERNEL_HYPERGUARD_PROFILE_INFORMATION, *PSYSTEM_SECURE_KERNEL_HYPERGUARD_PROFILE_INFORMATION; + +typedef struct _SYSTEM_SECUREBOOT_PLATFORM_MANIFEST_INFORMATION +{ + ULONG PlatformManifestSize; + UCHAR PlatformManifest[1]; +} SYSTEM_SECUREBOOT_PLATFORM_MANIFEST_INFORMATION, *PSYSTEM_SECUREBOOT_PLATFORM_MANIFEST_INFORMATION; + +typedef struct _SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION +{ + PVOID HypervisorSharedUserVa; +} SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION, *PSYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION; + +typedef struct _SYSTEM_FIRMWARE_PARTITION_INFORMATION +{ + UNICODE_STRING FirmwarePartition; +} SYSTEM_FIRMWARE_PARTITION_INFORMATION, *PSYSTEM_FIRMWARE_PARTITION_INFORMATION; + +typedef struct _SYSTEM_DMA_GUARD_POLICY_INFORMATION +{ + BOOLEAN DmaGuardPolicyEnabled; +} SYSTEM_DMA_GUARD_POLICY_INFORMATION, *PSYSTEM_DMA_GUARD_POLICY_INFORMATION; + +typedef struct _SYSTEM_SHADOW_STACK_INFORMATION +{ + union + { + ULONG Flags; + struct + { + ULONG CetCapable : 1; + ULONG UserCetAllowed : 1; + ULONG ReservedForUserCet : 6; + ULONG KernelCetEnabled : 1; + ULONG KernelCetAuditModeEnabled : 1; + ULONG ReservedForKernelCet : 6; // since Windows 10 build 21387 + ULONG Reserved : 16; + } s; + } u; +} SYSTEM_SHADOW_STACK_INFORMATION, *PSYSTEM_SHADOW_STACK_INFORMATION; + +typedef union _SYSTEM_BUILD_VERSION_INFORMATION_FLAGS +{ + ULONG Value32; + struct + { + ULONG IsTopLevel : 1; + ULONG IsChecked : 1; + } s; +} SYSTEM_BUILD_VERSION_INFORMATION_FLAGS, *PSYSTEM_BUILD_VERSION_INFORMATION_FLAGS; + +typedef struct _SYSTEM_BUILD_VERSION_INFORMATION +{ + USHORT LayerNumber; + USHORT LayerCount; + ULONG OsMajorVersion; + ULONG OsMinorVersion; + ULONG NtBuildNumber; + ULONG NtBuildQfe; + UCHAR LayerName[128]; + UCHAR NtBuildBranch[128]; + UCHAR NtBuildLab[128]; + UCHAR NtBuildLabEx[128]; + UCHAR NtBuildStamp[26]; + UCHAR NtBuildArch[16]; + SYSTEM_BUILD_VERSION_INFORMATION_FLAGS Flags; +} SYSTEM_BUILD_VERSION_INFORMATION, *PSYSTEM_BUILD_VERSION_INFORMATION; + +typedef struct _SYSTEM_XFG_FAILURE_INFORMATION +{ + PVOID ReturnAddress; + PVOID TargetAddress; + ULONG DispatchMode; + ULONGLONG XfgValue; +} SYSTEM_XFG_FAILURE_INFORMATION, *PSYSTEM_XFG_FAILURE_INFORMATION; + +typedef enum _SYSTEM_IOMMU_STATE +{ + IommuStateBlock, + IommuStateUnblock +} SYSTEM_IOMMU_STATE; + +typedef struct _SYSTEM_IOMMU_STATE_INFORMATION +{ + SYSTEM_IOMMU_STATE State; + PVOID Pdo; +} SYSTEM_IOMMU_STATE_INFORMATION, *PSYSTEM_IOMMU_STATE_INFORMATION; + +typedef struct _SYSTEM_HYPERVISOR_BOOT_PAGES_INFORMATION +{ + ULONG RangeCount; + ULONG_PTR RangeArray[1]; +} SYSTEM_HYPERVISOR_BOOT_PAGES_INFORMATION, *PSYSTEM_HYPERVISOR_BOOT_PAGES_INFORMATION; + +typedef struct _SYSTEM_POINTER_AUTH_INFORMATION +{ + union + { + USHORT SupportedFlags; + struct + { + USHORT AddressAuthSupported : 1; + USHORT AddressAuthQarma : 1; + USHORT GenericAuthSupported : 1; + USHORT GenericAuthQarma : 1; + USHORT SupportedReserved : 12; + } s1; + } u1; + union + { + USHORT EnabledFlags; + struct + { + USHORT UserPerProcessIpAuthEnabled : 1; + USHORT UserGlobalIpAuthEnabled : 1; + USHORT UserEnabledReserved : 6; + USHORT KernelIpAuthEnabled : 1; + USHORT KernelEnabledReserved : 7; + } s2; + } u2; +} SYSTEM_POINTER_AUTH_INFORMATION, *PSYSTEM_POINTER_AUTH_INFORMATION; + +typedef +NTSTATUS +NTAPI +RTL_QUERY_REGISTRY_ROUTINE( + _In_z_ PWSTR ValueName, + _In_ ULONG ValueType, + _In_opt_ PVOID ValueData, + _In_ ULONG ValueLength, + _In_opt_ PVOID Context, + _In_opt_ PVOID EntryContext +); +typedef RTL_QUERY_REGISTRY_ROUTINE* PRTL_QUERY_REGISTRY_ROUTINE; + +typedef struct _RTL_QUERY_REGISTRY_TABLE +{ + PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine; + ULONG Flags; + PWSTR Name; + PVOID EntryContext; + ULONG DefaultType; + PVOID DefaultData; + ULONG DefaultLength; +} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE; + +// RtlQueryRegistryValues flags +#define RTL_QUERY_REGISTRY_SUBKEY 0x00000001 +#define RTL_QUERY_REGISTRY_TOPKEY 0x00000002 +#define RTL_QUERY_REGISTRY_REQUIRED 0x00000004 +#define RTL_QUERY_REGISTRY_NOVALUE 0x00000008 +#define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010 +#define RTL_QUERY_REGISTRY_DIRECT 0x00000020 +#define RTL_QUERY_REGISTRY_DELETE 0x00000040 +#define RTL_QUERY_REGISTRY_NOSTRING 0x00000080 +#define RTL_QUERY_REGISTRY_TYPECHECK 0x00000100 + +#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT 24 +#define RTL_QUERY_REGISTRY_TYPECHECK_MASK (0xff << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) + +// RtlWriteRegistryValue RelativeTo values +#define RTL_REGISTRY_ABSOLUTE 0 // Path is a full path +#define RTL_REGISTRY_SERVICES 1 // \Registry\Machine\System\CurrentControlSet\Services +#define RTL_REGISTRY_CONTROL 2 // \Registry\Machine\System\CurrentControlSet\Control +#define RTL_REGISTRY_WINDOWS_NT 3 // \Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion +#define RTL_REGISTRY_DEVICEMAP 4 // \Registry\Machine\Hardware\DeviceMap +#define RTL_REGISTRY_USER 5 // \Registry\User\CurrentUser +#define RTL_REGISTRY_MAXIMUM 6 +#define RTL_REGISTRY_HANDLE 0x40000000 // Low order bits are registry handle +#define RTL_REGISTRY_OPTIONAL 0x80000000 // Indicates the key node is optional + +typedef struct _PROCESS_HANDLE_INFORMATION +{ + ULONG HandleCount; + ULONG HandleCountHighWatermark; +} PROCESS_HANDLE_INFORMATION, *PPROCESS_HANDLE_INFORMATION; + +#if NTDDI_VERSION >= NTDDI_VISTA +typedef struct _PROCESS_MITIGATION_POLICY_INFORMATION +{ + PROCESS_MITIGATION_POLICY Policy; + union + { + PROCESS_MITIGATION_ASLR_POLICY ASLRPolicy; + PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY StrictHandleCheckPolicy; + PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY SystemCallDisablePolicy; + PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY ExtensionPointDisablePolicy; + PROCESS_MITIGATION_DYNAMIC_CODE_POLICY DynamicCodePolicy; + PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY ControlFlowGuardPolicy; + PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY SignaturePolicy; + PROCESS_MITIGATION_FONT_DISABLE_POLICY FontDisablePolicy; + PROCESS_MITIGATION_IMAGE_LOAD_POLICY ImageLoadPolicy; + PROCESS_MITIGATION_SYSTEM_CALL_FILTER_POLICY SystemCallFilterPolicy; + PROCESS_MITIGATION_PAYLOAD_RESTRICTION_POLICY PayloadRestrictionPolicy; + PROCESS_MITIGATION_CHILD_PROCESS_POLICY ChildProcessPolicy; + }; +} PROCESS_MITIGATION_POLICY_INFORMATION, *PPROCESS_MITIGATION_POLICY_INFORMATION; +#endif + typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO { USHORT UniqueProcessId; @@ -779,6 +1602,33 @@ typedef struct _OBJECT_HANDLE_FLAG_INFORMATION BOOLEAN ProtectFromClose; } OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION; +typedef struct _OBJECT_DIRECTORY_INFORMATION +{ + UNICODE_STRING Name; + UNICODE_STRING TypeName; +} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; + +typedef struct _SYSTEM_BIGPOOL_ENTRY +{ + union + { + PVOID VirtualAddress; + ULONG_PTR NonPaged : 1; + } u1; + SIZE_T SizeInBytes; + union + { + UCHAR Tag[4]; + ULONG TagUlong; + } u2; +} SYSTEM_BIGPOOL_ENTRY, *PSYSTEM_BIGPOOL_ENTRY; + +typedef struct _SYSTEM_BIGPOOL_INFORMATION +{ + ULONG Count; + SYSTEM_BIGPOOL_ENTRY AllocatedInfo[1]; +} SYSTEM_BIGPOOL_INFORMATION, *PSYSTEM_BIGPOOL_INFORMATION; + typedef struct _DBGKM_EXCEPTION { EXCEPTION_RECORD ExceptionRecord; @@ -1021,8 +1871,9 @@ typedef enum _RTL_PATH_TYPE RtlPathTypeRootLocalDevice, } RTL_PATH_TYPE; -#define DOS_MAX_COMPONENT_LENGTH 255 -#define DOS_MAX_PATH_LENGTH (DOS_MAX_COMPONENT_LENGTH + 5) +#define DOS_MAX_COMPONENT_LENGTH 255 +#define DOS_MAX_PATH_LENGTH (DOS_MAX_COMPONENT_LENGTH + 5) +#define NT_MAX_PATH_LENGTH ( (sizeof("\\??\\UNC\\") - sizeof(CHAR) ) + DOS_MAX_PATH_LENGTH + 1) typedef struct _CURDIR { @@ -1109,6 +1960,8 @@ typedef enum _LDR_DLL_LOAD_REASON LoadReasonDynamicLoad, LoadReasonAsImageLoad, LoadReasonAsDataLoad, + LoadReasonEnclavePrimary, // REDSTONE3 + LoadReasonEnclaveDependency, LoadReasonUnknown = -1 } LDR_DLL_LOAD_REASON, *PLDR_DLL_LOAD_REASON; @@ -1141,13 +1994,13 @@ typedef struct _RTL_BALANCED_NODE struct _RTL_BALANCED_NODE* Left; struct _RTL_BALANCED_NODE* Right; } s; - }; + } u1; union { UCHAR Red : 1; UCHAR Balance : 2; ULONG_PTR ParentValue; - } u; + } u2; } RTL_BALANCED_NODE, *PRTL_BALANCED_NODE; typedef struct _LDR_DATA_TABLE_ENTRY @@ -1260,12 +2113,6 @@ typedef struct _FILE_IO_COMPLETION_INFORMATION IO_STATUS_BLOCK IoStatusBlock; } FILE_IO_COMPLETION_INFORMATION, *PFILE_IO_COMPLETION_INFORMATION; -typedef struct _FILE_COMPLETION_INFORMATION -{ - HANDLE Port; - PVOID Key; -} FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION; - #ifdef __cplusplus typedef enum _PRIORITY_CLASS : UCHAR { @@ -1301,8 +2148,8 @@ typedef struct _PS_ATTRIBUTE typedef struct _PS_ATTRIBUTE_LIST { - SIZE_T TotalLength; // sizeof(PS_ATTRIBUTE_LIST) - PS_ATTRIBUTE Attributes[2]; // Depends on how many attribute entries should be supplied to NtCreateUserProcess + SIZE_T TotalLength; // sizeof(PS_ATTRIBUTE_LIST) + * sizeof(PS_ATTRIBUTE) + PS_ATTRIBUTE Attributes[1]; // Depends on how many attribute entries should be supplied to NtCreateUserProcess } PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST; typedef struct _PS_MEMORY_RESERVE @@ -1344,6 +2191,7 @@ typedef enum _PS_ATTRIBUTE_NUM PsAttributeSafeOpenPromptOriginClaim, PsAttributeBnoIsolation, PsAttributeDesktopAppPolicy, + PsAttributeChpe, // since REDSTONE3 PsAttributeMax } PS_ATTRIBUTE_NUM; @@ -1387,6 +2235,22 @@ typedef enum _PS_ATTRIBUTE_NUM PsAttributeValue(PsAttributeMitigationOptions, FALSE, TRUE, TRUE) // 0x60010 #define PS_ATTRIBUTE_PROTECTION_LEVEL \ PsAttributeValue(PsAttributeProtectionLevel, FALSE, TRUE, FALSE) // 0x20011 +#define PS_ATTRIBUTE_SECURE_PROCESS \ + PsAttributeValue(PsAttributeSecureProcess, FALSE, TRUE, FALSE) // 0x20012 +#define PS_ATTRIBUTE_JOB_LIST \ + PsAttributeValue(PsAttributeJobList, FALSE, TRUE, FALSE) // 0x20013 +#define PS_ATTRIBUTE_CHILD_PROCESS_POLICY \ + PsAttributeValue(PsAttributeChildProcessPolicy, FALSE, TRUE, FALSE) // 0x20014 +#define PS_ATTRIBUTE_ALL_APPLICATION_PACKAGES_POLICY \ + PsAttributeValue(PsAttributeAllApplicationPackagesPolicy, FALSE, TRUE, FALSE) // 0x20015 +#define PS_ATTRIBUTE_WIN32K_FILTER \ + PsAttributeValue(PsAttributeWin32kFilter, FALSE, TRUE, FALSE) // 0x20016 +#define PS_ATTRIBUTE_SAFE_OPEN_PROMPT_ORIGIN_CLAIM \ + PsAttributeValue(PsAttributeSafeOpenPromptOriginClaim, FALSE, TRUE, FALSE) // 0x20017 +#define PS_ATTRIBUTE_BNO_ISOLATION \ + PsAttributeValue(PsAttributeBnoIsolation, FALSE, TRUE, FALSE) // 0x20018 +#define PS_ATTRIBUTE_DESKTOP_APP_POLICY \ + PsAttributeValue(PsAttributeDesktopAppPolicy, FALSE, TRUE, FALSE) // 0x20019 typedef enum _PS_STD_HANDLE_STATE { @@ -1414,7 +2278,7 @@ typedef struct _PS_STD_HANDLE_INFO ULONG StdHandleState : 2; // PS_STD_HANDLE_STATE ULONG PseudoHandleMask : 3; // PS_STD_* } s; - }; + } u; ULONG StdHandleSubsystemType; } PS_STD_HANDLE_INFO, *PPS_STD_HANDLE_INFO; @@ -1447,7 +2311,15 @@ typedef enum _PS_MITIGATION_OPTION PS_MITIGATION_OPTION_RETURN_FLOW_GUARD, PS_MITIGATION_OPTION_LOADER_INTEGRITY_CONTINUITY, PS_MITIGATION_OPTION_STRICT_CONTROL_FLOW_GUARD, - PS_MITIGATION_OPTION_RESTRICT_SET_THREAD_CONTEXT + PS_MITIGATION_OPTION_RESTRICT_SET_THREAD_CONTEXT, + PS_MITIGATION_OPTION_ROP_STACKPIVOT, // since REDSTONE3 + PS_MITIGATION_OPTION_ROP_CALLER_CHECK, + PS_MITIGATION_OPTION_ROP_SIMEXEC, + PS_MITIGATION_OPTION_EXPORT_ADDRESS_FILTER, + PS_MITIGATION_OPTION_EXPORT_ADDRESS_FILTER_PLUS, + PS_MITIGATION_OPTION_RESTRICT_CHILD_PROCESS_CREATION, + PS_MITIGATION_OPTION_IMPORT_ADDRESS_FILTER, + PS_MITIGATION_OPTION_MODULE_TAMPERING_PROTECTION } PS_MITIGATION_OPTION; typedef enum _PS_CREATE_STATE @@ -1484,7 +2356,7 @@ typedef struct _PS_CREATE_INFO UCHAR SpareBits2 : 8; USHORT ProhibitedImageCharacteristics : 16; } s1; - } u1; + } u2; ACCESS_MASK AdditionalFileAccess; } InitState; @@ -1523,7 +2395,7 @@ typedef struct _PS_CREATE_INFO UCHAR SpareBits2 : 8; USHORT SpareBits3 : 16; } s2; - } u2; + } u3; HANDLE FileHandle; HANDLE SectionHandle; ULONGLONG UserProcessParametersNative; @@ -1534,7 +2406,7 @@ typedef struct _PS_CREATE_INFO ULONGLONG ManifestAddress; ULONG ManifestSize; } SuccessState; - }; + } u1; } PS_CREATE_INFO, *PPS_CREATE_INFO; #define PROCESS_CREATE_FLAGS_BREAKAWAY 0x00000001 @@ -1548,6 +2420,8 @@ typedef struct _PS_CREATE_INFO #define PROCESS_CREATE_FLAGS_PROTECTED_PROCESS 0x00000040 // Only allowed if the calling process is itself protected #define PROCESS_CREATE_FLAGS_CREATE_SESSION 0x00000080 #define PROCESS_CREATE_FLAGS_INHERIT_FROM_PARENT 0x00000100 +#define PROCESS_CREATE_FLAGS_SUSPENDED 0x00000200 +#define PROCESS_CREATE_FLAGS_EXTENDED_UNKNOWN 0x00000400 typedef enum _MEMORY_RESERVE_TYPE { @@ -1569,7 +2443,6 @@ typedef struct _PROCESS_HANDLE_TRACING_ENABLE_EX ULONG TotalSlots; } PROCESS_HANDLE_TRACING_ENABLE_EX, *PPROCESS_HANDLE_TRACING_ENABLE_EX; -// Source: http://processhacker.sourceforge.net typedef enum _PROCESSINFOCLASS { ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION @@ -1580,20 +2453,20 @@ typedef enum _PROCESSINFOCLASS ProcessBasePriority, // s: KPRIORITY ProcessRaisePriority, // s: ULONG ProcessDebugPort, // q: HANDLE - ProcessExceptionPort, // s: HANDLE + ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT (requires SeTcbPrivilege) ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10 ProcessLdtSize, // s: PROCESS_LDT_SIZE ProcessDefaultHardErrorMode, // qs: ULONG - ProcessIoPortHandlers, // (kernel-mode only) + ProcessIoPortHandlers, // (kernel-mode only) // PROCESS_IO_PORT_HANDLER_INFORMATION ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void - ProcessUserModeIOPL, + ProcessUserModeIOPL, // qs: ULONG (requires SeTcbPrivilege) ProcessEnableAlignmentFaultFixup, // s: BOOLEAN ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS - ProcessWx86Information, + ProcessWx86Information, // qs: ULONG (requires SeTcbPrivilege) (VdmAllowed) ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20 - ProcessAffinityMask, // s: KAFFINITY + ProcessAffinityMask, // (q >WIN7)s: KAFFINITY, qs: GROUP_AFFINITY ProcessPriorityBoost, // qs: ULONG ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION @@ -1607,12 +2480,12 @@ typedef enum _PROCESSINFOCLASS ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables ProcessIoPriority, // qs: IO_PRIORITY_HINT ProcessExecuteFlags, // qs: ULONG - ProcessResourceManagement, + ProcessTlsInformation, // PROCESS_TLS_INFORMATION // ProcessResourceManagement ProcessCookie, // q: ULONG ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA - ProcessPagePriority, // q: ULONG - ProcessInstrumentationCallback, // 40 + ProcessPagePriority, // qs: PAGE_PRIORITY_INFORMATION + ProcessInstrumentationCallback, // s: PVOID or PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40 ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[] ProcessImageFileNameWin32, // q: UNICODE_STRING @@ -1621,44 +2494,72 @@ typedef enum _PROCESSINFOCLASS ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE ProcessGroupInformation, // q: USHORT[] ProcessTokenVirtualizationEnabled, // s: ULONG - ProcessConsoleHostProcess, // q: ULONG_PTR + ProcessConsoleHostProcess, // q: ULONG_PTR // ProcessOwnerInformation ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50 ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION ProcessDynamicFunctionTableInformation, - ProcessHandleCheckingMode, + ProcessHandleCheckingMode, // qs: ULONG; s: 0 disables, otherwise enables ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL - ProcessHandleTable, // since WINBLUE - ProcessCheckStackExtentsMode, + ProcessHandleTable, // q: ULONG[] // since WINBLUE + ProcessCheckStackExtentsMode, // qs: ULONG // KPROCESS->CheckStackExtents (CFG) ProcessCommandLineInformation, // q: UNICODE_STRING // 60 ProcessProtectionInformation, // q: PS_PROTECTION ProcessMemoryExhaustion, // PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD ProcessFaultInformation, // PROCESS_FAULT_INFORMATION - ProcessTelemetryIdInformation, // PROCESS_TELEMETRY_ID_INFORMATION + ProcessTelemetryIdInformation, // q: PROCESS_TELEMETRY_ID_INFORMATION ProcessCommitReleaseInformation, // PROCESS_COMMIT_RELEASE_INFORMATION - ProcessDefaultCpuSetsInformation, - ProcessAllowedCpuSetsInformation, + ProcessDefaultCpuSetsInformation, // SYSTEM_CPU_SET_INFORMATION[5] + ProcessAllowedCpuSetsInformation, // SYSTEM_CPU_SET_INFORMATION[5] ProcessSubsystemProcess, - ProcessJobMemoryInformation, // PROCESS_JOB_MEMORY_INFO - ProcessInPrivate, // since THRESHOLD2 // 70 - ProcessRaiseUMExceptionOnInvalidHandleClose, + ProcessJobMemoryInformation, // q: PROCESS_JOB_MEMORY_INFO + ProcessInPrivate, // s: void // ETW // since THRESHOLD2 // 70 + ProcessRaiseUMExceptionOnInvalidHandleClose, // qs: ULONG; s: 0 disables, otherwise enables ProcessIumChallengeResponse, - ProcessChildProcessInformation, // PROCESS_CHILD_PROCESS_INFORMATION - ProcessHighGraphicsPriorityInformation, + ProcessChildProcessInformation, // q: PROCESS_CHILD_PROCESS_INFORMATION + ProcessHighGraphicsPriorityInformation, // qs: BOOLEAN (requires SeTcbPrivilege) ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 - ProcessEnergyValues, // PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES - ProcessActivityThrottleState, // PROCESS_ACTIVITY_THROTTLE_STATE - ProcessActivityThrottlePolicy, // PROCESS_ACTIVITY_THROTTLE_POLICY - ProcessWin32kSyscallFilterInformation, - ProcessDisableSystemAllowedCpuSets, + ProcessEnergyValues, // q: PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES + ProcessPowerThrottlingState, // qs: POWER_THROTTLING_PROCESS_STATE + ProcessReserved3Information, // ProcessActivityThrottlePolicy // PROCESS_ACTIVITY_THROTTLE_POLICY + ProcessWin32kSyscallFilterInformation, // q: WIN32K_SYSCALL_FILTER + ProcessDisableSystemAllowedCpuSets, // 80 ProcessWakeInformation, // PROCESS_WAKE_INFORMATION ProcessEnergyTrackingState, // PROCESS_ENERGY_TRACKING_STATE + ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 + ProcessCaptureTrustletLiveDump, + ProcessTelemetryCoverage, + ProcessEnclaveInformation, + ProcessEnableReadWriteVmLogging, // PROCESS_READWRITEVM_LOGGING_INFORMATION + ProcessUptimeInformation, // q: PROCESS_UPTIME_INFORMATION + ProcessImageSection, // q: HANDLE + ProcessDebugAuthInformation, // since REDSTONE4 // 90 + ProcessSystemResourceManagement, // PROCESS_SYSTEM_RESOURCE_MANAGEMENT + ProcessSequenceNumber, // q: ULONGLONG + ProcessLoaderDetour, // since REDSTONE5 + ProcessSecurityDomainInformation, // PROCESS_SECURITY_DOMAIN_INFORMATION + ProcessCombineSecurityDomainsInformation, // PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION + ProcessEnableLogging, // PROCESS_LOGGING_INFORMATION + ProcessLeapSecondInformation, // PROCESS_LEAP_SECOND_INFORMATION + ProcessFiberShadowStackAllocation, // PROCESS_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION // since 19H1 + ProcessFreeFiberShadowStackAllocation, // PROCESS_FREE_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION + ProcessAltSystemCallInformation, // qs: BOOLEAN (kernel-mode only) // INT2E // since 20H1 // 100 + ProcessDynamicEHContinuationTargets, // PROCESS_DYNAMIC_EH_CONTINUATION_TARGETS_INFORMATION + ProcessDynamicEnforcedCetCompatibleRanges, // PROCESS_DYNAMIC_ENFORCED_ADDRESS_RANGE_INFORMATION // since 20H2 + ProcessCreateStateChange, // since WIN11 + ProcessApplyStateChange, + ProcessEnableOptionalXStateFeatures, + ProcessAltPrefetchParam, // since 22H1 + ProcessAssignCpuPartitions, + ProcessPriorityClassEx, // s: PROCESS_PRIORITY_CLASS_EX + ProcessMembershipInformation, + ProcessEffectiveIoPriority, // q: IO_PRIORITY_HINT + ProcessEffectivePagePriority, // q: ULONG MaxProcessInfoClass } PROCESSINFOCLASS; -// Source: http://processhacker.sourceforge.net typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation, // q: SYSTEM_BASIC_INFORMATION @@ -1669,7 +2570,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS SystemProcessInformation, // q: SYSTEM_PROCESS_INFORMATION SystemCallCountInformation, // q: SYSTEM_CALL_COUNT_INFORMATION SystemDeviceInformation, // q: SYSTEM_DEVICE_INFORMATION - SystemProcessorPerformanceInformation, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION + SystemProcessorPerformanceInformation, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION (EX in: USHORT ProcessorGroup) SystemFlagsInformation, // q: SYSTEM_FLAGS_INFORMATION SystemCallTimeInformation, // not implemented // SYSTEM_CALL_TIME_INFORMATION // 10 SystemModuleInformation, // q: RTL_PROCESS_MODULES @@ -1680,22 +2581,22 @@ typedef enum _SYSTEM_INFORMATION_CLASS SystemHandleInformation, // q: SYSTEM_HANDLE_INFORMATION SystemObjectInformation, // q: SYSTEM_OBJECTTYPE_INFORMATION mixed with SYSTEM_OBJECT_INFORMATION SystemPageFileInformation, // q: SYSTEM_PAGEFILE_INFORMATION - SystemVdmInstemulInformation, // q + SystemVdmInstemulInformation, // q: SYSTEM_VDM_INSTEMUL_INFO SystemVdmBopInformation, // not implemented // 20 SystemFileCacheInformation, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypeSystemCache) SystemPoolTagInformation, // q: SYSTEM_POOLTAG_INFORMATION - SystemInterruptInformation, // q: SYSTEM_INTERRUPT_INFORMATION + SystemInterruptInformation, // q: SYSTEM_INTERRUPT_INFORMATION (EX in: USHORT ProcessorGroup) SystemDpcBehaviorInformation, // q: SYSTEM_DPC_BEHAVIOR_INFORMATION; s: SYSTEM_DPC_BEHAVIOR_INFORMATION (requires SeLoadDriverPrivilege) - SystemFullMemoryInformation, // not implemented + SystemFullMemoryInformation, // not implemented // SYSTEM_MEMORY_USAGE_INFORMATION SystemLoadGdiDriverInformation, // s (kernel-mode only) SystemUnloadGdiDriverInformation, // s (kernel-mode only) SystemTimeAdjustmentInformation, // q: SYSTEM_QUERY_TIME_ADJUST_INFORMATION; s: SYSTEM_SET_TIME_ADJUST_INFORMATION (requires SeSystemtimePrivilege) - SystemSummaryMemoryInformation, // not implemented + SystemSummaryMemoryInformation, // not implemented // SYSTEM_MEMORY_USAGE_INFORMATION SystemMirrorMemoryInformation, // s (requires license value "Kernel-MemoryMirroringSupported") (requires SeShutdownPrivilege) // 30 SystemPerformanceTraceInformation, // q; s: (type depends on EVENT_TRACE_INFORMATION_CLASS) SystemObsolete0, // not implemented SystemExceptionInformation, // q: SYSTEM_EXCEPTION_INFORMATION - SystemCrashDumpStateInformation, // s (requires SeDebugPrivilege) + SystemCrashDumpStateInformation, // s: SYSTEM_CRASH_DUMP_STATE_INFORMATION (requires SeDebugPrivilege) SystemKernelDebuggerInformation, // q: SYSTEM_KERNEL_DEBUGGER_INFORMATION SystemContextSwitchInformation, // q: SYSTEM_CONTEXT_SWITCH_INFORMATION SystemRegistryQuotaInformation, // q: SYSTEM_REGISTRY_QUOTA_INFORMATION; s (requires SeIncreaseQuotaPrivilege) @@ -1703,40 +2604,40 @@ typedef enum _SYSTEM_INFORMATION_CLASS SystemPrioritySeperation, // s (requires SeTcbPrivilege) SystemVerifierAddDriverInformation, // s (requires SeDebugPrivilege) // 40 SystemVerifierRemoveDriverInformation, // s (requires SeDebugPrivilege) - SystemProcessorIdleInformation, // q: SYSTEM_PROCESSOR_IDLE_INFORMATION + SystemProcessorIdleInformation, // q: SYSTEM_PROCESSOR_IDLE_INFORMATION (EX in: USHORT ProcessorGroup) SystemLegacyDriverInformation, // q: SYSTEM_LEGACY_DRIVER_INFORMATION - SystemCurrentTimeZoneInformation, // q + SystemCurrentTimeZoneInformation, // q; s: RTL_TIME_ZONE_INFORMATION SystemLookasideInformation, // q: SYSTEM_LOOKASIDE_INFORMATION - SystemTimeSlipNotification, // s (requires SeSystemtimePrivilege) + SystemTimeSlipNotification, // s: HANDLE (NtCreateEvent) (requires SeSystemtimePrivilege) SystemSessionCreate, // not implemented SystemSessionDetach, // not implemented - SystemSessionInformation, // not implemented + SystemSessionInformation, // not implemented (SYSTEM_SESSION_INFORMATION) SystemRangeStartInformation, // q: SYSTEM_RANGE_START_INFORMATION // 50 SystemVerifierInformation, // q: SYSTEM_VERIFIER_INFORMATION; s (requires SeDebugPrivilege) SystemVerifierThunkExtend, // s (kernel-mode only) SystemSessionProcessInformation, // q: SYSTEM_SESSION_PROCESS_INFORMATION - SystemLoadGdiDriverInSystemSpace, // s (kernel-mode only) (same as SystemLoadGdiDriverInformation) - SystemNumaProcessorMap, // q - SystemPrefetcherInformation, // q: PREFETCHER_INFORMATION; s: PREFETCHER_INFORMATION // PfSnQueryPrefetcherInformation + SystemLoadGdiDriverInSystemSpace, // s: SYSTEM_GDI_DRIVER_INFORMATION (kernel-mode only) (same as SystemLoadGdiDriverInformation) + SystemNumaProcessorMap, // q: SYSTEM_NUMA_INFORMATION + SystemPrefetcherInformation, // q; s: PREFETCHER_INFORMATION // PfSnQueryPrefetcherInformation SystemExtendedProcessInformation, // q: SYSTEM_PROCESS_INFORMATION - SystemRecommendedSharedDataAlignment, // q - SystemComPlusPackage, // q; s - SystemNumaAvailableMemory, // 60 - SystemProcessorPowerInformation, // q: SYSTEM_PROCESSOR_POWER_INFORMATION - SystemEmulationBasicInformation, // q - SystemEmulationProcessorInformation, + SystemRecommendedSharedDataAlignment, // q: ULONG // KeGetRecommendedSharedDataAlignment + SystemComPlusPackage, // q; s: ULONG + SystemNumaAvailableMemory, // q: SYSTEM_NUMA_INFORMATION // 60 + SystemProcessorPowerInformation, // q: SYSTEM_PROCESSOR_POWER_INFORMATION (EX in: USHORT ProcessorGroup) + SystemEmulationBasicInformation, // q: SYSTEM_BASIC_INFORMATION + SystemEmulationProcessorInformation, // q: SYSTEM_PROCESSOR_INFORMATION SystemExtendedHandleInformation, // q: SYSTEM_HANDLE_INFORMATION_EX SystemLostDelayedWriteInformation, // q: ULONG SystemBigPoolInformation, // q: SYSTEM_BIGPOOL_INFORMATION SystemSessionPoolTagInformation, // q: SYSTEM_SESSION_POOLTAG_INFORMATION SystemSessionMappedViewInformation, // q: SYSTEM_SESSION_MAPPED_VIEW_INFORMATION - SystemHotpatchInformation, // q; s - SystemObjectSecurityMode, // q // 70 - SystemWatchdogTimerHandler, // s (kernel-mode only) - SystemWatchdogTimerInformation, // q (kernel-mode only); s (kernel-mode only) - SystemLogicalProcessorInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION + SystemHotpatchInformation, // q; s: SYSTEM_HOTPATCH_CODE_INFORMATION + SystemObjectSecurityMode, // q: ULONG // 70 + SystemWatchdogTimerHandler, // s: SYSTEM_WATCHDOG_HANDLER_INFORMATION // (kernel-mode only) + SystemWatchdogTimerInformation, // q: SYSTEM_WATCHDOG_TIMER_INFORMATION // (kernel-mode only) + SystemLogicalProcessorInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION (EX in: USHORT ProcessorGroup) SystemWow64SharedInformationObsolete, // not implemented - SystemRegisterFirmwareTableInformationHandler, // s (kernel-mode only) + SystemRegisterFirmwareTableInformationHandler, // s: SYSTEM_FIRMWARE_TABLE_HANDLER // (kernel-mode only) SystemFirmwareTableInformation, // SYSTEM_FIRMWARE_TABLE_INFORMATION SystemModuleInformationEx, // q: RTL_PROCESS_MODULE_INFORMATION_EX SystemVerifierTriageInformation, // not implemented @@ -1744,45 +2645,45 @@ typedef enum _SYSTEM_INFORMATION_CLASS SystemMemoryListInformation, // q: SYSTEM_MEMORY_LIST_INFORMATION; s: SYSTEM_MEMORY_LIST_COMMAND (requires SeProfileSingleProcessPrivilege) // 80 SystemFileCacheInformationEx, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (same as SystemFileCacheInformation) SystemThreadPriorityClientIdInformation, // s: SYSTEM_THREAD_CID_PRIORITY_INFORMATION (requires SeIncreaseBasePriorityPrivilege) - SystemProcessorIdleCycleTimeInformation, // q: SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION[] - SystemVerifierCancellationInformation, // not implemented // name:wow64:whNT32QuerySystemVerifierCancellationInformation + SystemProcessorIdleCycleTimeInformation, // q: SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION[] (EX in: USHORT ProcessorGroup) + SystemVerifierCancellationInformation, // SYSTEM_VERIFIER_CANCELLATION_INFORMATION // name:wow64:whNT32QuerySystemVerifierCancellationInformation SystemProcessorPowerInformationEx, // not implemented SystemRefTraceInformation, // q; s: SYSTEM_REF_TRACE_INFORMATION // ObQueryRefTraceInformation - SystemSpecialPoolInformation, // q; s (requires SeDebugPrivilege) // MmSpecialPoolTag, then MmSpecialPoolCatchOverruns != 0 + SystemSpecialPoolInformation, // q; s: SYSTEM_SPECIAL_POOL_INFORMATION (requires SeDebugPrivilege) // MmSpecialPoolTag, then MmSpecialPoolCatchOverruns != 0 SystemProcessIdInformation, // q: SYSTEM_PROCESS_ID_INFORMATION SystemErrorPortInformation, // s (requires SeTcbPrivilege) SystemBootEnvironmentInformation, // q: SYSTEM_BOOT_ENVIRONMENT_INFORMATION // 90 - SystemHypervisorInformation, // q; s (kernel-mode only) + SystemHypervisorInformation, // q: SYSTEM_HYPERVISOR_QUERY_INFORMATION SystemVerifierInformationEx, // q; s: SYSTEM_VERIFIER_INFORMATION_EX - SystemTimeZoneInformation, // s (requires SeTimeZonePrivilege) + SystemTimeZoneInformation, // q; s: RTL_TIME_ZONE_INFORMATION (requires SeTimeZonePrivilege) SystemImageFileExecutionOptionsInformation, // s: SYSTEM_IMAGE_FILE_EXECUTION_OPTIONS_INFORMATION (requires SeTcbPrivilege) - SystemCoverageInformation, // q; s // name:wow64:whNT32QuerySystemCoverageInformation; ExpCovQueryInformation - SystemPrefetchPatchInformation, // not implemented - SystemVerifierFaultsInformation, // s (requires SeDebugPrivilege) + SystemCoverageInformation, // q: COVERAGE_MODULES s: COVERAGE_MODULE_REQUEST // ExpCovQueryInformation (requires SeDebugPrivilege) + SystemPrefetchPatchInformation, // SYSTEM_PREFETCH_PATCH_INFORMATION + SystemVerifierFaultsInformation, // s: SYSTEM_VERIFIER_FAULTS_INFORMATION (requires SeDebugPrivilege) SystemSystemPartitionInformation, // q: SYSTEM_SYSTEM_PARTITION_INFORMATION SystemSystemDiskInformation, // q: SYSTEM_SYSTEM_DISK_INFORMATION - SystemProcessorPerformanceDistribution, // q: SYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION // 100 - SystemNumaProximityNodeInformation, // q - SystemDynamicTimeZoneInformation, // q; s (requires SeTimeZonePrivilege) + SystemProcessorPerformanceDistribution, // q: SYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION (EX in: USHORT ProcessorGroup) // 100 + SystemNumaProximityNodeInformation, // q; s: SYSTEM_NUMA_PROXIMITY_MAP + SystemDynamicTimeZoneInformation, // q; s: RTL_DYNAMIC_TIME_ZONE_INFORMATION (requires SeTimeZonePrivilege) SystemCodeIntegrityInformation, // q: SYSTEM_CODEINTEGRITY_INFORMATION // SeCodeIntegrityQueryInformation - SystemProcessorMicrocodeUpdateInformation, // s - SystemProcessorBrandString, // q // HaliQuerySystemInformation -> HalpGetProcessorBrandString, info class 23 + SystemProcessorMicrocodeUpdateInformation, // s: SYSTEM_PROCESSOR_MICROCODE_UPDATE_INFORMATION + SystemProcessorBrandString, // q: CHAR[] // HaliQuerySystemInformation -> HalpGetProcessorBrandString, info class 23 SystemVirtualAddressInformation, // q: SYSTEM_VA_LIST_INFORMATION[]; s: SYSTEM_VA_LIST_INFORMATION[] (requires SeIncreaseQuotaPrivilege) // MmQuerySystemVaInformation - SystemLogicalProcessorAndGroupInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX // since WIN7 // KeQueryLogicalProcessorRelationship - SystemProcessorCycleTimeInformation, // q: SYSTEM_PROCESSOR_CYCLE_TIME_INFORMATION[] - SystemStoreInformation, // q; s // SmQueryStoreInformation + SystemLogicalProcessorAndGroupInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX (EX in: LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType) // since WIN7 // KeQueryLogicalProcessorRelationship + SystemProcessorCycleTimeInformation, // q: SYSTEM_PROCESSOR_CYCLE_TIME_INFORMATION[] (EX in: USHORT ProcessorGroup) + SystemStoreInformation, // q; s: SYSTEM_STORE_INFORMATION (requires SeProfileSingleProcessPrivilege) // SmQueryStoreInformation SystemRegistryAppendString, // s: SYSTEM_REGISTRY_APPEND_STRING_PARAMETERS // 110 SystemAitSamplingValue, // s: ULONG (requires SeProfileSingleProcessPrivilege) SystemVhdBootInformation, // q: SYSTEM_VHD_BOOT_INFORMATION - SystemCpuQuotaInformation, // q; s // PsQueryCpuQuotaInformation - SystemNativeBasicInformation, // not implemented - SystemSpare1, // not implemented + SystemCpuQuotaInformation, // q; s: PS_CPU_QUOTA_QUERY_INFORMATION + SystemNativeBasicInformation, // q: SYSTEM_BASIC_INFORMATION + SystemErrorPortTimeouts, // SYSTEM_ERROR_PORT_TIMEOUTS SystemLowPriorityIoInformation, // q: SYSTEM_LOW_PRIORITY_IO_INFORMATION SystemTpmBootEntropyInformation, // q: TPM_BOOT_ENTROPY_NT_RESULT // ExQueryTpmBootEntropyInformation SystemVerifierCountersInformation, // q: SYSTEM_VERIFIER_COUNTERS_INFORMATION SystemPagedPoolInformationEx, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypePagedPool) SystemSystemPtesInformationEx, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypeSystemPtes) // 120 - SystemNodeDistanceInformation, // q + SystemNodeDistanceInformation, // q: USHORT[4*NumaNodes] // (EX in: USHORT NodeNumber) SystemAcpiAuditInformation, // q: SYSTEM_ACPI_AUDIT_INFORMATION // HaliQuerySystemInformation -> HalpAuditQueryResults, info class 26 SystemBasicPerformanceInformation, // q: SYSTEM_BASIC_PERFORMANCE_INFORMATION // name:wow64:whNtQuerySystemInformation_SystemBasicPerformanceInformation SystemQueryPerformanceCounterInformation, // q: SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION // since WIN7 SP1 @@ -1792,18 +2693,18 @@ typedef enum _SYSTEM_INFORMATION_CLASS SystemBadPageInformation, SystemProcessorProfileControlArea, // q; s: SYSTEM_PROCESSOR_PROFILE_CONTROL_AREA SystemCombinePhysicalMemoryInformation, // s: MEMORY_COMBINE_INFORMATION, MEMORY_COMBINE_INFORMATION_EX, MEMORY_COMBINE_INFORMATION_EX2 // 130 - SystemEntropyInterruptTimingCallback, - SystemConsoleInformation, // q: SYSTEM_CONSOLE_INFORMATION - SystemPlatformBinaryInformation, // q: SYSTEM_PLATFORM_BINARY_INFORMATION - SystemThrottleNotificationInformation, + SystemEntropyInterruptTimingInformation, // q; s: SYSTEM_ENTROPY_TIMING_INFORMATION + SystemConsoleInformation, // q; s: SYSTEM_CONSOLE_INFORMATION + SystemPlatformBinaryInformation, // q: SYSTEM_PLATFORM_BINARY_INFORMATION (requires SeTcbPrivilege) + SystemPolicyInformation, // q: SYSTEM_POLICY_INFORMATION SystemHypervisorProcessorCountInformation, // q: SYSTEM_HYPERVISOR_PROCESSOR_COUNT_INFORMATION SystemDeviceDataInformation, // q: SYSTEM_DEVICE_DATA_INFORMATION - SystemDeviceDataEnumerationInformation, + SystemDeviceDataEnumerationInformation, // q: SYSTEM_DEVICE_DATA_INFORMATION SystemMemoryTopologyInformation, // q: SYSTEM_MEMORY_TOPOLOGY_INFORMATION SystemMemoryChannelInformation, // q: SYSTEM_MEMORY_CHANNEL_INFORMATION SystemBootLogoInformation, // q: SYSTEM_BOOT_LOGO_INFORMATION // 140 - SystemProcessorPerformanceInformationEx, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_EX // since WINBLUE - SystemSpare0, + SystemProcessorPerformanceInformationEx, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_EX // (EX in: USHORT ProcessorGroup) // since WINBLUE + SystemCriticalProcessErrorLogInformation, SystemSecureBootPolicyInformation, // q: SYSTEM_SECUREBOOT_POLICY_INFORMATION SystemPageFileInformationEx, // q: SYSTEM_PAGEFILE_INFORMATION_EX SystemSecureBootInformation, // q: SYSTEM_SECUREBOOT_INFORMATION @@ -1812,48 +2713,94 @@ typedef enum _SYSTEM_INFORMATION_CLASS SystemFullProcessInformation, // q: SYSTEM_PROCESS_INFORMATION with SYSTEM_PROCESS_INFORMATION_EXTENSION (requires admin) SystemKernelDebuggerInformationEx, // q: SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX SystemBootMetadataInformation, // 150 - SystemSoftRebootInformation, + SystemSoftRebootInformation, // q: ULONG SystemElamCertificateInformation, // s: SYSTEM_ELAM_CERTIFICATE_INFORMATION - SystemOfflineDumpConfigInformation, + SystemOfflineDumpConfigInformation, // q: OFFLINE_CRASHDUMP_CONFIGURATION_TABLE_V2 SystemProcessorFeaturesInformation, // q: SYSTEM_PROCESSOR_FEATURES_INFORMATION - SystemRegistryReconciliationInformation, - SystemEdidInformation, + SystemRegistryReconciliationInformation, // s: NULL (requires admin) (flushes registry hives) + SystemEdidInformation, // q: SYSTEM_EDID_INFORMATION SystemManufacturingInformation, // q: SYSTEM_MANUFACTURING_INFORMATION // since THRESHOLD SystemEnergyEstimationConfigInformation, // q: SYSTEM_ENERGY_ESTIMATION_CONFIG_INFORMATION SystemHypervisorDetailInformation, // q: SYSTEM_HYPERVISOR_DETAIL_INFORMATION - SystemProcessorCycleStatsInformation, // q: SYSTEM_PROCESSOR_CYCLE_STATS_INFORMATION // 160 + SystemProcessorCycleStatsInformation, // q: SYSTEM_PROCESSOR_CYCLE_STATS_INFORMATION (EX in: USHORT ProcessorGroup) // 160 SystemVmGenerationCountInformation, SystemTrustedPlatformModuleInformation, // q: SYSTEM_TPM_INFORMATION - SystemKernelDebuggerFlags, - SystemCodeIntegrityPolicyInformation, // q: SYSTEM_CODEINTEGRITYPOLICY_INFORMATION + SystemKernelDebuggerFlags, // SYSTEM_KERNEL_DEBUGGER_FLAGS + SystemCodeIntegrityPolicyInformation, // q; s: SYSTEM_CODEINTEGRITYPOLICY_INFORMATION SystemIsolatedUserModeInformation, // q: SYSTEM_ISOLATED_USER_MODE_INFORMATION SystemHardwareSecurityTestInterfaceResultsInformation, SystemSingleModuleInformation, // q: SYSTEM_SINGLE_MODULE_INFORMATION SystemAllowedCpuSetsInformation, - SystemDmaProtectionInformation, // q: SYSTEM_DMA_PROTECTION_INFORMATION + SystemVsmProtectionInformation, // q: SYSTEM_VSM_PROTECTION_INFORMATION (previously SystemDmaProtectionInformation) SystemInterruptCpuSetsInformation, // q: SYSTEM_INTERRUPT_CPU_SET_INFORMATION // 170 SystemSecureBootPolicyFullInformation, // q: SYSTEM_SECUREBOOT_POLICY_FULL_INFORMATION SystemCodeIntegrityPolicyFullInformation, - SystemAffinitizedInterruptProcessorInformation, + SystemAffinitizedInterruptProcessorInformation, // (requires SeIncreaseBasePriorityPrivilege) SystemRootSiloInformation, // q: SYSTEM_ROOT_SILO_INFORMATION SystemCpuSetInformation, // q: SYSTEM_CPU_SET_INFORMATION // since THRESHOLD2 SystemCpuSetTagInformation, // q: SYSTEM_CPU_SET_TAG_INFORMATION SystemWin32WerStartCallout, SystemSecureKernelProfileInformation, // q: SYSTEM_SECURE_KERNEL_HYPERGUARD_PROFILE_INFORMATION SystemCodeIntegrityPlatformManifestInformation, // q: SYSTEM_SECUREBOOT_PLATFORM_MANIFEST_INFORMATION // since REDSTONE - SystemInterruptSteeringInformation, // 180 - SystemSupportedProcessorArchitectures, + SystemInterruptSteeringInformation, // SYSTEM_INTERRUPT_STEERING_INFORMATION_INPUT // 180 + SystemSupportedProcessorArchitectures, // p: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx SystemMemoryUsageInformation, // q: SYSTEM_MEMORY_USAGE_INFORMATION SystemCodeIntegrityCertificateInformation, // q: SYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION SystemPhysicalMemoryInformation, // q: SYSTEM_PHYSICAL_MEMORY_INFORMATION // since REDSTONE2 SystemControlFlowTransition, - SystemKernelDebuggingAllowed, + SystemKernelDebuggingAllowed, // s: ULONG SystemActivityModerationExeState, // SYSTEM_ACTIVITY_MODERATION_EXE_STATE SystemActivityModerationUserSettings, // SYSTEM_ACTIVITY_MODERATION_USER_SETTINGS SystemCodeIntegrityPoliciesFullInformation, SystemCodeIntegrityUnlockInformation, // SYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION // 190 SystemIntegrityQuotaInformation, SystemFlushInformation, // q: SYSTEM_FLUSH_INFORMATION + SystemProcessorIdleMaskInformation, // q: ULONG_PTR[ActiveGroupCount] // since REDSTONE3 + SystemSecureDumpEncryptionInformation, + SystemWriteConstraintInformation, // SYSTEM_WRITE_CONSTRAINT_INFORMATION + SystemKernelVaShadowInformation, // SYSTEM_KERNEL_VA_SHADOW_INFORMATION + SystemHypervisorSharedPageInformation, // SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION // since REDSTONE4 + SystemFirmwareBootPerformanceInformation, + SystemCodeIntegrityVerificationInformation, // SYSTEM_CODEINTEGRITYVERIFICATION_INFORMATION + SystemFirmwarePartitionInformation, // SYSTEM_FIRMWARE_PARTITION_INFORMATION // 200 + SystemSpeculationControlInformation, // SYSTEM_SPECULATION_CONTROL_INFORMATION // (CVE-2017-5715) REDSTONE3 and above. + SystemDmaGuardPolicyInformation, // SYSTEM_DMA_GUARD_POLICY_INFORMATION + SystemEnclaveLaunchControlInformation, // SYSTEM_ENCLAVE_LAUNCH_CONTROL_INFORMATION + SystemWorkloadAllowedCpuSetsInformation, // SYSTEM_WORKLOAD_ALLOWED_CPU_SET_INFORMATION // since REDSTONE5 + SystemCodeIntegrityUnlockModeInformation, + SystemLeapSecondInformation, // SYSTEM_LEAP_SECOND_INFORMATION + SystemFlags2Information, // q: SYSTEM_FLAGS_INFORMATION + SystemSecurityModelInformation, // SYSTEM_SECURITY_MODEL_INFORMATION // since 19H1 + SystemCodeIntegritySyntheticCacheInformation, + SystemFeatureConfigurationInformation, // SYSTEM_FEATURE_CONFIGURATION_INFORMATION // since 20H1 // 210 + SystemFeatureConfigurationSectionInformation, // SYSTEM_FEATURE_CONFIGURATION_SECTIONS_INFORMATION + SystemFeatureUsageSubscriptionInformation, // SYSTEM_FEATURE_USAGE_SUBSCRIPTION_DETAILS + SystemSecureSpeculationControlInformation, // SECURE_SPECULATION_CONTROL_INFORMATION + SystemSpacesBootInformation, // since 20H2 + SystemFwRamdiskInformation, // SYSTEM_FIRMWARE_RAMDISK_INFORMATION + SystemWheaIpmiHardwareInformation, + SystemDifSetRuleClassInformation, + SystemDifClearRuleClassInformation, + SystemDifApplyPluginVerificationOnDriver, + SystemDifRemovePluginVerificationOnDriver, // 220 + SystemShadowStackInformation, // SYSTEM_SHADOW_STACK_INFORMATION + SystemBuildVersionInformation, // SYSTEM_BUILD_VERSION_INFORMATION + SystemPoolLimitInformation, // SYSTEM_POOL_LIMIT_INFORMATION + SystemCodeIntegrityAddDynamicStore, + SystemCodeIntegrityClearDynamicStores, + SystemDifPoolTrackingInformation, + SystemPoolZeroingInformation, // SYSTEM_POOL_ZEROING_INFORMATION + SystemDpcWatchdogInformation, + SystemDpcWatchdogInformation2, + SystemSupportedProcessorArchitectures2, // q: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx // 230 + SystemSingleProcessorRelationshipInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX // (EX in: PROCESSOR_NUMBER Processor) + SystemXfgCheckFailureInformation, + SystemIommuStateInformation, // SYSTEM_IOMMU_STATE_INFORMATION // since 22H1 + SystemHypervisorMinrootInformation, // SYSTEM_HYPERVISOR_MINROOT_INFORMATION + SystemHypervisorBootPagesInformation, // SYSTEM_HYPERVISOR_BOOT_PAGES_INFORMATION + SystemPointerAuthInformation, // SYSTEM_POINTER_AUTH_INFORMATION + SystemSecureKernelDebuggerInformation, + SystemOriginalImageFeatureInformation, MaxSystemInfoClass } SYSTEM_INFORMATION_CLASS; @@ -1869,60 +2816,120 @@ typedef enum _OBJECT_INFORMATION_CLASS MaxObjectInfoClass } OBJECT_INFORMATION_CLASS; -//Source: http://processhacker.sourceforge.net +// Source: http://processhacker.sourceforge.net typedef enum _THREADINFOCLASS { ThreadBasicInformation, // q: THREAD_BASIC_INFORMATION ThreadTimes, // q: KERNEL_USER_TIMES - ThreadPriority, // s: KPRIORITY - ThreadBasePriority, // s: LONG + ThreadPriority, // s: KPRIORITY (requires SeIncreaseBasePriorityPrivilege) + ThreadBasePriority, // s: KPRIORITY ThreadAffinityMask, // s: KAFFINITY ThreadImpersonationToken, // s: HANDLE ThreadDescriptorTableEntry, // q: DESCRIPTOR_TABLE_ENTRY (or WOW64_DESCRIPTOR_TABLE_ENTRY) ThreadEnableAlignmentFaultFixup, // s: BOOLEAN ThreadEventPair, - ThreadQuerySetWin32StartAddress, // q: PVOID - ThreadZeroTlsCell, // 10 + ThreadQuerySetWin32StartAddress, // q: ULONG_PTR + ThreadZeroTlsCell, // s: ULONG // TlsIndex // 10 ThreadPerformanceCount, // q: LARGE_INTEGER ThreadAmILastThread, // q: ULONG ThreadIdealProcessor, // s: ULONG ThreadPriorityBoost, // qs: ULONG - ThreadSetTlsArrayAddress, + ThreadSetTlsArrayAddress, // s: ULONG_PTR ThreadIsIoPending, // q: ULONG - ThreadHideFromDebugger, // s: void + ThreadHideFromDebugger, // q: BOOLEAN; s: void ThreadBreakOnTermination, // qs: ULONG - ThreadSwitchLegacyState, + ThreadSwitchLegacyState, // s: void // NtCurrentThread // NPX/FPU ThreadIsTerminated, // q: ULONG // 20 ThreadLastSystemCall, // q: THREAD_LAST_SYSCALL_INFORMATION - ThreadIoPriority, // qs: IO_PRIORITY_HINT + ThreadIoPriority, // qs: IO_PRIORITY_HINT (requires SeIncreaseBasePriorityPrivilege) ThreadCycleTime, // q: THREAD_CYCLE_TIME_INFORMATION - ThreadPagePriority, // q: ULONG - ThreadActualBasePriority, + ThreadPagePriority, // qs: PAGE_PRIORITY_INFORMATION + ThreadActualBasePriority, // s: LONG (requires SeIncreaseBasePriorityPrivilege) ThreadTebInformation, // q: THREAD_TEB_INFORMATION (requires THREAD_GET_CONTEXT + THREAD_SET_CONTEXT) ThreadCSwitchMon, ThreadCSwitchPmu, - ThreadWow64Context, // q: WOW64_CONTEXT - ThreadGroupInformation, // q: GROUP_AFFINITY // 30 + ThreadWow64Context, // qs: WOW64_CONTEXT + ThreadGroupInformation, // qs: GROUP_AFFINITY // 30 ThreadUmsInformation, // q: THREAD_UMS_INFORMATION - ThreadCounterProfiling, - ThreadIdealProcessorEx, // q: PROCESSOR_NUMBER - ThreadCpuAccountingInformation, // since WIN8 - ThreadSuspendCount, // since WINBLUE + ThreadCounterProfiling, // q: BOOLEAN; s: THREAD_PROFILING_INFORMATION? + ThreadIdealProcessorEx, // qs: PROCESSOR_NUMBER; s: previous PROCESSOR_NUMBER on return + ThreadCpuAccountingInformation, // q: BOOLEAN; s: HANDLE (NtOpenSession) // NtCurrentThread // since WIN8 + ThreadSuspendCount, // q: ULONG // since WINBLUE ThreadHeterogeneousCpuPolicy, // q: KHETERO_CPU_POLICY // since THRESHOLD ThreadContainerId, // q: GUID ThreadNameInformation, // qs: THREAD_NAME_INFORMATION ThreadSelectedCpuSets, ThreadSystemThreadInformation, // q: SYSTEM_THREAD_INFORMATION // 40 - ThreadActualGroupAffinity, // since THRESHOLD2 - ThreadDynamicCodePolicyInfo, - ThreadExplicitCaseSensitivity, - ThreadWorkOnBehalfTicket, + ThreadActualGroupAffinity, // q: GROUP_AFFINITY // since THRESHOLD2 + ThreadDynamicCodePolicyInfo, // q: ULONG; s: ULONG (NtCurrentThread) + ThreadExplicitCaseSensitivity, // qs: ULONG; s: 0 disables, otherwise enables + ThreadWorkOnBehalfTicket, // RTL_WORK_ON_BEHALF_TICKET_EX ThreadSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 - ThreadDbgkWerReportActive, - ThreadAttachContainer, + ThreadDbgkWerReportActive, // s: ULONG; s: 0 disables, otherwise enables + ThreadAttachContainer, // s: HANDLE (job object) // NtCurrentThread + ThreadManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 + ThreadPowerThrottlingState, // POWER_THROTTLING_THREAD_STATE + ThreadWorkloadClass, // THREAD_WORKLOAD_CLASS // since REDSTONE5 // 50 + ThreadCreateStateChange, // since WIN11 + ThreadApplyStateChange, + ThreadStrongerBadHandleChecks, // since 22H1 + ThreadEffectiveIoPriority, // q: IO_PRIORITY_HINT + ThreadEffectivePagePriority, // q: ULONG MaxThreadInfoClass } THREADINFOCLASS; +// JOBOBJECTINFOCLASS +// Source: http://processhacker.sourceforge.net +// Note: We don't use an enum since it conflicts with the Windows SDK. +#define JobObjectBasicAccountingInformation ((JOBOBJECTINFOCLASS)1) // JOBOBJECT_BASIC_ACCOUNTING_INFORMATION +#define JobObjectBasicLimitInformation ((JOBOBJECTINFOCLASS)2) // JOBOBJECT_BASIC_LIMIT_INFORMATION +#define JobObjectBasicProcessIdList ((JOBOBJECTINFOCLASS)3) // JOBOBJECT_BASIC_PROCESS_ID_LIST +#define JobObjectBasicUIRestrictions ((JOBOBJECTINFOCLASS)4) // JOBOBJECT_BASIC_UI_RESTRICTIONS +#define JobObjectSecurityLimitInformation ((JOBOBJECTINFOCLASS)5) // JOBOBJECT_SECURITY_LIMIT_INFORMATION +#define JobObjectEndOfJobTimeInformation ((JOBOBJECTINFOCLASS)6) // JOBOBJECT_END_OF_JOB_TIME_INFORMATION +#define JobObjectAssociateCompletionPortInformation ((JOBOBJECTINFOCLASS)7) // JOBOBJECT_ASSOCIATE_COMPLETION_PORT +#define JobObjectBasicAndIoAccountingInformation ((JOBOBJECTINFOCLASS)8) // JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION +#define JobObjectExtendedLimitInformation ((JOBOBJECTINFOCLASS)9) // JOBOBJECT_EXTENDED_LIMIT_INFORMATION +#define JobObjectJobSetInformation ((JOBOBJECTINFOCLASS)10) // JOBOBJECT_JOBSET_INFORMATION +#define JobObjectGroupInformation ((JOBOBJECTINFOCLASS)11) // USHORT +#define JobObjectNotificationLimitInformation ((JOBOBJECTINFOCLASS)12) // JOBOBJECT_NOTIFICATION_LIMIT_INFORMATION +#define JobObjectLimitViolationInformation ((JOBOBJECTINFOCLASS)13) // JOBOBJECT_LIMIT_VIOLATION_INFORMATION +#define JobObjectGroupInformationEx ((JOBOBJECTINFOCLASS)14) // GROUP_AFFINITY (ARRAY) +#define JobObjectCpuRateControlInformation ((JOBOBJECTINFOCLASS)15) // JOBOBJECT_CPU_RATE_CONTROL_INFORMATION +#define JobObjectCompletionFilter ((JOBOBJECTINFOCLASS)16) +#define JobObjectCompletionCounter ((JOBOBJECTINFOCLASS)17) +#define JobObjectFreezeInformation ((JOBOBJECTINFOCLASS)18) // JOBOBJECT_FREEZE_INFORMATION +#define JobObjectExtendedAccountingInformation ((JOBOBJECTINFOCLASS)19) // JOBOBJECT_EXTENDED_ACCOUNTING_INFORMATION +#define JobObjectWakeInformation ((JOBOBJECTINFOCLASS)20) // JOBOBJECT_WAKE_INFORMATION +#define JobObjectBackgroundInformation ((JOBOBJECTINFOCLASS)21) +#define JobObjectSchedulingRankBiasInformation ((JOBOBJECTINFOCLASS)22) +#define JobObjectTimerVirtualizationInformation ((JOBOBJECTINFOCLASS)23) +#define JobObjectCycleTimeNotification ((JOBOBJECTINFOCLASS)24) +#define JobObjectClearEvent ((JOBOBJECTINFOCLASS)25) +#define JobObjectInterferenceInformation ((JOBOBJECTINFOCLASS)26) // JOBOBJECT_INTERFERENCE_INFORMATION +#define JobObjectClearPeakJobMemoryUsed ((JOBOBJECTINFOCLASS)27) +#define JobObjectMemoryUsageInformation ((JOBOBJECTINFOCLASS)28) // JOBOBJECT_MEMORY_USAGE_INFORMATION // JOBOBJECT_MEMORY_USAGE_INFORMATION_V2 +#define JobObjectSharedCommit ((JOBOBJECTINFOCLASS)29) +#define JobObjectContainerId ((JOBOBJECTINFOCLASS)30) +#define JobObjectIoRateControlInformation ((JOBOBJECTINFOCLASS)31) +#define JobObjectNetRateControlInformation ((JOBOBJECTINFOCLASS)32) // JOBOBJECT_NET_RATE_CONTROL_INFORMATION +#define JobObjectNotificationLimitInformation2 ((JOBOBJECTINFOCLASS)33) // JOBOBJECT_NOTIFICATION_LIMIT_INFORMATION_2 +#define JobObjectLimitViolationInformation2 ((JOBOBJECTINFOCLASS)34) // JOBOBJECT_LIMIT_VIOLATION_INFORMATION_2 +#define JobObjectCreateSilo ((JOBOBJECTINFOCLASS)35) +#define JobObjectSiloBasicInformation ((JOBOBJECTINFOCLASS)36) // SILOOBJECT_BASIC_INFORMATION +#define JobObjectSiloRootDirectory ((JOBOBJECTINFOCLASS)37) // SILOOBJECT_ROOT_DIRECTORY +#define JobObjectServerSiloBasicInformation ((JOBOBJECTINFOCLASS)38) // SERVERSILO_BASIC_INFORMATION +#define JobObjectServerSiloUserSharedData ((JOBOBJECTINFOCLASS)39) // SILO_USER_SHARED_DATA +#define JobObjectServerSiloInitialize ((JOBOBJECTINFOCLASS)40) +#define JobObjectServerSiloRunningState ((JOBOBJECTINFOCLASS)41) +#define JobObjectIoAttribution ((JOBOBJECTINFOCLASS)42) +#define JobObjectMemoryPartitionInformation ((JOBOBJECTINFOCLASS)43) +#define JobObjectContainerTelemetryId ((JOBOBJECTINFOCLASS)44) +#define JobObjectSiloSystemRoot ((JOBOBJECTINFOCLASS)45) +#define JobObjectEnergyTrackingState ((JOBOBJECTINFOCLASS)46) // JOBOBJECT_ENERGY_TRACKING_STATE +#define JobObjectThreadImpersonationInformation ((JOBOBJECTINFOCLASS)47) +#define MaxJobObjectInfoClass ((JOBOBJECTINFOCLASS)48) + typedef enum _FSINFOCLASS { FileFsVolumeInformation = 1, // FILE_FS_VOLUME_INFORMATION @@ -1956,8 +2963,8 @@ typedef enum _MEMORY_INFORMATION_CLASS typedef enum _SECTION_INFORMATION_CLASS { - SectionBasicInformation, - SectionImageInformation, + SectionBasicInformation, // q; SECTION_BASIC_INFORMATION + SectionImageInformation, // q; SECTION_IMAGE_INFORMATION SectionRelocationInformation, // name:wow64:whNtQuerySection_SectionRelocationInformation SectionOriginalBaseInformation, // PVOID BaseAddress SectionInternalImageInformation, // SECTION_INTERNAL_IMAGE_INFORMATION // since REDSTONE2 @@ -1968,7 +2975,7 @@ typedef enum _SECTION_INFORMATION_CLASS #define REG_INIT_BOOT_SM 0x0000 #define REG_INIT_BOOT_SETUP 0x0001 #define REG_INIT_BOOT_ACCEPTED_BASE 0x0002 -#define REG_INIT_BOOT_ACCEPTED_MAX REG_INIT_BOOT_ACCEPTED_BASE + 999 +#define REG_INIT_BOOT_ACCEPTED_MAX (REG_INIT_BOOT_ACCEPTED_BASE + 999) #define REG_MAX_KEY_VALUE_NAME_LENGTH 32767 #define REG_MAX_KEY_NAME_LENGTH 512 @@ -2082,6 +3089,7 @@ typedef enum _KEY_SET_INFORMATION_CLASS KeySetVirtualizationInformation, // KEY_SET_VIRTUALIZATION_INFORMATION KeySetDebugInformation, KeySetHandleTagsInformation, // KEY_HANDLE_TAGS_INFORMATION + KeySetLayerInformation, // KEY_SET_LAYER_INFORMATION MaxKeySetInfoClass } KEY_SET_INFORMATION_CLASS; @@ -2100,6 +3108,15 @@ typedef struct _KEY_HANDLE_TAGS_INFORMATION ULONG HandleTags; } KEY_HANDLE_TAGS_INFORMATION, *PKEY_HANDLE_TAGS_INFORMATION; +typedef struct _KEY_SET_LAYER_INFORMATION +{ + ULONG IsTombstone : 1; + ULONG IsSupersedeLocal : 1; + ULONG IsSupersedeTree : 1; + ULONG ClassIsInherited : 1; + ULONG Reserved : 28; +} KEY_SET_LAYER_INFORMATION, *PKEY_SET_LAYER_INFORMATION; + typedef struct _KEY_CONTROL_FLAGS_INFORMATION { ULONG ControlFlags; @@ -2240,16 +3257,24 @@ typedef enum _SYSDBG_COMMAND SysDbgClearUmBreakPid, SysDbgGetUmAttachPid, SysDbgClearUmAttachPid, - SysDbgGetLiveKernelDump + SysDbgGetLiveKernelDump, + SysDbgKdPullRemoteFile } SYSDBG_COMMAND, *PSYSDBG_COMMAND; +typedef enum _SHUTDOWN_ACTION +{ + ShutdownNoReboot, + ShutdownReboot, + ShutdownPowerOff +} SHUTDOWN_ACTION, *PSHUTDOWN_ACTION; + typedef enum _DEBUGOBJECTINFOCLASS { DebugObjectFlags = 1, MaxDebugObjectInfoClass } DEBUGOBJECTINFOCLASS, *PDEBUGOBJECTINFOCLASS; -//Source: http://processhacker.sourceforge.net +// Source: http://processhacker.sourceforge.net typedef enum _FILE_INFORMATION_CLASS { FileDirectoryInformation = 1, // FILE_DIRECTORY_INFORMATION @@ -2316,13 +3341,20 @@ typedef enum _FILE_INFORMATION_CLASS FileHardLinkFullIdInformation, // FILE_LINK_ENTRY_FULL_ID_INFORMATION FileIdExtdBothDirectoryInformation, // FILE_ID_EXTD_BOTH_DIR_INFORMATION // since THRESHOLD FileDispositionInformationEx, // FILE_DISPOSITION_INFO_EX // since REDSTONE - FileRenameInformationEx, - FileRenameInformationExBypassAccessCheck, + FileRenameInformationEx, // FILE_RENAME_INFORMATION_EX + FileRenameInformationExBypassAccessCheck, // (kernel-mode only); FILE_RENAME_INFORMATION_EX FileDesiredStorageClassInformation, // FILE_DESIRED_STORAGE_CLASS_INFORMATION // since REDSTONE2 FileStatInformation, // FILE_STAT_INFORMATION + FileMemoryPartitionInformation, // FILE_MEMORY_PARTITION_INFORMATION // since REDSTONE3 FileMaximumInformation } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; +typedef enum _DIRECTORY_NOTIFY_INFORMATION_CLASS +{ + DirectoryNotifyInformation = 1, + DirectoryNotifyExtendedInformation // 2 +} DIRECTORY_NOTIFY_INFORMATION_CLASS, *PDIRECTORY_NOTIFY_INFORMATION_CLASS; + typedef struct _SYSTEM_BASIC_INFORMATION { ULONG Reserved; @@ -2338,6 +3370,45 @@ typedef struct _SYSTEM_BASIC_INFORMATION CCHAR NumberOfProcessors; } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; +typedef struct _SYSTEM_PROCESSOR_INFORMATION +{ + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + USHORT MaximumProcessors; + ULONG ProcessorFeatureBits; +} SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION; + +// Named pipe FS control definitions +#define DEVICE_NAMED_PIPE L"\\Device\\NamedPipe\\" + +#define FSCTL_PIPE_ASSIGN_EVENT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_DISCONNECT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_LISTEN CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_PEEK CTL_CODE(FILE_DEVICE_NAMED_PIPE, 3, METHOD_BUFFERED, FILE_READ_DATA) +#define FSCTL_PIPE_QUERY_EVENT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_TRANSCEIVE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 5, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA) +#define FSCTL_PIPE_WAIT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_IMPERSONATE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_SET_CLIENT_PROCESS CTL_CODE(FILE_DEVICE_NAMED_PIPE, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_QUERY_CLIENT_PROCESS CTL_CODE(FILE_DEVICE_NAMED_PIPE, 9, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_GET_PIPE_ATTRIBUTE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_SET_PIPE_ATTRIBUTE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_SET_CONNECTION_ATTRIBUTE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 13, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_GET_HANDLE_ATTRIBUTE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 14, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_SET_HANDLE_ATTRIBUTE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_FLUSH CTL_CODE(FILE_DEVICE_NAMED_PIPE, 16, METHOD_BUFFERED, FILE_WRITE_DATA) + +#define FSCTL_PIPE_INTERNAL_READ CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2045, METHOD_BUFFERED, FILE_READ_DATA) +#define FSCTL_PIPE_INTERNAL_WRITE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2046, METHOD_BUFFERED, FILE_WRITE_DATA) +#define FSCTL_PIPE_INTERNAL_TRANSCEIVE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2047, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA) +#define FSCTL_PIPE_INTERNAL_READ_OVFLOW CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2048, METHOD_BUFFERED, FILE_READ_DATA) + +// Flags for query event +#define FILE_PIPE_READ_DATA 0x00000000 +#define FILE_PIPE_WRITE_SPACE 0x00000001 + typedef struct _FILE_PIPE_PEEK_BUFFER { ULONG NamedPipeState; @@ -2359,17 +3430,6 @@ typedef struct _NAMED_PIPE_CREATE_PARAMETERS BOOLEAN TimeoutSpecified; } NAMED_PIPE_CREATE_PARAMETERS, *PNAMED_PIPE_CREATE_PARAMETERS; -typedef struct _FILE_NETWORK_OPEN_INFORMATION -{ - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - LARGE_INTEGER AllocationSize; - LARGE_INTEGER EndOfFile; - ULONG FileAttributes; -} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION; - typedef struct _SYSTEM_TIMEOFDAY_INFORMATION { LARGE_INTEGER BootTime; @@ -2381,12 +3441,44 @@ typedef struct _SYSTEM_TIMEOFDAY_INFORMATION ULONGLONG SleepTimeBias; } SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION; +typedef struct _FILE_FS_DEVICE_INFORMATION +{ + ULONG DeviceType; + ULONG Characteristics; +} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION; + +typedef struct _TIME_FIELDS +{ + SHORT Year; // range [1601...] + SHORT Month; // range [1..12] + SHORT Day; // range [1..31] + SHORT Hour; // range [0..23] + SHORT Minute; // range [0..59] + SHORT Second; // range [0..59] + SHORT Milliseconds; // range [0..999] + SHORT Weekday; // range [0..6] == [Sunday..Saturday] +} TIME_FIELDS, *PTIME_FIELDS; + typedef struct _SYSTEM_CONSOLE_INFORMATION { ULONG DriverLoaded : 1; ULONG Spare : 31; } SYSTEM_CONSOLE_INFORMATION, *PSYSTEM_CONSOLE_INFORMATION; +typedef struct _COMPRESSED_DATA_INFO +{ + USHORT CompressionFormatAndEngine; // COMPRESSION_FORMAT_* and COMPRESSION_ENGINE_* + + UCHAR CompressionUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + UCHAR Reserved; + + USHORT NumberOfChunks; + + ULONG CompressedChunkSizes[1]; +} COMPRESSED_DATA_INFO, *PCOMPRESSED_DATA_INFO; + typedef struct _KSYSTEM_TIME { ULONG LowPart; @@ -2441,7 +3533,7 @@ typedef struct _PS_PROTECTION PS_PROTECTED_SIGNER Signer : 4; } s; UCHAR Level; - }; + } u; } PS_PROTECTION, *PPS_PROTECTION; #define RTL_CREATE_ENVIRONMENT_TRANSLATE 0x1 // Translate from multi-byte to Unicode @@ -2524,8 +3616,8 @@ typedef struct _RTL_USER_PROCESS_PARAMETERS typedef struct _RTL_USER_PROCESS_INFORMATION { ULONG Length; - HANDLE Process; - HANDLE Thread; + HANDLE ProcessHandle; + HANDLE ThreadHandle; CLIENT_ID ClientId; SECTION_IMAGE_INFORMATION ImageInformation; } RTL_USER_PROCESS_INFORMATION, *PRTL_USER_PROCESS_INFORMATION; @@ -2549,8 +3641,6 @@ typedef ULONG GDI_HANDLE_BUFFER32[GDI_HANDLE_BUFFER_SIZE32]; typedef ULONG GDI_HANDLE_BUFFER64[GDI_HANDLE_BUFFER_SIZE64]; typedef ULONG GDI_HANDLE_BUFFER[GDI_HANDLE_BUFFER_SIZE]; -#define FLS_MAXIMUM_AVAILABLE 128 -#define TLS_MINIMUM_AVAILABLE 64 #define TLS_EXPANSION_SLOTS 1024 typedef struct _PEB_LDR_DATA @@ -2831,7 +3921,9 @@ typedef struct _TEB union { +#if (_WIN32_WINNT >= 0x0601) PROCESSOR_NUMBER CurrentIdealProcessor; +#endif ULONG IdealProcessorValue; struct { @@ -2953,7 +4045,7 @@ typedef struct _KUSER_SHARED_DATA LONG TimeZoneBiasStamp; ULONG NtBuildNumber; - ULONG NtProductType; + NT_PRODUCT_TYPE NtProductType; BOOLEAN ProductTypeIsValid; UCHAR Reserved0[1]; USHORT NativeProcessorArchitecture; @@ -3018,7 +4110,8 @@ typedef struct _KUSER_SHARED_DATA ULONG DbgSecureBootEnabled : 1; ULONG DbgMultiSessionSku : 1; ULONG DbgMultiUsersInSessionSku : 1; - ULONG SpareBits : 22; + ULONG DbgStateSeparationEnabled : 1; + ULONG SpareBits : 21; } s2; } u2; ULONG DataFlagsPad[1]; @@ -3051,7 +4144,9 @@ typedef struct _KUSER_SHARED_DATA USHORT UnparkedProcessorCount; ULONG EnclaveFeatureMask[4]; - ULONG Reserved8; + + ULONG TelemetryCoverageRound; + USHORT UserModeGlobalLogger[16]; ULONG ImageFileExecutionOptions; @@ -3165,36 +4260,65 @@ typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION } u; } PROCESS_EXTENDED_BASIC_INFORMATION, *PPROCESS_EXTENDED_BASIC_INFORMATION; -typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION +typedef struct _VM_COUNTERS { - SYSTEM_THREAD_INFORMATION ThreadInfo; - PVOID StackBase; - PVOID StackLimit; - PVOID Win32StartAddress; - PTEB TebBase; // Since Vista - ULONG_PTR Reserved2; - ULONG_PTR Reserved3; - ULONG_PTR Reserved4; -} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION; + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; +} VM_COUNTERS, *PVM_COUNTERS; -#ifndef FIELD_OFFSET -#if !defined(__clang__) -#define FIELD_OFFSET(type, field) ((LONG)(LONG_PTR)&(((type *)0)->field)) -#else -#define FIELD_OFFSET(type, field) ((LONG)__builtin_offsetof(type, field)) -#endif -#endif -#ifndef UFIELD_OFFSET -#if !defined(__clang__) -#define UFIELD_OFFSET(type, field) ((ULONG)(LONG_PTR)&(((type *)0)->field)) -#else -#define UFIELD_OFFSET(type, field) ((ULONG)__builtin_offsetof(type, field)) -#endif -#endif +typedef struct _VM_COUNTERS_EX +{ + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivateUsage; +} VM_COUNTERS_EX, *PVM_COUNTERS_EX; + +typedef struct _JOBOBJECT_WAKE_FILTER +{ + ULONG HighEdgeFilter; + ULONG LowEdgeFilter; +} JOBOBJECT_WAKE_FILTER, *PJOBOBJECT_WAKE_FILTER; + +typedef struct _JOBOBJECT_FREEZE_INFORMATION +{ + union + { + ULONG Flags; + struct + { + ULONG FreezeOperation : 1; + ULONG FilterOperation : 1; + ULONG SwapOperation : 1; + ULONG Reserved : 29; + } s; + } u; + BOOLEAN Freeze; + BOOLEAN Swap; + UCHAR Reserved0[2]; + JOBOBJECT_WAKE_FILTER WakeFilter; +} JOBOBJECT_FREEZE_INFORMATION, *PJOBOBJECT_FREEZE_INFORMATION; #define PTR_ADD_OFFSET(Pointer, Offset) ((PVOID)((ULONG_PTR)(Pointer) + (ULONG_PTR)(Offset))) #define PTR_SUB_OFFSET(Pointer, Offset) ((PVOID)((ULONG_PTR)(Pointer) - (ULONG_PTR)(Offset))) -#define ALIGN_DOWN_BY(Address, Align) ((ULONG_PTR)(Address) & ~(Align - 1)) +#define ALIGN_DOWN_BY(Address, Align) ((ULONG_PTR)(Address) & ~((Align) - 1)) #define ALIGN_DOWN_POINTER_BY(Pointer, Align) ((PVOID)ALIGN_DOWN_BY(Pointer, Align)) #define ALIGN_DOWN_POINTER(Pointer, Type) ((PVOID)ALIGN_DOWN(Pointer, Type)) #define ALIGN_UP_BY(Address, Align) (((ULONG_PTR)(Address) + (Align) - 1) & ~((Align) - 1)) @@ -3210,6 +4334,14 @@ typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION (p)->SecurityQualityOfService = NULL; \ } +#if !defined(__cplusplus) +#define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) \ + { sizeof(OBJECT_ATTRIBUTES), NULL, ((PUNICODE_STRING)(n)), (a), NULL, NULL } +#else +#define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) \ + { sizeof(OBJECT_ATTRIBUTES), nullptr, ((remove_constref::type)(n)), (a), nullptr, nullptr } +#endif + #define OBJ_INHERIT 0x00000002L #define OBJ_PERMANENT 0x00000010L #define OBJ_EXCLUSIVE 0x00000020L @@ -3223,18 +4355,23 @@ typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION #define OBJ_VALID_ATTRIBUTES 0x00001FF2 #if NTDDI_VERSION >= NTDDI_VISTA +#ifndef THREAD_ALL_ACCESS #define THREAD_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \ 0xFFFF) +#endif #else +#ifndef THREAD_ALL_ACCESS #define THREAD_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \ 0x3FF) #endif +#endif #define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001 #define THREAD_CREATE_FLAGS_SUPPRESS_DLLMAINS 0x00000002 #define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004 #define THREAD_CREATE_FLAGS_HAS_SECURITY_DESCRIPTOR 0x00000010 // ? #define THREAD_CREATE_FLAGS_ACCESS_CHECK_IN_TARGET 0x00000020 // ? +#define THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE 0x00000040 // 19H1+ #define THREAD_CREATE_FLAGS_INITIAL_THREAD 0x00000080 #define DEBUG_READ_EVENT 0x0001 @@ -3341,9 +4478,44 @@ typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION WORKER_FACTORY_READY_WORKER | \ WORKER_FACTORY_SHUTDOWN) +typedef struct _WORKER_FACTORY_DEFERRED_WORK +{ + struct _PORT_MESSAGE* AlpcSendMessage; + HANDLE AlpcSendMessagePort; + ULONG AlpcSendMessageFlags; + ULONG Flags; +} WORKER_FACTORY_DEFERRED_WORK, *PWORKER_FACTORY_DEFERRED_WORK; + #define NtCurrentProcess ((HANDLE)(LONG_PTR)-1) #define NtCurrentThread ((HANDLE)(LONG_PTR)-2) -#define NtCurrentPeb() (NtCurrentTeb()->ProcessEnvironmentBlock) + +FORCEINLINE +PPEB +NtCurrentPeb( + VOID +) +{ +#if defined(_M_AMD64) + return (PPEB)__readgsqword(FIELD_OFFSET(TEB, ProcessEnvironmentBlock)); +#elif defined(_M_IX86) + return (PPEB)__readfsdword(FIELD_OFFSET(TEB, ProcessEnvironmentBlock)); +#elif defined(_M_ARM) + return (PPEB)(((PTEB)(ULONG_PTR)_MoveFromCoprocessor(CP15_TPIDRURW))->ProcessEnvironmentBlock); +#elif defined(_M_ARM64) + return (PPEB)(((PTEB)__getReg(18))->ProcessEnvironmentBlock); +#elif defined(_M_IA64) + return *(PPEB*)((size_t)_rdteb() + FIELD_OFFSET(TEB, ProcessEnvironmentBlock)); +#elif defined(_M_ALPHA) + return *(PPEB*)((size_t)_rdteb() + FIELD_OFFSET(TEB, ProcessEnvironmentBlock)); +#elif defined(_M_MIPS) + return *(PPEB*)((*(size_t*)(0x7ffff030)) + FIELD_OFFSET(TEB, ProcessEnvironmentBlock)); +#elif defined(_M_PPC) + return *(PPEB*)(__gregister_get(13) + FIELD_OFFSET(TEB, ProcessEnvironmentBlock)); +#else +#error "Unsupported architecture" +#endif +} + #define NtCurrentProcessId() (NtCurrentTeb()->ClientId.UniqueProcess) #define NtCurrentThreadId() (NtCurrentTeb()->ClientId.UniqueThread) #define RtlProcessHeap() (NtCurrentPeb()->ProcessHeap) @@ -3484,18 +4656,19 @@ typedef struct _RTL_HEAP_WALK_ENTRY PVOID FirstEntry; PVOID LastEntry; } Segment; - }; + } u; } RTL_HEAP_WALK_ENTRY, *PRTL_HEAP_WALK_ENTRY; // HEAP_INFORMATION_CLASS. winnt.h is incomplete -#define HeapCompatibilityInformation 0x0 // q; s: ULONG -#define HeapEnableTerminationOnCorruption 0x1 // q; s: NULL -#define HeapExtendedInformation 0x2 // q; s: HEAP_EXTENDED_INFORMATION -#define HeapOptimizeResources 0x3 // q; s: HEAP_OPTIMIZE_RESOURCES_INFORMATION -#define HeapTaggingInformation 0x4 -#define HeapStackDatabase 0x5 -#define HeapDetailedFailureInformation 0x80000001 -#define HeapSetDebuggingInformation 0x80000002 // q; s: HEAP_DEBUGGING_INFORMATION +#define HeapCompatibilityInformation ((HEAP_INFORMATION_CLASS)0x0) // q; s: ULONG +#define HeapEnableTerminationOnCorruption ((HEAP_INFORMATION_CLASS)0x1) // q; s: NULL +#define HeapExtendedInformation ((HEAP_INFORMATION_CLASS)0x2) // q; s: HEAP_EXTENDED_INFORMATION +#define HeapOptimizeResources ((HEAP_INFORMATION_CLASS)0x3) // q; s: HEAP_OPTIMIZE_RESOURCES_INFORMATION +#define HeapTaggingInformation ((HEAP_INFORMATION_CLASS)0x4) +#define HeapStackDatabase ((HEAP_INFORMATION_CLASS)0x5) +#define HeapMemoryLimit ((HEAP_INFORMATION_CLASS)0x6) // 19H2 +#define HeapDetailedFailureInformation ((HEAP_INFORMATION_CLASS)0x80000001) +#define HeapSetDebuggingInformation ((HEAP_INFORMATION_CLASS)0x80000002) // q; s: HEAP_DEBUGGING_INFORMATION typedef struct _PROCESS_HEAP_INFORMATION { @@ -3566,6 +4739,7 @@ NTSTATUS #define LDR_FORMAT_MESSAGE_FROM_SYSTEM_MESSAGE_TABLE 11 +#define RTL_ERRORMODE_FAILCRITICALERRORS 0x0010 #define RTL_ERRORMODE_NOGPFAULTERRORBOX 0x0020 #define RTL_ERRORMODE_NOOPENFILEERRORBOX 0x0040 @@ -3773,14 +4947,14 @@ typedef struct _IO_COMPLETION_BASIC_INFORMATION typedef enum _WORKERFACTORYINFOCLASS { - WorkerFactoryTimeout, - WorkerFactoryRetryTimeout, - WorkerFactoryIdleTimeout, + WorkerFactoryTimeout, // q; s: LARGE_INTEGER + WorkerFactoryRetryTimeout, // q; s: LARGE_INTEGER + WorkerFactoryIdleTimeout, // q; s: LARGE_INTEGER WorkerFactoryBindingCount, - WorkerFactoryThreadMinimum, - WorkerFactoryThreadMaximum, - WorkerFactoryPaused, - WorkerFactoryBasicInformation, + WorkerFactoryThreadMinimum, // q; s: ULONG + WorkerFactoryThreadMaximum, // q; s: ULONG + WorkerFactoryPaused, // ULONG or BOOLEAN + WorkerFactoryBasicInformation, // WORKER_FACTORY_BASIC_INFORMATION WorkerFactoryAdjustThreadGoal, WorkerFactoryCallbackType, WorkerFactoryStackInformation, // 10 @@ -3788,6 +4962,7 @@ typedef enum _WORKERFACTORYINFOCLASS WorkerFactoryTimeoutWaiters, // since THRESHOLD WorkerFactoryFlags, WorkerFactoryThreadSoftMaximum, + WorkerFactoryThreadCpuSets, // since REDSTONE5 MaxWorkerFactoryInfoClass } WORKERFACTORYINFOCLASS, *PWORKERFACTORYINFOCLASS; @@ -4009,7 +5184,7 @@ NtCreateProcess( _In_ BOOLEAN InheritObjectTable, _In_opt_ HANDLE SectionHandle, _In_opt_ HANDLE DebugPort, - _In_opt_ HANDLE ExceptionPort + _In_opt_ HANDLE TokenHandle ); NTSYSCALLAPI @@ -4023,8 +5198,8 @@ NtCreateProcessEx( _In_ ULONG Flags, _In_opt_ HANDLE SectionHandle, _In_opt_ HANDLE DebugPort, - _In_opt_ HANDLE ExceptionPort, - _In_ BOOLEAN InJob + _In_opt_ HANDLE TokenHandle, + _In_ ULONG JobMemberLevel ); #if NTDDI_VERSION >= NTDDI_VISTA @@ -4071,7 +5246,7 @@ NTSYSCALLAPI NTSTATUS NTAPI NtQueryObject( - _In_ HANDLE Handle, + _In_opt_ HANDLE Handle, _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, _Out_opt_ PVOID ObjectInformation, _In_ ULONG ObjectInformationLength, @@ -4083,7 +5258,7 @@ NTSTATUS NTAPI NtQuerySystemInformation( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, - _Out_opt_ PVOID SystemInformation, + _Out_writes_bytes_to_opt_(SystemInformationLength, *ReturnLength) PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength ); @@ -4094,9 +5269,9 @@ NTSTATUS NTAPI NtQuerySystemInformationEx( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, - _In_ PVOID InputBuffer, + _In_reads_bytes_(InputBufferLength) PVOID InputBuffer, _In_ ULONG InputBufferLength, - _Out_ PVOID SystemInformation, + _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength ); @@ -4107,7 +5282,7 @@ NTSTATUS NTAPI NtSetSystemInformation( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, - _In_opt_ PVOID SystemInformation, + _In_reads_bytes_opt_(SystemInformationLength) PVOID SystemInformation, _In_ ULONG SystemInformationLength ); @@ -4137,9 +5312,22 @@ NTSTATUS NTAPI NtUnmapViewOfSection( _In_ HANDLE ProcessHandle, - _In_ PVOID BaseAddress + _In_opt_ PVOID BaseAddress ); +#if NTDDI_VERSION >= NTDDI_WIN8 + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtUnmapViewOfSectionEx( + _In_ HANDLE ProcessHandle, + _In_opt_ PVOID BaseAddress, + _In_ ULONG Flags +); + +#endif + NTSYSCALLAPI NTSTATUS NTAPI @@ -4183,6 +5371,7 @@ NTSYSCALLAPI ULONG NTAPI NtGetCurrentProcessorNumber( + VOID ); #endif @@ -4210,7 +5399,7 @@ NTSTATUS NTAPI NtWaitForMultipleObjects( _In_ ULONG Count, - _In_ PHANDLE Handles, + _In_reads_(Count) HANDLE Handles[], _In_ WAIT_TYPE WaitType, _In_ BOOLEAN Alertable, _In_opt_ PLARGE_INTEGER Timeout @@ -4222,7 +5411,7 @@ NTSTATUS NTAPI NtWaitForMultipleObjects32( _In_ ULONG Count, - _In_ PHANDLE Handles, + _In_reads_(Count) HANDLE Handles[], _In_ WAIT_TYPE WaitType, _In_ BOOLEAN Alertable, _In_opt_ PLARGE_INTEGER Timeout @@ -4244,7 +5433,7 @@ NTAPI NtQuerySecurityObject( _In_ HANDLE Handle, _In_ SECURITY_INFORMATION SecurityInformation, - _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _Out_writes_bytes_to_(Length, *LengthNeeded) PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Length, _Out_ PULONG LengthNeeded ); @@ -4306,6 +5495,7 @@ NTSYSCALLAPI NTSTATUS NTAPI NtFlushWriteBuffer( + VOID ); NTSYSCALLAPI @@ -4318,9 +5508,9 @@ NtFsControlFile( _In_opt_ PVOID ApcContext, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG FsControlCode, - _In_opt_ PVOID InputBuffer, + _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer, _In_ ULONG InputBufferLength, - _Out_opt_ PVOID OutputBuffer, + _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer, _In_ ULONG OutputBufferLength ); @@ -4366,7 +5556,7 @@ NTSTATUS NTAPI NtQueryVirtualMemory( _In_ HANDLE ProcessHandle, - _In_ PVOID BaseAddress, + _In_opt_ PVOID BaseAddress, _In_ MEMORY_INFORMATION_CLASS MemoryInformationClass, _Out_ PVOID MemoryInformation, _In_ SIZE_T MemoryInformationLength, @@ -4398,17 +5588,41 @@ NTSTATUS NTAPI NtSystemDebugControl( _In_ SYSDBG_COMMAND Command, - _Inout_opt_ PVOID InputBuffer, + _Inout_updates_bytes_opt_(InputBufferLength) PVOID InputBuffer, _In_ ULONG InputBufferLength, - _Out_opt_ PVOID OutputBuffer, + _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer, _In_ ULONG OutputBufferLength, _Out_opt_ PULONG ReturnLength ); +NTSYSCALLAPI +NTSTATUS +NTAPI +NtShutdownSystem( + _In_ SHUTDOWN_ACTION Action +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtDisplayString( + _In_ PUNICODE_STRING String +); + +#if NTDDI_VERSION >= NTDDI_WIN7 +NTSYSCALLAPI +NTSTATUS +NTAPI +NtDrawText( + _In_ PUNICODE_STRING Text +); +#endif + NTSYSCALLAPI NTSTATUS NTAPI NtYieldExecution( + VOID ); NTSYSCALLAPI @@ -4434,13 +5648,26 @@ NtQueryFullAttributesFile( _Out_ PFILE_NETWORK_OPEN_INFORMATION FileInformation ); +#if NTDDI_VERSION >= NTDDI_WIN10_RS2 +NTSYSCALLAPI +NTSTATUS +NTAPI +NtQueryInformationByName( + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_writes_bytes_(Length) PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass +); +#endif + NTSYSCALLAPI NTSTATUS NTAPI NtQueryInformationFile( _In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, - _Out_ PVOID FileInformation, + _Out_writes_bytes_(Length) PVOID FileInformation, _In_ ULONG Length, _In_ FILE_INFORMATION_CLASS FileInformationClass ); @@ -4451,7 +5678,7 @@ NTAPI NtSetInformationFile( _In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, - _In_ PVOID FileInformation, + _In_reads_bytes_(Length) PVOID FileInformation, _In_ ULONG Length, _In_ FILE_INFORMATION_CLASS FileInformationClass ); @@ -4462,7 +5689,7 @@ NTAPI NtSetQuotaInformationFile( _In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, - _In_ PVOID Buffer, + _In_reads_bytes_(Length) PVOID Buffer, _In_ ULONG Length ); @@ -4472,7 +5699,7 @@ NTAPI NtSetVolumeInformationFile( _In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, - _In_ PVOID FsInformation, + _In_reads_bytes_(Length) PVOID FsInformation, _In_ ULONG Length, _In_ FS_INFORMATION_CLASS FsInformationClass ); @@ -4490,7 +5717,7 @@ NtCreateFile( _In_ ULONG ShareAccess, _In_ ULONG CreateDisposition, _In_ ULONG CreateOptions, - _In_opt_ PVOID EaBuffer, + _In_reads_bytes_opt_(EaLength) PVOID EaBuffer, _In_ ULONG EaLength ); @@ -4623,7 +5850,7 @@ NTSYSCALLAPI NTSTATUS NTAPI NtGetNextProcess( - _In_ HANDLE ProcessHandle, + _In_opt_ HANDLE ProcessHandle, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG HandleAttributes, _In_ ULONG Flags, @@ -4635,7 +5862,7 @@ NTSTATUS NTAPI NtGetNextThread( _In_ HANDLE ProcessHandle, - _In_ HANDLE ThreadHandle, + _In_opt_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG HandleAttributes, _In_ ULONG Flags, @@ -4704,13 +5931,85 @@ NtCreateThreadEx( _In_ PUSER_THREAD_START_ROUTINE StartRoutine, _In_opt_ PVOID Argument, _In_ ULONG CreateFlags, - _In_opt_ ULONG_PTR ZeroBits, + _In_opt_ SIZE_T ZeroBits, _In_opt_ SIZE_T StackSize, _In_opt_ SIZE_T MaximumStackSize, _In_opt_ PPS_ATTRIBUTE_LIST AttributeList ); #endif +NTSYSCALLAPI +NTSTATUS +NTAPI +NtCreateJobObject( + _Out_ PHANDLE JobHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtOpenJobObject( + _Out_ PHANDLE JobHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtAssignProcessToJobObject( + _In_ HANDLE JobHandle, + _In_ HANDLE ProcessHandle +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtTerminateJobObject( + _In_ HANDLE JobHandle, + _In_ NTSTATUS ExitStatus +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtIsProcessInJob( + _In_ HANDLE ProcessHandle, + _In_opt_ HANDLE JobHandle +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtQueryInformationJobObject( + _In_opt_ HANDLE JobHandle, + _In_ JOBOBJECTINFOCLASS JobObjectInformationClass, + _Out_writes_bytes_(JobObjectInformationLength) PVOID JobObjectInformation, + _In_ ULONG JobObjectInformationLength, + _Out_opt_ PULONG ReturnLength +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtSetInformationJobObject( + _In_ HANDLE JobHandle, + _In_ JOBOBJECTINFOCLASS JobObjectInformationClass, + _In_reads_bytes_(JobObjectInformationLength) PVOID JobObjectInformation, + _In_ ULONG JobObjectInformationLength +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtCreateJobSet( + _In_ ULONG NumJob, + _In_reads_(NumJob) PJOB_SET_ARRAY UserJobSet, + _In_ ULONG Flags +); + #if NTDDI_VERSION >= NTDDI_WIN7 NTSYSCALLAPI NTSTATUS @@ -4735,8 +6034,8 @@ NTAPI NtRaiseHardError( _In_ NTSTATUS ErrorStatus, _In_ ULONG NumberOfParameters, - _In_opt_ ULONG UnicodeStringParameterMask, - _In_ PULONG_PTR Parameters, + _In_ ULONG UnicodeStringParameterMask, + _In_reads_(NumberOfParameters) PULONG_PTR Parameters, _In_ HARDERROR_RESPONSE_OPTION ResponseOption, _Out_ PHARDERROR_RESPONSE Response ); @@ -4746,7 +6045,7 @@ NTSTATUS NTAPI NtAllocateVirtualMemory( _In_ HANDLE ProcessHandle, - _Inout_ PVOID* BaseAddress, + _Inout_ _At_(*BaseAddress, _Readable_bytes_(*RegionSize) _Writable_bytes_(*RegionSize) _Post_readable_byte_size_(*RegionSize)) PVOID* BaseAddress, _In_ ULONG_PTR ZeroBits, _Inout_ PSIZE_T RegionSize, _In_ ULONG AllocationType, @@ -4769,7 +6068,7 @@ NTAPI NtReadVirtualMemory( _In_ HANDLE ProcessHandle, _In_opt_ PVOID BaseAddress, - _Out_ PVOID Buffer, + _Out_writes_bytes_(BufferSize) PVOID Buffer, _In_ SIZE_T BufferSize, _Out_opt_ PSIZE_T NumberOfBytesRead ); @@ -4780,7 +6079,7 @@ NTAPI NtWriteVirtualMemory( _In_ HANDLE ProcessHandle, _In_opt_ PVOID BaseAddress, - _In_ CONST VOID* Buffer, + _In_reads_bytes_(BufferSize) CONST VOID* Buffer, _In_ SIZE_T BufferSize, _Out_opt_ PSIZE_T NumberOfBytesWritten ); @@ -4791,7 +6090,7 @@ NTAPI NtAllocateUserPhysicalPages( _In_ HANDLE ProcessHandle, _Inout_ PULONG_PTR NumberOfPages, - _Out_ PULONG_PTR UserPfnArray + _Out_writes_(*NumberOfPages) PULONG_PTR UserPfnArray ); NTSYSCALLAPI @@ -4800,16 +6099,16 @@ NTAPI NtMapUserPhysicalPages( _In_ PVOID VirtualAddress, _In_ ULONG_PTR NumberOfPages, - _In_ PULONG_PTR UserPfnArray + _In_reads_opt_(NumberOfPages) PULONG_PTR UserPfnArray ); NTSYSCALLAPI NTSTATUS NTAPI NtMapUserPhysicalPagesScatter( - _In_ PVOID* VirtualAddresses, + _In_reads_(NumberOfPages) PVOID* VirtualAddresses, _In_ ULONG_PTR NumberOfPages, - _In_ PULONG_PTR UserPfnArray + _In_reads_opt_(NumberOfPages) PULONG_PTR UserPfnArray ); NTSYSCALLAPI @@ -4818,7 +6117,7 @@ NTAPI NtFreeUserPhysicalPages( _In_ HANDLE ProcessHandle, _Inout_ PULONG_PTR NumberOfPages, - _In_ PULONG_PTR UserPfnArray + _In_reads_(*NumberOfPages) PULONG_PTR UserPfnArray ); NTSYSCALLAPI @@ -4827,7 +6126,7 @@ NTAPI NtQuerySection( _In_ HANDLE SectionHandle, _In_ SECTION_INFORMATION_CLASS SectionInformationClass, - _Out_ PVOID SectionInformation, + _Out_writes_bytes_(SectionInformationLength) PVOID SectionInformation, _In_ SIZE_T SectionInformationLength, _Out_opt_ PSIZE_T ReturnLength ); @@ -4853,6 +6152,25 @@ NtCreateSection( _In_opt_ HANDLE FileHandle ); +#if NTDDI_VERSION >= NTDDI_WIN10_RS5 + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtCreateSectionEx( + _Out_ PHANDLE SectionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ PLARGE_INTEGER MaximumSize, + _In_ ULONG SectionPageProtection, + _In_ ULONG AllocationAttributes, + _In_opt_ HANDLE FileHandle, + _Inout_updates_opt_(ExtendedParameterCount) struct _MEM_EXTENDED_PARAMETER* ExtendedParameters, + _In_ ULONG ExtendedParameterCount +); + +#endif + NTSYSCALLAPI NTSTATUS NTAPI @@ -4868,7 +6186,7 @@ NTAPI NtMapViewOfSection( _In_ HANDLE SectionHandle, _In_ HANDLE ProcessHandle, - _Inout_ PVOID* BaseAddress, + _Inout_ _At_(*BaseAddress, _Readable_bytes_(*ViewSize) _Writable_bytes_(*ViewSize) _Post_readable_byte_size_(*ViewSize)) PVOID* BaseAddress, _In_ ULONG_PTR ZeroBits, _In_ SIZE_T CommitSize, _Inout_opt_ PLARGE_INTEGER SectionOffset, @@ -4878,6 +6196,25 @@ NtMapViewOfSection( _In_ ULONG Win32Protect ); +#if NTDDI_VERSION >= NTDDI_WIN10_RS4 + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtMapViewOfSectionEx( + _In_ HANDLE SectionHandle, + _In_ HANDLE ProcessHandle, + _Inout_opt_ PVOID* BaseAddress, + _In_ PLARGE_INTEGER ViewOffset, + _Inout_ PSIZE_T ViewSize, + _In_ ULONG AllocationType, + _In_ ULONG Win32Protect, + _Inout_updates_opt_(ParameterCount) struct _MEM_EXTENDED_PARAMETER* ExtendedParameters, + _In_ ULONG ParameterCount +); + +#endif + #if NTDDI_VERSION >= NTDDI_VISTA NTSYSCALLAPI NTSTATUS @@ -4904,6 +6241,24 @@ NtNotifyChangeDirectoryFile( _In_ BOOLEAN WatchTree ); +#if NTDDI_VERSION >= NTDDI_WIN10_RS3 +NTSYSCALLAPI +NTSTATUS +NTAPI +NtNotifyChangeDirectoryFileEx( + _In_ HANDLE FileHandle, + _In_opt_ HANDLE Event, + _In_opt_ PIO_APC_ROUTINE ApcRoutine, + _In_opt_ PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_writes_bytes_(Length) PVOID Buffer, + _In_ ULONG Length, + _In_ ULONG CompletionFilter, + _In_ BOOLEAN WatchTree, + _In_opt_ DIRECTORY_NOTIFY_INFORMATION_CLASS DirectoryNotifyInformationClass +); +#endif + NTSYSCALLAPI NTSTATUS NTAPI @@ -4925,7 +6280,7 @@ NtQueryDirectoryFile( _In_opt_ PIO_APC_ROUTINE ApcRoutine, _In_opt_ PVOID ApcContext, _Out_ PIO_STATUS_BLOCK IoStatusBlock, - _Out_ PVOID FileInformation, + _Out_writes_bytes_(Length) PVOID FileInformation, _In_ ULONG Length, _In_ FILE_INFORMATION_CLASS FileInformationClass, _In_ BOOLEAN ReturnSingleEntry, @@ -4933,16 +6288,47 @@ NtQueryDirectoryFile( _In_ BOOLEAN RestartScan ); +#if NTDDI_VERSION >= NTDDI_WIN10_RS3 +NTSYSCALLAPI +NTSTATUS +NTAPI +NtQueryDirectoryFileEx( + _In_ HANDLE FileHandle, + _In_opt_ HANDLE Event, + _In_opt_ PIO_APC_ROUTINE ApcRoutine, + _In_opt_ PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_writes_bytes_(Length) PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass, + _In_ ULONG QueryFlags, + _In_opt_ PUNICODE_STRING FileName +); +#endif + +#if (NTDDI_VERSION >= NTDDI_WIN10_RS2) +NTSYSCALLAPI +NTSTATUS +NTAPI +NtQueryInformationByName( + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_writes_bytes_(Length) PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass +); +#endif + NTSYSCALLAPI NTSTATUS NTAPI NtQueryEaFile( _In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, - _Out_ PVOID Buffer, + _Out_writes_bytes_(Length) PVOID Buffer, _In_ ULONG Length, _In_ BOOLEAN ReturnSingleEntry, - _In_ PVOID EaList, + _In_reads_bytes_opt_(EaListLength) PVOID EaList, _In_ ULONG EaListLength, _In_opt_ PULONG EaIndex, _In_ BOOLEAN RestartScan @@ -4954,7 +6340,7 @@ NTAPI NtSetEaFile( _In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, - _In_ PVOID Buffer, + _In_reads_bytes_(Length) PVOID Buffer, _In_ ULONG Length ); @@ -4981,7 +6367,7 @@ NtReadFile( _In_opt_ PIO_APC_ROUTINE ApcRoutine, _In_opt_ PVOID ApcContext, _Out_ PIO_STATUS_BLOCK IoStatusBlock, - _Out_ PVOID Buffer, + _Out_writes_bytes_(Length) PVOID Buffer, _In_ ULONG Length, _In_opt_ PLARGE_INTEGER ByteOffset, _In_opt_ PULONG Key @@ -5033,7 +6419,7 @@ NtWriteFile( _In_opt_ PIO_APC_ROUTINE ApcRoutine, _In_opt_ PVOID ApcContext, _Out_ PIO_STATUS_BLOCK IoStatusBlock, - _In_ PVOID Buffer, + _In_reads_bytes_(Length) PVOID Buffer, _In_ ULONG Length, _In_opt_ PLARGE_INTEGER ByteOffset, _In_opt_ PULONG Key @@ -5049,9 +6435,9 @@ NtDeviceIoControlFile( _In_opt_ PVOID ApcContext, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG IoControlCode, - _In_opt_ PVOID InputBuffer, + _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer, _In_ ULONG InputBufferLength, - _Out_opt_ PVOID OutputBuffer, + _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer, _In_ ULONG OutputBufferLength ); @@ -5061,7 +6447,7 @@ NTAPI NtSetInformationObject( _In_ HANDLE Handle, _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, - _In_ PVOID ObjectInformation, + _In_reads_bytes_(ObjectInformationLength) PVOID ObjectInformation, _In_ ULONG ObjectInformationLength ); @@ -5115,8 +6501,8 @@ NTSTATUS NTAPI NtQueryDirectoryObject( _In_ HANDLE DirectoryHandle, - _Out_ PVOID Buffer, - _In_ ULONG BufferLength, + _Out_writes_bytes_opt_(Length) PVOID Buffer, + _In_ ULONG Length, _In_ BOOLEAN ReturnSingleEntry, _In_ BOOLEAN RestartScan, _Inout_ PULONG Context, @@ -5131,7 +6517,7 @@ NtCreatePrivateNamespace( _Out_ PHANDLE NamespaceHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, - _In_ PVOID BoundaryDescriptor + _In_ HANDLE BoundaryDescriptor ); NTSYSCALLAPI @@ -5141,7 +6527,7 @@ NtOpenPrivateNamespace( _Out_ PHANDLE NamespaceHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, - _In_ PVOID BoundaryDescriptor + _In_ HANDLE BoundaryDescriptor ); NTSYSCALLAPI @@ -5299,7 +6685,7 @@ NTAPI NtQueryVolumeInformationFile( _In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, - _Out_ PVOID FsInformation, + _Out_writes_bytes_(Length) PVOID FsInformation, _In_ ULONG Length, _In_ FS_INFORMATION_CLASS FsInformationClass ); @@ -5317,7 +6703,7 @@ NtCreateKey( _Out_opt_ PULONG Disposition ); -#if NTDDI_VERSION >= PNTDDI_VISTA +#if NTDDI_VERSION >= NTDDI_VISTA NTSYSCALLAPI NTSTATUS NTAPI @@ -5342,7 +6728,7 @@ NtOpenKey( _In_ POBJECT_ATTRIBUTES ObjectAttributes ); -#if NTDDI_VERSION >= PNTDDI_VISTA +#if NTDDI_VERSION >= NTDDI_VISTA NTSYSCALLAPI NTSTATUS NTAPI @@ -5406,7 +6792,7 @@ NTAPI NtQueryKey( _In_ HANDLE KeyHandle, _In_ KEY_INFORMATION_CLASS KeyInformationClass, - _Out_ PVOID KeyInformation, + _Out_writes_bytes_to_opt_(Length, *ResultLength) PVOID KeyInformation, _In_ ULONG Length, _Out_ PULONG ResultLength ); @@ -5417,7 +6803,7 @@ NTAPI NtSetInformationKey( _In_ HANDLE KeyHandle, _In_ KEY_SET_INFORMATION_CLASS KeySetInformationClass, - _In_ PVOID KeySetInformation, + _In_reads_bytes_(KeySetInformationLength) PVOID KeySetInformation, _In_ ULONG KeySetInformationLength ); @@ -5428,7 +6814,7 @@ NtQueryValueKey( _In_ HANDLE KeyHandle, _In_ PUNICODE_STRING ValueName, _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, - _Out_ PVOID KeyValueInformation, + _Out_writes_bytes_to_opt_(Length, *ResultLength) PVOID KeyValueInformation, _In_ ULONG Length, _Out_ PULONG ResultLength ); @@ -5441,7 +6827,7 @@ NtSetValueKey( _In_ PUNICODE_STRING ValueName, _In_opt_ ULONG TitleIndex, _In_ ULONG Type, - _In_ PVOID Data, + _In_reads_bytes_opt_(DataSize) PVOID Data, _In_ ULONG DataSize ); @@ -5450,9 +6836,9 @@ NTSTATUS NTAPI NtQueryMultipleValueKey( _In_ HANDLE KeyHandle, - _Inout_ PKEY_VALUE_ENTRY ValueEntries, + _Inout_updates_(EntryCount) PKEY_VALUE_ENTRY ValueEntries, _In_ ULONG EntryCount, - _Out_ PVOID ValueBuffer, + _Out_writes_bytes_(*BufferLength) PVOID ValueBuffer, _Inout_ PULONG BufferLength, _Out_opt_ PULONG RequiredBufferLength ); @@ -5464,7 +6850,7 @@ NtEnumerateKey( _In_ HANDLE KeyHandle, _In_ ULONG Index, _In_ KEY_INFORMATION_CLASS KeyInformationClass, - _Out_ PVOID KeyInformation, + _Out_writes_bytes_to_opt_(Length, *ResultLength) PVOID KeyInformation, _In_ ULONG Length, _Out_ PULONG ResultLength ); @@ -5476,7 +6862,7 @@ NtEnumerateValueKey( _In_ HANDLE KeyHandle, _In_ ULONG Index, _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, - _Out_ PVOID KeyValueInformation, + _Out_writes_bytes_to_opt_(Length, *ResultLength) PVOID KeyValueInformation, _In_ ULONG Length, _Out_ PULONG ResultLength ); @@ -5576,7 +6962,7 @@ NTSTATUS NTAPI NtRestoreKey( _In_ HANDLE KeyHandle, - _In_ HANDLE FileHandle, + _In_opt_ HANDLE FileHandle, _In_ ULONG Flags ); @@ -5616,7 +7002,7 @@ NtNotifyChangeKey( _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG CompletionFilter, _In_ BOOLEAN WatchTree, - _Out_ PVOID Buffer, + _Out_writes_bytes_opt_(BufferSize) PVOID Buffer, _In_ ULONG BufferSize, _In_ BOOLEAN Asynchronous ); @@ -5627,14 +7013,14 @@ NTAPI NtNotifyChangeMultipleKeys( _In_ HANDLE MasterKeyHandle, _In_opt_ ULONG Count, - _In_ POBJECT_ATTRIBUTES SubordinateObjects, + _In_reads_opt_(Count) OBJECT_ATTRIBUTES SubordinateObjects[], _In_opt_ HANDLE Event, _In_opt_ PIO_APC_ROUTINE ApcRoutine, _In_opt_ PVOID ApcContext, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG CompletionFilter, _In_ BOOLEAN WatchTree, - _Out_ PVOID Buffer, + _Out_writes_bytes_opt_(BufferSize) PVOID Buffer, _In_ ULONG BufferSize, _In_ BOOLEAN Asynchronous ); @@ -5654,7 +7040,7 @@ NTAPI NtQueryOpenSubKeysEx( _In_ POBJECT_ATTRIBUTES TargetKey, _In_ ULONG BufferLength, - _Out_ PVOID Buffer, + _Out_writes_bytes_opt_(BufferLength) PVOID Buffer, _Out_ PULONG RequiredSize ); #endif @@ -5681,7 +7067,7 @@ NtLockProductActivationKeys( _Out_opt_ ULONG* pSafeMode ); -#if NTDDI_VERSION >= PNTDDI_VISTA +#if NTDDI_VERSION >= NTDDI_VISTA NTSYSCALLAPI NTSTATUS NTAPI @@ -5701,14 +7087,14 @@ NTSTATUS NTAPI NtDelayExecution( _In_ BOOLEAN Alertable, - _In_ PLARGE_INTEGER DelayInterval + _In_opt_ PLARGE_INTEGER DelayInterval ); NTSYSCALLAPI NTSTATUS NTAPI NtCallbackReturn( - _In_ PVOID OutputBuffer, + _In_reads_bytes_opt_(OutputLength) PVOID OutputBuffer, _In_ ULONG OutputLength, _In_ NTSTATUS Status ); @@ -5841,12 +7227,23 @@ NTAPI NtDuplicateToken( _In_ HANDLE ExistingTokenHandle, _In_ ACCESS_MASK DesiredAccess, - _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _Out_ PHANDLE NewTokenHandle ); +NTSYSCALLAPI +NTSTATUS +NTAPI +NtQueryInformationToken( + _In_ HANDLE TokenHandle, + _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, + _Out_writes_bytes_to_opt_(TokenInformationLength, *ReturnLength) PVOID TokenInformation, + _In_ ULONG TokenInformationLength, + _Out_ PULONG ReturnLength +); + NTSYSCALLAPI NTSTATUS NTAPI @@ -5866,8 +7263,8 @@ NtAdjustGroupsToken( _In_ HANDLE TokenHandle, _In_ BOOLEAN ResetToDefault, _In_opt_ PTOKEN_GROUPS NewState, - _In_opt_ ULONG BufferLength, - _Out_ PTOKEN_GROUPS PreviousState, + _In_range_( >=, sizeof(TOKEN_GROUPS)) ULONG BufferLength, + _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PTOKEN_GROUPS PreviousState, _Out_ PULONG ReturnLength ); @@ -6005,7 +7402,7 @@ NTAPI NtQueryIoCompletion( _In_ HANDLE IoCompletionHandle, _In_ IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass, - _Out_ PVOID IoCompletionInformation, + _Out_writes_bytes_(IoCompletionInformationLength) PVOID IoCompletionInformation, _In_ ULONG IoCompletionInformationLength, _Out_opt_ PULONG ReturnLength ); @@ -6052,7 +7449,7 @@ NTSTATUS NTAPI NtRemoveIoCompletionEx( _In_ HANDLE IoCompletionHandle, - _Out_ PFILE_IO_COMPLETION_INFORMATION IoCompletionInformation, + _Out_writes_to_(Count, *NumEntriesRemoved) PFILE_IO_COMPLETION_INFORMATION IoCompletionInformation, _In_ ULONG Count, _Out_ PULONG NumEntriesRemoved, _In_opt_ PLARGE_INTEGER Timeout, @@ -6060,6 +7457,39 @@ NtRemoveIoCompletionEx( ); #endif +#if NTDDI_VERSION >= NTDDI_WIN8 +NTSYSCALLAPI +NTSTATUS +NTAPI +NtCreateWaitCompletionPacket( + _Out_ PHANDLE WaitCompletionPacketHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtAssociateWaitCompletionPacket( + _In_ HANDLE WaitCompletionPacketHandle, + _In_ HANDLE IoCompletionHandle, + _In_ HANDLE TargetObjectHandle, + _In_opt_ PVOID KeyContext, + _In_opt_ PVOID ApcContext, + _In_ NTSTATUS IoStatus, + _In_ ULONG_PTR IoStatusInformation, + _Out_opt_ PBOOLEAN AlreadySignaled +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtCancelWaitCompletionPacket( + _In_ HANDLE WaitCompletionPacketHandle, + _In_ BOOLEAN RemoveSignaledPacket +); +#endif + #if NTDDI_VERSION >= NTDDI_WIN7 NTSYSCALLAPI NTSTATUS @@ -6071,7 +7501,7 @@ NtNotifyChangeSession( _In_ IO_SESSION_EVENT Event, _In_ IO_SESSION_STATE NewState, _In_ IO_SESSION_STATE PreviousState, - _In_ PVOID Payload, + _In_reads_bytes_opt_(PayloadSize) PVOID Payload, _In_ ULONG PayloadSize ); #endif @@ -6122,6 +7552,7 @@ NTSYSCALLAPI NTSTATUS NTAPI NtTestAlert( + VOID ); NTSYSCALLAPI @@ -6168,7 +7599,7 @@ NTAPI NtQuerySemaphore( _In_ HANDLE SemaphoreHandle, _In_ SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, - _Out_ PVOID SemaphoreInformation, + _Out_writes_bytes_(SemaphoreInformationLength) PVOID SemaphoreInformation, _In_ ULONG SemaphoreInformationLength, _Out_opt_ PULONG ReturnLength ); @@ -6212,7 +7643,7 @@ NTAPI NtSetTimerEx( _In_ HANDLE TimerHandle, _In_ TIMER_SET_INFORMATION_CLASS TimerSetInformationClass, - _Inout_ PVOID TimerSetInformation, + _Inout_updates_bytes_opt_(TimerSetInformationLength) PVOID TimerSetInformation, _In_ ULONG TimerSetInformationLength ); #endif @@ -6338,7 +7769,7 @@ NTAPI NtQueryInformationTransactionManager( _In_ HANDLE TransactionManagerHandle, _In_ TRANSACTIONMANAGER_INFORMATION_CLASS TransactionManagerInformationClass, - _Out_ PVOID TransactionManagerInformation, + _Out_writes_bytes_(TransactionManagerInformationLength) PVOID TransactionManagerInformation, _In_ ULONG TransactionManagerInformationLength, _Out_opt_ PULONG ReturnLength ); @@ -6347,7 +7778,7 @@ NTSYSCALLAPI NTSTATUS NTAPI NtSetInformationTransactionManager( - _In_opt_ HANDLE TmHandle, + _In_ HANDLE TmHandle, _In_ TRANSACTIONMANAGER_INFORMATION_CLASS TransactionManagerInformationClass, _In_ PVOID TransactionManagerInformation, _In_ ULONG TransactionManagerInformationLength @@ -6386,7 +7817,7 @@ NTAPI NtOpenTransaction( _Out_ PHANDLE TransactionHandle, _In_ ACCESS_MASK DesiredAccess, - _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ LPGUID Uow, _In_opt_ HANDLE TmHandle ); @@ -6397,7 +7828,7 @@ NTAPI NtQueryInformationTransaction( _In_ HANDLE TransactionHandle, _In_ TRANSACTION_INFORMATION_CLASS TransactionInformationClass, - _Out_ PVOID TransactionInformation, + _Out_writes_bytes_(TransactionInformationLength) PVOID TransactionInformation, _In_ ULONG TransactionInformationLength, _Out_opt_ PULONG ReturnLength ); @@ -6459,7 +7890,7 @@ NTAPI NtQueryInformationEnlistment( _In_ HANDLE EnlistmentHandle, _In_ ENLISTMENT_INFORMATION_CLASS EnlistmentInformationClass, - _Out_ PVOID EnlistmentInformation, + _Out_writes_bytes_(EnlistmentInformationLength) PVOID EnlistmentInformation, _In_ ULONG EnlistmentInformationLength, _Out_opt_ PULONG ReturnLength ); @@ -6470,7 +7901,7 @@ NTAPI NtSetInformationEnlistment( _In_opt_ HANDLE EnlistmentHandle, _In_ ENLISTMENT_INFORMATION_CLASS EnlistmentInformationClass, - _In_ PVOID EnlistmentInformation, + _In_reads_bytes_(EnlistmentInformationLength) PVOID EnlistmentInformation, _In_ ULONG EnlistmentInformationLength ); @@ -6569,7 +8000,7 @@ NtCreateResourceManager( _Out_ PHANDLE ResourceManagerHandle, _In_ ACCESS_MASK DesiredAccess, _In_ HANDLE TmHandle, - _In_ LPGUID RmGuid, + _In_opt_ LPGUID ResourceManagerGuid, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_opt_ ULONG CreateOptions, _In_opt_ PUNICODE_STRING Description @@ -6582,7 +8013,7 @@ NtOpenResourceManager( _Out_ PHANDLE ResourceManagerHandle, _In_ ACCESS_MASK DesiredAccess, _In_ HANDLE TmHandle, - _In_opt_ LPGUID ResourceManagerGuid, + _In_ LPGUID ResourceManagerGuid, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes ); @@ -6600,7 +8031,7 @@ NtGetNotificationResourceManager( _In_ HANDLE ResourceManagerHandle, _Out_ PTRANSACTION_NOTIFICATION TransactionNotification, _In_ ULONG NotificationLength, - _In_opt_ PLARGE_INTEGER Timeout, + _In_ PLARGE_INTEGER Timeout, _Out_opt_ PULONG ReturnLength, _In_ ULONG Asynchronous, _In_opt_ ULONG_PTR AsynchronousContext @@ -6612,7 +8043,7 @@ NTAPI NtQueryInformationResourceManager( _In_ HANDLE ResourceManagerHandle, _In_ RESOURCEMANAGER_INFORMATION_CLASS ResourceManagerInformationClass, - _Out_ PVOID ResourceManagerInformation, + _Out_writes_bytes_(ResourceManagerInformationLength) PVOID ResourceManagerInformation, _In_ ULONG ResourceManagerInformationLength, _Out_opt_ PULONG ReturnLength ); @@ -6731,30 +8162,47 @@ NTAPI NtWorkerFactoryWorkerReady( _In_ HANDLE WorkerFactoryHandle ); -#endif -#if NTDDI_VERSION >= NTDDI_VISTA #if NTDDI_VERSION >= NTDDI_WIN8 || defined(_WIN64) -// Windows 8+ declaration, but can be used on any x64 Windows Vista+ +// Windows 8+ declaration, can be used on Vista/7 x64 NTSYSCALLAPI NTSTATUS NTAPI NtWaitForWorkViaWorkerFactory( _In_ HANDLE WorkerFactoryHandle, - _Out_ PFILE_IO_COMPLETION_INFORMATION MiniPacket, + _Out_writes_to_(Count, *PacketsReturned) PFILE_IO_COMPLETION_INFORMATION MiniPackets, _In_ ULONG Count, - _Out_ PULONG NumEntriesRemoved, - _In_ PLARGE_INTEGER Unknown // Wrong type (but works) + _Out_ PULONG PacketsReturned, + _In_ PWORKER_FACTORY_DEFERRED_WORK DeferredWork ); #else -// Windows Vista/7 x86 +// Allow Windows Vista/7 x86 to link (import '@8' decorated stdcall name from ntdll.lib instead of '@20') +// If you're using a newer **x86 32 bit** version of Windows, use the previous declaration (or make a typedef) NTSYSCALLAPI NTSTATUS NTAPI -NtWaitForWorkViaWorkerFactory( +ZwWaitForWorkViaWorkerFactory( _In_ HANDLE WorkerFactoryHandle, _Out_ PFILE_IO_COMPLETION_INFORMATION MiniPacket ); + +FORCEINLINE +NTSTATUS +NtWaitForWorkViaWorkerFactory( + _In_ HANDLE WorkerFactoryHandle, + _Out_ PFILE_IO_COMPLETION_INFORMATION MiniPackets, + _Reserved_ ULONG Count, + _Reserved_ PULONG PacketsReturned, + _Reserved_ PWORKER_FACTORY_DEFERRED_WORK DeferredWork +) +{ + UNREFERENCED_PARAMETER(Count); + UNREFERENCED_PARAMETER(PacketsReturned); + UNREFERENCED_PARAMETER(DeferredWork); + + return ZwWaitForWorkViaWorkerFactory(WorkerFactoryHandle, + MiniPackets); +} #endif #endif @@ -6763,7 +8211,7 @@ NTSTATUS NTAPI NtQuerySystemEnvironmentValue( _In_ PUNICODE_STRING VariableName, - _Out_ PWSTR VariableValue, + _Out_writes_bytes_(ValueLength) PWSTR VariableValue, _In_ USHORT ValueLength, _Out_opt_ PUSHORT ReturnLength ); @@ -6782,7 +8230,7 @@ NTAPI NtQuerySystemEnvironmentValueEx( _In_ PUNICODE_STRING VariableName, _In_ LPGUID VendorGuid, - _Out_ PVOID Value, + _Out_writes_bytes_opt_(*ValueLength) PVOID Value, _Inout_ PULONG ValueLength, _Out_opt_ PULONG Attributes ); @@ -6793,7 +8241,7 @@ NTAPI NtSetSystemEnvironmentValueEx( _In_ PUNICODE_STRING VariableName, _In_ LPGUID VendorGuid, - _In_ PVOID Value, + _In_reads_bytes_opt_(ValueLength) PVOID Value, _In_ ULONG ValueLength, _In_ ULONG Attributes ); @@ -6973,18 +8421,21 @@ NTSYSAPI VOID NTAPI DbgBreakPoint( + VOID ); NTSYSAPI NTSTATUS NTAPI DbgUiConnectToDbg( + VOID ); NTSYSAPI HANDLE NTAPI DbgUiGetThreadDebugObject( + VOID ); NTSYSAPI @@ -7203,6 +8654,16 @@ LdrVerifyImageMatchesChecksumEx( ); #endif +NTSYSAPI +NTSTATUS +NTAPI +LdrAccessResource( + _In_ PVOID DllHandle, + _In_ CONST PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry, + _Out_opt_ PVOID* Address, + _Out_ PULONG Size +); + NTSYSAPI NTSTATUS NTAPI @@ -7340,6 +8801,7 @@ NTSYSAPI VOID NTAPI RtlEnableEarlyCriticalSectionEventCreation( + VOID ); NTSYSAPI @@ -7441,6 +8903,117 @@ RtlDecompressBuffer( _Out_ PULONG FinalUncompressedSize ); +#if NTDDI_VERSION >= NTDDI_WIN8 +NTSYSAPI +NTSTATUS +NTAPI +RtlDecompressBufferEx( + _In_ USHORT CompressionFormat, + _Out_writes_bytes_to_(UncompressedBufferSize, *FinalUncompressedSize) PUCHAR UncompressedBuffer, + _In_ ULONG UncompressedBufferSize, + _In_reads_bytes_(CompressedBufferSize) PUCHAR CompressedBuffer, + _In_ ULONG CompressedBufferSize, + _Out_ PULONG FinalUncompressedSize, + _In_opt_ PVOID WorkSpace +); +#endif + +#if NTDDI_VERSION >= NTDDI_WINBLUE +NTSYSAPI +NTSTATUS +NTAPI +RtlDecompressBufferEx2( + _In_ USHORT CompressionFormat, + _Out_writes_bytes_to_(UncompressedBufferSize, *FinalUncompressedSize) PUCHAR UncompressedBuffer, + _In_ ULONG UncompressedBufferSize, + _In_reads_bytes_(CompressedBufferSize) PUCHAR CompressedBuffer, + _In_ ULONG CompressedBufferSize, + _In_ ULONG UncompressedChunkSize, + _Out_ PULONG FinalUncompressedSize, + _In_opt_ PVOID WorkSpace +); +#endif + +NTSYSAPI +NTSTATUS +NTAPI +RtlDecompressFragment( + _In_ USHORT CompressionFormat, + _Out_writes_bytes_to_(UncompressedFragmentSize, *FinalUncompressedSize) PUCHAR UncompressedFragment, + _In_ ULONG UncompressedFragmentSize, + _In_reads_bytes_(CompressedBufferSize) PUCHAR CompressedBuffer, + _In_ ULONG CompressedBufferSize, + _In_range_( <, CompressedBufferSize) ULONG FragmentOffset, + _Out_ PULONG FinalUncompressedSize, + _In_ PVOID WorkSpace +); + +#if NTDDI_VERSION >= NTDDI_WINBLUE +NTSYSAPI +NTSTATUS +NTAPI +RtlDecompressFragmentEx( + _In_ USHORT CompressionFormat, + _Out_writes_bytes_to_(UncompressedFragmentSize, *FinalUncompressedSize) PUCHAR UncompressedFragment, + _In_ ULONG UncompressedFragmentSize, + _In_reads_bytes_(CompressedBufferSize) PUCHAR CompressedBuffer, + _In_ ULONG CompressedBufferSize, + _In_range_( <, CompressedBufferSize) ULONG FragmentOffset, + _In_ ULONG UncompressedChunkSize, + _Out_ PULONG FinalUncompressedSize, + _In_ PVOID WorkSpace +); +#endif + +NTSYSAPI +NTSTATUS +NTAPI +RtlDescribeChunk( + _In_ USHORT CompressionFormat, + _Inout_ PUCHAR* CompressedBuffer, + _In_ PUCHAR EndOfCompressedBufferPlus1, + _Out_ PUCHAR* ChunkBuffer, + _Out_ PULONG ChunkSize +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlReserveChunk( + _In_ USHORT CompressionFormat, + _Inout_ PUCHAR* CompressedBuffer, + _In_ PUCHAR EndOfCompressedBufferPlus1, + _Out_ PUCHAR* ChunkBuffer, + _In_ ULONG ChunkSize +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlDecompressChunks( + _Out_writes_bytes_(UncompressedBufferSize) PUCHAR UncompressedBuffer, + _In_ ULONG UncompressedBufferSize, + _In_reads_bytes_(CompressedBufferSize) PUCHAR CompressedBuffer, + _In_ ULONG CompressedBufferSize, + _In_reads_bytes_(CompressedTailSize) PUCHAR CompressedTail, + _In_ ULONG CompressedTailSize, + _In_ PCOMPRESSED_DATA_INFO CompressedDataInfo +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlCompressChunks( + _In_reads_bytes_(UncompressedBufferSize) PUCHAR UncompressedBuffer, + _In_ ULONG UncompressedBufferSize, + _Out_writes_bytes_(CompressedBufferSize) PUCHAR CompressedBuffer, + _In_range_( >=, (UncompressedBufferSize - (UncompressedBufferSize / 16))) ULONG CompressedBufferSize, + _Inout_updates_bytes_(CompressedDataInfoLength) PCOMPRESSED_DATA_INFO CompressedDataInfo, + _In_range_( >, sizeof(COMPRESSED_DATA_INFO)) ULONG CompressedDataInfoLength, + _In_ PVOID WorkSpace +); + +_Must_inspect_result_ NTSYSAPI PVOID NTAPI @@ -7457,9 +9030,12 @@ NTSYSAPI PVOID NTAPI RtlDestroyHeap( - _Inout_ PVOID HeapHandle + _In_ PVOID HeapHandle ); +_Must_inspect_result_ +_Ret_maybenull_ +_Post_writable_byte_size_(Size) NTSYSAPI PVOID NTAPI @@ -7486,11 +9062,13 @@ RtlWalkHeap( _Inout_ PRTL_HEAP_WALK_ENTRY Entry ); +// NOTE: mingw had an incorrect definition for these +#ifndef __MINGW32__ NTSYSAPI NTSTATUS NTAPI RtlQueryHeapInformation( - _In_ PVOID HeapHandle, + _In_opt_ PVOID HeapHandle, _In_ HEAP_INFORMATION_CLASS HeapInformationClass, _Out_opt_ PVOID HeapInformation, _In_opt_ SIZE_T HeapInformationLength, @@ -7506,6 +9084,7 @@ RtlSetHeapInformation( _In_opt_ PVOID HeapInformation, _In_opt_ SIZE_T HeapInformationLength ); +#endif // __MINGW__ NTSYSAPI SIZE_T @@ -7630,6 +9209,7 @@ NTSYSAPI BOOLEAN NTAPI RtlValidateProcessHeaps( + VOID ); NTSYSAPI @@ -7648,6 +9228,14 @@ RtlEnumProcessHeaps( _In_ PVOID Parameter ); +NTSYSAPI +VOID +NTAPI +RtlTimeToTimeFields( + _In_ PLARGE_INTEGER Time, + _Out_ PTIME_FIELDS TimeFields +); + NTSYSAPI ULONG NTAPI @@ -7655,6 +9243,7 @@ RtlUniform( _Inout_ PULONG Seed ); +_Ret_range_( <=, MAXLONG) NTSYSAPI ULONG NTAPI @@ -7662,6 +9251,7 @@ RtlRandom( _Inout_ PULONG Seed ); +_Ret_range_( <=, MAXLONG) NTSYSAPI ULONG NTAPI @@ -7713,12 +9303,14 @@ NTSYSAPI NTSTATUS NTAPI RtlGetLastNtStatus( + VOID ); NTSYSAPI LONG NTAPI RtlGetLastWin32Error( + VOID ); NTSYSAPI @@ -7747,6 +9339,7 @@ NTSYSAPI ULONG NTAPI RtlGetThreadErrorMode( + VOID ); NTSYSAPI @@ -7758,6 +9351,16 @@ RtlSetThreadErrorMode( ); #endif +_Success_(return != 0) +_Must_inspect_result_ +NTSYSAPI +BOOLEAN +NTAPI +RtlCreateUnicodeString( + _Out_ PUNICODE_STRING DestinationString, + _In_z_ PCWSTR SourceString +); + NTSYSAPI NTSTATUS NTAPI @@ -7772,7 +9375,15 @@ VOID NTAPI RtlInitUnicodeString( _Out_ PUNICODE_STRING DestinationString, - _In_opt_ PWSTR SourceString + _In_opt_z_ PCWSTR SourceString +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlInitUnicodeStringEx( + _Out_ PUNICODE_STRING DestinationString, + _In_opt_z_ PCWSTR SourceString ); NTSYSAPI @@ -7817,6 +9428,39 @@ RtlUnicodeStringToAnsiString( _In_ BOOLEAN AllocateDestinationString ); +NTSYSAPI +CHAR +NTAPI +RtlUpperChar( + _In_ CHAR Character +); + +_Must_inspect_result_ +NTSYSAPI +BOOLEAN +NTAPI +RtlPrefixString( + _In_ PSTRING String1, + _In_ PSTRING String2, + _In_ BOOLEAN CaseInSensitive +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlAppendStringToString( + _Inout_ PSTRING Destination, + _In_ PSTRING Source +); + +NTSYSAPI +VOID +NTAPI +RtlUpperString( + _In_ PSTRING DestinationString, + _In_ PSTRING SourceString +); + NTSYSAPI VOID NTAPI @@ -7824,6 +9468,22 @@ RtlFreeAnsiString( _Inout_ PANSI_STRING AnsiString ); +NTSYSAPI +VOID +NTAPI +RtlFreeUnicodeString( + _In_ PUNICODE_STRING UnicodeString +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlUnicodeStringToInteger( + _In_ PCUNICODE_STRING String, + _In_opt_ ULONG Base, + _Out_ PULONG Value +); + NTSYSAPI NTSTATUS NTAPI @@ -7831,6 +9491,37 @@ RtlDefaultNpAcl( _Out_ PACL* Dacl ); +NTSYSAPI +NTSTATUS +NTAPI +RtlCreateRegistryKey( + _In_ ULONG RelativeTo, + _In_ PWSTR Path +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlQueryRegistryValues( + _In_ ULONG RelativeTo, + _In_ PCWSTR Path, + _Inout_ PRTL_QUERY_REGISTRY_TABLE QueryTable, + _In_opt_ PVOID Context, + _In_opt_ PVOID Environment +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlWriteRegistryValue( + _In_ ULONG RelativeTo, + _In_ PCWSTR Path, + _In_ PCWSTR ValueName, + _In_ ULONG ValueType, + _In_opt_ PVOID ValueData, + _In_ ULONG ValueLength +); + NTSYSAPI NTSTATUS NTAPI @@ -7870,7 +9561,7 @@ NTSYSAPI NTSTATUS NTAPI RtlSetEnvironmentVar( - _In_opt_ PWSTR* Environment, + _Inout_opt_ PVOID* Environment, _In_ PWSTR Name, _In_ SIZE_T NameLength, _In_ PWSTR Value, @@ -7882,7 +9573,7 @@ NTSYSAPI NTSTATUS NTAPI RtlSetEnvironmentVariable( - _In_opt_ PVOID* Environment, + _Inout_opt_ PVOID* Environment, _In_ PUNICODE_STRING Name, _In_ PUNICODE_STRING Value ); @@ -7907,7 +9598,7 @@ NTAPI RtlQueryEnvironmentVariable_U( _In_opt_ PVOID Environment, _In_ PUNICODE_STRING Name, - _Out_ PUNICODE_STRING Value + _Inout_ PUNICODE_STRING Value ); #if NTDDI_VERSION >= NTDDI_VISTA @@ -7930,7 +9621,7 @@ NTAPI RtlExpandEnvironmentStrings_U( _In_opt_ PVOID Environment, _In_ PUNICODE_STRING Source, - _Out_ PUNICODE_STRING Destination, + _Inout_ PUNICODE_STRING Destination, _Out_opt_ PULONG ReturnedLength ); @@ -7944,6 +9635,21 @@ RtlSetEnvironmentStrings( ); #endif +#if NTDDI_VERSION >= NTDDI_VISTA +NTSYSAPI +HANDLE +NTAPI +RtlGetCurrentTransaction( +); + +NTSYSAPI +LOGICAL +NTAPI +RtlSetCurrentTransaction( + _In_ HANDLE TransactionHandle +); +#endif + NTSYSAPI NTSTATUS NTAPI @@ -8032,6 +9738,13 @@ RtlCreateUserThread( _Out_opt_ PCLIENT_ID ClientId ); +NTSYSAPI +NTSTATUS +NTAPI +RtlExitUserThread( + _In_ NTSTATUS ExitStatus +); + NTSYSAPI NTSTATUS NTAPI @@ -8175,16 +9888,6 @@ RtlReleasePrivilege( ); #endif -NTSYSAPI -ULONG -NTAPI -RtlGetFullPathName_U( - _In_ PWSTR FileName, - _In_ ULONG BufferLength, - _Out_ PWSTR Buffer, - _Out_opt_ PWSTR* FilePart -); - NTSYSAPI BOOLEAN NTAPI @@ -8224,22 +9927,60 @@ RtlDetermineDosPathNameType_U( _In_ PCWSTR Path ); +NTSYSAPI +ULONG +NTAPI +RtlIsDosDeviceName_U( + _In_ PWSTR DosFileName +); + +NTSYSAPI +ULONG +NTAPI +RtlGetFullPathName_U( + _In_ PWSTR FileName, + _In_ ULONG BufferLength, + _Out_writes_bytes_(BufferLength) PWSTR Buffer, + _Out_opt_ PWSTR* FilePart +); + +#if NTDDI_VERSION >= NTDDI_WIN7 +NTSYSAPI +NTSTATUS +NTAPI +RtlGetFullPathName_UEx( + _In_ PWSTR FileName, + _In_ ULONG BufferLength, + _Out_writes_bytes_(BufferLength) PWSTR Buffer, + _Out_opt_ PWSTR* FilePart, + _Out_opt_ ULONG* BytesRequired +); +#endif + #if NTDDI_VERSION >= NTDDI_WS03 NTSYSAPI NTSTATUS NTAPI RtlGetFullPathName_UstrEx( _In_ PUNICODE_STRING FileName, - _In_opt_ PUNICODE_STRING StaticString, - _In_opt_ PUNICODE_STRING DynamicString, + _Inout_ PUNICODE_STRING StaticString, + _Out_opt_ PUNICODE_STRING DynamicString, _Out_opt_ PUNICODE_STRING* StringUsed, - _Out_opt_ PSIZE_T FilePartSize, + _Out_opt_ SIZE_T* FilePartPrefixCch, _Out_opt_ PBOOLEAN NameInvalid, - _Out_ RTL_PATH_TYPE* PathType, - _Out_opt_ PSIZE_T LengthNeeded + _Out_ RTL_PATH_TYPE* InputPathType, + _Out_opt_ SIZE_T* BytesRequired ); #endif +NTSYSAPI +ULONG +NTAPI +RtlGetCurrentDirectory_U( + _In_ ULONG BufferLength, + _Out_writes_bytes_(BufferLength) PWSTR Buffer +); + NTSYSAPI NTSTATUS NTAPI @@ -8467,12 +10208,13 @@ RtlCaptureContext( ); NTSYSAPI +_Success_(return != 0) USHORT NTAPI RtlCaptureStackBackTrace( _In_ ULONG FramesToSkip, _In_ ULONG FramesToCapture, - _Out_ PVOID* BackTrace, + _Out_writes_to_(FramesToCapture, return) PVOID* BackTrace, _Out_opt_ PULONG BackTraceHash ); @@ -8544,15 +10286,63 @@ RtlCopyLuid( _In_ PLUID SourceLuid ); +_Must_inspect_result_ +NTSYSAPI +NTSTATUS +NTAPI +RtlAllocateAndInitializeSid( + _In_ PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, + _In_ UCHAR SubAuthorityCount, + _In_ ULONG SubAuthority0, + _In_ ULONG SubAuthority1, + _In_ ULONG SubAuthority2, + _In_ ULONG SubAuthority3, + _In_ ULONG SubAuthority4, + _In_ ULONG SubAuthority5, + _In_ ULONG SubAuthority6, + _In_ ULONG SubAuthority7, + _Outptr_ PSID* Sid +); + +#if NTDDI_VERSION >= NTDDI_WIN8 +_Must_inspect_result_ +NTSYSAPI +NTSTATUS +NTAPI +RtlAllocateAndInitializeSidEx( + _In_ PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, + _In_ UCHAR SubAuthorityCount, + _In_reads_(SubAuthorityCount) PULONG SubAuthorities, + _Outptr_ PSID* Sid +); + +#endif + NTSYSAPI NTSTATUS NTAPI RtlCopySid( _In_ ULONG DestinationSidLength, - _Out_ PSID DestinationSid, + _Out_writes_bytes_(DestinationSidLength) PSID DestinationSid, _In_ PSID SourceSid ); +NTSYSAPI +NTSTATUS +NTAPI +RtlCreateServiceSid( + _In_ PUNICODE_STRING ServiceName, + _Out_writes_bytes_opt_(*ServiceSidLength) PSID ServiceSid, + _Inout_ PULONG ServiceSidLength +); + +NTSYSAPI +PVOID +NTAPI +RtlFreeSid( + _Inout_ PSID Sid +); + NTSYSAPI NTSTATUS NTAPI @@ -8641,6 +10431,7 @@ RtlEmptyAtomTable( _In_ BOOLEAN IncludePinnedAtoms ); +_Must_inspect_result_ NTSYSAPI BOOLEAN NTAPI @@ -8767,7 +10558,7 @@ NTAPI RtlGetDaclSecurityDescriptor( _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _Out_ PBOOLEAN DaclPresent, - _Out_ PACL* Dacl, + _Outptr_result_maybenull_ PACL* Dacl, _Out_ PBOOLEAN DaclDefaulted ); @@ -8776,7 +10567,7 @@ NTSTATUS NTAPI RtlGetGroupSecurityDescriptor( _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, - _Out_ PSID* Group, + _Outptr_result_maybenull_ PSID* Group, _Out_ PBOOLEAN GroupDefaulted ); @@ -8785,7 +10576,7 @@ NTSTATUS NTAPI RtlGetOwnerSecurityDescriptor( _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, - _Out_ PSID* Owner, + _Outptr_result_maybenull_ PSID* Owner, _Out_ PBOOLEAN OwnerDefaulted ); @@ -8815,6 +10606,7 @@ NTSYSAPI NTSTATUS NTAPI RtlCreateBootStatusDataFile( + VOID ); NTSYSAPI @@ -9028,7 +10820,7 @@ NTAPI RtlSetGroupSecurityDescriptor( _Inout_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_opt_ PSID Group, - _In_opt_ BOOLEAN GroupDefaulted + _In_ BOOLEAN GroupDefaulted ); NTSYSAPI @@ -9135,6 +10927,7 @@ RtlValidSecurityDescriptor( _In_ PSECURITY_DESCRIPTOR SecurityDescriptor ); +_Must_inspect_result_ NTSYSAPI BOOLEAN NTAPI @@ -9161,6 +10954,7 @@ VerSetConditionMask( ); #if NTDDI_VERSION >= NTDDI_VISTA +_Check_return_ NTSYSAPI NTSTATUS NTAPI @@ -9190,7 +10984,7 @@ VOID NTAPI TpSetPoolMaxThreads( _Inout_ PTP_POOL Pool, - _In_ LONG MaxThreads + _In_ ULONG MaxThreads ); NTSYSAPI @@ -9198,7 +10992,7 @@ NTSTATUS NTAPI TpSetPoolMinThreads( _Inout_ PTP_POOL Pool, - _In_ LONG MinThreads + _In_ ULONG MinThreads ); #if NTDDI_VERSION >= NTDDI_WIN7 @@ -9219,6 +11013,7 @@ TpSetPoolStackInformation( ); #endif +_Check_return_ NTSYSAPI NTSTATUS NTAPI @@ -9242,6 +11037,62 @@ TpReleaseCleanupGroupMembers( _Inout_opt_ PVOID CleanupParameter ); +NTSYSAPI +VOID +NTAPI +TpCallbackSetEventOnCompletion( + _Inout_ PTP_CALLBACK_INSTANCE Instance, + _In_ HANDLE Event +); + +NTSYSAPI +VOID +NTAPI +TpCallbackReleaseSemaphoreOnCompletion( + _Inout_ PTP_CALLBACK_INSTANCE Instance, + _In_ HANDLE Semaphore, + _In_ ULONG ReleaseCount +); + +NTSYSAPI +VOID +NTAPI +TpCallbackReleaseMutexOnCompletion( + _Inout_ PTP_CALLBACK_INSTANCE Instance, + _In_ HANDLE Mutex +); + +NTSYSAPI +VOID +NTAPI +TpCallbackLeaveCriticalSectionOnCompletion( + _Inout_ PTP_CALLBACK_INSTANCE Instance, + _Inout_ PRTL_CRITICAL_SECTION CriticalSection +); + +NTSYSAPI +VOID +NTAPI +TpCallbackUnloadDllOnCompletion( + _Inout_ PTP_CALLBACK_INSTANCE Instance, + _In_ PVOID DllHandle +); + +NTSYSAPI +NTSTATUS +NTAPI +TpCallbackMayRunLong( + _Inout_ PTP_CALLBACK_INSTANCE Instance +); + +NTSYSAPI +VOID +NTAPI +TpDisassociateCallback( + _Inout_ PTP_CALLBACK_INSTANCE Instance +); + +_Check_return_ NTSYSAPI NTSTATUS NTAPI @@ -9251,6 +11102,7 @@ TpSimpleTryPost( _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron ); +_Check_return_ NTSYSAPI NTSTATUS NTAPI @@ -9283,6 +11135,7 @@ TpWaitForWork( _In_ LOGICAL CancelPendingCallbacks ); +_Check_return_ NTSYSAPI NTSTATUS NTAPI @@ -9306,10 +11159,22 @@ NTAPI TpSetTimer( _Inout_ PTP_TIMER Timer, _In_opt_ PLARGE_INTEGER DueTime, - _In_ LONG Period, - _In_opt_ LONG WindowLength + _In_ ULONG Period, + _In_opt_ ULONG WindowLength ); +#if NTDDI_VERSION >= NTDDI_WIN7 +NTSYSAPI +NTSTATUS +NTAPI +TpSetTimerEx( + _Inout_ PTP_TIMER Timer, + _In_opt_ PLARGE_INTEGER DueTime, + _In_ ULONG Period, + _In_opt_ ULONG WindowLength +); +#endif + NTSYSAPI LOGICAL NTAPI @@ -9325,6 +11190,7 @@ TpWaitForTimer( _In_ LOGICAL CancelPendingCallbacks ); +_Check_return_ NTSYSAPI NTSTATUS NTAPI @@ -9351,6 +11217,19 @@ TpSetWait( _In_opt_ PLARGE_INTEGER Timeout ); +#if NTDDI_VERSION >= NTDDI_WIN7 +NTSYSAPI +NTSTATUS +NTAPI +TpSetWaitEx( + _Inout_ PTP_WAIT Wait, + _In_opt_ HANDLE Handle, + _In_opt_ PLARGE_INTEGER Timeout, + _In_opt_ PVOID Reserved +); +#endif + +_Check_return_ NTSYSAPI NTSTATUS NTAPI @@ -9426,7 +11305,5 @@ TpAlpcUnregisterCompletionList( #endif #ifdef __cplusplus -}; +} #endif - -#endif // _NTDLL_H diff --git a/TitanEngine/scylla_wrapper.h b/TitanEngine/scylla_wrapper.h index 8663202..ea2396c 100644 --- a/TitanEngine/scylla_wrapper.h +++ b/TitanEngine/scylla_wrapper.h @@ -7,9 +7,6 @@ const BYTE SCY_ERROR_IATWRITE = -2; const BYTE SCY_ERROR_IATSEARCH = -3; const BYTE SCY_ERROR_IATNOTFOUND = -4; -#ifdef __cplusplus -extern "C" { -#endif /*__cplusplus*/ //iat exports int scylla_searchIAT(DWORD pid, DWORD_PTR & iatStart, DWORD & iatSize, DWORD_PTR searchStart, bool advancedSearch); int scylla_getImports(DWORD_PTR iatAddr, DWORD iatSize, DWORD pid, LPVOID invalidImportCallback = NULL); @@ -35,8 +32,5 @@ bool scylla_dumpProcessA(DWORD_PTR pid, const char* fileToDump, DWORD_PTR imageb //rebuilder exports bool scylla_rebuildFileW(const WCHAR* fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); bool scylla_rebuildFileA(const char* fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); -#ifdef __cplusplus -} -#endif /*__cplusplus*/ /* Scylla definitions */ diff --git a/distorm/COPYING b/distorm/COPYING new file mode 100644 index 0000000..9046eba --- /dev/null +++ b/distorm/COPYING @@ -0,0 +1,26 @@ +:[diStorm3}: +The ultimate disassembler library. +Copyright (c) 2003-2021, Gil Dabah +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Gil Dabah nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL GIL DABAH BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/distorm/distorm.vcxproj b/distorm/distorm.vcxproj new file mode 100644 index 0000000..c7d6d15 --- /dev/null +++ b/distorm/distorm.vcxproj @@ -0,0 +1,157 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + 17.0 + Win32Proj + {25ff4a19-7088-4687-aa32-76e61bd62e51} + distorm + 7.0 + + + + StaticLibrary + true + v141_xp + Unicode + + + StaticLibrary + false + v141_xp + true + Unicode + + + StaticLibrary + true + v141_xp + Unicode + + + StaticLibrary + false + v141_xp + true + Unicode + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ + + + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ + + + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ + + + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + ProgramDatabase + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + ProgramDatabase + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Console + true + + + + + + \ No newline at end of file diff --git a/distorm/distorm.vcxproj.filters b/distorm/distorm.vcxproj.filters new file mode 100644 index 0000000..2919110 --- /dev/null +++ b/distorm/distorm.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;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 + + + + + Header Files + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/TitanEngine/distorm.h b/distorm/include/distorm.h similarity index 78% rename from TitanEngine/distorm.h rename to distorm/include/distorm.h index c2e2f21..795b744 100644 --- a/TitanEngine/distorm.h +++ b/distorm/include/distorm.h @@ -1,4 +1,4 @@ -/* diStorm3 3.3 */ +/* diStorm 3.5.3 */ /* distorm.h @@ -6,20 +6,8 @@ distorm.h diStorm3 - Powerful disassembler for X86/AMD64 http://ragestorm.net/distorm/ distorm at gmail dot com -Copyright (C) 2003-2012 Gil Dabah - -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 -(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. - -You should have received a copy of the GNU General Public License -along with this program. If not, see +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. */ @@ -45,29 +33,27 @@ along with this program. If not, see #undef SUPPORT_64BIT_OFFSET #endif -/* If your compiler doesn't support stdint.h, define your own 64 bits type. */ -#ifdef SUPPORT_64BIT_OFFSET -#ifdef _MSC_VER -#define OFFSET_INTEGER unsigned __int64 -#else +#ifndef _MSC_VER #include -#define OFFSET_INTEGER uint64_t -#endif #else -/* 32 bit offsets are used. */ -#define OFFSET_INTEGER unsigned long +/* Since MSVC < 2010 isn't shipped with stdint.h, + * here are those from MSVC 2017, which also match + * those in tinycc/libc. */ +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; #endif -#ifdef _MSC_VER -/* Since MSVC isn't shipped with stdint.h, we will have our own: */ -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; -typedef signed __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef signed __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef signed __int8 int8_t; -typedef unsigned __int8 uint8_t; +#ifdef SUPPORT_64BIT_OFFSET +#define OFFSET_INTEGER uint64_t +#else +/* 32 bit offsets are used. */ +#define OFFSET_INTEGER uint32_t #endif /* Support C++ compilers */ @@ -79,10 +65,10 @@ extern "C" { /* *** Helper Macros *** */ /* Get the ISC of the instruction, used with the definitions below. */ -#define META_GET_ISC(meta) (((meta) >> 3) & 0x1f) -#define META_SET_ISC(di, isc) (((di)->meta) |= ((isc) << 3)) +#define META_GET_ISC(meta) (((meta) >> 8) & 0x1f) +#define META_SET_ISC(di, isc) (((di)->meta) |= ((isc) << 8)) /* Get the flow control flags of the instruction, see 'features for decompose' below. */ -#define META_GET_FC(meta) ((meta) & 0x7) +#define META_GET_FC(meta) ((meta) & 0xf) /* Get the target address of a branching instruction. O_PC operand type. */ #define INSTRUCTION_GET_TARGET(di) ((_OffsetType)(((di)->addr + (di)->imm.addr + (di)->size))) @@ -91,10 +77,10 @@ extern "C" { /* * Operand Size or Adderss size are stored inside the flags: - * 0 - 16 bits - * 1 - 32 bits - * 2 - 64 bits - * 3 - reserved + * 00 - 16 bits + * 01 - 32 bits + * 10 - 64 bits + * 11 - reserved * * If you call these set-macros more than once, you will have to clean the bits before doing so. */ @@ -103,29 +89,28 @@ extern "C" { #define FLAG_GET_OPSIZE(flags) (((flags) >> 8) & 3) #define FLAG_GET_ADDRSIZE(flags) (((flags) >> 10) & 3) /* To get the LOCK/REPNZ/REP prefixes. */ -#define FLAG_GET_PREFIX(flags) ((flags) & 7) +#define FLAG_GET_PREFIX(flags) (((unsigned int)((int16_t)flags)) & 7) +/* Indicates whether the instruction is privileged. */ +#define FLAG_GET_PRIVILEGED(flags) (((flags) & FLAG_PRIVILEGED_INSTRUCTION) != 0) /* * Macros to extract segment registers from 'segment': */ #define SEGMENT_DEFAULT 0x80 -#define SEGMENT_SET(di, seg) ((di->segment) |= seg) #define SEGMENT_GET(segment) (((segment) == R_NONE) ? R_NONE : ((segment) & 0x7f)) -#define SEGMENT_IS_DEFAULT(segment) (((segment) & SEGMENT_DEFAULT) == SEGMENT_DEFAULT) - +#define SEGMENT_GET_UNSAFE(segment) ((segment) & 0x7f) +#define SEGMENT_IS_DEFAULT(segment) (((int8_t)segment) < -1) /* Quick check it's a negative number that isn't -1, so it's (0x80 | SEGREG). */ +#define SEGMENT_IS_DEFAULT_OR_NONE(segment) (((uint8_t)(segment)) > 0x80) /* Decodes modes of the disassembler, 16 bits or 32 bits or 64 bits for AMD64, x86-64. */ -typedef enum -{ - Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2 -} -_DecodeType; +typedef enum { Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2 } _DecodeType; typedef OFFSET_INTEGER _OffsetType; typedef struct { - _OffsetType codeOffset, nextOffset; /* nextOffset is OUT only. */ + _OffsetType codeOffset, addrMask; + _OffsetType nextOffset; /* nextOffset is OUT only. */ const uint8_t* code; int codeLen; /* Using signed integer makes it easier to detect an underflow. */ _DecodeType dt; @@ -188,7 +173,7 @@ typedef struct */ uint8_t index; - /* Size of: + /* Size in bits of: O_REG: register O_IMM: instruction.imm O_IMM1: instruction.imm.ex.i1 @@ -215,13 +200,18 @@ typedef struct #define FLAG_HINT_TAKEN (1 << 3) /* Indicates there is a hint non-taken for Jcc instructions only. */ #define FLAG_HINT_NOT_TAKEN (1 << 4) -/* The Imm value is signed extended. */ +/* The Imm value is signed extended (E.G in 64 bit decoding mode, a 32 bit imm is usually sign extended into 64 bit imm). */ #define FLAG_IMM_SIGNED (1 << 5) /* The destination operand is writable. */ #define FLAG_DST_WR (1 << 6) /* The instruction uses RIP-relative indirection. */ #define FLAG_RIP_RELATIVE (1 << 7) +/* See flag FLAG_GET_XXX macros above. */ + +/* The instruction is privileged and can only be used from Ring0. */ +#define FLAG_PRIVILEGED_INSTRUCTION (1 << 15) + /* No register was defined. */ #define R_NONE ((uint8_t)-1) @@ -253,12 +243,14 @@ typedef struct /* Unused prefixes mask, for each bit that is set that prefix is not used (LSB is byte [addr + 0]). */ uint16_t unusedPrefixesMask; /* Mask of registers that were used in the operands, only used for quick look up, in order to know *some* operand uses that register class. */ - uint16_t usedRegistersMask; + uint32_t usedRegistersMask; /* ID of opcode in the global opcode table. Use for mnemonic look up. */ uint16_t opcode; /* Up to four operands per instruction, ignored if ops[n].type == O_NONE. */ _Operand ops[OPERANDS_NO]; - /* Size of the whole instruction. */ + /* Number of valid ops entries. */ + uint8_t opsNo; + /* Size of the whole instruction in bytes. */ uint8_t size; /* Segment information of memory indirection, default segment, or overriden one, can be -1. Use SEGMENT macros. */ uint8_t segment; @@ -266,9 +258,9 @@ typedef struct uint8_t base, scale; uint8_t dispSize; /* Meta defines the instruction set class, and the flow control flags. Use META macros. */ - uint8_t meta; - /* The CPU flags that the instruction operates upon. */ - uint8_t modifiedFlagsMask, testedFlagsMask, undefinedFlagsMask; + uint16_t meta; + /* The CPU flags that the instruction operates upon, set only with DF_FILL_EFLAGS enabled, otherwise 0. */ + uint16_t modifiedFlagsMask, testedFlagsMask, undefinedFlagsMask; } _DInst; #ifndef DISTORM_LIGHT @@ -288,11 +280,11 @@ typedef struct */ typedef struct { + _OffsetType offset; /* Start offset of the decoded instruction. */ + unsigned int size; /* Size of decoded instruction in bytes. */ _WString mnemonic; /* Mnemonic of decoded instruction, prefixed if required by REP, LOCK etc. */ _WString operands; /* Operands of the decoded instruction, up to 3 operands, comma-seperated. */ _WString instructionHex; /* Hex dump - little endian, including prefixes. */ - unsigned int size; /* Size of decoded instruction. */ - _OffsetType offset; /* Start offset of the decoded instruction. */ } _DecodedInst; #endif /* DISTORM_LIGHT */ @@ -312,20 +304,30 @@ typedef struct #define RM_AVX 0x800 /* YMM0 - YMM15 */ #define RM_CR 0x1000 /* CR0, CR2, CR3, CR4, CR8 */ #define RM_DR 0x2000 /* DR0, DR1, DR2, DR3, DR6, DR7 */ +#define RM_R8 0x4000 /* R8B, R8W, R8D, R8 */ +#define RM_R9 0x8000 /* R9B, R9W, R9D, R9 */ +#define RM_R10 0x10000 /* R10B, R10W, R10D, R10 */ +#define RM_R11 0x20000 /* R11B, R11W, R11D, R11 */ +#define RM_R12 0x40000 /* R12B, R12W, R12D, R12 */ +#define RM_R13 0x80000 /* R13B, R13W, R13D, R13 */ +#define RM_R14 0x100000 /* R14B, R14W, R14D, R14 */ +#define RM_R15 0x200000 /* R15B, R15W, R15D, R15 */ +#define RM_SEG 0x400000 /* CS, SS, DS, ES, FS, GS */ + /* RIP should be checked using the 'flags' field and FLAG_RIP_RELATIVE. * Segments should be checked using the segment macros. * For now R8 - R15 are not supported and non general purpose registers map into same RM. */ -/* CPU Flags that instructions modify, test or undefine. */ -#define D_ZF 1 /* Zero */ -#define D_SF 2 /* Sign */ -#define D_CF 4 /* Carry */ -#define D_OF 8 /* Overflow */ -#define D_PF 0x10 /* Parity */ -#define D_AF 0x20 /* Auxilary */ -#define D_DF 0x40 /* Direction */ -#define D_IF 0x80 /* Interrupt */ +/* CPU flags that instructions modify, test or undefine (are EFLAGS compatible!). */ +#define D_CF 1 /* Carry */ +#define D_PF 4 /* Parity */ +#define D_AF 0x10 /* Auxiliary */ +#define D_ZF 0x40 /* Zero */ +#define D_SF 0x80 /* Sign */ +#define D_IF 0x200 /* Interrupt */ +#define D_DF 0x400 /* Direction */ +#define D_OF 0x800 /* Overflow */ /* * Instructions Set classes: @@ -392,8 +394,21 @@ typedef struct #define DF_STOP_ON_INT 0x100 /* The decoder will stop and return to the caller when any of the 'CMOVxx' instruction was decoded. */ #define DF_STOP_ON_CMOV 0x200 +/* The decoder will stop and return to the caller when it encounters the HLT instruction. */ +#define DF_STOP_ON_HLT 0x400 +/* The decoder will stop and return to the caller when it encounters a privileged instruction. */ +#define DF_STOP_ON_PRIVILEGED 0x800 +/* The decoder will stop and return to the caller when an instruction couldn't be decoded. */ +#define DF_STOP_ON_UNDECODEABLE 0x1000 +/* The decoder will not synchronize to the next byte after the previosuly decoded instruction, instead it will start decoding at the next byte. */ +#define DF_SINGLE_BYTE_STEP 0x2000 +/* The decoder will fill in the eflags fields for the decoded instruction. */ +#define DF_FILL_EFLAGS 0x4000 +/* The decoder will use the addrMask in CodeInfo structure instead of DF_MAXIMUM_ADDR16/32. */ +#define DF_USE_ADDR_MASK 0x8000 + /* The decoder will stop and return to the caller when any flow control instruction was decoded. */ -#define DF_STOP_ON_FLOW_CONTROL (DF_STOP_ON_CALL | DF_STOP_ON_RET | DF_STOP_ON_SYS | DF_STOP_ON_UNC_BRANCH | DF_STOP_ON_CND_BRANCH | DF_STOP_ON_INT | DF_STOP_ON_CMOV) +#define DF_STOP_ON_FLOW_CONTROL (DF_STOP_ON_CALL | DF_STOP_ON_RET | DF_STOP_ON_SYS | DF_STOP_ON_UNC_BRANCH | DF_STOP_ON_CND_BRANCH | DF_STOP_ON_INT | DF_STOP_ON_CMOV | DF_STOP_ON_HLT) /* Indicates the instruction is not a flow-control instruction. */ #define FC_NONE 0 @@ -414,9 +429,11 @@ typedef struct #define FC_INT 6 /* Indicates the instruction is one of: CMOVxx. */ #define FC_CMOV 7 +/* Indicates the instruction is HLT. */ +#define FC_HLT 8 /* Return code of the decoding function. */ -typedef enum { DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR, DECRES_FILTERED } _DecodeResult; +typedef enum { DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR } _DecodeResult; /* Define the following interface functions only for outer projects. */ #if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC)) @@ -439,6 +456,11 @@ typedef enum { DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR, D * Notes: 1)The minimal size of maxInstructions is 15. * 2)You will have to synchronize the offset,code and length by yourself if you pass code fragments and not a complete code block! */ + +/* distorm_decompose + * See more documentation online at the GitHub project's wiki. + * + */ #ifdef SUPPORT_64BIT_OFFSET _DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); @@ -474,7 +496,7 @@ void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* resul * * Output: unsigned int - version of compiled library. */ -unsigned int distorm_version(); +unsigned int distorm_version(void); #endif /* DISTORM_STATIC */ diff --git a/distorm/include/mnemonics.h b/distorm/include/mnemonics.h new file mode 100644 index 0000000..6cedb0c --- /dev/null +++ b/distorm/include/mnemonics.h @@ -0,0 +1,305 @@ +/* +mnemonics.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef MNEMONICS_H +#define MNEMONICS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DISTORM_LIGHT + +typedef struct WMnemonic +{ + unsigned char length; + unsigned char p[1]; /* p is a null terminated string, which contains 'length' characters. */ +} _WMnemonic; + +typedef struct WRegister +{ + unsigned int length; + unsigned char p[6]; /* p is a null terminated string. */ +} _WRegister; + +extern const unsigned char _MNEMONICS[]; +extern const _WRegister _REGISTERS[]; + +#endif /* DISTORM_LIGHT */ + +#ifdef __cplusplus +} /* End Of Extern */ +#endif + +#define GET_REGISTER_NAME(r) (unsigned char*)_REGISTERS[(r)].p +#define GET_MNEMONIC_NAME(m) ((_WMnemonic*)&_MNEMONICS[(m)])->p + +typedef enum +{ + I_UNDEFINED = 0, I_AAA = 66, I_AAD = 388, I_AAM = 383, I_AAS = 76, I_ADC = 31, I_ADD = 11, I_ADDPD = 3143, + I_ADDPS = 3136, I_ADDSD = 3157, I_ADDSS = 3150, I_ADDSUBPD = 6427, I_ADDSUBPS = 6437, + I_AESDEC = 9242, I_AESDECLAST = 9259, I_AESENC = 9200, I_AESENCLAST = 9217, + I_AESIMC = 9183, I_AESKEYGENASSIST = 9828, I_AND = 41, I_ANDNPD = 3054, I_ANDNPS = 3046, + I_ANDPD = 3023, I_ANDPS = 3016, I_ARPL = 111, I_BLENDPD = 9405, I_BLENDPS = 9386, + I_BLENDVPD = 7652, I_BLENDVPS = 7642, I_BOUND = 104, I_BSF = 4379, I_BSR = 4391, + I_BSWAP = 959, I_BT = 871, I_BTC = 933, I_BTR = 911, I_BTS = 886, I_CALL = 455, + I_CALL_FAR = 260, I_CBW = 228, I_CDQ = 250, I_CDQE = 239, I_CLAC = 1786, I_CLC = 491, + I_CLD = 511, I_CLFLUSH = 4362, I_CLGI = 1866, I_CLI = 501, I_CLTS = 540, I_CMC = 486, + I_CMOVA = 693, I_CMOVAE = 662, I_CMOVB = 655, I_CMOVBE = 685, I_CMOVG = 753, + I_CMOVGE = 737, I_CMOVL = 730, I_CMOVLE = 745, I_CMOVNO = 647, I_CMOVNP = 722, + I_CMOVNS = 707, I_CMOVNZ = 677, I_CMOVO = 640, I_CMOVP = 715, I_CMOVS = 700, + I_CMOVZ = 670, I_CMP = 71, I_CMPEQPD = 4482, I_CMPEQPS = 4403, I_CMPEQSD = 4640, + I_CMPEQSS = 4561, I_CMPLEPD = 4500, I_CMPLEPS = 4421, I_CMPLESD = 4658, I_CMPLESS = 4579, + I_CMPLTPD = 4491, I_CMPLTPS = 4412, I_CMPLTSD = 4649, I_CMPLTSS = 4570, I_CMPNEQPD = 4521, + I_CMPNEQPS = 4442, I_CMPNEQSD = 4679, I_CMPNEQSS = 4600, I_CMPNLEPD = 4541, + I_CMPNLEPS = 4462, I_CMPNLESD = 4699, I_CMPNLESS = 4620, I_CMPNLTPD = 4531, + I_CMPNLTPS = 4452, I_CMPNLTSD = 4689, I_CMPNLTSS = 4610, I_CMPORDPD = 4551, + I_CMPORDPS = 4472, I_CMPORDSD = 4709, I_CMPORDSS = 4630, I_CMPS = 301, I_CMPUNORDPD = 4509, + I_CMPUNORDPS = 4430, I_CMPUNORDSD = 4667, I_CMPUNORDSS = 4588, I_CMPXCHG = 897, + I_CMPXCHG16B = 6406, I_CMPXCHG8B = 6395, I_COMISD = 2812, I_COMISS = 2804, + I_CPUID = 864, I_CQO = 255, I_CRC32 = 9291, I_CVTDQ2PD = 6820, I_CVTDQ2PS = 3340, + I_CVTPD2DQ = 6830, I_CVTPD2PI = 2714, I_CVTPD2PS = 3266, I_CVTPH2PS = 4194, + I_CVTPI2PD = 2528, I_CVTPI2PS = 2518, I_CVTPS2DQ = 3350, I_CVTPS2PD = 3256, + I_CVTPS2PH = 4204, I_CVTPS2PI = 2704, I_CVTSD2SI = 2734, I_CVTSD2SS = 3286, + I_CVTSI2SD = 2548, I_CVTSI2SS = 2538, I_CVTSS2SD = 3276, I_CVTSS2SI = 2724, + I_CVTTPD2DQ = 6809, I_CVTTPD2PI = 2647, I_CVTTPS2DQ = 3360, I_CVTTPS2PI = 2636, + I_CVTTSD2SI = 2669, I_CVTTSS2SI = 2658, I_CWD = 245, I_CWDE = 233, I_DAA = 46, + I_DAS = 56, I_DEC = 86, I_DIV = 1645, I_DIVPD = 3532, I_DIVPS = 3525, I_DIVSD = 3546, + I_DIVSS = 3539, I_DPPD = 9648, I_DPPS = 9635, I_EMMS = 4133, I_ENTER = 340, + I_EXTRACTPS = 9513, I_EXTRQ = 4169, I_F2XM1 = 1191, I_FABS = 1122, I_FADD = 1022, + I_FADDP = 1548, I_FBLD = 1600, I_FBSTP = 1606, I_FCHS = 1116, I_FCLEX = 7322, + I_FCMOVB = 1375, I_FCMOVBE = 1391, I_FCMOVE = 1383, I_FCMOVNB = 1444, I_FCMOVNBE = 1462, + I_FCMOVNE = 1453, I_FCMOVNU = 1472, I_FCMOVU = 1400, I_FCOM = 1034, I_FCOMI = 1511, + I_FCOMIP = 1622, I_FCOMP = 1040, I_FCOMPP = 1562, I_FCOS = 1310, I_FDECSTP = 1237, + I_FDIV = 1060, I_FDIVP = 1593, I_FDIVR = 1066, I_FDIVRP = 1585, I_FEDISI = 1487, + I_FEMMS = 573, I_FENI = 1481, I_FFREE = 1526, I_FIADD = 1316, I_FICOM = 1330, + I_FICOMP = 1337, I_FIDIV = 1360, I_FIDIVR = 1367, I_FILD = 1417, I_FIMUL = 1323, + I_FINCSTP = 1246, I_FINIT = 7337, I_FIST = 1431, I_FISTP = 1437, I_FISTTP = 1423, + I_FISUB = 1345, I_FISUBR = 1352, I_FLD = 1073, I_FLD1 = 1140, I_FLDCW = 1097, + I_FLDENV = 1089, I_FLDL2E = 1154, I_FLDL2T = 1146, I_FLDLG2 = 1169, I_FLDLN2 = 1177, + I_FLDPI = 1162, I_FLDZ = 1185, I_FMUL = 1028, I_FMULP = 1555, I_FNCLEX = 7314, + I_FNINIT = 7329, I_FNOP = 1110, I_FNSAVE = 7344, I_FNSTCW = 7299, I_FNSTENV = 7282, + I_FNSTSW = 7359, I_FPATAN = 1212, I_FPREM = 1255, I_FPREM1 = 1229, I_FPTAN = 1205, + I_FRNDINT = 1287, I_FRSTOR = 1518, I_FSAVE = 7352, I_FSCALE = 1296, I_FSETPM = 1495, + I_FSIN = 1304, I_FSINCOS = 1278, I_FSQRT = 1271, I_FST = 1078, I_FSTCW = 7307, + I_FSTENV = 7291, I_FSTP = 1083, I_FSTSW = 7367, I_FSUB = 1047, I_FSUBP = 1578, + I_FSUBR = 1053, I_FSUBRP = 1570, I_FTST = 1128, I_FUCOM = 1533, I_FUCOMI = 1503, + I_FUCOMIP = 1613, I_FUCOMP = 1540, I_FUCOMPP = 1408, I_FXAM = 1134, I_FXCH = 1104, + I_FXRSTOR = 9925, I_FXRSTOR64 = 9934, I_FXSAVE = 9897, I_FXSAVE64 = 9905, + I_FXTRACT = 1220, I_FYL2X = 1198, I_FYL2XP1 = 1262, I_GETSEC = 632, I_HADDPD = 4214, + I_HADDPS = 4222, I_HLT = 481, I_HSUBPD = 4248, I_HSUBPS = 4256, I_IDIV = 1650, + I_IMUL = 117, I_IN = 446, I_INC = 81, I_INS = 123, I_INSERTPS = 9580, I_INSERTQ = 4176, + I_INT = 366, I_INT1 = 475, I_INT3 = 360, I_INTO = 371, I_INVD = 554, I_INVEPT = 8317, + I_INVLPG = 1726, I_INVLPGA = 1880, I_INVPCID = 8334, I_INVVPID = 8325, I_IRET = 377, + I_JA = 166, I_JAE = 147, I_JB = 143, I_JBE = 161, I_JCXZ = 426, I_JECXZ = 432, + I_JG = 202, I_JGE = 192, I_JL = 188, I_JLE = 197, I_JMP = 461, I_JMP_FAR = 466, + I_JNO = 138, I_JNP = 183, I_JNS = 174, I_JNZ = 156, I_JO = 134, I_JP = 179, + I_JRCXZ = 439, I_JS = 170, I_JZ = 152, I_LAHF = 289, I_LAR = 521, I_LDDQU = 7027, + I_LDMXCSR = 9955, I_LDS = 335, I_LEA = 223, I_LEAVE = 347, I_LES = 330, I_LFENCE = 4298, + I_LFS = 916, I_LGDT = 1702, I_LGS = 921, I_LIDT = 1708, I_LLDT = 1667, I_LMSW = 1720, + I_LODS = 313, I_LOOP = 420, I_LOOPNZ = 405, I_LOOPZ = 413, I_LSL = 526, I_LSS = 906, + I_LTR = 1673, I_LZCNT = 4396, I_MASKMOVDQU = 7152, I_MASKMOVQ = 7142, I_MAXPD = 3592, + I_MAXPS = 3585, I_MAXSD = 3606, I_MAXSS = 3599, I_MFENCE = 4324, I_MINPD = 3472, + I_MINPS = 3465, I_MINSD = 3486, I_MINSS = 3479, I_MONITOR = 1770, I_MOV = 218, + I_MOVAPD = 2492, I_MOVAPS = 2484, I_MOVBE = 9284, I_MOVD = 3953, I_MOVDDUP = 2219, + I_MOVDQ2Q = 6555, I_MOVDQA = 3979, I_MOVDQU = 3987, I_MOVHLPS = 2184, I_MOVHPD = 2378, + I_MOVHPS = 2370, I_MOVLHPS = 2361, I_MOVLPD = 2201, I_MOVLPS = 2193, I_MOVMSKPD = 2848, + I_MOVMSKPS = 2838, I_MOVNTDQ = 6882, I_MOVNTDQA = 7928, I_MOVNTI = 951, I_MOVNTPD = 2589, + I_MOVNTPS = 2580, I_MOVNTQ = 6874, I_MOVNTSD = 2607, I_MOVNTSS = 2598, I_MOVQ = 3959, + I_MOVQ2DQ = 6546, I_MOVS = 295, I_MOVSD = 2143, I_MOVSHDUP = 2386, I_MOVSLDUP = 2209, + I_MOVSS = 2136, I_MOVSX = 938, I_MOVSXD = 10038, I_MOVUPD = 2128, I_MOVUPS = 2120, + I_MOVZX = 926, I_MPSADBW = 9661, I_MUL = 1640, I_MULPD = 3203, I_MULPS = 3196, + I_MULSD = 3217, I_MULSS = 3210, I_MWAIT = 1779, I_NEG = 1635, I_NOP = 580, + I_NOT = 1630, I_OR = 27, I_ORPD = 3086, I_ORPS = 3080, I_OUT = 450, I_OUTS = 128, + I_PABSB = 7721, I_PABSD = 7751, I_PABSW = 7736, I_PACKSSDW = 3882, I_PACKSSWB = 3714, + I_PACKUSDW = 7949, I_PACKUSWB = 3792, I_PADDB = 7237, I_PADDD = 7267, I_PADDQ = 6514, + I_PADDSB = 6963, I_PADDSW = 6980, I_PADDUSB = 6653, I_PADDUSW = 6672, I_PADDW = 7252, + I_PALIGNR = 9443, I_PAND = 6640, I_PANDN = 6698, I_PAUSE = 10046, I_PAVGB = 6713, + I_PAVGUSB = 2111, I_PAVGW = 6758, I_PBLENDVB = 7632, I_PBLENDW = 9424, I_PCLMULQDQ = 9680, + I_PCMPEQB = 4076, I_PCMPEQD = 4114, I_PCMPEQQ = 7909, I_PCMPEQW = 4095, I_PCMPESTRI = 9759, + I_PCMPESTRM = 9736, I_PCMPGTB = 3735, I_PCMPGTD = 3773, I_PCMPGTQ = 8120, + I_PCMPGTW = 3754, I_PCMPISTRI = 9805, I_PCMPISTRM = 9782, I_PEXTRB = 9462, + I_PEXTRD = 9479, I_PEXTRQ = 9487, I_PEXTRW = 6344, I_PF2ID = 1947, I_PF2IW = 1940, + I_PFACC = 2061, I_PFADD = 2010, I_PFCMPEQ = 2068, I_PFCMPGE = 1971, I_PFCMPGT = 2017, + I_PFMAX = 2026, I_PFMIN = 1980, I_PFMUL = 2077, I_PFNACC = 1954, I_PFPNACC = 1962, + I_PFRCP = 1987, I_PFRCPIT1 = 2033, I_PFRCPIT2 = 2084, I_PFRSQIT1 = 2043, I_PFRSQRT = 1994, + I_PFSUB = 2003, I_PFSUBR = 2053, I_PHADDD = 7408, I_PHADDSW = 7425, I_PHADDW = 7391, + I_PHMINPOSUW = 8292, I_PHSUBD = 7484, I_PHSUBSW = 7501, I_PHSUBW = 7467, I_PI2FD = 1933, + I_PI2FW = 1926, I_PINSRB = 9563, I_PINSRD = 9601, I_PINSRQ = 9609, I_PINSRW = 6327, + I_PMADDUBSW = 7444, I_PMADDWD = 7106, I_PMAXSB = 8207, I_PMAXSD = 8224, I_PMAXSW = 6997, + I_PMAXUB = 6681, I_PMAXUD = 8258, I_PMAXUW = 8241, I_PMINSB = 8139, I_PMINSD = 8156, + I_PMINSW = 6935, I_PMINUB = 6623, I_PMINUD = 8190, I_PMINUW = 8173, I_PMOVMSKB = 6564, + I_PMOVSXBD = 7787, I_PMOVSXBQ = 7808, I_PMOVSXBW = 7766, I_PMOVSXDQ = 7871, + I_PMOVSXWD = 7829, I_PMOVSXWQ = 7850, I_PMOVZXBD = 8015, I_PMOVZXBQ = 8036, + I_PMOVZXBW = 7994, I_PMOVZXDQ = 8099, I_PMOVZXWD = 8057, I_PMOVZXWQ = 8078, + I_PMULDQ = 7892, I_PMULHRSW = 7571, I_PMULHRW = 2094, I_PMULHUW = 6773, I_PMULHW = 6792, + I_PMULLD = 8275, I_PMULLW = 6529, I_PMULUDQ = 7087, I_POP = 22, I_POPA = 98, + I_POPCNT = 4371, I_POPF = 277, I_POR = 6952, I_PREFETCH = 1905, I_PREFETCHNTA = 2435, + I_PREFETCHT0 = 2448, I_PREFETCHT1 = 2460, I_PREFETCHT2 = 2472, I_PREFETCHW = 1915, + I_PSADBW = 7125, I_PSHUFB = 7374, I_PSHUFD = 4021, I_PSHUFHW = 4029, I_PSHUFLW = 4038, + I_PSHUFW = 4013, I_PSIGNB = 7520, I_PSIGND = 7554, I_PSIGNW = 7537, I_PSLLD = 7057, + I_PSLLDQ = 9880, I_PSLLQ = 7072, I_PSLLW = 7042, I_PSRAD = 6743, I_PSRAW = 6728, + I_PSRLD = 6484, I_PSRLDQ = 9863, I_PSRLQ = 6499, I_PSRLW = 6469, I_PSUBB = 7177, + I_PSUBD = 7207, I_PSUBQ = 7222, I_PSUBSB = 6901, I_PSUBSW = 6918, I_PSUBUSB = 6585, + I_PSUBUSW = 6604, I_PSUBW = 7192, I_PSWAPD = 2103, I_PTEST = 7662, I_PUNPCKHBW = 3813, + I_PUNPCKHDQ = 3859, I_PUNPCKHQDQ = 3928, I_PUNPCKHWD = 3836, I_PUNPCKLBW = 3645, + I_PUNPCKLDQ = 3691, I_PUNPCKLQDQ = 3903, I_PUNPCKLWD = 3668, I_PUSH = 16, + I_PUSHA = 91, I_PUSHF = 270, I_PXOR = 7014, I_RCL = 976, I_RCPPS = 2986, I_RCPSS = 2993, + I_RCR = 981, I_RDFSBASE = 9915, I_RDGSBASE = 9945, I_RDMSR = 599, I_RDPMC = 606, + I_RDRAND = 10059, I_RDTSC = 592, I_RDTSCP = 1897, I_RET = 325, I_RETF = 354, + I_ROL = 966, I_ROR = 971, I_ROUNDPD = 9329, I_ROUNDPS = 9310, I_ROUNDSD = 9367, + I_ROUNDSS = 9348, I_RSM = 881, I_RSQRTPS = 2948, I_RSQRTSS = 2957, I_SAHF = 283, + I_SAL = 996, I_SALC = 393, I_SAR = 1001, I_SBB = 36, I_SCAS = 319, I_SETA = 806, + I_SETAE = 779, I_SETB = 773, I_SETBE = 799, I_SETG = 858, I_SETGE = 844, I_SETL = 838, + I_SETLE = 851, I_SETNO = 766, I_SETNP = 831, I_SETNS = 818, I_SETNZ = 792, + I_SETO = 760, I_SETP = 825, I_SETS = 812, I_SETZ = 786, I_SFENCE = 4354, I_SGDT = 1690, + I_SHL = 986, I_SHLD = 875, I_SHR = 991, I_SHRD = 891, I_SHUFPD = 6369, I_SHUFPS = 6361, + I_SIDT = 1696, I_SKINIT = 1872, I_SLDT = 1656, I_SMSW = 1714, I_SQRTPD = 2888, + I_SQRTPS = 2880, I_SQRTSD = 2904, I_SQRTSS = 2896, I_STAC = 1792, I_STC = 496, + I_STD = 516, I_STGI = 1860, I_STI = 506, I_STMXCSR = 9984, I_STOS = 307, I_STR = 1662, + I_SUB = 51, I_SUBPD = 3412, I_SUBPS = 3405, I_SUBSD = 3426, I_SUBSS = 3419, + I_SWAPGS = 1889, I_SYSCALL = 531, I_SYSENTER = 613, I_SYSEXIT = 623, I_SYSRET = 546, + I_TEST = 206, I_TZCNT = 4384, I_UCOMISD = 2775, I_UCOMISS = 2766, I_UD2 = 568, + I_UNPCKHPD = 2329, I_UNPCKHPS = 2319, I_UNPCKLPD = 2287, I_UNPCKLPS = 2277, + I_VADDPD = 3172, I_VADDPS = 3164, I_VADDSD = 3188, I_VADDSS = 3180, I_VADDSUBPD = 6447, + I_VADDSUBPS = 6458, I_VAESDEC = 9250, I_VAESDECLAST = 9271, I_VAESENC = 9208, + I_VAESENCLAST = 9229, I_VAESIMC = 9191, I_VAESKEYGENASSIST = 9845, I_VANDNPD = 3071, + I_VANDNPS = 3062, I_VANDPD = 3038, I_VANDPS = 3030, I_VBLENDPD = 9414, I_VBLENDPS = 9395, + I_VBLENDVPD = 9714, I_VBLENDVPS = 9703, I_VBROADCASTF128 = 7705, I_VBROADCASTSD = 7691, + I_VBROADCASTSS = 7677, I_VCMPEQPD = 5121, I_VCMPEQPS = 4719, I_VCMPEQSD = 5925, + I_VCMPEQSS = 5523, I_VCMPEQ_OSPD = 5302, I_VCMPEQ_OSPS = 4900, I_VCMPEQ_OSSD = 6106, + I_VCMPEQ_OSSS = 5704, I_VCMPEQ_UQPD = 5208, I_VCMPEQ_UQPS = 4806, I_VCMPEQ_UQSD = 6012, + I_VCMPEQ_UQSS = 5610, I_VCMPEQ_USPD = 5411, I_VCMPEQ_USPS = 5009, I_VCMPEQ_USSD = 6215, + I_VCMPEQ_USSS = 5813, I_VCMPFALSEPD = 5243, I_VCMPFALSEPS = 4841, I_VCMPFALSESD = 6047, + I_VCMPFALSESS = 5645, I_VCMPFALSE_OSPD = 5452, I_VCMPFALSE_OSPS = 5050, I_VCMPFALSE_OSSD = 6256, + I_VCMPFALSE_OSSS = 5854, I_VCMPGEPD = 5270, I_VCMPGEPS = 4868, I_VCMPGESD = 6074, + I_VCMPGESS = 5672, I_VCMPGE_OQPD = 5482, I_VCMPGE_OQPS = 5080, I_VCMPGE_OQSD = 6286, + I_VCMPGE_OQSS = 5884, I_VCMPGTPD = 5280, I_VCMPGTPS = 4878, I_VCMPGTSD = 6084, + I_VCMPGTSS = 5682, I_VCMPGT_OQPD = 5495, I_VCMPGT_OQPS = 5093, I_VCMPGT_OQSD = 6299, + I_VCMPGT_OQSS = 5897, I_VCMPLEPD = 5141, I_VCMPLEPS = 4739, I_VCMPLESD = 5945, + I_VCMPLESS = 5543, I_VCMPLE_OQPD = 5328, I_VCMPLE_OQPS = 4926, I_VCMPLE_OQSD = 6132, + I_VCMPLE_OQSS = 5730, I_VCMPLTPD = 5131, I_VCMPLTPS = 4729, I_VCMPLTSD = 5935, + I_VCMPLTSS = 5533, I_VCMPLT_OQPD = 5315, I_VCMPLT_OQPS = 4913, I_VCMPLT_OQSD = 6119, + I_VCMPLT_OQSS = 5717, I_VCMPNEQPD = 5164, I_VCMPNEQPS = 4762, I_VCMPNEQSD = 5968, + I_VCMPNEQSS = 5566, I_VCMPNEQ_OQPD = 5256, I_VCMPNEQ_OQPS = 4854, I_VCMPNEQ_OQSD = 6060, + I_VCMPNEQ_OQSS = 5658, I_VCMPNEQ_OSPD = 5468, I_VCMPNEQ_OSPS = 5066, I_VCMPNEQ_OSSD = 6272, + I_VCMPNEQ_OSSS = 5870, I_VCMPNEQ_USPD = 5356, I_VCMPNEQ_USPS = 4954, I_VCMPNEQ_USSD = 6160, + I_VCMPNEQ_USSS = 5758, I_VCMPNGEPD = 5221, I_VCMPNGEPS = 4819, I_VCMPNGESD = 6025, + I_VCMPNGESS = 5623, I_VCMPNGE_UQPD = 5424, I_VCMPNGE_UQPS = 5022, I_VCMPNGE_UQSD = 6228, + I_VCMPNGE_UQSS = 5826, I_VCMPNGTPD = 5232, I_VCMPNGTPS = 4830, I_VCMPNGTSD = 6036, + I_VCMPNGTSS = 5634, I_VCMPNGT_UQPD = 5438, I_VCMPNGT_UQPS = 5036, I_VCMPNGT_UQSD = 6242, + I_VCMPNGT_UQSS = 5840, I_VCMPNLEPD = 5186, I_VCMPNLEPS = 4784, I_VCMPNLESD = 5990, + I_VCMPNLESS = 5588, I_VCMPNLE_UQPD = 5384, I_VCMPNLE_UQPS = 4982, I_VCMPNLE_UQSD = 6188, + I_VCMPNLE_UQSS = 5786, I_VCMPNLTPD = 5175, I_VCMPNLTPS = 4773, I_VCMPNLTSD = 5979, + I_VCMPNLTSS = 5577, I_VCMPNLT_UQPD = 5370, I_VCMPNLT_UQPS = 4968, I_VCMPNLT_UQSD = 6174, + I_VCMPNLT_UQSS = 5772, I_VCMPORDPD = 5197, I_VCMPORDPS = 4795, I_VCMPORDSD = 6001, + I_VCMPORDSS = 5599, I_VCMPORD_SPD = 5398, I_VCMPORD_SPS = 4996, I_VCMPORD_SSD = 6202, + I_VCMPORD_SSS = 5800, I_VCMPTRUEPD = 5290, I_VCMPTRUEPS = 4888, I_VCMPTRUESD = 6094, + I_VCMPTRUESS = 5692, I_VCMPTRUE_USPD = 5508, I_VCMPTRUE_USPS = 5106, I_VCMPTRUE_USSD = 6312, + I_VCMPTRUE_USSS = 5910, I_VCMPUNORDPD = 5151, I_VCMPUNORDPS = 4749, I_VCMPUNORDSD = 5955, + I_VCMPUNORDSS = 5553, I_VCMPUNORD_SPD = 5341, I_VCMPUNORD_SPS = 4939, I_VCMPUNORD_SSD = 6145, + I_VCMPUNORD_SSS = 5743, I_VCOMISD = 2829, I_VCOMISS = 2820, I_VCVTDQ2PD = 6852, + I_VCVTDQ2PS = 3371, I_VCVTPD2DQ = 6863, I_VCVTPD2PS = 3307, I_VCVTPS2DQ = 3382, + I_VCVTPS2PD = 3296, I_VCVTSD2SI = 2755, I_VCVTSD2SS = 3329, I_VCVTSI2SD = 2569, + I_VCVTSI2SS = 2558, I_VCVTSS2SD = 3318, I_VCVTSS2SI = 2744, I_VCVTTPD2DQ = 6840, + I_VCVTTPS2DQ = 3393, I_VCVTTSD2SI = 2692, I_VCVTTSS2SI = 2680, I_VDIVPD = 3561, + I_VDIVPS = 3553, I_VDIVSD = 3577, I_VDIVSS = 3569, I_VDPPD = 9654, I_VDPPS = 9641, + I_VERR = 1678, I_VERW = 1684, I_VEXTRACTF128 = 9549, I_VEXTRACTPS = 9524, + I_VFMADD132PD = 8420, I_VFMADD132PS = 8407, I_VFMADD132SD = 8446, I_VFMADD132SS = 8433, + I_VFMADD213PD = 8700, I_VFMADD213PS = 8687, I_VFMADD213SD = 8726, I_VFMADD213SS = 8713, + I_VFMADD231PD = 8980, I_VFMADD231PS = 8967, I_VFMADD231SD = 9006, I_VFMADD231SS = 8993, + I_VFMADDSUB132PD = 8359, I_VFMADDSUB132PS = 8343, I_VFMADDSUB213PD = 8639, + I_VFMADDSUB213PS = 8623, I_VFMADDSUB231PD = 8919, I_VFMADDSUB231PS = 8903, + I_VFMSUB132PD = 8472, I_VFMSUB132PS = 8459, I_VFMSUB132SD = 8498, I_VFMSUB132SS = 8485, + I_VFMSUB213PD = 8752, I_VFMSUB213PS = 8739, I_VFMSUB213SD = 8778, I_VFMSUB213SS = 8765, + I_VFMSUB231PD = 9032, I_VFMSUB231PS = 9019, I_VFMSUB231SD = 9058, I_VFMSUB231SS = 9045, + I_VFMSUBADD132PD = 8391, I_VFMSUBADD132PS = 8375, I_VFMSUBADD213PD = 8671, + I_VFMSUBADD213PS = 8655, I_VFMSUBADD231PD = 8951, I_VFMSUBADD231PS = 8935, + I_VFNMADD132PD = 8525, I_VFNMADD132PS = 8511, I_VFNMADD132SD = 8553, I_VFNMADD132SS = 8539, + I_VFNMADD213PD = 8805, I_VFNMADD213PS = 8791, I_VFNMADD213SD = 8833, I_VFNMADD213SS = 8819, + I_VFNMADD231PD = 9085, I_VFNMADD231PS = 9071, I_VFNMADD231SD = 9113, I_VFNMADD231SS = 9099, + I_VFNMSUB132PD = 8581, I_VFNMSUB132PS = 8567, I_VFNMSUB132SD = 8609, I_VFNMSUB132SS = 8595, + I_VFNMSUB213PD = 8861, I_VFNMSUB213PS = 8847, I_VFNMSUB213SD = 8889, I_VFNMSUB213SS = 8875, + I_VFNMSUB231PD = 9141, I_VFNMSUB231PS = 9127, I_VFNMSUB231SD = 9169, I_VFNMSUB231SS = 9155, + I_VHADDPD = 4230, I_VHADDPS = 4239, I_VHSUBPD = 4264, I_VHSUBPS = 4273, I_VINSERTF128 = 9536, + I_VINSERTPS = 9590, I_VLDDQU = 7034, I_VLDMXCSR = 9974, I_VMASKMOVDQU = 7164, + I_VMASKMOVPD = 7982, I_VMASKMOVPS = 7970, I_VMAXPD = 3621, I_VMAXPS = 3613, + I_VMAXSD = 3637, I_VMAXSS = 3629, I_VMCALL = 1734, I_VMCLEAR = 10022, I_VMFUNC = 1814, + I_VMINPD = 3501, I_VMINPS = 3493, I_VMINSD = 3517, I_VMINSS = 3509, I_VMLAUNCH = 1742, + I_VMLOAD = 1844, I_VMMCALL = 1835, I_VMOVAPD = 2509, I_VMOVAPS = 2500, I_VMOVD = 3965, + I_VMOVDDUP = 2267, I_VMOVDQA = 3995, I_VMOVDQU = 4004, I_VMOVHLPS = 2228, + I_VMOVHPD = 2415, I_VMOVHPS = 2406, I_VMOVLHPS = 2396, I_VMOVLPD = 2247, I_VMOVLPS = 2238, + I_VMOVMSKPD = 2869, I_VMOVMSKPS = 2858, I_VMOVNTDQ = 6891, I_VMOVNTDQA = 7938, + I_VMOVNTPD = 2626, I_VMOVNTPS = 2616, I_VMOVQ = 3972, I_VMOVSD = 2176, I_VMOVSHDUP = 2424, + I_VMOVSLDUP = 2256, I_VMOVSS = 2168, I_VMOVUPD = 2159, I_VMOVUPS = 2150, I_VMPSADBW = 9670, + I_VMPTRLD = 10013, I_VMPTRST = 6418, I_VMREAD = 4161, I_VMRESUME = 1752, I_VMRUN = 1828, + I_VMSAVE = 1852, I_VMULPD = 3232, I_VMULPS = 3224, I_VMULSD = 3248, I_VMULSS = 3240, + I_VMWRITE = 4185, I_VMXOFF = 1762, I_VMXON = 10031, I_VORPD = 3099, I_VORPS = 3092, + I_VPABSB = 7728, I_VPABSD = 7758, I_VPABSW = 7743, I_VPACKSSDW = 3892, I_VPACKSSWB = 3724, + I_VPACKUSDW = 7959, I_VPACKUSWB = 3802, I_VPADDB = 7244, I_VPADDD = 7274, + I_VPADDQ = 6521, I_VPADDSB = 6971, I_VPADDSW = 6988, I_VPADDUSW = 6662, I_VPADDW = 7259, + I_VPALIGNR = 9452, I_VPAND = 6646, I_VPANDN = 6705, I_VPAVGB = 6720, I_VPAVGW = 6765, + I_VPBLENDVB = 9725, I_VPBLENDW = 9433, I_VPCLMULQDQ = 9691, I_VPCMPEQB = 4085, + I_VPCMPEQD = 4123, I_VPCMPEQQ = 7918, I_VPCMPEQW = 4104, I_VPCMPESTRI = 9770, + I_VPCMPESTRM = 9747, I_VPCMPGTB = 3744, I_VPCMPGTD = 3782, I_VPCMPGTQ = 8129, + I_VPCMPGTW = 3763, I_VPCMPISTRI = 9816, I_VPCMPISTRM = 9793, I_VPERM2F128 = 9298, + I_VPERMILPD = 7603, I_VPERMILPS = 7592, I_VPEXTRB = 9470, I_VPEXTRD = 9495, + I_VPEXTRQ = 9504, I_VPEXTRW = 6352, I_VPHADDD = 7416, I_VPHADDSW = 7434, I_VPHADDW = 7399, + I_VPHMINPOSUW = 8304, I_VPHSUBD = 7492, I_VPHSUBSW = 7510, I_VPHSUBW = 7475, + I_VPINSRB = 9571, I_VPINSRD = 9617, I_VPINSRQ = 9626, I_VPINSRW = 6335, I_VPMADDUBSW = 7455, + I_VPMADDWD = 7115, I_VPMAXSB = 8215, I_VPMAXSD = 8232, I_VPMAXSW = 7005, I_VPMAXUB = 6689, + I_VPMAXUD = 8266, I_VPMAXUW = 8249, I_VPMINSB = 8147, I_VPMINSD = 8164, I_VPMINSW = 6943, + I_VPMINUB = 6631, I_VPMINUD = 8198, I_VPMINUW = 8181, I_VPMOVMSKB = 6574, + I_VPMOVSXBD = 7797, I_VPMOVSXBQ = 7818, I_VPMOVSXBW = 7776, I_VPMOVSXDQ = 7881, + I_VPMOVSXWD = 7839, I_VPMOVSXWQ = 7860, I_VPMOVZXBD = 8025, I_VPMOVZXBQ = 8046, + I_VPMOVZXBW = 8004, I_VPMOVZXDQ = 8109, I_VPMOVZXWD = 8067, I_VPMOVZXWQ = 8088, + I_VPMULDQ = 7900, I_VPMULHRSW = 7581, I_VPMULHUW = 6782, I_VPMULHW = 6800, + I_VPMULLD = 8283, I_VPMULLW = 6537, I_VPMULUDQ = 7096, I_VPOR = 6957, I_VPSADBW = 7133, + I_VPSHUFB = 7382, I_VPSHUFD = 4047, I_VPSHUFHW = 4056, I_VPSHUFLW = 4066, + I_VPSIGNB = 7528, I_VPSIGND = 7562, I_VPSIGNW = 7545, I_VPSLLD = 7064, I_VPSLLDQ = 9888, + I_VPSLLQ = 7079, I_VPSLLW = 7049, I_VPSRAD = 6750, I_VPSRAW = 6735, I_VPSRLD = 6491, + I_VPSRLDQ = 9871, I_VPSRLQ = 6506, I_VPSRLW = 6476, I_VPSUBB = 7184, I_VPSUBD = 7214, + I_VPSUBQ = 7229, I_VPSUBSB = 6909, I_VPSUBSW = 6926, I_VPSUBUSB = 6594, I_VPSUBUSW = 6613, + I_VPSUBW = 7199, I_VPTEST = 7669, I_VPUNPCKHBW = 3824, I_VPUNPCKHDQ = 3870, + I_VPUNPCKHQDQ = 3940, I_VPUNPCKHWD = 3847, I_VPUNPCKLBW = 3656, I_VPUNPCKLDQ = 3702, + I_VPUNPCKLQDQ = 3915, I_VPUNPCKLWD = 3679, I_VPXOR = 7020, I_VRCPPS = 3000, + I_VRCPSS = 3008, I_VROUNDPD = 9338, I_VROUNDPS = 9319, I_VROUNDSD = 9376, + I_VROUNDSS = 9357, I_VRSQRTPS = 2966, I_VRSQRTSS = 2976, I_VSHUFPD = 6386, + I_VSHUFPS = 6377, I_VSQRTPD = 2921, I_VSQRTPS = 2912, I_VSQRTSD = 2939, I_VSQRTSS = 2930, + I_VSTMXCSR = 10003, I_VSUBPD = 3441, I_VSUBPS = 3433, I_VSUBSD = 3457, I_VSUBSS = 3449, + I_VTESTPD = 7623, I_VTESTPS = 7614, I_VUCOMISD = 2794, I_VUCOMISS = 2784, + I_VUNPCKHPD = 2350, I_VUNPCKHPS = 2339, I_VUNPCKLPD = 2308, I_VUNPCKLPS = 2297, + I_VXORPD = 3128, I_VXORPS = 3120, I_VZEROALL = 4151, I_VZEROUPPER = 4139, + I_WAIT = 10053, I_WBINVD = 560, I_WRFSBASE = 9964, I_WRGSBASE = 9993, I_WRMSR = 585, + I_XABORT = 1006, I_XADD = 945, I_XBEGIN = 1014, I_XCHG = 212, I_XEND = 1822, + I_XGETBV = 1798, I_XLAT = 399, I_XOR = 61, I_XORPD = 3113, I_XORPS = 3106, + I_XRSTOR = 4306, I_XRSTOR64 = 4314, I_XSAVE = 4282, I_XSAVE64 = 4289, I_XSAVEOPT = 4332, + I_XSAVEOPT64 = 4342, I_XSETBV = 1806, I__3DNOW = 10067 +} _InstructionType; + +typedef enum +{ + R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15, + R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI, R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D, + R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI, R_R8W, R_R9W, R_R10W, R_R11W, R_R12W, R_R13W, R_R14W, R_R15W, + R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH, R_R8B, R_R9B, R_R10B, R_R11B, R_R12B, R_R13B, R_R14B, R_R15B, + R_SPL, R_BPL, R_SIL, R_DIL, + R_ES, R_CS, R_SS, R_DS, R_FS, R_GS, + R_RIP, + R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7, + R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7, + R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15, + R_YMM0, R_YMM1, R_YMM2, R_YMM3, R_YMM4, R_YMM5, R_YMM6, R_YMM7, R_YMM8, R_YMM9, R_YMM10, R_YMM11, R_YMM12, R_YMM13, R_YMM14, R_YMM15, + R_CR0, R_UNUSED0, R_CR2, R_CR3, R_CR4, R_UNUSED1, R_UNUSED2, R_UNUSED3, R_CR8, + R_DR0, R_DR1, R_DR2, R_DR3, R_UNUSED4, R_UNUSED5, R_DR6, R_DR7 +} _RegisterType; + +#endif /* MNEMONICS_H */ diff --git a/distorm/src/distorm.c b/distorm/src/distorm.c new file mode 100644 index 0000000..0bf9d29 --- /dev/null +++ b/distorm/src/distorm.c @@ -0,0 +1,13911 @@ +/* +mnemonics.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +/* +mnemonics.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef MNEMONICS_H +#define MNEMONICS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DISTORM_LIGHT + +typedef struct WMnemonic +{ + unsigned char length; + unsigned char p[1]; /* p is a null terminated string, which contains 'length' characters. */ +} _WMnemonic; + +typedef struct WRegister +{ + unsigned int length; + unsigned char p[6]; /* p is a null terminated string. */ +} _WRegister; + +extern const unsigned char _MNEMONICS[]; +extern const _WRegister _REGISTERS[]; + +#endif /* DISTORM_LIGHT */ + +#ifdef __cplusplus +} /* End Of Extern */ +#endif + +#define GET_REGISTER_NAME(r) (unsigned char*)_REGISTERS[(r)].p +#define GET_MNEMONIC_NAME(m) ((_WMnemonic*)&_MNEMONICS[(m)])->p + +typedef enum +{ + I_UNDEFINED = 0, I_AAA = 66, I_AAD = 388, I_AAM = 383, I_AAS = 76, I_ADC = 31, I_ADD = 11, I_ADDPD = 3143, + I_ADDPS = 3136, I_ADDSD = 3157, I_ADDSS = 3150, I_ADDSUBPD = 6427, I_ADDSUBPS = 6437, + I_AESDEC = 9242, I_AESDECLAST = 9259, I_AESENC = 9200, I_AESENCLAST = 9217, + I_AESIMC = 9183, I_AESKEYGENASSIST = 9828, I_AND = 41, I_ANDNPD = 3054, I_ANDNPS = 3046, + I_ANDPD = 3023, I_ANDPS = 3016, I_ARPL = 111, I_BLENDPD = 9405, I_BLENDPS = 9386, + I_BLENDVPD = 7652, I_BLENDVPS = 7642, I_BOUND = 104, I_BSF = 4379, I_BSR = 4391, + I_BSWAP = 959, I_BT = 871, I_BTC = 933, I_BTR = 911, I_BTS = 886, I_CALL = 455, + I_CALL_FAR = 260, I_CBW = 228, I_CDQ = 250, I_CDQE = 239, I_CLAC = 1786, I_CLC = 491, + I_CLD = 511, I_CLFLUSH = 4362, I_CLGI = 1866, I_CLI = 501, I_CLTS = 540, I_CMC = 486, + I_CMOVA = 693, I_CMOVAE = 662, I_CMOVB = 655, I_CMOVBE = 685, I_CMOVG = 753, + I_CMOVGE = 737, I_CMOVL = 730, I_CMOVLE = 745, I_CMOVNO = 647, I_CMOVNP = 722, + I_CMOVNS = 707, I_CMOVNZ = 677, I_CMOVO = 640, I_CMOVP = 715, I_CMOVS = 700, + I_CMOVZ = 670, I_CMP = 71, I_CMPEQPD = 4482, I_CMPEQPS = 4403, I_CMPEQSD = 4640, + I_CMPEQSS = 4561, I_CMPLEPD = 4500, I_CMPLEPS = 4421, I_CMPLESD = 4658, I_CMPLESS = 4579, + I_CMPLTPD = 4491, I_CMPLTPS = 4412, I_CMPLTSD = 4649, I_CMPLTSS = 4570, I_CMPNEQPD = 4521, + I_CMPNEQPS = 4442, I_CMPNEQSD = 4679, I_CMPNEQSS = 4600, I_CMPNLEPD = 4541, + I_CMPNLEPS = 4462, I_CMPNLESD = 4699, I_CMPNLESS = 4620, I_CMPNLTPD = 4531, + I_CMPNLTPS = 4452, I_CMPNLTSD = 4689, I_CMPNLTSS = 4610, I_CMPORDPD = 4551, + I_CMPORDPS = 4472, I_CMPORDSD = 4709, I_CMPORDSS = 4630, I_CMPS = 301, I_CMPUNORDPD = 4509, + I_CMPUNORDPS = 4430, I_CMPUNORDSD = 4667, I_CMPUNORDSS = 4588, I_CMPXCHG = 897, + I_CMPXCHG16B = 6406, I_CMPXCHG8B = 6395, I_COMISD = 2812, I_COMISS = 2804, + I_CPUID = 864, I_CQO = 255, I_CRC32 = 9291, I_CVTDQ2PD = 6820, I_CVTDQ2PS = 3340, + I_CVTPD2DQ = 6830, I_CVTPD2PI = 2714, I_CVTPD2PS = 3266, I_CVTPH2PS = 4194, + I_CVTPI2PD = 2528, I_CVTPI2PS = 2518, I_CVTPS2DQ = 3350, I_CVTPS2PD = 3256, + I_CVTPS2PH = 4204, I_CVTPS2PI = 2704, I_CVTSD2SI = 2734, I_CVTSD2SS = 3286, + I_CVTSI2SD = 2548, I_CVTSI2SS = 2538, I_CVTSS2SD = 3276, I_CVTSS2SI = 2724, + I_CVTTPD2DQ = 6809, I_CVTTPD2PI = 2647, I_CVTTPS2DQ = 3360, I_CVTTPS2PI = 2636, + I_CVTTSD2SI = 2669, I_CVTTSS2SI = 2658, I_CWD = 245, I_CWDE = 233, I_DAA = 46, + I_DAS = 56, I_DEC = 86, I_DIV = 1645, I_DIVPD = 3532, I_DIVPS = 3525, I_DIVSD = 3546, + I_DIVSS = 3539, I_DPPD = 9648, I_DPPS = 9635, I_EMMS = 4133, I_ENTER = 340, + I_EXTRACTPS = 9513, I_EXTRQ = 4169, I_F2XM1 = 1191, I_FABS = 1122, I_FADD = 1022, + I_FADDP = 1548, I_FBLD = 1600, I_FBSTP = 1606, I_FCHS = 1116, I_FCLEX = 7322, + I_FCMOVB = 1375, I_FCMOVBE = 1391, I_FCMOVE = 1383, I_FCMOVNB = 1444, I_FCMOVNBE = 1462, + I_FCMOVNE = 1453, I_FCMOVNU = 1472, I_FCMOVU = 1400, I_FCOM = 1034, I_FCOMI = 1511, + I_FCOMIP = 1622, I_FCOMP = 1040, I_FCOMPP = 1562, I_FCOS = 1310, I_FDECSTP = 1237, + I_FDIV = 1060, I_FDIVP = 1593, I_FDIVR = 1066, I_FDIVRP = 1585, I_FEDISI = 1487, + I_FEMMS = 573, I_FENI = 1481, I_FFREE = 1526, I_FIADD = 1316, I_FICOM = 1330, + I_FICOMP = 1337, I_FIDIV = 1360, I_FIDIVR = 1367, I_FILD = 1417, I_FIMUL = 1323, + I_FINCSTP = 1246, I_FINIT = 7337, I_FIST = 1431, I_FISTP = 1437, I_FISTTP = 1423, + I_FISUB = 1345, I_FISUBR = 1352, I_FLD = 1073, I_FLD1 = 1140, I_FLDCW = 1097, + I_FLDENV = 1089, I_FLDL2E = 1154, I_FLDL2T = 1146, I_FLDLG2 = 1169, I_FLDLN2 = 1177, + I_FLDPI = 1162, I_FLDZ = 1185, I_FMUL = 1028, I_FMULP = 1555, I_FNCLEX = 7314, + I_FNINIT = 7329, I_FNOP = 1110, I_FNSAVE = 7344, I_FNSTCW = 7299, I_FNSTENV = 7282, + I_FNSTSW = 7359, I_FPATAN = 1212, I_FPREM = 1255, I_FPREM1 = 1229, I_FPTAN = 1205, + I_FRNDINT = 1287, I_FRSTOR = 1518, I_FSAVE = 7352, I_FSCALE = 1296, I_FSETPM = 1495, + I_FSIN = 1304, I_FSINCOS = 1278, I_FSQRT = 1271, I_FST = 1078, I_FSTCW = 7307, + I_FSTENV = 7291, I_FSTP = 1083, I_FSTSW = 7367, I_FSUB = 1047, I_FSUBP = 1578, + I_FSUBR = 1053, I_FSUBRP = 1570, I_FTST = 1128, I_FUCOM = 1533, I_FUCOMI = 1503, + I_FUCOMIP = 1613, I_FUCOMP = 1540, I_FUCOMPP = 1408, I_FXAM = 1134, I_FXCH = 1104, + I_FXRSTOR = 9925, I_FXRSTOR64 = 9934, I_FXSAVE = 9897, I_FXSAVE64 = 9905, + I_FXTRACT = 1220, I_FYL2X = 1198, I_FYL2XP1 = 1262, I_GETSEC = 632, I_HADDPD = 4214, + I_HADDPS = 4222, I_HLT = 481, I_HSUBPD = 4248, I_HSUBPS = 4256, I_IDIV = 1650, + I_IMUL = 117, I_IN = 446, I_INC = 81, I_INS = 123, I_INSERTPS = 9580, I_INSERTQ = 4176, + I_INT = 366, I_INT1 = 475, I_INT3 = 360, I_INTO = 371, I_INVD = 554, I_INVEPT = 8317, + I_INVLPG = 1726, I_INVLPGA = 1880, I_INVPCID = 8334, I_INVVPID = 8325, I_IRET = 377, + I_JA = 166, I_JAE = 147, I_JB = 143, I_JBE = 161, I_JCXZ = 426, I_JECXZ = 432, + I_JG = 202, I_JGE = 192, I_JL = 188, I_JLE = 197, I_JMP = 461, I_JMP_FAR = 466, + I_JNO = 138, I_JNP = 183, I_JNS = 174, I_JNZ = 156, I_JO = 134, I_JP = 179, + I_JRCXZ = 439, I_JS = 170, I_JZ = 152, I_LAHF = 289, I_LAR = 521, I_LDDQU = 7027, + I_LDMXCSR = 9955, I_LDS = 335, I_LEA = 223, I_LEAVE = 347, I_LES = 330, I_LFENCE = 4298, + I_LFS = 916, I_LGDT = 1702, I_LGS = 921, I_LIDT = 1708, I_LLDT = 1667, I_LMSW = 1720, + I_LODS = 313, I_LOOP = 420, I_LOOPNZ = 405, I_LOOPZ = 413, I_LSL = 526, I_LSS = 906, + I_LTR = 1673, I_LZCNT = 4396, I_MASKMOVDQU = 7152, I_MASKMOVQ = 7142, I_MAXPD = 3592, + I_MAXPS = 3585, I_MAXSD = 3606, I_MAXSS = 3599, I_MFENCE = 4324, I_MINPD = 3472, + I_MINPS = 3465, I_MINSD = 3486, I_MINSS = 3479, I_MONITOR = 1770, I_MOV = 218, + I_MOVAPD = 2492, I_MOVAPS = 2484, I_MOVBE = 9284, I_MOVD = 3953, I_MOVDDUP = 2219, + I_MOVDQ2Q = 6555, I_MOVDQA = 3979, I_MOVDQU = 3987, I_MOVHLPS = 2184, I_MOVHPD = 2378, + I_MOVHPS = 2370, I_MOVLHPS = 2361, I_MOVLPD = 2201, I_MOVLPS = 2193, I_MOVMSKPD = 2848, + I_MOVMSKPS = 2838, I_MOVNTDQ = 6882, I_MOVNTDQA = 7928, I_MOVNTI = 951, I_MOVNTPD = 2589, + I_MOVNTPS = 2580, I_MOVNTQ = 6874, I_MOVNTSD = 2607, I_MOVNTSS = 2598, I_MOVQ = 3959, + I_MOVQ2DQ = 6546, I_MOVS = 295, I_MOVSD = 2143, I_MOVSHDUP = 2386, I_MOVSLDUP = 2209, + I_MOVSS = 2136, I_MOVSX = 938, I_MOVSXD = 10038, I_MOVUPD = 2128, I_MOVUPS = 2120, + I_MOVZX = 926, I_MPSADBW = 9661, I_MUL = 1640, I_MULPD = 3203, I_MULPS = 3196, + I_MULSD = 3217, I_MULSS = 3210, I_MWAIT = 1779, I_NEG = 1635, I_NOP = 580, + I_NOT = 1630, I_OR = 27, I_ORPD = 3086, I_ORPS = 3080, I_OUT = 450, I_OUTS = 128, + I_PABSB = 7721, I_PABSD = 7751, I_PABSW = 7736, I_PACKSSDW = 3882, I_PACKSSWB = 3714, + I_PACKUSDW = 7949, I_PACKUSWB = 3792, I_PADDB = 7237, I_PADDD = 7267, I_PADDQ = 6514, + I_PADDSB = 6963, I_PADDSW = 6980, I_PADDUSB = 6653, I_PADDUSW = 6672, I_PADDW = 7252, + I_PALIGNR = 9443, I_PAND = 6640, I_PANDN = 6698, I_PAUSE = 10046, I_PAVGB = 6713, + I_PAVGUSB = 2111, I_PAVGW = 6758, I_PBLENDVB = 7632, I_PBLENDW = 9424, I_PCLMULQDQ = 9680, + I_PCMPEQB = 4076, I_PCMPEQD = 4114, I_PCMPEQQ = 7909, I_PCMPEQW = 4095, I_PCMPESTRI = 9759, + I_PCMPESTRM = 9736, I_PCMPGTB = 3735, I_PCMPGTD = 3773, I_PCMPGTQ = 8120, + I_PCMPGTW = 3754, I_PCMPISTRI = 9805, I_PCMPISTRM = 9782, I_PEXTRB = 9462, + I_PEXTRD = 9479, I_PEXTRQ = 9487, I_PEXTRW = 6344, I_PF2ID = 1947, I_PF2IW = 1940, + I_PFACC = 2061, I_PFADD = 2010, I_PFCMPEQ = 2068, I_PFCMPGE = 1971, I_PFCMPGT = 2017, + I_PFMAX = 2026, I_PFMIN = 1980, I_PFMUL = 2077, I_PFNACC = 1954, I_PFPNACC = 1962, + I_PFRCP = 1987, I_PFRCPIT1 = 2033, I_PFRCPIT2 = 2084, I_PFRSQIT1 = 2043, I_PFRSQRT = 1994, + I_PFSUB = 2003, I_PFSUBR = 2053, I_PHADDD = 7408, I_PHADDSW = 7425, I_PHADDW = 7391, + I_PHMINPOSUW = 8292, I_PHSUBD = 7484, I_PHSUBSW = 7501, I_PHSUBW = 7467, I_PI2FD = 1933, + I_PI2FW = 1926, I_PINSRB = 9563, I_PINSRD = 9601, I_PINSRQ = 9609, I_PINSRW = 6327, + I_PMADDUBSW = 7444, I_PMADDWD = 7106, I_PMAXSB = 8207, I_PMAXSD = 8224, I_PMAXSW = 6997, + I_PMAXUB = 6681, I_PMAXUD = 8258, I_PMAXUW = 8241, I_PMINSB = 8139, I_PMINSD = 8156, + I_PMINSW = 6935, I_PMINUB = 6623, I_PMINUD = 8190, I_PMINUW = 8173, I_PMOVMSKB = 6564, + I_PMOVSXBD = 7787, I_PMOVSXBQ = 7808, I_PMOVSXBW = 7766, I_PMOVSXDQ = 7871, + I_PMOVSXWD = 7829, I_PMOVSXWQ = 7850, I_PMOVZXBD = 8015, I_PMOVZXBQ = 8036, + I_PMOVZXBW = 7994, I_PMOVZXDQ = 8099, I_PMOVZXWD = 8057, I_PMOVZXWQ = 8078, + I_PMULDQ = 7892, I_PMULHRSW = 7571, I_PMULHRW = 2094, I_PMULHUW = 6773, I_PMULHW = 6792, + I_PMULLD = 8275, I_PMULLW = 6529, I_PMULUDQ = 7087, I_POP = 22, I_POPA = 98, + I_POPCNT = 4371, I_POPF = 277, I_POR = 6952, I_PREFETCH = 1905, I_PREFETCHNTA = 2435, + I_PREFETCHT0 = 2448, I_PREFETCHT1 = 2460, I_PREFETCHT2 = 2472, I_PREFETCHW = 1915, + I_PSADBW = 7125, I_PSHUFB = 7374, I_PSHUFD = 4021, I_PSHUFHW = 4029, I_PSHUFLW = 4038, + I_PSHUFW = 4013, I_PSIGNB = 7520, I_PSIGND = 7554, I_PSIGNW = 7537, I_PSLLD = 7057, + I_PSLLDQ = 9880, I_PSLLQ = 7072, I_PSLLW = 7042, I_PSRAD = 6743, I_PSRAW = 6728, + I_PSRLD = 6484, I_PSRLDQ = 9863, I_PSRLQ = 6499, I_PSRLW = 6469, I_PSUBB = 7177, + I_PSUBD = 7207, I_PSUBQ = 7222, I_PSUBSB = 6901, I_PSUBSW = 6918, I_PSUBUSB = 6585, + I_PSUBUSW = 6604, I_PSUBW = 7192, I_PSWAPD = 2103, I_PTEST = 7662, I_PUNPCKHBW = 3813, + I_PUNPCKHDQ = 3859, I_PUNPCKHQDQ = 3928, I_PUNPCKHWD = 3836, I_PUNPCKLBW = 3645, + I_PUNPCKLDQ = 3691, I_PUNPCKLQDQ = 3903, I_PUNPCKLWD = 3668, I_PUSH = 16, + I_PUSHA = 91, I_PUSHF = 270, I_PXOR = 7014, I_RCL = 976, I_RCPPS = 2986, I_RCPSS = 2993, + I_RCR = 981, I_RDFSBASE = 9915, I_RDGSBASE = 9945, I_RDMSR = 599, I_RDPMC = 606, + I_RDRAND = 10059, I_RDTSC = 592, I_RDTSCP = 1897, I_RET = 325, I_RETF = 354, + I_ROL = 966, I_ROR = 971, I_ROUNDPD = 9329, I_ROUNDPS = 9310, I_ROUNDSD = 9367, + I_ROUNDSS = 9348, I_RSM = 881, I_RSQRTPS = 2948, I_RSQRTSS = 2957, I_SAHF = 283, + I_SAL = 996, I_SALC = 393, I_SAR = 1001, I_SBB = 36, I_SCAS = 319, I_SETA = 806, + I_SETAE = 779, I_SETB = 773, I_SETBE = 799, I_SETG = 858, I_SETGE = 844, I_SETL = 838, + I_SETLE = 851, I_SETNO = 766, I_SETNP = 831, I_SETNS = 818, I_SETNZ = 792, + I_SETO = 760, I_SETP = 825, I_SETS = 812, I_SETZ = 786, I_SFENCE = 4354, I_SGDT = 1690, + I_SHL = 986, I_SHLD = 875, I_SHR = 991, I_SHRD = 891, I_SHUFPD = 6369, I_SHUFPS = 6361, + I_SIDT = 1696, I_SKINIT = 1872, I_SLDT = 1656, I_SMSW = 1714, I_SQRTPD = 2888, + I_SQRTPS = 2880, I_SQRTSD = 2904, I_SQRTSS = 2896, I_STAC = 1792, I_STC = 496, + I_STD = 516, I_STGI = 1860, I_STI = 506, I_STMXCSR = 9984, I_STOS = 307, I_STR = 1662, + I_SUB = 51, I_SUBPD = 3412, I_SUBPS = 3405, I_SUBSD = 3426, I_SUBSS = 3419, + I_SWAPGS = 1889, I_SYSCALL = 531, I_SYSENTER = 613, I_SYSEXIT = 623, I_SYSRET = 546, + I_TEST = 206, I_TZCNT = 4384, I_UCOMISD = 2775, I_UCOMISS = 2766, I_UD2 = 568, + I_UNPCKHPD = 2329, I_UNPCKHPS = 2319, I_UNPCKLPD = 2287, I_UNPCKLPS = 2277, + I_VADDPD = 3172, I_VADDPS = 3164, I_VADDSD = 3188, I_VADDSS = 3180, I_VADDSUBPD = 6447, + I_VADDSUBPS = 6458, I_VAESDEC = 9250, I_VAESDECLAST = 9271, I_VAESENC = 9208, + I_VAESENCLAST = 9229, I_VAESIMC = 9191, I_VAESKEYGENASSIST = 9845, I_VANDNPD = 3071, + I_VANDNPS = 3062, I_VANDPD = 3038, I_VANDPS = 3030, I_VBLENDPD = 9414, I_VBLENDPS = 9395, + I_VBLENDVPD = 9714, I_VBLENDVPS = 9703, I_VBROADCASTF128 = 7705, I_VBROADCASTSD = 7691, + I_VBROADCASTSS = 7677, I_VCMPEQPD = 5121, I_VCMPEQPS = 4719, I_VCMPEQSD = 5925, + I_VCMPEQSS = 5523, I_VCMPEQ_OSPD = 5302, I_VCMPEQ_OSPS = 4900, I_VCMPEQ_OSSD = 6106, + I_VCMPEQ_OSSS = 5704, I_VCMPEQ_UQPD = 5208, I_VCMPEQ_UQPS = 4806, I_VCMPEQ_UQSD = 6012, + I_VCMPEQ_UQSS = 5610, I_VCMPEQ_USPD = 5411, I_VCMPEQ_USPS = 5009, I_VCMPEQ_USSD = 6215, + I_VCMPEQ_USSS = 5813, I_VCMPFALSEPD = 5243, I_VCMPFALSEPS = 4841, I_VCMPFALSESD = 6047, + I_VCMPFALSESS = 5645, I_VCMPFALSE_OSPD = 5452, I_VCMPFALSE_OSPS = 5050, I_VCMPFALSE_OSSD = 6256, + I_VCMPFALSE_OSSS = 5854, I_VCMPGEPD = 5270, I_VCMPGEPS = 4868, I_VCMPGESD = 6074, + I_VCMPGESS = 5672, I_VCMPGE_OQPD = 5482, I_VCMPGE_OQPS = 5080, I_VCMPGE_OQSD = 6286, + I_VCMPGE_OQSS = 5884, I_VCMPGTPD = 5280, I_VCMPGTPS = 4878, I_VCMPGTSD = 6084, + I_VCMPGTSS = 5682, I_VCMPGT_OQPD = 5495, I_VCMPGT_OQPS = 5093, I_VCMPGT_OQSD = 6299, + I_VCMPGT_OQSS = 5897, I_VCMPLEPD = 5141, I_VCMPLEPS = 4739, I_VCMPLESD = 5945, + I_VCMPLESS = 5543, I_VCMPLE_OQPD = 5328, I_VCMPLE_OQPS = 4926, I_VCMPLE_OQSD = 6132, + I_VCMPLE_OQSS = 5730, I_VCMPLTPD = 5131, I_VCMPLTPS = 4729, I_VCMPLTSD = 5935, + I_VCMPLTSS = 5533, I_VCMPLT_OQPD = 5315, I_VCMPLT_OQPS = 4913, I_VCMPLT_OQSD = 6119, + I_VCMPLT_OQSS = 5717, I_VCMPNEQPD = 5164, I_VCMPNEQPS = 4762, I_VCMPNEQSD = 5968, + I_VCMPNEQSS = 5566, I_VCMPNEQ_OQPD = 5256, I_VCMPNEQ_OQPS = 4854, I_VCMPNEQ_OQSD = 6060, + I_VCMPNEQ_OQSS = 5658, I_VCMPNEQ_OSPD = 5468, I_VCMPNEQ_OSPS = 5066, I_VCMPNEQ_OSSD = 6272, + I_VCMPNEQ_OSSS = 5870, I_VCMPNEQ_USPD = 5356, I_VCMPNEQ_USPS = 4954, I_VCMPNEQ_USSD = 6160, + I_VCMPNEQ_USSS = 5758, I_VCMPNGEPD = 5221, I_VCMPNGEPS = 4819, I_VCMPNGESD = 6025, + I_VCMPNGESS = 5623, I_VCMPNGE_UQPD = 5424, I_VCMPNGE_UQPS = 5022, I_VCMPNGE_UQSD = 6228, + I_VCMPNGE_UQSS = 5826, I_VCMPNGTPD = 5232, I_VCMPNGTPS = 4830, I_VCMPNGTSD = 6036, + I_VCMPNGTSS = 5634, I_VCMPNGT_UQPD = 5438, I_VCMPNGT_UQPS = 5036, I_VCMPNGT_UQSD = 6242, + I_VCMPNGT_UQSS = 5840, I_VCMPNLEPD = 5186, I_VCMPNLEPS = 4784, I_VCMPNLESD = 5990, + I_VCMPNLESS = 5588, I_VCMPNLE_UQPD = 5384, I_VCMPNLE_UQPS = 4982, I_VCMPNLE_UQSD = 6188, + I_VCMPNLE_UQSS = 5786, I_VCMPNLTPD = 5175, I_VCMPNLTPS = 4773, I_VCMPNLTSD = 5979, + I_VCMPNLTSS = 5577, I_VCMPNLT_UQPD = 5370, I_VCMPNLT_UQPS = 4968, I_VCMPNLT_UQSD = 6174, + I_VCMPNLT_UQSS = 5772, I_VCMPORDPD = 5197, I_VCMPORDPS = 4795, I_VCMPORDSD = 6001, + I_VCMPORDSS = 5599, I_VCMPORD_SPD = 5398, I_VCMPORD_SPS = 4996, I_VCMPORD_SSD = 6202, + I_VCMPORD_SSS = 5800, I_VCMPTRUEPD = 5290, I_VCMPTRUEPS = 4888, I_VCMPTRUESD = 6094, + I_VCMPTRUESS = 5692, I_VCMPTRUE_USPD = 5508, I_VCMPTRUE_USPS = 5106, I_VCMPTRUE_USSD = 6312, + I_VCMPTRUE_USSS = 5910, I_VCMPUNORDPD = 5151, I_VCMPUNORDPS = 4749, I_VCMPUNORDSD = 5955, + I_VCMPUNORDSS = 5553, I_VCMPUNORD_SPD = 5341, I_VCMPUNORD_SPS = 4939, I_VCMPUNORD_SSD = 6145, + I_VCMPUNORD_SSS = 5743, I_VCOMISD = 2829, I_VCOMISS = 2820, I_VCVTDQ2PD = 6852, + I_VCVTDQ2PS = 3371, I_VCVTPD2DQ = 6863, I_VCVTPD2PS = 3307, I_VCVTPS2DQ = 3382, + I_VCVTPS2PD = 3296, I_VCVTSD2SI = 2755, I_VCVTSD2SS = 3329, I_VCVTSI2SD = 2569, + I_VCVTSI2SS = 2558, I_VCVTSS2SD = 3318, I_VCVTSS2SI = 2744, I_VCVTTPD2DQ = 6840, + I_VCVTTPS2DQ = 3393, I_VCVTTSD2SI = 2692, I_VCVTTSS2SI = 2680, I_VDIVPD = 3561, + I_VDIVPS = 3553, I_VDIVSD = 3577, I_VDIVSS = 3569, I_VDPPD = 9654, I_VDPPS = 9641, + I_VERR = 1678, I_VERW = 1684, I_VEXTRACTF128 = 9549, I_VEXTRACTPS = 9524, + I_VFMADD132PD = 8420, I_VFMADD132PS = 8407, I_VFMADD132SD = 8446, I_VFMADD132SS = 8433, + I_VFMADD213PD = 8700, I_VFMADD213PS = 8687, I_VFMADD213SD = 8726, I_VFMADD213SS = 8713, + I_VFMADD231PD = 8980, I_VFMADD231PS = 8967, I_VFMADD231SD = 9006, I_VFMADD231SS = 8993, + I_VFMADDSUB132PD = 8359, I_VFMADDSUB132PS = 8343, I_VFMADDSUB213PD = 8639, + I_VFMADDSUB213PS = 8623, I_VFMADDSUB231PD = 8919, I_VFMADDSUB231PS = 8903, + I_VFMSUB132PD = 8472, I_VFMSUB132PS = 8459, I_VFMSUB132SD = 8498, I_VFMSUB132SS = 8485, + I_VFMSUB213PD = 8752, I_VFMSUB213PS = 8739, I_VFMSUB213SD = 8778, I_VFMSUB213SS = 8765, + I_VFMSUB231PD = 9032, I_VFMSUB231PS = 9019, I_VFMSUB231SD = 9058, I_VFMSUB231SS = 9045, + I_VFMSUBADD132PD = 8391, I_VFMSUBADD132PS = 8375, I_VFMSUBADD213PD = 8671, + I_VFMSUBADD213PS = 8655, I_VFMSUBADD231PD = 8951, I_VFMSUBADD231PS = 8935, + I_VFNMADD132PD = 8525, I_VFNMADD132PS = 8511, I_VFNMADD132SD = 8553, I_VFNMADD132SS = 8539, + I_VFNMADD213PD = 8805, I_VFNMADD213PS = 8791, I_VFNMADD213SD = 8833, I_VFNMADD213SS = 8819, + I_VFNMADD231PD = 9085, I_VFNMADD231PS = 9071, I_VFNMADD231SD = 9113, I_VFNMADD231SS = 9099, + I_VFNMSUB132PD = 8581, I_VFNMSUB132PS = 8567, I_VFNMSUB132SD = 8609, I_VFNMSUB132SS = 8595, + I_VFNMSUB213PD = 8861, I_VFNMSUB213PS = 8847, I_VFNMSUB213SD = 8889, I_VFNMSUB213SS = 8875, + I_VFNMSUB231PD = 9141, I_VFNMSUB231PS = 9127, I_VFNMSUB231SD = 9169, I_VFNMSUB231SS = 9155, + I_VHADDPD = 4230, I_VHADDPS = 4239, I_VHSUBPD = 4264, I_VHSUBPS = 4273, I_VINSERTF128 = 9536, + I_VINSERTPS = 9590, I_VLDDQU = 7034, I_VLDMXCSR = 9974, I_VMASKMOVDQU = 7164, + I_VMASKMOVPD = 7982, I_VMASKMOVPS = 7970, I_VMAXPD = 3621, I_VMAXPS = 3613, + I_VMAXSD = 3637, I_VMAXSS = 3629, I_VMCALL = 1734, I_VMCLEAR = 10022, I_VMFUNC = 1814, + I_VMINPD = 3501, I_VMINPS = 3493, I_VMINSD = 3517, I_VMINSS = 3509, I_VMLAUNCH = 1742, + I_VMLOAD = 1844, I_VMMCALL = 1835, I_VMOVAPD = 2509, I_VMOVAPS = 2500, I_VMOVD = 3965, + I_VMOVDDUP = 2267, I_VMOVDQA = 3995, I_VMOVDQU = 4004, I_VMOVHLPS = 2228, + I_VMOVHPD = 2415, I_VMOVHPS = 2406, I_VMOVLHPS = 2396, I_VMOVLPD = 2247, I_VMOVLPS = 2238, + I_VMOVMSKPD = 2869, I_VMOVMSKPS = 2858, I_VMOVNTDQ = 6891, I_VMOVNTDQA = 7938, + I_VMOVNTPD = 2626, I_VMOVNTPS = 2616, I_VMOVQ = 3972, I_VMOVSD = 2176, I_VMOVSHDUP = 2424, + I_VMOVSLDUP = 2256, I_VMOVSS = 2168, I_VMOVUPD = 2159, I_VMOVUPS = 2150, I_VMPSADBW = 9670, + I_VMPTRLD = 10013, I_VMPTRST = 6418, I_VMREAD = 4161, I_VMRESUME = 1752, I_VMRUN = 1828, + I_VMSAVE = 1852, I_VMULPD = 3232, I_VMULPS = 3224, I_VMULSD = 3248, I_VMULSS = 3240, + I_VMWRITE = 4185, I_VMXOFF = 1762, I_VMXON = 10031, I_VORPD = 3099, I_VORPS = 3092, + I_VPABSB = 7728, I_VPABSD = 7758, I_VPABSW = 7743, I_VPACKSSDW = 3892, I_VPACKSSWB = 3724, + I_VPACKUSDW = 7959, I_VPACKUSWB = 3802, I_VPADDB = 7244, I_VPADDD = 7274, + I_VPADDQ = 6521, I_VPADDSB = 6971, I_VPADDSW = 6988, I_VPADDUSW = 6662, I_VPADDW = 7259, + I_VPALIGNR = 9452, I_VPAND = 6646, I_VPANDN = 6705, I_VPAVGB = 6720, I_VPAVGW = 6765, + I_VPBLENDVB = 9725, I_VPBLENDW = 9433, I_VPCLMULQDQ = 9691, I_VPCMPEQB = 4085, + I_VPCMPEQD = 4123, I_VPCMPEQQ = 7918, I_VPCMPEQW = 4104, I_VPCMPESTRI = 9770, + I_VPCMPESTRM = 9747, I_VPCMPGTB = 3744, I_VPCMPGTD = 3782, I_VPCMPGTQ = 8129, + I_VPCMPGTW = 3763, I_VPCMPISTRI = 9816, I_VPCMPISTRM = 9793, I_VPERM2F128 = 9298, + I_VPERMILPD = 7603, I_VPERMILPS = 7592, I_VPEXTRB = 9470, I_VPEXTRD = 9495, + I_VPEXTRQ = 9504, I_VPEXTRW = 6352, I_VPHADDD = 7416, I_VPHADDSW = 7434, I_VPHADDW = 7399, + I_VPHMINPOSUW = 8304, I_VPHSUBD = 7492, I_VPHSUBSW = 7510, I_VPHSUBW = 7475, + I_VPINSRB = 9571, I_VPINSRD = 9617, I_VPINSRQ = 9626, I_VPINSRW = 6335, I_VPMADDUBSW = 7455, + I_VPMADDWD = 7115, I_VPMAXSB = 8215, I_VPMAXSD = 8232, I_VPMAXSW = 7005, I_VPMAXUB = 6689, + I_VPMAXUD = 8266, I_VPMAXUW = 8249, I_VPMINSB = 8147, I_VPMINSD = 8164, I_VPMINSW = 6943, + I_VPMINUB = 6631, I_VPMINUD = 8198, I_VPMINUW = 8181, I_VPMOVMSKB = 6574, + I_VPMOVSXBD = 7797, I_VPMOVSXBQ = 7818, I_VPMOVSXBW = 7776, I_VPMOVSXDQ = 7881, + I_VPMOVSXWD = 7839, I_VPMOVSXWQ = 7860, I_VPMOVZXBD = 8025, I_VPMOVZXBQ = 8046, + I_VPMOVZXBW = 8004, I_VPMOVZXDQ = 8109, I_VPMOVZXWD = 8067, I_VPMOVZXWQ = 8088, + I_VPMULDQ = 7900, I_VPMULHRSW = 7581, I_VPMULHUW = 6782, I_VPMULHW = 6800, + I_VPMULLD = 8283, I_VPMULLW = 6537, I_VPMULUDQ = 7096, I_VPOR = 6957, I_VPSADBW = 7133, + I_VPSHUFB = 7382, I_VPSHUFD = 4047, I_VPSHUFHW = 4056, I_VPSHUFLW = 4066, + I_VPSIGNB = 7528, I_VPSIGND = 7562, I_VPSIGNW = 7545, I_VPSLLD = 7064, I_VPSLLDQ = 9888, + I_VPSLLQ = 7079, I_VPSLLW = 7049, I_VPSRAD = 6750, I_VPSRAW = 6735, I_VPSRLD = 6491, + I_VPSRLDQ = 9871, I_VPSRLQ = 6506, I_VPSRLW = 6476, I_VPSUBB = 7184, I_VPSUBD = 7214, + I_VPSUBQ = 7229, I_VPSUBSB = 6909, I_VPSUBSW = 6926, I_VPSUBUSB = 6594, I_VPSUBUSW = 6613, + I_VPSUBW = 7199, I_VPTEST = 7669, I_VPUNPCKHBW = 3824, I_VPUNPCKHDQ = 3870, + I_VPUNPCKHQDQ = 3940, I_VPUNPCKHWD = 3847, I_VPUNPCKLBW = 3656, I_VPUNPCKLDQ = 3702, + I_VPUNPCKLQDQ = 3915, I_VPUNPCKLWD = 3679, I_VPXOR = 7020, I_VRCPPS = 3000, + I_VRCPSS = 3008, I_VROUNDPD = 9338, I_VROUNDPS = 9319, I_VROUNDSD = 9376, + I_VROUNDSS = 9357, I_VRSQRTPS = 2966, I_VRSQRTSS = 2976, I_VSHUFPD = 6386, + I_VSHUFPS = 6377, I_VSQRTPD = 2921, I_VSQRTPS = 2912, I_VSQRTSD = 2939, I_VSQRTSS = 2930, + I_VSTMXCSR = 10003, I_VSUBPD = 3441, I_VSUBPS = 3433, I_VSUBSD = 3457, I_VSUBSS = 3449, + I_VTESTPD = 7623, I_VTESTPS = 7614, I_VUCOMISD = 2794, I_VUCOMISS = 2784, + I_VUNPCKHPD = 2350, I_VUNPCKHPS = 2339, I_VUNPCKLPD = 2308, I_VUNPCKLPS = 2297, + I_VXORPD = 3128, I_VXORPS = 3120, I_VZEROALL = 4151, I_VZEROUPPER = 4139, + I_WAIT = 10053, I_WBINVD = 560, I_WRFSBASE = 9964, I_WRGSBASE = 9993, I_WRMSR = 585, + I_XABORT = 1006, I_XADD = 945, I_XBEGIN = 1014, I_XCHG = 212, I_XEND = 1822, + I_XGETBV = 1798, I_XLAT = 399, I_XOR = 61, I_XORPD = 3113, I_XORPS = 3106, + I_XRSTOR = 4306, I_XRSTOR64 = 4314, I_XSAVE = 4282, I_XSAVE64 = 4289, I_XSAVEOPT = 4332, + I_XSAVEOPT64 = 4342, I_XSETBV = 1806, I__3DNOW = 10067 +} _InstructionType; + +typedef enum +{ + R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15, + R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI, R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D, + R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI, R_R8W, R_R9W, R_R10W, R_R11W, R_R12W, R_R13W, R_R14W, R_R15W, + R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH, R_R8B, R_R9B, R_R10B, R_R11B, R_R12B, R_R13B, R_R14B, R_R15B, + R_SPL, R_BPL, R_SIL, R_DIL, + R_ES, R_CS, R_SS, R_DS, R_FS, R_GS, + R_RIP, + R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7, + R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7, + R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15, + R_YMM0, R_YMM1, R_YMM2, R_YMM3, R_YMM4, R_YMM5, R_YMM6, R_YMM7, R_YMM8, R_YMM9, R_YMM10, R_YMM11, R_YMM12, R_YMM13, R_YMM14, R_YMM15, + R_CR0, R_UNUSED0, R_CR2, R_CR3, R_CR4, R_UNUSED1, R_UNUSED2, R_UNUSED3, R_CR8, + R_DR0, R_DR1, R_DR2, R_DR3, R_UNUSED4, R_UNUSED5, R_DR6, R_DR7 +} _RegisterType; + +#endif /* MNEMONICS_H */ + +#ifndef DISTORM_LIGHT + +const unsigned char _MNEMONICS[] = + "\x09" "UNDEFINED\0" "\x03" "ADD\0" "\x04" "PUSH\0" "\x03" "POP\0" \ + "\x02" "OR\0" "\x03" "ADC\0" "\x03" "SBB\0" "\x03" "AND\0" "\x03" "DAA\0" \ + "\x03" "SUB\0" "\x03" "DAS\0" "\x03" "XOR\0" "\x03" "AAA\0" "\x03" "CMP\0" \ + "\x03" "AAS\0" "\x03" "INC\0" "\x03" "DEC\0" "\x05" "PUSHA\0" "\x04" "POPA\0" \ + "\x05" "BOUND\0" "\x04" "ARPL\0" "\x04" "IMUL\0" "\x03" "INS\0" "\x04" "OUTS\0" \ + "\x02" "JO\0" "\x03" "JNO\0" "\x02" "JB\0" "\x03" "JAE\0" "\x02" "JZ\0" \ + "\x03" "JNZ\0" "\x03" "JBE\0" "\x02" "JA\0" "\x02" "JS\0" "\x03" "JNS\0" \ + "\x02" "JP\0" "\x03" "JNP\0" "\x02" "JL\0" "\x03" "JGE\0" "\x03" "JLE\0" \ + "\x02" "JG\0" "\x04" "TEST\0" "\x04" "XCHG\0" "\x03" "MOV\0" "\x03" "LEA\0" \ + "\x03" "CBW\0" "\x04" "CWDE\0" "\x04" "CDQE\0" "\x03" "CWD\0" "\x03" "CDQ\0" \ + "\x03" "CQO\0" "\x08" "CALL FAR\0" "\x05" "PUSHF\0" "\x04" "POPF\0" \ + "\x04" "SAHF\0" "\x04" "LAHF\0" "\x04" "MOVS\0" "\x04" "CMPS\0" "\x04" "STOS\0" \ + "\x04" "LODS\0" "\x04" "SCAS\0" "\x03" "RET\0" "\x03" "LES\0" "\x03" "LDS\0" \ + "\x05" "ENTER\0" "\x05" "LEAVE\0" "\x04" "RETF\0" "\x04" "INT3\0" "\x03" "INT\0" \ + "\x04" "INTO\0" "\x04" "IRET\0" "\x03" "AAM\0" "\x03" "AAD\0" "\x04" "SALC\0" \ + "\x04" "XLAT\0" "\x06" "LOOPNZ\0" "\x05" "LOOPZ\0" "\x04" "LOOP\0" \ + "\x04" "JCXZ\0" "\x05" "JECXZ\0" "\x05" "JRCXZ\0" "\x02" "IN\0" "\x03" "OUT\0" \ + "\x04" "CALL\0" "\x03" "JMP\0" "\x07" "JMP FAR\0" "\x04" "INT1\0" "\x03" "HLT\0" \ + "\x03" "CMC\0" "\x03" "CLC\0" "\x03" "STC\0" "\x03" "CLI\0" "\x03" "STI\0" \ + "\x03" "CLD\0" "\x03" "STD\0" "\x03" "LAR\0" "\x03" "LSL\0" "\x07" "SYSCALL\0" \ + "\x04" "CLTS\0" "\x06" "SYSRET\0" "\x04" "INVD\0" "\x06" "WBINVD\0" \ + "\x03" "UD2\0" "\x05" "FEMMS\0" "\x03" "NOP\0" "\x05" "WRMSR\0" "\x05" "RDTSC\0" \ + "\x05" "RDMSR\0" "\x05" "RDPMC\0" "\x08" "SYSENTER\0" "\x07" "SYSEXIT\0" \ + "\x06" "GETSEC\0" "\x05" "CMOVO\0" "\x06" "CMOVNO\0" "\x05" "CMOVB\0" \ + "\x06" "CMOVAE\0" "\x05" "CMOVZ\0" "\x06" "CMOVNZ\0" "\x06" "CMOVBE\0" \ + "\x05" "CMOVA\0" "\x05" "CMOVS\0" "\x06" "CMOVNS\0" "\x05" "CMOVP\0" \ + "\x06" "CMOVNP\0" "\x05" "CMOVL\0" "\x06" "CMOVGE\0" "\x06" "CMOVLE\0" \ + "\x05" "CMOVG\0" "\x04" "SETO\0" "\x05" "SETNO\0" "\x04" "SETB\0" "\x05" "SETAE\0" \ + "\x04" "SETZ\0" "\x05" "SETNZ\0" "\x05" "SETBE\0" "\x04" "SETA\0" "\x04" "SETS\0" \ + "\x05" "SETNS\0" "\x04" "SETP\0" "\x05" "SETNP\0" "\x04" "SETL\0" "\x05" "SETGE\0" \ + "\x05" "SETLE\0" "\x04" "SETG\0" "\x05" "CPUID\0" "\x02" "BT\0" "\x04" "SHLD\0" \ + "\x03" "RSM\0" "\x03" "BTS\0" "\x04" "SHRD\0" "\x07" "CMPXCHG\0" "\x03" "LSS\0" \ + "\x03" "BTR\0" "\x03" "LFS\0" "\x03" "LGS\0" "\x05" "MOVZX\0" "\x03" "BTC\0" \ + "\x05" "MOVSX\0" "\x04" "XADD\0" "\x06" "MOVNTI\0" "\x05" "BSWAP\0" \ + "\x03" "ROL\0" "\x03" "ROR\0" "\x03" "RCL\0" "\x03" "RCR\0" "\x03" "SHL\0" \ + "\x03" "SHR\0" "\x03" "SAL\0" "\x03" "SAR\0" "\x06" "XABORT\0" "\x06" "XBEGIN\0" \ + "\x04" "FADD\0" "\x04" "FMUL\0" "\x04" "FCOM\0" "\x05" "FCOMP\0" "\x04" "FSUB\0" \ + "\x05" "FSUBR\0" "\x04" "FDIV\0" "\x05" "FDIVR\0" "\x03" "FLD\0" "\x03" "FST\0" \ + "\x04" "FSTP\0" "\x06" "FLDENV\0" "\x05" "FLDCW\0" "\x04" "FXCH\0" \ + "\x04" "FNOP\0" "\x04" "FCHS\0" "\x04" "FABS\0" "\x04" "FTST\0" "\x04" "FXAM\0" \ + "\x04" "FLD1\0" "\x06" "FLDL2T\0" "\x06" "FLDL2E\0" "\x05" "FLDPI\0" \ + "\x06" "FLDLG2\0" "\x06" "FLDLN2\0" "\x04" "FLDZ\0" "\x05" "F2XM1\0" \ + "\x05" "FYL2X\0" "\x05" "FPTAN\0" "\x06" "FPATAN\0" "\x07" "FXTRACT\0" \ + "\x06" "FPREM1\0" "\x07" "FDECSTP\0" "\x07" "FINCSTP\0" "\x05" "FPREM\0" \ + "\x07" "FYL2XP1\0" "\x05" "FSQRT\0" "\x07" "FSINCOS\0" "\x07" "FRNDINT\0" \ + "\x06" "FSCALE\0" "\x04" "FSIN\0" "\x04" "FCOS\0" "\x05" "FIADD\0" \ + "\x05" "FIMUL\0" "\x05" "FICOM\0" "\x06" "FICOMP\0" "\x05" "FISUB\0" \ + "\x06" "FISUBR\0" "\x05" "FIDIV\0" "\x06" "FIDIVR\0" "\x06" "FCMOVB\0" \ + "\x06" "FCMOVE\0" "\x07" "FCMOVBE\0" "\x06" "FCMOVU\0" "\x07" "FUCOMPP\0" \ + "\x04" "FILD\0" "\x06" "FISTTP\0" "\x04" "FIST\0" "\x05" "FISTP\0" \ + "\x07" "FCMOVNB\0" "\x07" "FCMOVNE\0" "\x08" "FCMOVNBE\0" "\x07" "FCMOVNU\0" \ + "\x04" "FENI\0" "\x06" "FEDISI\0" "\x06" "FSETPM\0" "\x06" "FUCOMI\0" \ + "\x05" "FCOMI\0" "\x06" "FRSTOR\0" "\x05" "FFREE\0" "\x05" "FUCOM\0" \ + "\x06" "FUCOMP\0" "\x05" "FADDP\0" "\x05" "FMULP\0" "\x06" "FCOMPP\0" \ + "\x06" "FSUBRP\0" "\x05" "FSUBP\0" "\x06" "FDIVRP\0" "\x05" "FDIVP\0" \ + "\x04" "FBLD\0" "\x05" "FBSTP\0" "\x07" "FUCOMIP\0" "\x06" "FCOMIP\0" \ + "\x03" "NOT\0" "\x03" "NEG\0" "\x03" "MUL\0" "\x03" "DIV\0" "\x04" "IDIV\0" \ + "\x04" "SLDT\0" "\x03" "STR\0" "\x04" "LLDT\0" "\x03" "LTR\0" "\x04" "VERR\0" \ + "\x04" "VERW\0" "\x04" "SGDT\0" "\x04" "SIDT\0" "\x04" "LGDT\0" "\x04" "LIDT\0" \ + "\x04" "SMSW\0" "\x04" "LMSW\0" "\x06" "INVLPG\0" "\x06" "VMCALL\0" \ + "\x08" "VMLAUNCH\0" "\x08" "VMRESUME\0" "\x06" "VMXOFF\0" "\x07" "MONITOR\0" \ + "\x05" "MWAIT\0" "\x04" "CLAC\0" "\x04" "STAC\0" "\x06" "XGETBV\0" \ + "\x06" "XSETBV\0" "\x06" "VMFUNC\0" "\x04" "XEND\0" "\x05" "VMRUN\0" \ + "\x07" "VMMCALL\0" "\x06" "VMLOAD\0" "\x06" "VMSAVE\0" "\x04" "STGI\0" \ + "\x04" "CLGI\0" "\x06" "SKINIT\0" "\x07" "INVLPGA\0" "\x06" "SWAPGS\0" \ + "\x06" "RDTSCP\0" "\x08" "PREFETCH\0" "\x09" "PREFETCHW\0" "\x05" "PI2FW\0" \ + "\x05" "PI2FD\0" "\x05" "PF2IW\0" "\x05" "PF2ID\0" "\x06" "PFNACC\0" \ + "\x07" "PFPNACC\0" "\x07" "PFCMPGE\0" "\x05" "PFMIN\0" "\x05" "PFRCP\0" \ + "\x07" "PFRSQRT\0" "\x05" "PFSUB\0" "\x05" "PFADD\0" "\x07" "PFCMPGT\0" \ + "\x05" "PFMAX\0" "\x08" "PFRCPIT1\0" "\x08" "PFRSQIT1\0" "\x06" "PFSUBR\0" \ + "\x05" "PFACC\0" "\x07" "PFCMPEQ\0" "\x05" "PFMUL\0" "\x08" "PFRCPIT2\0" \ + "\x07" "PMULHRW\0" "\x06" "PSWAPD\0" "\x07" "PAVGUSB\0" "\x06" "MOVUPS\0" \ + "\x06" "MOVUPD\0" "\x05" "MOVSS\0" "\x05" "MOVSD\0" "\x07" "VMOVUPS\0" \ + "\x07" "VMOVUPD\0" "\x06" "VMOVSS\0" "\x06" "VMOVSD\0" "\x07" "MOVHLPS\0" \ + "\x06" "MOVLPS\0" "\x06" "MOVLPD\0" "\x08" "MOVSLDUP\0" "\x07" "MOVDDUP\0" \ + "\x08" "VMOVHLPS\0" "\x07" "VMOVLPS\0" "\x07" "VMOVLPD\0" "\x09" "VMOVSLDUP\0" \ + "\x08" "VMOVDDUP\0" "\x08" "UNPCKLPS\0" "\x08" "UNPCKLPD\0" "\x09" "VUNPCKLPS\0" \ + "\x09" "VUNPCKLPD\0" "\x08" "UNPCKHPS\0" "\x08" "UNPCKHPD\0" "\x09" "VUNPCKHPS\0" \ + "\x09" "VUNPCKHPD\0" "\x07" "MOVLHPS\0" "\x06" "MOVHPS\0" "\x06" "MOVHPD\0" \ + "\x08" "MOVSHDUP\0" "\x08" "VMOVLHPS\0" "\x07" "VMOVHPS\0" "\x07" "VMOVHPD\0" \ + "\x09" "VMOVSHDUP\0" "\x0b" "PREFETCHNTA\0" "\x0a" "PREFETCHT0\0" "\x0a" "PREFETCHT1\0" \ + "\x0a" "PREFETCHT2\0" "\x06" "MOVAPS\0" "\x06" "MOVAPD\0" "\x07" "VMOVAPS\0" \ + "\x07" "VMOVAPD\0" "\x08" "CVTPI2PS\0" "\x08" "CVTPI2PD\0" "\x08" "CVTSI2SS\0" \ + "\x08" "CVTSI2SD\0" "\x09" "VCVTSI2SS\0" "\x09" "VCVTSI2SD\0" "\x07" "MOVNTPS\0" \ + "\x07" "MOVNTPD\0" "\x07" "MOVNTSS\0" "\x07" "MOVNTSD\0" "\x08" "VMOVNTPS\0" \ + "\x08" "VMOVNTPD\0" "\x09" "CVTTPS2PI\0" "\x09" "CVTTPD2PI\0" "\x09" "CVTTSS2SI\0" \ + "\x09" "CVTTSD2SI\0" "\x0a" "VCVTTSS2SI\0" "\x0a" "VCVTTSD2SI\0" "\x08" "CVTPS2PI\0" \ + "\x08" "CVTPD2PI\0" "\x08" "CVTSS2SI\0" "\x08" "CVTSD2SI\0" "\x09" "VCVTSS2SI\0" \ + "\x09" "VCVTSD2SI\0" "\x07" "UCOMISS\0" "\x07" "UCOMISD\0" "\x08" "VUCOMISS\0" \ + "\x08" "VUCOMISD\0" "\x06" "COMISS\0" "\x06" "COMISD\0" "\x07" "VCOMISS\0" \ + "\x07" "VCOMISD\0" "\x08" "MOVMSKPS\0" "\x08" "MOVMSKPD\0" "\x09" "VMOVMSKPS\0" \ + "\x09" "VMOVMSKPD\0" "\x06" "SQRTPS\0" "\x06" "SQRTPD\0" "\x06" "SQRTSS\0" \ + "\x06" "SQRTSD\0" "\x07" "VSQRTPS\0" "\x07" "VSQRTPD\0" "\x07" "VSQRTSS\0" \ + "\x07" "VSQRTSD\0" "\x07" "RSQRTPS\0" "\x07" "RSQRTSS\0" "\x08" "VRSQRTPS\0" \ + "\x08" "VRSQRTSS\0" "\x05" "RCPPS\0" "\x05" "RCPSS\0" "\x06" "VRCPPS\0" \ + "\x06" "VRCPSS\0" "\x05" "ANDPS\0" "\x05" "ANDPD\0" "\x06" "VANDPS\0" \ + "\x06" "VANDPD\0" "\x06" "ANDNPS\0" "\x06" "ANDNPD\0" "\x07" "VANDNPS\0" \ + "\x07" "VANDNPD\0" "\x04" "ORPS\0" "\x04" "ORPD\0" "\x05" "VORPS\0" \ + "\x05" "VORPD\0" "\x05" "XORPS\0" "\x05" "XORPD\0" "\x06" "VXORPS\0" \ + "\x06" "VXORPD\0" "\x05" "ADDPS\0" "\x05" "ADDPD\0" "\x05" "ADDSS\0" \ + "\x05" "ADDSD\0" "\x06" "VADDPS\0" "\x06" "VADDPD\0" "\x06" "VADDSS\0" \ + "\x06" "VADDSD\0" "\x05" "MULPS\0" "\x05" "MULPD\0" "\x05" "MULSS\0" \ + "\x05" "MULSD\0" "\x06" "VMULPS\0" "\x06" "VMULPD\0" "\x06" "VMULSS\0" \ + "\x06" "VMULSD\0" "\x08" "CVTPS2PD\0" "\x08" "CVTPD2PS\0" "\x08" "CVTSS2SD\0" \ + "\x08" "CVTSD2SS\0" "\x09" "VCVTPS2PD\0" "\x09" "VCVTPD2PS\0" "\x09" "VCVTSS2SD\0" \ + "\x09" "VCVTSD2SS\0" "\x08" "CVTDQ2PS\0" "\x08" "CVTPS2DQ\0" "\x09" "CVTTPS2DQ\0" \ + "\x09" "VCVTDQ2PS\0" "\x09" "VCVTPS2DQ\0" "\x0a" "VCVTTPS2DQ\0" "\x05" "SUBPS\0" \ + "\x05" "SUBPD\0" "\x05" "SUBSS\0" "\x05" "SUBSD\0" "\x06" "VSUBPS\0" \ + "\x06" "VSUBPD\0" "\x06" "VSUBSS\0" "\x06" "VSUBSD\0" "\x05" "MINPS\0" \ + "\x05" "MINPD\0" "\x05" "MINSS\0" "\x05" "MINSD\0" "\x06" "VMINPS\0" \ + "\x06" "VMINPD\0" "\x06" "VMINSS\0" "\x06" "VMINSD\0" "\x05" "DIVPS\0" \ + "\x05" "DIVPD\0" "\x05" "DIVSS\0" "\x05" "DIVSD\0" "\x06" "VDIVPS\0" \ + "\x06" "VDIVPD\0" "\x06" "VDIVSS\0" "\x06" "VDIVSD\0" "\x05" "MAXPS\0" \ + "\x05" "MAXPD\0" "\x05" "MAXSS\0" "\x05" "MAXSD\0" "\x06" "VMAXPS\0" \ + "\x06" "VMAXPD\0" "\x06" "VMAXSS\0" "\x06" "VMAXSD\0" "\x09" "PUNPCKLBW\0" \ + "\x0a" "VPUNPCKLBW\0" "\x09" "PUNPCKLWD\0" "\x0a" "VPUNPCKLWD\0" "\x09" "PUNPCKLDQ\0" \ + "\x0a" "VPUNPCKLDQ\0" "\x08" "PACKSSWB\0" "\x09" "VPACKSSWB\0" "\x07" "PCMPGTB\0" \ + "\x08" "VPCMPGTB\0" "\x07" "PCMPGTW\0" "\x08" "VPCMPGTW\0" "\x07" "PCMPGTD\0" \ + "\x08" "VPCMPGTD\0" "\x08" "PACKUSWB\0" "\x09" "VPACKUSWB\0" "\x09" "PUNPCKHBW\0" \ + "\x0a" "VPUNPCKHBW\0" "\x09" "PUNPCKHWD\0" "\x0a" "VPUNPCKHWD\0" "\x09" "PUNPCKHDQ\0" \ + "\x0a" "VPUNPCKHDQ\0" "\x08" "PACKSSDW\0" "\x09" "VPACKSSDW\0" "\x0a" "PUNPCKLQDQ\0" \ + "\x0b" "VPUNPCKLQDQ\0" "\x0a" "PUNPCKHQDQ\0" "\x0b" "VPUNPCKHQDQ\0" "\x04" "MOVD\0" \ + "\x04" "MOVQ\0" "\x05" "VMOVD\0" "\x05" "VMOVQ\0" "\x06" "MOVDQA\0" \ + "\x06" "MOVDQU\0" "\x07" "VMOVDQA\0" "\x07" "VMOVDQU\0" "\x06" "PSHUFW\0" \ + "\x06" "PSHUFD\0" "\x07" "PSHUFHW\0" "\x07" "PSHUFLW\0" "\x07" "VPSHUFD\0" \ + "\x08" "VPSHUFHW\0" "\x08" "VPSHUFLW\0" "\x07" "PCMPEQB\0" "\x08" "VPCMPEQB\0" \ + "\x07" "PCMPEQW\0" "\x08" "VPCMPEQW\0" "\x07" "PCMPEQD\0" "\x08" "VPCMPEQD\0" \ + "\x04" "EMMS\0" "\x0a" "VZEROUPPER\0" "\x08" "VZEROALL\0" "\x06" "VMREAD\0" \ + "\x05" "EXTRQ\0" "\x07" "INSERTQ\0" "\x07" "VMWRITE\0" "\x08" "CVTPH2PS\0" \ + "\x08" "CVTPS2PH\0" "\x06" "HADDPD\0" "\x06" "HADDPS\0" "\x07" "VHADDPD\0" \ + "\x07" "VHADDPS\0" "\x06" "HSUBPD\0" "\x06" "HSUBPS\0" "\x07" "VHSUBPD\0" \ + "\x07" "VHSUBPS\0" "\x05" "XSAVE\0" "\x07" "XSAVE64\0" "\x06" "LFENCE\0" \ + "\x06" "XRSTOR\0" "\x08" "XRSTOR64\0" "\x06" "MFENCE\0" "\x08" "XSAVEOPT\0" \ + "\x0a" "XSAVEOPT64\0" "\x06" "SFENCE\0" "\x07" "CLFLUSH\0" "\x06" "POPCNT\0" \ + "\x03" "BSF\0" "\x05" "TZCNT\0" "\x03" "BSR\0" "\x05" "LZCNT\0" "\x07" "CMPEQPS\0" \ + "\x07" "CMPLTPS\0" "\x07" "CMPLEPS\0" "\x0a" "CMPUNORDPS\0" "\x08" "CMPNEQPS\0" \ + "\x08" "CMPNLTPS\0" "\x08" "CMPNLEPS\0" "\x08" "CMPORDPS\0" "\x07" "CMPEQPD\0" \ + "\x07" "CMPLTPD\0" "\x07" "CMPLEPD\0" "\x0a" "CMPUNORDPD\0" "\x08" "CMPNEQPD\0" \ + "\x08" "CMPNLTPD\0" "\x08" "CMPNLEPD\0" "\x08" "CMPORDPD\0" "\x07" "CMPEQSS\0" \ + "\x07" "CMPLTSS\0" "\x07" "CMPLESS\0" "\x0a" "CMPUNORDSS\0" "\x08" "CMPNEQSS\0" \ + "\x08" "CMPNLTSS\0" "\x08" "CMPNLESS\0" "\x08" "CMPORDSS\0" "\x07" "CMPEQSD\0" \ + "\x07" "CMPLTSD\0" "\x07" "CMPLESD\0" "\x0a" "CMPUNORDSD\0" "\x08" "CMPNEQSD\0" \ + "\x08" "CMPNLTSD\0" "\x08" "CMPNLESD\0" "\x08" "CMPORDSD\0" "\x08" "VCMPEQPS\0" \ + "\x08" "VCMPLTPS\0" "\x08" "VCMPLEPS\0" "\x0b" "VCMPUNORDPS\0" "\x09" "VCMPNEQPS\0" \ + "\x09" "VCMPNLTPS\0" "\x09" "VCMPNLEPS\0" "\x09" "VCMPORDPS\0" "\x0b" "VCMPEQ_UQPS\0" \ + "\x09" "VCMPNGEPS\0" "\x09" "VCMPNGTPS\0" "\x0b" "VCMPFALSEPS\0" "\x0c" "VCMPNEQ_OQPS\0" \ + "\x08" "VCMPGEPS\0" "\x08" "VCMPGTPS\0" "\x0a" "VCMPTRUEPS\0" "\x0b" "VCMPEQ_OSPS\0" \ + "\x0b" "VCMPLT_OQPS\0" "\x0b" "VCMPLE_OQPS\0" "\x0d" "VCMPUNORD_SPS\0" \ + "\x0c" "VCMPNEQ_USPS\0" "\x0c" "VCMPNLT_UQPS\0" "\x0c" "VCMPNLE_UQPS\0" \ + "\x0b" "VCMPORD_SPS\0" "\x0b" "VCMPEQ_USPS\0" "\x0c" "VCMPNGE_UQPS\0" \ + "\x0c" "VCMPNGT_UQPS\0" "\x0e" "VCMPFALSE_OSPS\0" "\x0c" "VCMPNEQ_OSPS\0" \ + "\x0b" "VCMPGE_OQPS\0" "\x0b" "VCMPGT_OQPS\0" "\x0d" "VCMPTRUE_USPS\0" \ + "\x08" "VCMPEQPD\0" "\x08" "VCMPLTPD\0" "\x08" "VCMPLEPD\0" "\x0b" "VCMPUNORDPD\0" \ + "\x09" "VCMPNEQPD\0" "\x09" "VCMPNLTPD\0" "\x09" "VCMPNLEPD\0" "\x09" "VCMPORDPD\0" \ + "\x0b" "VCMPEQ_UQPD\0" "\x09" "VCMPNGEPD\0" "\x09" "VCMPNGTPD\0" "\x0b" "VCMPFALSEPD\0" \ + "\x0c" "VCMPNEQ_OQPD\0" "\x08" "VCMPGEPD\0" "\x08" "VCMPGTPD\0" "\x0a" "VCMPTRUEPD\0" \ + "\x0b" "VCMPEQ_OSPD\0" "\x0b" "VCMPLT_OQPD\0" "\x0b" "VCMPLE_OQPD\0" \ + "\x0d" "VCMPUNORD_SPD\0" "\x0c" "VCMPNEQ_USPD\0" "\x0c" "VCMPNLT_UQPD\0" \ + "\x0c" "VCMPNLE_UQPD\0" "\x0b" "VCMPORD_SPD\0" "\x0b" "VCMPEQ_USPD\0" \ + "\x0c" "VCMPNGE_UQPD\0" "\x0c" "VCMPNGT_UQPD\0" "\x0e" "VCMPFALSE_OSPD\0" \ + "\x0c" "VCMPNEQ_OSPD\0" "\x0b" "VCMPGE_OQPD\0" "\x0b" "VCMPGT_OQPD\0" \ + "\x0d" "VCMPTRUE_USPD\0" "\x08" "VCMPEQSS\0" "\x08" "VCMPLTSS\0" "\x08" "VCMPLESS\0" \ + "\x0b" "VCMPUNORDSS\0" "\x09" "VCMPNEQSS\0" "\x09" "VCMPNLTSS\0" "\x09" "VCMPNLESS\0" \ + "\x09" "VCMPORDSS\0" "\x0b" "VCMPEQ_UQSS\0" "\x09" "VCMPNGESS\0" "\x09" "VCMPNGTSS\0" \ + "\x0b" "VCMPFALSESS\0" "\x0c" "VCMPNEQ_OQSS\0" "\x08" "VCMPGESS\0" "\x08" "VCMPGTSS\0" \ + "\x0a" "VCMPTRUESS\0" "\x0b" "VCMPEQ_OSSS\0" "\x0b" "VCMPLT_OQSS\0" "\x0b" "VCMPLE_OQSS\0" \ + "\x0d" "VCMPUNORD_SSS\0" "\x0c" "VCMPNEQ_USSS\0" "\x0c" "VCMPNLT_UQSS\0" \ + "\x0c" "VCMPNLE_UQSS\0" "\x0b" "VCMPORD_SSS\0" "\x0b" "VCMPEQ_USSS\0" \ + "\x0c" "VCMPNGE_UQSS\0" "\x0c" "VCMPNGT_UQSS\0" "\x0e" "VCMPFALSE_OSSS\0" \ + "\x0c" "VCMPNEQ_OSSS\0" "\x0b" "VCMPGE_OQSS\0" "\x0b" "VCMPGT_OQSS\0" \ + "\x0d" "VCMPTRUE_USSS\0" "\x08" "VCMPEQSD\0" "\x08" "VCMPLTSD\0" "\x08" "VCMPLESD\0" \ + "\x0b" "VCMPUNORDSD\0" "\x09" "VCMPNEQSD\0" "\x09" "VCMPNLTSD\0" "\x09" "VCMPNLESD\0" \ + "\x09" "VCMPORDSD\0" "\x0b" "VCMPEQ_UQSD\0" "\x09" "VCMPNGESD\0" "\x09" "VCMPNGTSD\0" \ + "\x0b" "VCMPFALSESD\0" "\x0c" "VCMPNEQ_OQSD\0" "\x08" "VCMPGESD\0" "\x08" "VCMPGTSD\0" \ + "\x0a" "VCMPTRUESD\0" "\x0b" "VCMPEQ_OSSD\0" "\x0b" "VCMPLT_OQSD\0" "\x0b" "VCMPLE_OQSD\0" \ + "\x0d" "VCMPUNORD_SSD\0" "\x0c" "VCMPNEQ_USSD\0" "\x0c" "VCMPNLT_UQSD\0" \ + "\x0c" "VCMPNLE_UQSD\0" "\x0b" "VCMPORD_SSD\0" "\x0b" "VCMPEQ_USSD\0" \ + "\x0c" "VCMPNGE_UQSD\0" "\x0c" "VCMPNGT_UQSD\0" "\x0e" "VCMPFALSE_OSSD\0" \ + "\x0c" "VCMPNEQ_OSSD\0" "\x0b" "VCMPGE_OQSD\0" "\x0b" "VCMPGT_OQSD\0" \ + "\x0d" "VCMPTRUE_USSD\0" "\x06" "PINSRW\0" "\x07" "VPINSRW\0" "\x06" "PEXTRW\0" \ + "\x07" "VPEXTRW\0" "\x06" "SHUFPS\0" "\x06" "SHUFPD\0" "\x07" "VSHUFPS\0" \ + "\x07" "VSHUFPD\0" "\x09" "CMPXCHG8B\0" "\x0a" "CMPXCHG16B\0" "\x07" "VMPTRST\0" \ + "\x08" "ADDSUBPD\0" "\x08" "ADDSUBPS\0" "\x09" "VADDSUBPD\0" "\x09" "VADDSUBPS\0" \ + "\x05" "PSRLW\0" "\x06" "VPSRLW\0" "\x05" "PSRLD\0" "\x06" "VPSRLD\0" \ + "\x05" "PSRLQ\0" "\x06" "VPSRLQ\0" "\x05" "PADDQ\0" "\x06" "VPADDQ\0" \ + "\x06" "PMULLW\0" "\x07" "VPMULLW\0" "\x07" "MOVQ2DQ\0" "\x07" "MOVDQ2Q\0" \ + "\x08" "PMOVMSKB\0" "\x09" "VPMOVMSKB\0" "\x07" "PSUBUSB\0" "\x08" "VPSUBUSB\0" \ + "\x07" "PSUBUSW\0" "\x08" "VPSUBUSW\0" "\x06" "PMINUB\0" "\x07" "VPMINUB\0" \ + "\x04" "PAND\0" "\x05" "VPAND\0" "\x07" "PADDUSB\0" "\x08" "VPADDUSW\0" \ + "\x07" "PADDUSW\0" "\x06" "PMAXUB\0" "\x07" "VPMAXUB\0" "\x05" "PANDN\0" \ + "\x06" "VPANDN\0" "\x05" "PAVGB\0" "\x06" "VPAVGB\0" "\x05" "PSRAW\0" \ + "\x06" "VPSRAW\0" "\x05" "PSRAD\0" "\x06" "VPSRAD\0" "\x05" "PAVGW\0" \ + "\x06" "VPAVGW\0" "\x07" "PMULHUW\0" "\x08" "VPMULHUW\0" "\x06" "PMULHW\0" \ + "\x07" "VPMULHW\0" "\x09" "CVTTPD2DQ\0" "\x08" "CVTDQ2PD\0" "\x08" "CVTPD2DQ\0" \ + "\x0a" "VCVTTPD2DQ\0" "\x09" "VCVTDQ2PD\0" "\x09" "VCVTPD2DQ\0" "\x06" "MOVNTQ\0" \ + "\x07" "MOVNTDQ\0" "\x08" "VMOVNTDQ\0" "\x06" "PSUBSB\0" "\x07" "VPSUBSB\0" \ + "\x06" "PSUBSW\0" "\x07" "VPSUBSW\0" "\x06" "PMINSW\0" "\x07" "VPMINSW\0" \ + "\x03" "POR\0" "\x04" "VPOR\0" "\x06" "PADDSB\0" "\x07" "VPADDSB\0" \ + "\x06" "PADDSW\0" "\x07" "VPADDSW\0" "\x06" "PMAXSW\0" "\x07" "VPMAXSW\0" \ + "\x04" "PXOR\0" "\x05" "VPXOR\0" "\x05" "LDDQU\0" "\x06" "VLDDQU\0" \ + "\x05" "PSLLW\0" "\x06" "VPSLLW\0" "\x05" "PSLLD\0" "\x06" "VPSLLD\0" \ + "\x05" "PSLLQ\0" "\x06" "VPSLLQ\0" "\x07" "PMULUDQ\0" "\x08" "VPMULUDQ\0" \ + "\x07" "PMADDWD\0" "\x08" "VPMADDWD\0" "\x06" "PSADBW\0" "\x07" "VPSADBW\0" \ + "\x08" "MASKMOVQ\0" "\x0a" "MASKMOVDQU\0" "\x0b" "VMASKMOVDQU\0" "\x05" "PSUBB\0" \ + "\x06" "VPSUBB\0" "\x05" "PSUBW\0" "\x06" "VPSUBW\0" "\x05" "PSUBD\0" \ + "\x06" "VPSUBD\0" "\x05" "PSUBQ\0" "\x06" "VPSUBQ\0" "\x05" "PADDB\0" \ + "\x06" "VPADDB\0" "\x05" "PADDW\0" "\x06" "VPADDW\0" "\x05" "PADDD\0" \ + "\x06" "VPADDD\0" "\x07" "FNSTENV\0" "\x06" "FSTENV\0" "\x06" "FNSTCW\0" \ + "\x05" "FSTCW\0" "\x06" "FNCLEX\0" "\x05" "FCLEX\0" "\x06" "FNINIT\0" \ + "\x05" "FINIT\0" "\x06" "FNSAVE\0" "\x05" "FSAVE\0" "\x06" "FNSTSW\0" \ + "\x05" "FSTSW\0" "\x06" "PSHUFB\0" "\x07" "VPSHUFB\0" "\x06" "PHADDW\0" \ + "\x07" "VPHADDW\0" "\x06" "PHADDD\0" "\x07" "VPHADDD\0" "\x07" "PHADDSW\0" \ + "\x08" "VPHADDSW\0" "\x09" "PMADDUBSW\0" "\x0a" "VPMADDUBSW\0" "\x06" "PHSUBW\0" \ + "\x07" "VPHSUBW\0" "\x06" "PHSUBD\0" "\x07" "VPHSUBD\0" "\x07" "PHSUBSW\0" \ + "\x08" "VPHSUBSW\0" "\x06" "PSIGNB\0" "\x07" "VPSIGNB\0" "\x06" "PSIGNW\0" \ + "\x07" "VPSIGNW\0" "\x06" "PSIGND\0" "\x07" "VPSIGND\0" "\x08" "PMULHRSW\0" \ + "\x09" "VPMULHRSW\0" "\x09" "VPERMILPS\0" "\x09" "VPERMILPD\0" "\x07" "VTESTPS\0" \ + "\x07" "VTESTPD\0" "\x08" "PBLENDVB\0" "\x08" "BLENDVPS\0" "\x08" "BLENDVPD\0" \ + "\x05" "PTEST\0" "\x06" "VPTEST\0" "\x0c" "VBROADCASTSS\0" "\x0c" "VBROADCASTSD\0" \ + "\x0e" "VBROADCASTF128\0" "\x05" "PABSB\0" "\x06" "VPABSB\0" "\x05" "PABSW\0" \ + "\x06" "VPABSW\0" "\x05" "PABSD\0" "\x06" "VPABSD\0" "\x08" "PMOVSXBW\0" \ + "\x09" "VPMOVSXBW\0" "\x08" "PMOVSXBD\0" "\x09" "VPMOVSXBD\0" "\x08" "PMOVSXBQ\0" \ + "\x09" "VPMOVSXBQ\0" "\x08" "PMOVSXWD\0" "\x09" "VPMOVSXWD\0" "\x08" "PMOVSXWQ\0" \ + "\x09" "VPMOVSXWQ\0" "\x08" "PMOVSXDQ\0" "\x09" "VPMOVSXDQ\0" "\x06" "PMULDQ\0" \ + "\x07" "VPMULDQ\0" "\x07" "PCMPEQQ\0" "\x08" "VPCMPEQQ\0" "\x08" "MOVNTDQA\0" \ + "\x09" "VMOVNTDQA\0" "\x08" "PACKUSDW\0" "\x09" "VPACKUSDW\0" "\x0a" "VMASKMOVPS\0" \ + "\x0a" "VMASKMOVPD\0" "\x08" "PMOVZXBW\0" "\x09" "VPMOVZXBW\0" "\x08" "PMOVZXBD\0" \ + "\x09" "VPMOVZXBD\0" "\x08" "PMOVZXBQ\0" "\x09" "VPMOVZXBQ\0" "\x08" "PMOVZXWD\0" \ + "\x09" "VPMOVZXWD\0" "\x08" "PMOVZXWQ\0" "\x09" "VPMOVZXWQ\0" "\x08" "PMOVZXDQ\0" \ + "\x09" "VPMOVZXDQ\0" "\x07" "PCMPGTQ\0" "\x08" "VPCMPGTQ\0" "\x06" "PMINSB\0" \ + "\x07" "VPMINSB\0" "\x06" "PMINSD\0" "\x07" "VPMINSD\0" "\x06" "PMINUW\0" \ + "\x07" "VPMINUW\0" "\x06" "PMINUD\0" "\x07" "VPMINUD\0" "\x06" "PMAXSB\0" \ + "\x07" "VPMAXSB\0" "\x06" "PMAXSD\0" "\x07" "VPMAXSD\0" "\x06" "PMAXUW\0" \ + "\x07" "VPMAXUW\0" "\x06" "PMAXUD\0" "\x07" "VPMAXUD\0" "\x06" "PMULLD\0" \ + "\x07" "VPMULLD\0" "\x0a" "PHMINPOSUW\0" "\x0b" "VPHMINPOSUW\0" "\x06" "INVEPT\0" \ + "\x07" "INVVPID\0" "\x07" "INVPCID\0" "\x0e" "VFMADDSUB132PS\0" "\x0e" "VFMADDSUB132PD\0" \ + "\x0e" "VFMSUBADD132PS\0" "\x0e" "VFMSUBADD132PD\0" "\x0b" "VFMADD132PS\0" \ + "\x0b" "VFMADD132PD\0" "\x0b" "VFMADD132SS\0" "\x0b" "VFMADD132SD\0" \ + "\x0b" "VFMSUB132PS\0" "\x0b" "VFMSUB132PD\0" "\x0b" "VFMSUB132SS\0" \ + "\x0b" "VFMSUB132SD\0" "\x0c" "VFNMADD132PS\0" "\x0c" "VFNMADD132PD\0" \ + "\x0c" "VFNMADD132SS\0" "\x0c" "VFNMADD132SD\0" "\x0c" "VFNMSUB132PS\0" \ + "\x0c" "VFNMSUB132PD\0" "\x0c" "VFNMSUB132SS\0" "\x0c" "VFNMSUB132SD\0" \ + "\x0e" "VFMADDSUB213PS\0" "\x0e" "VFMADDSUB213PD\0" "\x0e" "VFMSUBADD213PS\0" \ + "\x0e" "VFMSUBADD213PD\0" "\x0b" "VFMADD213PS\0" "\x0b" "VFMADD213PD\0" \ + "\x0b" "VFMADD213SS\0" "\x0b" "VFMADD213SD\0" "\x0b" "VFMSUB213PS\0" \ + "\x0b" "VFMSUB213PD\0" "\x0b" "VFMSUB213SS\0" "\x0b" "VFMSUB213SD\0" \ + "\x0c" "VFNMADD213PS\0" "\x0c" "VFNMADD213PD\0" "\x0c" "VFNMADD213SS\0" \ + "\x0c" "VFNMADD213SD\0" "\x0c" "VFNMSUB213PS\0" "\x0c" "VFNMSUB213PD\0" \ + "\x0c" "VFNMSUB213SS\0" "\x0c" "VFNMSUB213SD\0" "\x0e" "VFMADDSUB231PS\0" \ + "\x0e" "VFMADDSUB231PD\0" "\x0e" "VFMSUBADD231PS\0" "\x0e" "VFMSUBADD231PD\0" \ + "\x0b" "VFMADD231PS\0" "\x0b" "VFMADD231PD\0" "\x0b" "VFMADD231SS\0" \ + "\x0b" "VFMADD231SD\0" "\x0b" "VFMSUB231PS\0" "\x0b" "VFMSUB231PD\0" \ + "\x0b" "VFMSUB231SS\0" "\x0b" "VFMSUB231SD\0" "\x0c" "VFNMADD231PS\0" \ + "\x0c" "VFNMADD231PD\0" "\x0c" "VFNMADD231SS\0" "\x0c" "VFNMADD231SD\0" \ + "\x0c" "VFNMSUB231PS\0" "\x0c" "VFNMSUB231PD\0" "\x0c" "VFNMSUB231SS\0" \ + "\x0c" "VFNMSUB231SD\0" "\x06" "AESIMC\0" "\x07" "VAESIMC\0" "\x06" "AESENC\0" \ + "\x07" "VAESENC\0" "\x0a" "AESENCLAST\0" "\x0b" "VAESENCLAST\0" "\x06" "AESDEC\0" \ + "\x07" "VAESDEC\0" "\x0a" "AESDECLAST\0" "\x0b" "VAESDECLAST\0" "\x05" "MOVBE\0" \ + "\x05" "CRC32\0" "\x0a" "VPERM2F128\0" "\x07" "ROUNDPS\0" "\x08" "VROUNDPS\0" \ + "\x07" "ROUNDPD\0" "\x08" "VROUNDPD\0" "\x07" "ROUNDSS\0" "\x08" "VROUNDSS\0" \ + "\x07" "ROUNDSD\0" "\x08" "VROUNDSD\0" "\x07" "BLENDPS\0" "\x08" "VBLENDPS\0" \ + "\x07" "BLENDPD\0" "\x08" "VBLENDPD\0" "\x07" "PBLENDW\0" "\x08" "VPBLENDW\0" \ + "\x07" "PALIGNR\0" "\x08" "VPALIGNR\0" "\x06" "PEXTRB\0" "\x07" "VPEXTRB\0" \ + "\x06" "PEXTRD\0" "\x06" "PEXTRQ\0" "\x07" "VPEXTRD\0" "\x07" "VPEXTRQ\0" \ + "\x09" "EXTRACTPS\0" "\x0a" "VEXTRACTPS\0" "\x0b" "VINSERTF128\0" "\x0c" "VEXTRACTF128\0" \ + "\x06" "PINSRB\0" "\x07" "VPINSRB\0" "\x08" "INSERTPS\0" "\x09" "VINSERTPS\0" \ + "\x06" "PINSRD\0" "\x06" "PINSRQ\0" "\x07" "VPINSRD\0" "\x07" "VPINSRQ\0" \ + "\x04" "DPPS\0" "\x05" "VDPPS\0" "\x04" "DPPD\0" "\x05" "VDPPD\0" "\x07" "MPSADBW\0" \ + "\x08" "VMPSADBW\0" "\x09" "PCLMULQDQ\0" "\x0a" "VPCLMULQDQ\0" "\x09" "VBLENDVPS\0" \ + "\x09" "VBLENDVPD\0" "\x09" "VPBLENDVB\0" "\x09" "PCMPESTRM\0" "\x0a" "VPCMPESTRM\0" \ + "\x09" "PCMPESTRI\0" "\x0a" "VPCMPESTRI\0" "\x09" "PCMPISTRM\0" "\x0a" "VPCMPISTRM\0" \ + "\x09" "PCMPISTRI\0" "\x0a" "VPCMPISTRI\0" "\x0f" "AESKEYGENASSIST\0" \ + "\x10" "VAESKEYGENASSIST\0" "\x06" "PSRLDQ\0" "\x07" "VPSRLDQ\0" "\x06" "PSLLDQ\0" \ + "\x07" "VPSLLDQ\0" "\x06" "FXSAVE\0" "\x08" "FXSAVE64\0" "\x08" "RDFSBASE\0" \ + "\x07" "FXRSTOR\0" "\x09" "FXRSTOR64\0" "\x08" "RDGSBASE\0" "\x07" "LDMXCSR\0" \ + "\x08" "WRFSBASE\0" "\x08" "VLDMXCSR\0" "\x07" "STMXCSR\0" "\x08" "WRGSBASE\0" \ + "\x08" "VSTMXCSR\0" "\x07" "VMPTRLD\0" "\x07" "VMCLEAR\0" "\x05" "VMXON\0" \ + "\x06" "MOVSXD\0" "\x05" "PAUSE\0" "\x04" "WAIT\0" "\x06" "RDRAND\0" \ + "\x06" "_3DNOW\0" \ + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; /* Sentinel mnemonic. */ + +const _WRegister _REGISTERS[] = +{ + {3, "RAX"}, {3, "RCX"}, {3, "RDX"}, {3, "RBX"}, {3, "RSP"}, {3, "RBP"}, {3, "RSI"}, {3, "RDI"}, {2, "R8"}, {2, "R9"}, {3, "R10"}, {3, "R11"}, {3, "R12"}, {3, "R13"}, {3, "R14"}, {3, "R15"}, + {3, "EAX"}, {3, "ECX"}, {3, "EDX"}, {3, "EBX"}, {3, "ESP"}, {3, "EBP"}, {3, "ESI"}, {3, "EDI"}, {3, "R8D"}, {3, "R9D"}, {4, "R10D"}, {4, "R11D"}, {4, "R12D"}, {4, "R13D"}, {4, "R14D"}, {4, "R15D"}, + {2, "AX"}, {2, "CX"}, {2, "DX"}, {2, "BX"}, {2, "SP"}, {2, "BP"}, {2, "SI"}, {2, "DI"}, {3, "R8W"}, {3, "R9W"}, {4, "R10W"}, {4, "R11W"}, {4, "R12W"}, {4, "R13W"}, {4, "R14W"}, {4, "R15W"}, + {2, "AL"}, {2, "CL"}, {2, "DL"}, {2, "BL"}, {2, "AH"}, {2, "CH"}, {2, "DH"}, {2, "BH"}, {3, "R8B"}, {3, "R9B"}, {4, "R10B"}, {4, "R11B"}, {4, "R12B"}, {4, "R13B"}, {4, "R14B"}, {4, "R15B"}, + {3, "SPL"}, {3, "BPL"}, {3, "SIL"}, {3, "DIL"}, + {2, "ES"}, {2, "CS"}, {2, "SS"}, {2, "DS"}, {2, "FS"}, {2, "GS"}, + {3, "RIP"}, + {3, "ST0"}, {3, "ST1"}, {3, "ST2"}, {3, "ST3"}, {3, "ST4"}, {3, "ST5"}, {3, "ST6"}, {3, "ST7"}, + {3, "MM0"}, {3, "MM1"}, {3, "MM2"}, {3, "MM3"}, {3, "MM4"}, {3, "MM5"}, {3, "MM6"}, {3, "MM7"}, + {4, "XMM0"}, {4, "XMM1"}, {4, "XMM2"}, {4, "XMM3"}, {4, "XMM4"}, {4, "XMM5"}, {4, "XMM6"}, {4, "XMM7"}, {4, "XMM8"}, {4, "XMM9"}, {5, "XMM10"}, {5, "XMM11"}, {5, "XMM12"}, {5, "XMM13"}, {5, "XMM14"}, {5, "XMM15"}, + {4, "YMM0"}, {4, "YMM1"}, {4, "YMM2"}, {4, "YMM3"}, {4, "YMM4"}, {4, "YMM5"}, {4, "YMM6"}, {4, "YMM7"}, {4, "YMM8"}, {4, "YMM9"}, {5, "YMM10"}, {5, "YMM11"}, {5, "YMM12"}, {5, "YMM13"}, {5, "YMM14"}, {5, "YMM15"}, + {3, "CR0"}, {0, ""}, {3, "CR2"}, {3, "CR3"}, {3, "CR4"}, {0, ""}, {0, ""}, {0, ""}, {3, "CR8"}, + {3, "DR0"}, {3, "DR1"}, {3, "DR2"}, {3, "DR3"}, {0, ""}, {0, ""}, {3, "DR6"}, {3, "DR7"}, + {0, ""} /* There must be an empty last reg, see strcat_WSR. */ +}; + +#endif /* DISTORM_LIGHT */ +/* +textdefs.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +/* +textdefs.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef TEXTDEFS_H +#define TEXTDEFS_H + +/* +config.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef CONFIG_H +#define CONFIG_H + +/* diStorm version number. */ +#define __DISTORMV__ 0x030503 + +#include /* memset, memcpy - can be easily self implemented for libc independency. */ + +/* diStorm 3.5.3 */ + +/* +distorm.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef DISTORM_H +#define DISTORM_H + +/* + * 64 bit offsets support: + * If the diStorm library you use was compiled with 64 bits offsets, + * make sure you compile your own code with the following macro set: + * SUPPORT_64BIT_OFFSET + * Otherwise comment it out, or you will get a linker error of an unresolved symbol... + * Turned on by default! + */ + +#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC)) +/* Define this macro for outer projects by default. */ +#define SUPPORT_64BIT_OFFSET +#endif + +/* TINYC has a problem with some 64bits library functions, so ignore 64 bit offsets. */ +#ifdef __TINYC__ +#undef SUPPORT_64BIT_OFFSET +#endif + +#ifndef _MSC_VER +#include +#else +/* Since MSVC < 2010 isn't shipped with stdint.h, + * here are those from MSVC 2017, which also match + * those in tinycc/libc. */ +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +#endif + +#ifdef SUPPORT_64BIT_OFFSET +#define OFFSET_INTEGER uint64_t +#else +/* 32 bit offsets are used. */ +#define OFFSET_INTEGER uint32_t +#endif + +/* Support C++ compilers */ +#ifdef __cplusplus +extern "C" { +#endif + + +/* *** Helper Macros *** */ + +/* Get the ISC of the instruction, used with the definitions below. */ +#define META_GET_ISC(meta) (((meta) >> 8) & 0x1f) +#define META_SET_ISC(di, isc) (((di)->meta) |= ((isc) << 8)) +/* Get the flow control flags of the instruction, see 'features for decompose' below. */ +#define META_GET_FC(meta) ((meta) & 0xf) + +/* Get the target address of a branching instruction. O_PC operand type. */ +#define INSTRUCTION_GET_TARGET(di) ((_OffsetType)(((di)->addr + (di)->imm.addr + (di)->size))) +/* Get the target address of a RIP-relative memory indirection. */ +#define INSTRUCTION_GET_RIP_TARGET(di) ((_OffsetType)(((di)->addr + (di)->disp + (di)->size))) + +/* + * Operand Size or Adderss size are stored inside the flags: + * 00 - 16 bits + * 01 - 32 bits + * 10 - 64 bits + * 11 - reserved + * + * If you call these set-macros more than once, you will have to clean the bits before doing so. + */ +#define FLAG_SET_OPSIZE(di, size) ((di->flags) |= (((size) & 3) << 8)) +#define FLAG_SET_ADDRSIZE(di, size) ((di->flags) |= (((size) & 3) << 10)) +#define FLAG_GET_OPSIZE(flags) (((flags) >> 8) & 3) +#define FLAG_GET_ADDRSIZE(flags) (((flags) >> 10) & 3) +/* To get the LOCK/REPNZ/REP prefixes. */ +#define FLAG_GET_PREFIX(flags) (((unsigned int)((int16_t)flags)) & 7) +/* Indicates whether the instruction is privileged. */ +#define FLAG_GET_PRIVILEGED(flags) (((flags) & FLAG_PRIVILEGED_INSTRUCTION) != 0) + +/* + * Macros to extract segment registers from 'segment': + */ +#define SEGMENT_DEFAULT 0x80 +#define SEGMENT_GET(segment) (((segment) == R_NONE) ? R_NONE : ((segment) & 0x7f)) +#define SEGMENT_GET_UNSAFE(segment) ((segment) & 0x7f) +#define SEGMENT_IS_DEFAULT(segment) (((int8_t)segment) < -1) /* Quick check it's a negative number that isn't -1, so it's (0x80 | SEGREG). */ +#define SEGMENT_IS_DEFAULT_OR_NONE(segment) (((uint8_t)(segment)) > 0x80) + +/* Decodes modes of the disassembler, 16 bits or 32 bits or 64 bits for AMD64, x86-64. */ +typedef enum { Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2 } _DecodeType; + +typedef OFFSET_INTEGER _OffsetType; + +typedef struct +{ + _OffsetType codeOffset, addrMask; + _OffsetType nextOffset; /* nextOffset is OUT only. */ + const uint8_t* code; + int codeLen; /* Using signed integer makes it easier to detect an underflow. */ + _DecodeType dt; + unsigned int features; +} _CodeInfo; + +typedef enum { O_NONE, O_REG, O_IMM, O_IMM1, O_IMM2, O_DISP, O_SMEM, O_MEM, O_PC, O_PTR } _OperandType; + +typedef union +{ + /* Used by O_IMM: */ + int8_t sbyte; + uint8_t byte; + int16_t sword; + uint16_t word; + int32_t sdword; + uint32_t dword; + int64_t sqword; /* All immediates are SIGN-EXTENDED to 64 bits! */ + uint64_t qword; + + /* Used by O_PC: (Use GET_TARGET_ADDR).*/ + _OffsetType addr; /* It's a relative offset as for now. */ + + /* Used by O_PTR: */ + struct + { + uint16_t seg; + /* Can be 16 or 32 bits, size is in ops[n].size. */ + uint32_t off; + } ptr; + + /* Used by O_IMM1 (i1) and O_IMM2 (i2). ENTER instruction only. */ + struct + { + uint32_t i1; + uint32_t i2; + } ex; +} _Value; + +typedef struct +{ + /* Type of operand: + O_NONE: operand is to be ignored. + O_REG: index holds global register index. + O_IMM: instruction.imm. + O_IMM1: instruction.imm.ex.i1. + O_IMM2: instruction.imm.ex.i2. + O_DISP: memory dereference with displacement only, instruction.disp. + O_SMEM: simple memory dereference with optional displacement (a single register memory dereference). + O_MEM: complex memory dereference (optional fields: s/i/b/disp). + O_PC: the relative address of a branch instruction (instruction.imm.addr). + O_PTR: the absolute target address of a far branch instruction (instruction.imm.ptr.seg/off). + */ + uint8_t type; /* _OperandType */ + + /* Index of: + O_REG: holds global register index + O_SMEM: holds the 'base' register. E.G: [ECX], [EBX+0x1234] are both in operand.index. + O_MEM: holds the 'index' register. E.G: [EAX*4] is in operand.index. + */ + uint8_t index; + + /* Size in bits of: + O_REG: register + O_IMM: instruction.imm + O_IMM1: instruction.imm.ex.i1 + O_IMM2: instruction.imm.ex.i2 + O_DISP: instruction.disp + O_SMEM: size of indirection. + O_MEM: size of indirection. + O_PC: size of the relative offset + O_PTR: size of instruction.imm.ptr.off (16 or 32) + */ + uint16_t size; +} _Operand; + +#define OPCODE_ID_NONE 0 +/* Instruction could not be disassembled. */ +#define FLAG_NOT_DECODABLE ((uint16_t)-1) +/* The instruction locks memory access. */ +#define FLAG_LOCK (1 << 0) +/* The instruction is prefixed with a REPNZ. */ +#define FLAG_REPNZ (1 << 1) +/* The instruction is prefixed with a REP, this can be a REPZ, it depends on the specific instruction. */ +#define FLAG_REP (1 << 2) +/* Indicates there is a hint taken for Jcc instructions only. */ +#define FLAG_HINT_TAKEN (1 << 3) +/* Indicates there is a hint non-taken for Jcc instructions only. */ +#define FLAG_HINT_NOT_TAKEN (1 << 4) +/* The Imm value is signed extended (E.G in 64 bit decoding mode, a 32 bit imm is usually sign extended into 64 bit imm). */ +#define FLAG_IMM_SIGNED (1 << 5) +/* The destination operand is writable. */ +#define FLAG_DST_WR (1 << 6) +/* The instruction uses RIP-relative indirection. */ +#define FLAG_RIP_RELATIVE (1 << 7) + +/* See flag FLAG_GET_XXX macros above. */ + +/* The instruction is privileged and can only be used from Ring0. */ +#define FLAG_PRIVILEGED_INSTRUCTION (1 << 15) + +/* No register was defined. */ +#define R_NONE ((uint8_t)-1) + +#define REGS64_BASE 0 +#define REGS32_BASE 16 +#define REGS16_BASE 32 +#define REGS8_BASE 48 +#define REGS8_REX_BASE 64 +#define SREGS_BASE 68 +#define FPUREGS_BASE 75 +#define MMXREGS_BASE 83 +#define SSEREGS_BASE 91 +#define AVXREGS_BASE 107 +#define CREGS_BASE 123 +#define DREGS_BASE 132 + +#define OPERANDS_NO (4) + +typedef struct +{ + /* Used by ops[n].type == O_IMM/O_IMM1&O_IMM2/O_PTR/O_PC. Its size is ops[n].size. */ + _Value imm; + /* Used by ops[n].type == O_SMEM/O_MEM/O_DISP. Its size is dispSize. */ + uint64_t disp; + /* Virtual address of first byte of instruction. */ + _OffsetType addr; + /* General flags of instruction, holds prefixes and more, if FLAG_NOT_DECODABLE, instruction is invalid. */ + uint16_t flags; + /* Unused prefixes mask, for each bit that is set that prefix is not used (LSB is byte [addr + 0]). */ + uint16_t unusedPrefixesMask; + /* Mask of registers that were used in the operands, only used for quick look up, in order to know *some* operand uses that register class. */ + uint32_t usedRegistersMask; + /* ID of opcode in the global opcode table. Use for mnemonic look up. */ + uint16_t opcode; + /* Up to four operands per instruction, ignored if ops[n].type == O_NONE. */ + _Operand ops[OPERANDS_NO]; + /* Number of valid ops entries. */ + uint8_t opsNo; + /* Size of the whole instruction in bytes. */ + uint8_t size; + /* Segment information of memory indirection, default segment, or overriden one, can be -1. Use SEGMENT macros. */ + uint8_t segment; + /* Used by ops[n].type == O_MEM. Base global register index (might be R_NONE), scale size (2/4/8), ignored for 0 or 1. */ + uint8_t base, scale; + uint8_t dispSize; + /* Meta defines the instruction set class, and the flow control flags. Use META macros. */ + uint16_t meta; + /* The CPU flags that the instruction operates upon, set only with DF_FILL_EFLAGS enabled, otherwise 0. */ + uint16_t modifiedFlagsMask, testedFlagsMask, undefinedFlagsMask; +} _DInst; + +#ifndef DISTORM_LIGHT + +/* Static size of strings. Do not change this value. Keep Python wrapper in sync. */ +#define MAX_TEXT_SIZE (48) +typedef struct +{ + unsigned int length; + unsigned char p[MAX_TEXT_SIZE]; /* p is a null terminated string. */ +} _WString; + +/* + * Old decoded instruction structure in text format. + * Used only for backward compatibility with diStorm64. + * This structure holds all information the disassembler generates per instruction. + */ +typedef struct +{ + _OffsetType offset; /* Start offset of the decoded instruction. */ + unsigned int size; /* Size of decoded instruction in bytes. */ + _WString mnemonic; /* Mnemonic of decoded instruction, prefixed if required by REP, LOCK etc. */ + _WString operands; /* Operands of the decoded instruction, up to 3 operands, comma-seperated. */ + _WString instructionHex; /* Hex dump - little endian, including prefixes. */ +} _DecodedInst; + +#endif /* DISTORM_LIGHT */ + +/* Register masks for quick look up, each mask indicates one of a register-class that is being used in some operand. */ +#define RM_AX 1 /* AL, AH, AX, EAX, RAX */ +#define RM_CX 2 /* CL, CH, CX, ECX, RCX */ +#define RM_DX 4 /* DL, DH, DX, EDX, RDX */ +#define RM_BX 8 /* BL, BH, BX, EBX, RBX */ +#define RM_SP 0x10 /* SPL, SP, ESP, RSP */ +#define RM_BP 0x20 /* BPL, BP, EBP, RBP */ +#define RM_SI 0x40 /* SIL, SI, ESI, RSI */ +#define RM_DI 0x80 /* DIL, DI, EDI, RDI */ +#define RM_FPU 0x100 /* ST(0) - ST(7) */ +#define RM_MMX 0x200 /* MM0 - MM7 */ +#define RM_SSE 0x400 /* XMM0 - XMM15 */ +#define RM_AVX 0x800 /* YMM0 - YMM15 */ +#define RM_CR 0x1000 /* CR0, CR2, CR3, CR4, CR8 */ +#define RM_DR 0x2000 /* DR0, DR1, DR2, DR3, DR6, DR7 */ +#define RM_R8 0x4000 /* R8B, R8W, R8D, R8 */ +#define RM_R9 0x8000 /* R9B, R9W, R9D, R9 */ +#define RM_R10 0x10000 /* R10B, R10W, R10D, R10 */ +#define RM_R11 0x20000 /* R11B, R11W, R11D, R11 */ +#define RM_R12 0x40000 /* R12B, R12W, R12D, R12 */ +#define RM_R13 0x80000 /* R13B, R13W, R13D, R13 */ +#define RM_R14 0x100000 /* R14B, R14W, R14D, R14 */ +#define RM_R15 0x200000 /* R15B, R15W, R15D, R15 */ +#define RM_SEG 0x400000 /* CS, SS, DS, ES, FS, GS */ + +/* RIP should be checked using the 'flags' field and FLAG_RIP_RELATIVE. + * Segments should be checked using the segment macros. + * For now R8 - R15 are not supported and non general purpose registers map into same RM. + */ + +/* CPU flags that instructions modify, test or undefine (are EFLAGS compatible!). */ +#define D_CF 1 /* Carry */ +#define D_PF 4 /* Parity */ +#define D_AF 0x10 /* Auxiliary */ +#define D_ZF 0x40 /* Zero */ +#define D_SF 0x80 /* Sign */ +#define D_IF 0x200 /* Interrupt */ +#define D_DF 0x400 /* Direction */ +#define D_OF 0x800 /* Overflow */ + +/* + * Instructions Set classes: + * if you want a better understanding of the available classes, look at disOps project, file: x86sets.py. + */ +/* Indicates the instruction belongs to the General Integer set. */ +#define ISC_INTEGER 1 +/* Indicates the instruction belongs to the 387 FPU set. */ +#define ISC_FPU 2 +/* Indicates the instruction belongs to the P6 set. */ +#define ISC_P6 3 +/* Indicates the instruction belongs to the MMX set. */ +#define ISC_MMX 4 +/* Indicates the instruction belongs to the SSE set. */ +#define ISC_SSE 5 +/* Indicates the instruction belongs to the SSE2 set. */ +#define ISC_SSE2 6 +/* Indicates the instruction belongs to the SSE3 set. */ +#define ISC_SSE3 7 +/* Indicates the instruction belongs to the SSSE3 set. */ +#define ISC_SSSE3 8 +/* Indicates the instruction belongs to the SSE4.1 set. */ +#define ISC_SSE4_1 9 +/* Indicates the instruction belongs to the SSE4.2 set. */ +#define ISC_SSE4_2 10 +/* Indicates the instruction belongs to the AMD's SSE4.A set. */ +#define ISC_SSE4_A 11 +/* Indicates the instruction belongs to the 3DNow! set. */ +#define ISC_3DNOW 12 +/* Indicates the instruction belongs to the 3DNow! Extensions set. */ +#define ISC_3DNOWEXT 13 +/* Indicates the instruction belongs to the VMX (Intel) set. */ +#define ISC_VMX 14 +/* Indicates the instruction belongs to the SVM (AMD) set. */ +#define ISC_SVM 15 +/* Indicates the instruction belongs to the AVX (Intel) set. */ +#define ISC_AVX 16 +/* Indicates the instruction belongs to the FMA (Intel) set. */ +#define ISC_FMA 17 +/* Indicates the instruction belongs to the AES/AVX (Intel) set. */ +#define ISC_AES 18 +/* Indicates the instruction belongs to the CLMUL (Intel) set. */ +#define ISC_CLMUL 19 + +/* Features for decompose: */ +#define DF_NONE 0 +/* The decoder will limit addresses to a maximum of 16 bits. */ +#define DF_MAXIMUM_ADDR16 1 +/* The decoder will limit addresses to a maximum of 32 bits. */ +#define DF_MAXIMUM_ADDR32 2 +/* The decoder will return only flow control instructions (and filter the others internally). */ +#define DF_RETURN_FC_ONLY 4 +/* The decoder will stop and return to the caller when the instruction 'CALL' (near and far) was decoded. */ +#define DF_STOP_ON_CALL 8 +/* The decoder will stop and return to the caller when the instruction 'RET' (near and far) was decoded. */ +#define DF_STOP_ON_RET 0x10 +/* The decoder will stop and return to the caller when the instruction system-call/ret was decoded. */ +#define DF_STOP_ON_SYS 0x20 +/* The decoder will stop and return to the caller when any of the branch 'JMP', (near and far) instructions were decoded. */ +#define DF_STOP_ON_UNC_BRANCH 0x40 +/* The decoder will stop and return to the caller when any of the conditional branch instruction were decoded. */ +#define DF_STOP_ON_CND_BRANCH 0x80 +/* The decoder will stop and return to the caller when the instruction 'INT' (INT, INT1, INTO, INT 3) was decoded. */ +#define DF_STOP_ON_INT 0x100 +/* The decoder will stop and return to the caller when any of the 'CMOVxx' instruction was decoded. */ +#define DF_STOP_ON_CMOV 0x200 +/* The decoder will stop and return to the caller when it encounters the HLT instruction. */ +#define DF_STOP_ON_HLT 0x400 +/* The decoder will stop and return to the caller when it encounters a privileged instruction. */ +#define DF_STOP_ON_PRIVILEGED 0x800 +/* The decoder will stop and return to the caller when an instruction couldn't be decoded. */ +#define DF_STOP_ON_UNDECODEABLE 0x1000 +/* The decoder will not synchronize to the next byte after the previosuly decoded instruction, instead it will start decoding at the next byte. */ +#define DF_SINGLE_BYTE_STEP 0x2000 +/* The decoder will fill in the eflags fields for the decoded instruction. */ +#define DF_FILL_EFLAGS 0x4000 +/* The decoder will use the addrMask in CodeInfo structure instead of DF_MAXIMUM_ADDR16/32. */ +#define DF_USE_ADDR_MASK 0x8000 + +/* The decoder will stop and return to the caller when any flow control instruction was decoded. */ +#define DF_STOP_ON_FLOW_CONTROL (DF_STOP_ON_CALL | DF_STOP_ON_RET | DF_STOP_ON_SYS | DF_STOP_ON_UNC_BRANCH | DF_STOP_ON_CND_BRANCH | DF_STOP_ON_INT | DF_STOP_ON_CMOV | DF_STOP_ON_HLT) + +/* Indicates the instruction is not a flow-control instruction. */ +#define FC_NONE 0 +/* Indicates the instruction is one of: CALL, CALL FAR. */ +#define FC_CALL 1 +/* Indicates the instruction is one of: RET, IRET, RETF. */ +#define FC_RET 2 +/* Indicates the instruction is one of: SYSCALL, SYSRET, SYSENTER, SYSEXIT. */ +#define FC_SYS 3 +/* Indicates the instruction is one of: JMP, JMP FAR. */ +#define FC_UNC_BRANCH 4 +/* + * Indicates the instruction is one of: + * JCXZ, JO, JNO, JB, JAE, JZ, JNZ, JBE, JA, JS, JNS, JP, JNP, JL, JGE, JLE, JG, LOOP, LOOPZ, LOOPNZ. + */ +#define FC_CND_BRANCH 5 +/* Indiciates the instruction is one of: INT, INT1, INT 3, INTO, UD2. */ +#define FC_INT 6 +/* Indicates the instruction is one of: CMOVxx. */ +#define FC_CMOV 7 +/* Indicates the instruction is HLT. */ +#define FC_HLT 8 + +/* Return code of the decoding function. */ +typedef enum { DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR } _DecodeResult; + +/* Define the following interface functions only for outer projects. */ +#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC)) + +/* distorm_decode + * Input: + * offset - Origin of the given code (virtual address that is), NOT an offset in code. + * code - Pointer to the code buffer to be disassembled. + * length - Amount of bytes that should be decoded from the code buffer. + * dt - Decoding mode, 16 bits (Decode16Bits), 32 bits (Decode32Bits) or AMD64 (Decode64Bits). + * result - Array of type _DecodeInst which will be used by this function in order to return the disassembled instructions. + * maxInstructions - The maximum number of entries in the result array that you pass to this function, so it won't exceed its bound. + * usedInstructionsCount - Number of the instruction that successfully were disassembled and written to the result array. + * Output: usedInstructionsCount will hold the number of entries used in the result array + * and the result array itself will be filled with the disassembled instructions. + * Return: DECRES_SUCCESS on success (no more to disassemble), DECRES_INPUTERR on input error (null code buffer, invalid decoding mode, etc...), + * DECRES_MEMORYERR when there are not enough entries to use in the result array, BUT YOU STILL have to check for usedInstructionsCount! + * Side-Effects: Even if the return code is DECRES_MEMORYERR, there might STILL be data in the + * array you passed, this function will try to use as much entries as possible! + * Notes: 1)The minimal size of maxInstructions is 15. + * 2)You will have to synchronize the offset,code and length by yourself if you pass code fragments and not a complete code block! + */ + +/* distorm_decompose + * See more documentation online at the GitHub project's wiki. + * + */ +#ifdef SUPPORT_64BIT_OFFSET + +_DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); +#define distorm_decompose distorm_decompose64 + +#ifndef DISTORM_LIGHT +/* If distorm-light is defined, we won't export these text-formatting functionality. */ +_DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); +void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result); +#define distorm_decode distorm_decode64 +#define distorm_format distorm_format64 +#endif /*DISTORM_LIGHT*/ + +#else /*SUPPORT_64BIT_OFFSET*/ + +_DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); +#define distorm_decompose distorm_decompose32 + +#ifndef DISTORM_LIGHT +/* If distorm-light is defined, we won't export these text-formatting functionality. */ +_DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); +void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result); +#define distorm_decode distorm_decode32 +#define distorm_format distorm_format32 +#endif /*DISTORM_LIGHT*/ + +#endif + +/* + * distorm_version + * Input: + * none + * + * Output: unsigned int - version of compiled library. + */ +unsigned int distorm_version(void); + +#endif /* DISTORM_STATIC */ + +#ifdef __cplusplus +} /* End Of Extern */ +#endif + +#endif /* DISTORM_H */ + + +/* + * 64 bit offsets support: + * This macro should be defined from compiler command line flags, e.g: -DSUPPORT_64BIT_OFFSET + * Note: make sure that the caller (library user) defines it too! + */ +/* #define SUPPORT_64BIT_OFFSET */ + +/* + * If you compile diStorm as a dynamic library (.dll or .so) file, make sure you uncomment the next line. + * So the interface functions will be exported, otherwise they are useable only for static library. + * For example, this macro is being set for compiling diStorm as a .dll for Python with CTypes. + */ +/* #define DISTORM_DYNAMIC */ + +/* + * If DISTORM_LIGHT is defined, everything involved in formatting the instructions + * as text will be excluded from compilation. + * distorm_decode(..) and distorm_format(..) will not be available. + * This will decrease the size of the executable and leave you with decomposition functionality only. + * + * Note: it should be either set in the preprocessor definitions manually or in command line -D switch. + * #define DISTORM_LIGHT + */ + +/* + * diStorm now supports little/big endian CPU's. + * It should detect the endianness according to predefined macro's of the compiler. + * If you don't use GCC/MSVC you will have to define it on your own. + */ + +/* These macros are used in order to make the code portable. */ +#ifdef __GNUC__ + +#include + +#define _DLLEXPORT_ +#define _FASTCALL_ +/* Keep inline as static (arrrrg) as it would break linux on some flavors otherwise. */ +#define _INLINE_ static +/* GCC ignores this directive... */ +/*#define _FASTCALL_ __attribute__((__fastcall__))*/ + +/* Set endianity (supposed to be LE though): */ +#ifdef __BIG_ENDIAN__ +#define BE_SYSTEM +#endif + +/* End of __GCC__ */ + +#elif __WATCOMC__ + +#include + +#define _DLLEXPORT_ +#define _FASTCALL_ +#define _INLINE_ __inline + +/* End of __WATCOMC__ */ + +#elif __DMC__ + +#include + +#define _DLLEXPORT_ +#define _FASTCALL_ +#define _INLINE_ __inline + +/* End of __DMC__ */ + +#elif __TINYC__ + +#include + +#define _DLLEXPORT_ +#define _FASTCALL_ +#define _INLINE_ static + +/* End of __TINYC__ */ + +#elif _MSC_VER + +/* stdint alternative is defined in distorm.h */ + +#define _DLLEXPORT_ __declspec(dllexport) +#define _FASTCALL_ __fastcall +#define _INLINE_ __inline + +/* Set endianity (supposed to be LE though): */ +#if !defined(_M_IX86) && !defined(_M_X64) +#define BE_SYSTEM +#endif + +#endif /* #elif _MSC_VER */ + +/* If the library isn't compiled as a dynamic library don't export any functions. */ +#ifndef DISTORM_DYNAMIC +#undef _DLLEXPORT_ +#define _DLLEXPORT_ +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +/* Define stream read functions for big endian systems. */ +#ifdef BE_SYSTEM + +/* Avoid defining 'static static' for GCC. */ +#ifndef __GNUC__ +#define STATIC_INLINE static _INLINE_ +#else +#define STATIC_INLINE static +#endif + +/* + * Assumption: These functions can read from the stream safely! + * Swap endianity of input to little endian. + */ +STATIC_INLINE int16_t RSHORT(const uint8_t* s) +{ + return s[0] | (s[1] << 8); +} +STATIC_INLINE uint16_t RUSHORT(const uint8_t* s) +{ + return s[0] | (s[1] << 8); +} +STATIC_INLINE int32_t RLONG(const uint8_t* s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); +} +STATIC_INLINE uint32_t RULONG(const uint8_t* s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); +} +STATIC_INLINE int64_t RLLONG(const uint8_t* s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56); +} +STATIC_INLINE uint64_t RULLONG(const uint8_t* s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56); +} + +#undef STATIC_INLINE + +#else +/* Little endian macro's will just make the cast. */ +#define RSHORT(x) *(int16_t *)x +#define RUSHORT(x) *(uint16_t *)x +#define RLONG(x) *(int32_t *)x +#define RULONG(x) *(uint32_t *)x +#define RLLONG(x) *(int64_t *)x +#define RULLONG(x) *(uint64_t *)x +#endif + +#endif /* CONFIG_H */ +/* +wstring.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef WSTRING_H +#define WSTRING_H + + +#ifndef DISTORM_LIGHT + +_INLINE_ void strcat_WSR(unsigned char** str, const _WRegister* reg) +{ + /* + * Longest register name is YMM15 - 5 characters, + * Copy 8 so compiler can do a QWORD move. + * We copy nul termination and fix the length, so it's okay to copy more to the output buffer. + * There's a sentinel register to make sure we don't read past the end of the registers table. + */ + memcpy((int8_t*)*str, (const int8_t*)reg->p, 8); + *str += reg->length; +} + +#define strfinalize_WS(s, end) do { *end = 0; s.length = (unsigned int)((size_t)end - (size_t)s.p); } while (0) +#define chrcat_WS(s, ch) do { *s = ch; s += 1; } while (0) +#define strcat_WS(s, buf, copylen, advancelen) do { memcpy((int8_t*)s, buf, copylen); s += advancelen; } while(0) + +#endif /* DISTORM_LIGHT */ + +#endif /* WSTRING_H */ + +#ifndef DISTORM_LIGHT + +#define PLUS_DISP_CHR '+' +#define MINUS_DISP_CHR '-' +#define OPEN_CHR '[' +#define CLOSE_CHR ']' +#define SP_CHR ' ' +#define SEG_OFF_CHR ':' + +/* +Naming Convention: + +* get - returns a pointer to a string. +* str - concatenates to string. + +* hex - means the function is used for hex dump (number is padded to required size) - Little Endian output. +* code - means the function is used for disassembled instruction - Big Endian output. +* off - means the function is used for 64bit offset - Big Endian output. + +* h - '0x' in front of the string. + +* b - byte +* dw - double word (can be used for word also) +* qw - quad word + +* all numbers are in HEX. +*/ + +void str_hex(_WString* s, const uint8_t* buf, unsigned int len); + +#ifdef SUPPORT_64BIT_OFFSET +#define str_int(s, x) str_int_impl((s), (x)) +void str_int_impl(unsigned char** s, uint64_t x); +#else +#define str_int(s, x) str_int_impl((s), (uint8_t*)&(x)) +void str_int_impl(unsigned char** s, uint8_t src[8]); +#endif + +#endif /* DISTORM_LIGHT */ + +#endif /* TEXTDEFS_H */ + +#ifndef DISTORM_LIGHT + +static uint8_t Nibble2ChrTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; +#define NIBBLE_TO_CHR Nibble2ChrTable[t] + +void str_hex(_WString* s, const uint8_t* buf, unsigned int len) +{ + /* 256 * 2 : 2 chars per byte value. */ + static const char* TextBTable = + "000102030405060708090a0b0c0d0e0f" \ + "101112131415161718191a1b1c1d1e1f" \ + "202122232425262728292a2b2c2d2e2f" \ + "303132333435363738393a3b3c3d3e3f" \ + "404142434445464748494a4b4c4d4e4f" \ + "505152535455565758595a5b5c5d5e5f" \ + "606162636465666768696a6b6c6d6e6f" \ + "707172737475767778797a7b7c7d7e7f" \ + "808182838485868788898a8b8c8d8e8f" \ + "909192939495969798999a9b9c9d9e9f" \ + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" \ + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" \ + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" \ + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" \ + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" \ + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; + + unsigned int i = 0; + /* Length is at least 1, enter loop. */ + s->length = len * 2; + s->p[len * 2] = 0; + do + { + RSHORT(&s->p[i]) = RSHORT(&TextBTable[(*buf) * 2]); + buf++; + i += 2; + } + while(i < len * 2); +} + +#ifdef SUPPORT_64BIT_OFFSET + +void str_int_impl(unsigned char** s, uint64_t x) +{ + int8_t* buf; + int shift = 0; + OFFSET_INTEGER t = x; + + buf = (int8_t*)*s; + + *buf++ = '0'; + *buf++ = 'x'; + + if(x == 0) + { + *buf = '0'; + *s += 3; + return; + } + + do + { + t >>= 4; + shift += 4; + } + while(t); + + do + { + shift -= 4; + t = (x >> shift) & 0xf; + *buf++ = NIBBLE_TO_CHR; + } + while(shift > 0); + + *s = (unsigned char*)buf; +} + +#else + +void str_int_impl(unsigned char** s, uint8_t src[8]) +{ + int8_t* buf; + int i = 0, shift = 0; + uint32_t x = RULONG(&src[sizeof(int32_t)]); + int t; + + buf = (int8_t*)*s; + buf[0] = '0'; + buf[1] = 'x'; + buf += 2; + + for(shift = 28; shift != -4; shift -= 4) + { + t = (x >> shift) & 0xf; + if(i | t) buf[i++] = NIBBLE_TO_CHR; + } + + x = RULONG(src); + for(shift = 28; shift != 0; shift -= 4) + { + t = (x >> shift) & 0xf; + if(i | t) buf[i++] = NIBBLE_TO_CHR; + } + t = x & 0xf; + buf[i++] = NIBBLE_TO_CHR; + + *s += (size_t)(i + 2); +} + +#endif /* SUPPORT_64BIT_OFFSET */ + +#endif /* DISTORM_LIGHT */ +/* +prefix.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +/* +prefix.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef PREFIX_H +#define PREFIX_H + +/* +decoder.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef DECODER_H +#define DECODER_H + + +typedef unsigned int _iflags; + +_DecodeResult decode_internal(_CodeInfo* _ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount); + +#endif /* DECODER_H */ + + +/* Specifies the type of the extension prefix, such as: REX, 2 bytes VEX, 3 bytes VEX. */ +typedef enum {PET_NONE = 0, PET_REX, PET_VEX2BYTES, PET_VEX3BYTES} _PrefixExtType; + +/* Specifies an index into a table of prefixes by their type. */ +typedef enum {PFXIDX_NONE = -1, PFXIDX_REX, PFXIDX_LOREP, PFXIDX_SEG, PFXIDX_OP_SIZE, PFXIDX_ADRS, PFXIDX_MAX} _PrefixIndexer; + +/* +* This holds the prefixes state for the current instruction we decode. +* decodedPrefixes includes all specific prefixes that the instruction got. +* start is a pointer to the first prefix to take into account. +* last is a pointer to the last byte we scanned. +* Other pointers are used to keep track of prefixes positions and help us know if they appeared already and where. +*/ +typedef struct +{ + _iflags decodedPrefixes, usedPrefixes; + /* Number of prefixes scanned for current instruction, including VEX! */ + unsigned int count; + uint16_t unusedPrefixesMask; + /* Holds the offset to the prefix byte by its type. */ + uint16_t pfxIndexer[PFXIDX_MAX]; + _PrefixExtType prefixExtType; + /* Indicates whether the operand size prefix (0x66) was used as a mandatory prefix. */ + int isOpSizeMandatory; + /* If VEX prefix is used, store the VEX.vvvv field. */ + unsigned int vexV; + /* The fields B/X/R/W/L of REX and VEX are stored together in this byte. */ + unsigned int vrex; + const uint8_t* vexPos; +} _PrefixState; + +/* +* Intel supports 6 types of prefixes, whereas AMD supports 5 types (lock is seperated from rep/nz). +* REX is the fifth prefix type, this time I'm based on AMD64. +* VEX is the 6th, though it can't be repeated. +*/ +#define MAX_PREFIXES (5) + +extern int PrefixTables[256 * 2]; + +_INLINE_ int prefixes_is_valid(unsigned char ch, _DecodeType dt) +{ + /* The predicate selects (branchlessly) second half table for 64 bits otherwise selects first half. */ + return PrefixTables[ch + ((dt >> 1) << 8)]; +} + +/* Ignore a specific prefix type. */ +_INLINE_ void prefixes_ignore(_PrefixState* ps, _PrefixIndexer pi) +{ + /* + * If that type of prefix appeared already, set the bit of that *former* prefix. + * Anyway, set the new index of that prefix type to the current index, so next time we know its position. + */ + ps->unusedPrefixesMask |= ps->pfxIndexer[pi]; +} + +void prefixes_ignore_all(_PrefixState* ps); +uint16_t prefixes_set_unused_mask(_PrefixState* ps); +void prefixes_decode(_CodeInfo* ci, _PrefixState* ps); +void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di); + +#endif /* PREFIX_H */ + +/* +x86defs.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef X86DEFS_H +#define X86DEFS_H + + +#define SEG_REGS_MAX (6) +#define CREGS_MAX (9) +#define DREGS_MAX (8) + +/* Maximum instruction size, including prefixes */ +#define INST_MAXIMUM_SIZE (15) + +/* Maximum range of imm8 (comparison type) of special SSE CMP instructions. */ +#define INST_CMP_MAX_RANGE (8) + +/* Maximum range of imm8 (comparison type) of special AVX VCMP instructions. */ +#define INST_VCMP_MAX_RANGE (32) + +/* Wait instruction byte code. */ +#define INST_WAIT_INDEX (0x9b) + +/* Lea instruction byte code. */ +#define INST_LEA_INDEX (0x8d) + +/* NOP/XCHG instruction byte code. */ +#define INST_NOP_INDEX (0x90) + +/* ARPL/MOVSXD instruction byte code. */ +#define INST_ARPL_INDEX (0x63) + +/* + * Minimal MODR/M value of divided instructions. + * It's 0xc0, two MSBs set, which indicates a general purpose register is used too. + */ +#define INST_DIVIDED_MODRM (0xc0) + +/* This is the escape byte value used for 3DNow! instructions. */ +#define _3DNOW_ESCAPE_BYTE (0x0f) + +#define PREFIX_LOCK (0xf0) +#define PREFIX_REPNZ (0xf2) +#define PREFIX_REP (0xf3) +#define PREFIX_CS (0x2e) +#define PREFIX_SS (0x36) +#define PREFIX_DS (0x3e) +#define PREFIX_ES (0x26) +#define PREFIX_FS (0x64) +#define PREFIX_GS (0x65) +#define PREFIX_OP_SIZE (0x66) +#define PREFIX_ADDR_SIZE (0x67) +#define PREFIX_VEX2b (0xc5) +#define PREFIX_VEX3b (0xc4) + +/* REX prefix value range, 64 bits mode decoding only. */ +#define PREFIX_REX_LOW (0x40) +#define PREFIX_REX_HI (0x4f) +/* In order to use the extended GPR's we have to add 8 to the Modr/M info values. */ +#define EX_GPR_BASE (8) + +/* Mask for REX and VEX features: */ +/* Base */ +#define PREFIX_EX_B (1) +/* Index */ +#define PREFIX_EX_X (2) +/* Register */ +#define PREFIX_EX_R (4) +/* Operand Width */ +#define PREFIX_EX_W (8) +/* Vector Lengh */ +#define PREFIX_EX_L (0x10) + +#endif /* X86DEFS_H */ +/* +instructions.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef INSTRUCTIONS_H +#define INSTRUCTIONS_H + + + +/* + * Operand type possibilities: + * Note "_FULL" suffix indicates to decode the operand as 16 bits or 32 bits depends on DecodeType - + * actually, it depends on the decoding mode, unless there's an operand/address size prefix. + * For example, the code: 33 c0 could be decoded/executed as XOR AX, AX or XOR EAX, EAX. + */ + +typedef enum OpType +{ + /* No operand is set */ + OT_NONE = 0, + + /* Read a byte(8 bits) immediate */ + OT_IMM8, + /* Force a read of a word(16 bits) immediate, used by ret only */ + OT_IMM16, + /* Read a word/dword immediate */ + OT_IMM_FULL, + /* Read a double-word(32 bits) immediate */ + OT_IMM32, + + /* Read a signed extended byte(8 bits) immediate */ + OT_SEIMM8, + + /* Use a 8bit register */ + OT_REG8, + /* Use a 16bit register */ + OT_REG16, + /* Use a 16/32/64bit register */ + OT_REG_FULL, + /* Use a 32bit register */ + OT_REG32, + /* + * If used with REX the reg operand size becomes 64 bits, otherwise 32 bits. + * VMX instructions are promoted automatically without a REX prefix. + */ + OT_REG32_64, + + /* Use AL */ + OT_ACC8, + /* Use AX (FSTSW) */ + OT_ACC16, + /* Use AX/EAX/RAX */ + OT_ACC_FULL, + /* Use AX/EAX, no REX is possible for RAX, used only with IN/OUT which don't support 64 bit registers */ + OT_ACC_FULL_NOT64, + + /* Read a byte(8 bits) immediate and calculate it relatively to the current offset of the instruction being decoded */ + OT_RELCB, + /* Read a word/dword immediate and calculate it relatively to the current offset of the instruction being decoded */ + OT_RELC_FULL, + + /* + * Instruction-Block for one byte long instructions, used by INC/DEC/PUSH/POP/XCHG, + * REG is extracted from the value of opcode + * Use a 8bit register + */ + OT_IB_RB, + /* Use a 16/32/64bit register */ + OT_IB_R_FULL, + + /* Read an immediate as an absolute address, size is known by instruction, used by MOV (memory offset) only */ + OT_MOFFS8, + OT_MOFFS_FULL, + /* Use [(r)SI] as INDIRECTION, for repeatable instructions */ + OT_REGI_ESI, + /* Use [(r)DI] as INDIRECTION, for repeatable instructions */ + OT_REGI_EDI, + /* Use [(r)BX + AL] as INDIRECTIOM, used by XLAT only */ + OT_REGI_EBXAL, + /* Use [(r)AX] as INDIRECTION, used by AMD's SVM instructions */ + OT_REGI_EAX, + /* Use DX, as for OUTS DX, BYTE [SI] */ + OT_REGDX, + /* Use ECX in INVLPGA instruction */ + OT_REGECX, + + /* FPU registers: */ + OT_FPU_SI, /* ST(i) */ + OT_FPU_SSI, /* ST(0), ST(i) */ + OT_FPU_SIS, /* ST(i), ST(0) */ + + /* SSE registers: */ + OT_XMM, + /* Extract the SSE register from the RM bits this time (used when the REG bits are used for opcode extension) */ + OT_XMM_RM, + /* Implied XMM0 register as operand, used in SSE4. */ + OT_REGXMM0, + /* Reg32/Reg 64 depends on prefix width only. */ + OT_WREG32_64, + + /* XMM is encoded in VEX.VVVV. */ + OT_VXMM, + /* XMM is encoded in the high nibble of an immediate byte. */ + OT_XMM_IMM, + /* YMM/XMM is dependent on VEX.L. */ + OT_YXMM, + /* YMM/XMM (depends on prefix length) is encoded in the high nibble of an immediate byte. */ + OT_YXMM_IMM, + /* YMM is encoded in reg. */ + OT_YMM, + /* YMM is encoded in VEX.VVVV. */ + OT_VYMM, + /* YMM/XMM is dependent on VEX.L, and encoded in VEX.VVVV. */ + OT_VYXMM, + + /* Use an immediate of 1, as for SHR R/M, 1 */ + OT_CONST1, + /* Use CL, as for SHR R/M, CL */ + OT_REGCL, + + /* Use a control register */ + OT_CREG, + /* Use a debug register */ + OT_DREG, + /* Use a segment register */ + OT_SREG, + /* + * SEG is encoded in the flags of the opcode itself! + * This is used for specific "push SS" where SS is a segment where + * each "push SS" has an absolutely different opcode byte. + * We need this to detect whether an operand size prefix is used. + */ + OT_SEG, + + /* + * Special immediates for instructions which have more than one immediate, + * which is an exception from standard instruction format. + * As to version v1.0: ENTER, INSERTQ, EXTRQ are the only problematic ones. + */ + /* 16 bits immediate using the first imm-slot */ + OT_IMM16_1, + /* 8 bits immediate using the first imm-slot */ + OT_IMM8_1, + /* 8 bits immediate using the second imm-slot */ + OT_IMM8_2, + + /* Read one word (seg) and a word/dword/qword (depends on operand size), usually SEG:OFF, JMP 1234:1234 */ + OT_PTR16_FULL, + + /* Used only by MOV CR/DR(n). Promoted with REX onlly. */ + OT_FREG32_64_RM, + + /* MMX registers: */ + OT_MM, + /* Extract the MMX register from the RM bits this time (used when the REG bits are used for opcode extension) */ + OT_MM_RM, + + + /**** MEMORY only operands: ****/ + + /* Use general memory indirection, with varying sizes: */ + OT_MEM, + OT_MEM32, + /* Memory dereference for MOVNTI, either 32 or 64 bits (with REX). */ + OT_MEM32_64, + OT_MEM64, + /* Used for cmpxchg8b/16b. */ + OT_MEM64_128, + OT_MEM128, + /* + * Read one word (seg), and a word/dword/qword (depends on operand size) from memory. + * JMP FAR [EBX] means EBX point to 16:32 ptr. + */ + OT_MEM16_FULL, + /* Read one word (limit) and a dword/qword (limit) (depends on operand size), used by SGDT, SIDT, LGDT, LIDT. */ + OT_MEM16_3264, + /* Used when a memory indirection is required, but if the mod field is 11, this operand will be ignored. */ + OT_MEM_OPT, + + /* Same as OT_RMXX but POINTS to 16 bits [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM16, + /* Same as OT_RMXX but POINTS to 32 bits (single precision) [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM32, + /* Same as OT_RMXX but POINTS to 64 bits (double precision) [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM64, + /* Same as OT_RMXX but POINTS to 80 bits (extended precision) [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM80, + + /* Mem128/Mem256 is dependent on VEX.L. */ + OT_LMEM128_256, + + + /**** MEMORY & REGISTER only operands: ****/ + + /* Use or read (indirection) a 8bit register or immediate byte */ + OT_RM8, + /* Some instructions force 16 bits (mov sreg, rm16) */ + OT_RM16, + /* ModR/M for 32 bits. */ + OT_RM32, + /* + * Special operand type for MOV reg16/32/64/mem16, segReg 8C /r. and SMSW. + * It supports all decoding modes, but if used as a memory indirection it's a 16 bit ModR/M indirection. + */ + OT_RFULL_M16, + /* Use or read a 16/32/64bit register or immediate word/dword/qword */ + OT_RM_FULL, + + /* RM32/RM64 depends on prefix width only. */ + OT_WRM32_64, + /* + * Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or + * a 8 bits memory indirection operand. + */ + OT_R32_64_M8, + /* + * Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or + * a 16 bits memory indirection operand. + */ + OT_R32_64_M16, + + /* + * 32 or 64 bits (with REX) operand size indirection memory operand. + * Some instructions are promoted automatically without a REX prefix. + */ + OT_RM32_64, + /* 16 or 32 bits RM. This is used only with MOVZXD instruction in 64bits. */ + OT_RM16_32, + + /* + * Special operand type for SSE4 where the ModR/M might + * be a 32 bits register or 8 bits memory indirection operand. + */ + OT_R32_M8, + /* + * Special ModR/M for PINSRW, which need a 16 bits memory operand or 32 bits register. + * In 16 bits decoding mode R32 becomes R16, operand size cannot affect this. + */ + OT_R32_M16, + /* Reg32/Reg64 (prefix width) or Mem8. */ + OT_REG32_64_M8, + /* Reg32/Reg64 (prefix width) or Mem16. */ + OT_REG32_64_M16, + + /* ModR/M points to 32 bits MMX variable */ + OT_MM32, + /* ModR/M points to 32 bits MMX variable */ + OT_MM64, + + /* ModR/M points to 16 bits SSE variable */ + OT_XMM16, + /* ModR/M points to 32 bits SSE variable */ + OT_XMM32, + /* ModR/M points to 64 bits SSE variable */ + OT_XMM64, + /* ModR/M points to 128 bits SSE variable */ + OT_XMM128, + + /* AVX operands: */ + /* XMM or Mem32/Mem64 depends on perfix width only. */ + OT_WXMM32_64, + /* YMM or Mem256. */ + OT_YMM256, + /* YMM/XMM or Mem64/Mem256 is dependent on VEX.L. */ + OT_YXMM64_256, + /* YMM/XMM or Mem128/Mem256 is dependent on VEX.L. */ + OT_YXMM128_256, + /* XMM or Mem64/Mem256 is dependent on VEX.L. */ + OT_LXMM64_128 +} _OpType; + +/* Flags for instruction: */ + +/* Empty flags indicator: */ +#define INST_FLAGS_NONE (0) +/* The instruction we are going to decode requires ModR/M encoding. */ +#define INST_MODRM_REQUIRED (1) +/* Special treatment for instructions which are in the divided-category but still needs the whole byte for ModR/M... */ +#define INST_NOT_DIVIDED (1 << 1) +/* + * Used explicitly in repeatable instructions, + * which needs a suffix letter in their mnemonic to specify operation-size (depend on operands). + */ +#define INST_16BITS (1 << 2) +/* If the opcode is supported by 80286 and upper models (16/32 bits). */ +#define INST_32BITS (1 << 3) +/* + * Prefix flags (6 types: lock/rep, seg override, addr-size, oper-size, REX, VEX) + * There are several specific instructions that can follow LOCK prefix, + * note that they must be using a memory operand form, otherwise they generate an exception. + */ +#define INST_PRE_LOCK (1 << 4) +/* REPNZ prefix for string instructions only - means an instruction can follow it. */ +#define INST_PRE_REPNZ (1 << 5) +/* REP prefix for string instructions only - means an instruction can follow it. */ +#define INST_PRE_REP (1 << 6) +/* CS override prefix. */ +#define INST_PRE_CS (1 << 7) +/* SS override prefix. */ +#define INST_PRE_SS (1 << 8) +/* DS override prefix. */ +#define INST_PRE_DS (1 << 9) +/* ES override prefix. */ +#define INST_PRE_ES (1 << 10) +/* FS override prefix. Funky Segment :) */ +#define INST_PRE_FS (1 << 11) +/* GS override prefix. Groovy Segment, of course not, duh ! */ +#define INST_PRE_GS (1 << 12) +/* Switch operand size from 32 to 16 and vice versa. */ +#define INST_PRE_OP_SIZE (1 << 13) +/* Switch address size from 32 to 16 and vice versa. */ +#define INST_PRE_ADDR_SIZE (1 << 14) +/* Native instructions which needs suffix letter to indicate their operation-size (and don't depend on operands). */ +#define INST_NATIVE (1 << 15) +/* Use extended mnemonic, means it's an _InstInfoEx structure, which contains another mnemonic for 32 bits specifically. */ +#define INST_USE_EXMNEMONIC (1 << 16) +/* Use third operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */ +#define INST_USE_OP3 (1 << 17) +/* Use fourth operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */ +#define INST_USE_OP4 (1 << 18) +/* The instruction's mnemonic depends on the mod value of the ModR/M byte (mod=11, mod!=11). */ +#define INST_MNEMONIC_MODRM_BASED (1 << 19) +/* The instruction uses a ModR/M byte which the MOD must be 11 (for registers operands only). */ +#define INST_MODRR_REQUIRED (1 << 20) +/* The way of 3DNow! instructions are built, we have to handle their locating specially. Suffix imm8 tells which instruction it is. */ +#define INST_3DNOW_FETCH (1 << 21) +/* The instruction needs two suffixes, one for the comparison type (imm8) and the second for its operation size indication (second mnemonic). */ +#define INST_PSEUDO_OPCODE (1 << 22) +/* Invalid instruction at 64 bits decoding mode. */ +#define INST_INVALID_64BITS (1 << 23) +/* Specific instruction can be promoted to 64 bits (without REX, it is promoted automatically). */ +#define INST_64BITS (1 << 24) +/* Indicates the instruction must be REX prefixed in order to use 64 bits operands. */ +#define INST_PRE_REX (1 << 25) +/* Third mnemonic is set. */ +#define INST_USE_EXMNEMONIC2 (1 << 26) +/* Instruction is only valid in 64 bits decoding mode. */ +#define INST_64BITS_FETCH (1 << 27) +/* Forces that the ModRM-REG/Opcode field will be 0. (For EXTRQ). */ +#define INST_FORCE_REG0 (1 << 28) +/* Indicates that instruction is encoded with a VEX prefix. */ +#define INST_PRE_VEX (1 << 29) +/* Indicates that the instruction is encoded with a ModRM byte (REG field specifically). */ +#define INST_MODRM_INCLUDED (1 << 30) +/* Indicates that the first (/destination) operand of the instruction is writable. */ +#define INST_DST_WR (1 << 31) + +#define INST_PRE_REPS (INST_PRE_REPNZ | INST_PRE_REP) +#define INST_PRE_LOKREP_MASK (INST_PRE_LOCK | INST_PRE_REPNZ | INST_PRE_REP) +#define INST_PRE_SEGOVRD_MASK32 (INST_PRE_CS | INST_PRE_SS | INST_PRE_DS | INST_PRE_ES) +#define INST_PRE_SEGOVRD_MASK64 (INST_PRE_FS | INST_PRE_GS) +#define INST_PRE_SEGOVRD_MASK (INST_PRE_SEGOVRD_MASK32 | INST_PRE_SEGOVRD_MASK64) + +/* Extended flags for VEX: */ +/* Indicates that the instruction might have VEX.L encoded. */ +#define INST_VEX_L (1) +/* Indicates that the instruction might have VEX.W encoded. */ +#define INST_VEX_W (1 << 1) +/* Indicates that the mnemonic of the instruction is based on the VEX.W bit. */ +#define INST_MNEMONIC_VEXW_BASED (1 << 2) +/* Indicates that the mnemonic of the instruction is based on the VEX.L bit. */ +#define INST_MNEMONIC_VEXL_BASED (1 << 3) +/* Forces the instruction to be encoded with VEX.L, otherwise it's undefined. */ +#define INST_FORCE_VEXL (1 << 4) +/* + * Indicates that the instruction is based on the MOD field of the ModRM byte. + * (MOD==11: got the right instruction, else skip +4 in prefixed table for the correct instruction). + */ +#define INST_MODRR_BASED (1 << 5) +/* Indicates that the instruction doesn't use the VVVV field of the VEX prefix, if it does then it's undecodable. */ +#define INST_VEX_V_UNUSED (1 << 6) + +/* Indication that the instruction is privileged (Ring 0), this should be checked on the opcodeId field. */ +#define META_INST_PRIVILEGED ((uint16_t)0x8000) + +/* + * Indicates which operand is being decoded. + * Destination (1st), Source (2nd), op3 (3rd), op4 (4th). + * Used to set the operands' fields in the _DInst structure! + */ +typedef enum {ONT_NONE = -1, ONT_1 = 0, ONT_2 = 1, ONT_3 = 2, ONT_4 = 3} _OperandNumberType; + +/* CPU Flags that instructions modify, test or undefine, in compacted form (CF,PF,AF,ZF,SF are 1:1 map to EFLAGS). */ +#define D_COMPACT_CF 1 /* Carry */ +#define D_COMPACT_PF 4 /* Parity */ +#define D_COMPACT_AF 0x10 /* Auxiliary */ +#define D_COMPACT_ZF 0x40 /* Zero */ +#define D_COMPACT_SF 0x80 /* Sign */ +/* The following flags have to be translated to EFLAGS. */ +#define D_COMPACT_IF 2 /* Interrupt */ +#define D_COMPACT_DF 8 /* Direction */ +#define D_COMPACT_OF 0x20 /* Overflow */ + +/* The mask of flags that are already compatible with EFLAGS. */ +#define D_COMPACT_SAME_FLAGS (D_COMPACT_CF | D_COMPACT_PF | D_COMPACT_AF | D_COMPACT_ZF | D_COMPACT_SF) + +/* + * In order to save more space for storing the DB statically, + * I came up with another level of shared info. + * Because I saw that most of the information that instructions use repeats itself. + * + * Info about the instruction, source/dest types, meta and flags. + * _InstInfo points to a table of _InstSharedInfo. + */ +typedef struct +{ + uint8_t flagsIndex; /* An index into FlagsTables */ + uint8_t s, d; /* OpType. */ + /* + * The following are CPU flag masks that the instruction changes. + * The flags are compacted so 8 bits representation is enough. + * They will be expanded in runtime to be compatible to EFLAGS. + */ + uint8_t modifiedFlagsMask; + uint8_t testedFlagsMask; + uint8_t undefinedFlagsMask; + uint16_t meta; /* High byte = Instruction set class | Low byte = flow control flags. */ +} _InstSharedInfo; + +/* + * This structure is used for the instructions DB and NOT for the disassembled result code! + * This is the BASE structure, there are extensions to this structure below. + */ +typedef struct +{ + uint16_t sharedIndex; /* An index into the SharedInfoTable. */ + uint16_t opcodeId; /* The opcodeId is really a byte-offset into the mnemonics table. MSB is a privileged indication. */ +} _InstInfo; + +/* + * There are merely few instructions which need a second mnemonic for 32 bits. + * Or a third for 64 bits. Therefore sometimes the second mnemonic is empty but not the third. + * In all decoding modes the first mnemonic is the default. + * A flag will indicate it uses another mnemonic. + * + * There are a couple of (SSE4) instructions in the whole DB which need both op3 and 3rd mnemonic for 64bits, + * therefore, I decided to make the extended structure contain all extra info in the same structure. + * There are a few instructions (SHLD/SHRD/IMUL and SSE too) which use third operand (or a fourth). + * A flag will indicate it uses a third/fourth operand. + */ +typedef struct +{ + /* Base structure (doesn't get accessed directly from code). */ + _InstInfo BASE; + + /* Extended starts here. */ + uint8_t flagsEx; /* 8 bits are enough, in the future we might make it a bigger integer. */ + uint8_t op3, op4; /* OpType. */ + uint16_t opcodeId2, opcodeId3; +} _InstInfoEx; + +/* Trie data structure node type: */ +typedef enum +{ + INT_NOTEXISTS = 0, /* Not exists. */ + INT_INFO = 1, /* It's an instruction info. */ + INT_INFOEX, + INT_INFO_TREAT, /* Extra intervention is required by inst_lookup. */ + INT_LIST_GROUP, + INT_LIST_FULL, + INT_LIST_DIVIDED, + INT_LIST_PREFIXED +} _InstNodeType; + +/* Used to check instType < INT_INFOS, means we got an inst-info. Cause it has to be only one of them. */ +#define INT_INFOS (INT_LIST_GROUP) + +/* Instruction node is treated as { int index:13; int type:3; } */ +typedef uint16_t _InstNode; + +_InstInfo* inst_lookup(_CodeInfo* ci, _PrefixState* ps, int* isPrefixed); +_InstInfo* inst_lookup_3dnow(_CodeInfo* ci); + +#endif /* INSTRUCTIONS_H */ + + + +/* + * The main purpose of this module is to keep track of all kind of prefixes a single instruction may have. + * The problem is that a single instruction may have up to six different prefix-types. + * That's why I have to detect such cases and drop those excess prefixes. + */ + + +int PrefixTables[256 * 2] = +{ + /* Decode 16/32 Bits */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* ES (0x26) CS (0x2e) */ + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* DS (0x3e) SS (0x36) */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* FS(0x64) GS(0x65) OP_SIZE(0x66) ADDR_SIZE(0x67) */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* VEX2b (0xc5) VEX3b (0xc4) */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* LOCK (0xf0) REPNZ (0xf2) REP (0xf3) */ + /* Decode64Bits */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* REX: 0x40 - 0x4f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* Ignore all prefix. */ +void prefixes_ignore_all(_PrefixState* ps) +{ + int i; + for(i = 0; i < PFXIDX_MAX; i++) + prefixes_ignore(ps, i); +} + +/* Calculates which prefixes weren't used and accordingly sets the bits in the unusedPrefixesMask. */ +uint16_t prefixes_set_unused_mask(_PrefixState* ps) +{ + /* + * The decodedPrefixes represents the prefixes that were *read* from the binary stream for the instruction. + * The usedPrefixes represents the prefixes that were actually used by the instruction in the *decode* phase. + * Xoring between the two will result in a 'diff' which returns the prefixes that were read + * from the stream *and* that were never used in the actual decoding. + * + * Only one prefix per type can be set in decodedPrefixes from the stream. + * Therefore it's enough to check each type once and set the flag accordingly. + * That's why we had to book-keep each prefix type and its position. + * So now we know which bits we need to set exactly in the mask. + */ + _iflags unusedPrefixesDiff = ps->decodedPrefixes ^ ps->usedPrefixes; + uint16_t unusedPrefixesMask = ps->unusedPrefixesMask; + + /* Examine unused prefixes by type: */ + /* + * About REX: it might be set in the diff although it was never in the stream itself. + * This is because the vrex is shared between VEX and REX and some places flag it as REX usage, while + * we were really decoding an AVX instruction. + * It's not a big problem, because the prefixes_ignore func will ignore it anyway, + * since it wasn't seen earlier. But it's important to know this. + */ + if(unusedPrefixesDiff) + { + if(unusedPrefixesDiff & INST_PRE_REX) unusedPrefixesMask |= ps->pfxIndexer[PFXIDX_REX]; + if(unusedPrefixesDiff & INST_PRE_SEGOVRD_MASK) unusedPrefixesMask |= ps->pfxIndexer[PFXIDX_SEG]; + if(unusedPrefixesDiff & INST_PRE_LOKREP_MASK) unusedPrefixesMask |= ps->pfxIndexer[PFXIDX_LOREP]; + if(unusedPrefixesDiff & INST_PRE_OP_SIZE) unusedPrefixesMask |= ps->pfxIndexer[PFXIDX_OP_SIZE]; + if(unusedPrefixesDiff & INST_PRE_ADDR_SIZE) unusedPrefixesMask |= ps->pfxIndexer[PFXIDX_ADRS]; + /* If a VEX instruction was found, its prefix is considered as used, therefore no point for checking for it. */ + } + + return unusedPrefixesMask; +} + +/* + * Mark a prefix as unused, and bookkeep where we last saw this same type, + * because in the future we might want to disable it too. + */ +_INLINE_ void prefixes_track_unused(_PrefixState* ps, int index, _PrefixIndexer pi) +{ + /* Mark the previously used prefix (if exists) in the unused mask. */ + prefixes_ignore(ps, pi); + /* Book-keep the current index for this type. */ + ps->pfxIndexer[pi] = 1 << index; +} + +/* + * Read as many prefixes as possible, up to 15 bytes, and halt when we encounter non-prefix byte. + * This algorithm tries to imitate a real processor, where the same prefix can appear a few times, etc. + * The tiny complexity is that we want to know when a prefix was superfluous and mark any copy of it as unused. + * Note that the last prefix of its type will be considered as used, and all the others (of same type) before it as unused. + */ +void prefixes_decode(_CodeInfo* ci, _PrefixState* ps) +{ + const uint8_t* rexPos = NULL; + const uint8_t* start = ci->code; + uint8_t byte, vex; + unsigned int index; + /* + * First thing to do, scan for prefixes, there are six types of prefixes. + * There may be up to six prefixes before a single instruction, not the same type, no special order, + * except REX/VEX must precede immediately the first opcode byte. + * BTW - This is the reason why I didn't make the REP prefixes part of the instructions (STOS/SCAS/etc). + * + * Another thing, the instruction maximum size is 15 bytes, thus if we read more than 15 bytes, we will halt. + * + * We attach all prefixes to the next instruction, there might be two or more occurrences from the same prefix. + * Also, since VEX can be allowed only once we will test it separately. + */ + for(index = 0; + (ci->codeLen > 0) && (index < INST_MAXIMUM_SIZE); + ci->code++, ci->codeLen--, index++) + { + /* + NOTE: AMD treat lock/rep as two different groups... But I am based on Intel. + + - Lock and Repeat: + - 0xF0 - LOCK + - 0xF2 - REPNE/REPNZ + - 0xF3 - REP/REPE/REPZ + - Segment Override: + - 0x2E - CS + - 0x36 - SS + - 0x3E - DS + - 0x26 - ES + - 0x64 - FS + - 0x65 - GS + - Operand-Size Override: 0x66, switching default size. + - Address-Size Override: 0x67, switching default size. + + 64 Bits: + - REX: 0x40 - 0x4f, extends register access. + - 2 Bytes VEX: 0xc4 + - 3 Bytes VEX: 0xc5 + 32 Bits: + - 2 Bytes VEX: 0xc4 11xx-xxxx + - 3 Bytes VEX: 0xc5 11xx-xxxx + */ + + /* Examine what type of prefix we got. */ + byte = *ci->code; + switch(byte) + { + case PREFIX_OP_SIZE: /* Op Size type: */ + { + ps->decodedPrefixes |= INST_PRE_OP_SIZE; + prefixes_track_unused(ps, index, PFXIDX_OP_SIZE); + } + break; + /* Look for both common arch prefixes. */ + case PREFIX_LOCK: + { + /* LOCK and REPx type: */ + ps->decodedPrefixes |= INST_PRE_LOCK; + prefixes_track_unused(ps, index, PFXIDX_LOREP); + } + break; + case PREFIX_REPNZ: + { + ps->decodedPrefixes |= INST_PRE_REPNZ; + prefixes_track_unused(ps, index, PFXIDX_LOREP); + } + break; + case PREFIX_REP: + { + ps->decodedPrefixes |= INST_PRE_REP; + prefixes_track_unused(ps, index, PFXIDX_LOREP); + } + break; + case PREFIX_CS: + { + /* Seg Overide type: */ + ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK; + ps->decodedPrefixes |= INST_PRE_CS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + } + break; + case PREFIX_SS: + { + ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK; + ps->decodedPrefixes |= INST_PRE_SS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + } + break; + case PREFIX_DS: + { + ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK; + ps->decodedPrefixes |= INST_PRE_DS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + } + break; + case PREFIX_ES: + { + ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK; + ps->decodedPrefixes |= INST_PRE_ES; + prefixes_track_unused(ps, index, PFXIDX_SEG); + } + break; + case PREFIX_FS: + { + ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK; + ps->decodedPrefixes |= INST_PRE_FS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + } + break; + case PREFIX_GS: + { + ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK; + ps->decodedPrefixes |= INST_PRE_GS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + } + break; + case PREFIX_ADDR_SIZE: + { + /* Addr Size type: */ + ps->decodedPrefixes |= INST_PRE_ADDR_SIZE; + prefixes_track_unused(ps, index, PFXIDX_ADRS); + } + break; + default: + if(ci->dt == Decode64Bits) + { + /* REX type, 64 bits decoding mode only: */ + if((byte & 0xf0) == 0x40) + { + ps->decodedPrefixes |= INST_PRE_REX; + rexPos = ci->code; + ps->vrex = byte & 0xf; /* Keep only BXRW. */ + ps->prefixExtType = PET_REX; + prefixes_track_unused(ps, index, PFXIDX_REX); + continue; + } + } + goto _Break2; + } + } +_Break2: + + /* 2 Bytes VEX: */ + if((ci->codeLen >= 2) && + (*ci->code == PREFIX_VEX2b) && + ((ci->code - start) <= INST_MAXIMUM_SIZE - 2)) + { + /* + * In 32 bits the second byte has to be in the special range of Mod=11. + * Otherwise it might be a normal LDS instruction. + */ + if((ci->dt == Decode64Bits) || (*(ci->code + 1) >= INST_DIVIDED_MODRM)) + { + ps->vexPos = ci->code + 1; + ps->decodedPrefixes |= INST_PRE_VEX; + ps->prefixExtType = PET_VEX2BYTES; + + /* + * VEX 1 byte bits: + * |7-6--3-2-10| + * |R|vvvv|L|pp| + * |-----------| + */ + + /* -- Convert from VEX prefix to VREX flags -- */ + vex = *ps->vexPos; + if(!(vex & 0x80) && (ci->dt == Decode64Bits)) ps->vrex |= PREFIX_EX_R; /* Convert VEX.R. */ + if(vex & 4) ps->vrex |= PREFIX_EX_L; /* Convert VEX.L. */ + + ci->code += 2; + ci->codeLen -= 2; + } + } + + /* 3 Bytes VEX: */ + if((ci->codeLen >= 3) && + (*ci->code == PREFIX_VEX3b) && + ((ci->code - start) <= INST_MAXIMUM_SIZE - 3) && + (!(ps->decodedPrefixes & INST_PRE_VEX))) + { + /* + * In 32 bits the second byte has to be in the special range of Mod=11. + * Otherwise it might be a normal LES instruction. + * And we don't care now about the 3rd byte. + */ + if((ci->dt == Decode64Bits) || (*(ci->code + 1) >= INST_DIVIDED_MODRM)) + { + ps->vexPos = ci->code + 1; + ps->decodedPrefixes |= INST_PRE_VEX; + ps->prefixExtType = PET_VEX3BYTES; + + /* + * VEX first and second bytes: + * |7-6-5-4----0| |7-6--3-2-10| + * |R|X|B|m-mmmm| |W|vvvv|L|pp| + * |------------| |-----------| + */ + + /* -- Convert from VEX prefix to VREX flags -- */ + vex = *ps->vexPos; + ps->vrex |= ((~vex >> 5) & 0x7); /* Shift and invert VEX.R/X/B to their place */ + vex = *(ps->vexPos + 1); + if(vex & 4) ps->vrex |= PREFIX_EX_L; /* Convert VEX.L. */ + if(vex & 0x80) ps->vrex |= PREFIX_EX_W; /* Convert VEX.W. */ + + /* Clear some flags if the mode isn't 64 bits. */ + if(ci->dt != Decode64Bits) ps->vrex &= ~(PREFIX_EX_B | PREFIX_EX_X | PREFIX_EX_R | PREFIX_EX_W); + + ci->code += 3; + ci->codeLen -= 3; + } + } + + if(ci->dt == Decode64Bits) + { + if(ps->decodedPrefixes & INST_PRE_REX) + { + /* REX prefix must precede first byte of instruction. */ + if(rexPos != (ci->code - 1)) + { + ps->decodedPrefixes &= ~INST_PRE_REX; + if(ps->prefixExtType == PET_REX) ps->prefixExtType = PET_NONE; /* It might be a VEX by now, keep it that way. */ + prefixes_ignore(ps, PFXIDX_REX); + } + /* + * We will disable operand size prefix, + * if it exists only after decoding the instruction, since it might be a mandatory prefix. + * This will be done after calling inst_lookup in decode_inst. + */ + } + /* In 64 bits, segment overrides of CS, DS, ES and SS are ignored. So don't take'em into account. */ + if(ps->decodedPrefixes & INST_PRE_SEGOVRD_MASK32) + { + ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK32; + prefixes_ignore(ps, PFXIDX_SEG); + } + } + + /* Store number of prefixes scanned. */ + ps->count = (uint8_t)(ci->code - start); +} + +/* + * For every memory-indirection operand we want to set a used segment. + * If the segment is being overrided with a prefix, we will need to check if it's a default. + * Defaults don't use their prefix, e.g "mov [rsp]" can ignore a given SS: prefix, + * but still set the used segment as SS. + * This function is called only with SS and DS as defaults. + * If there's a segment prefix used, it will override the default one. + * And If the prefix is a default seg in 64 bits, it will be ignored. + */ +void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di) +{ + /* Extract given segment prefix from the decoded prefixes. */ + _iflags flags; + + if(dt == Decode64Bits) + { + if(ps->decodedPrefixes & INST_PRE_SEGOVRD_MASK64) /* Either GS or FS. */ + { + di->segment = ps->decodedPrefixes & INST_PRE_GS ? R_GS : R_FS; + } + + return; + } + + flags = ps->decodedPrefixes & INST_PRE_SEGOVRD_MASK; + + /* Use the given prefix only if it's not the default. */ + if(flags && (flags != defaultSeg)) + { + ps->usedPrefixes |= flags; + + switch(flags >> 7) /* INST_PRE_CS is 1 << 7. And the rest of the prefixes follow as bit fields. */ + { + case 1: + di->segment = R_CS; + break; + case 2: + di->segment = R_SS; + break; + case 4: + di->segment = R_DS; + break; + case 8: + di->segment = R_ES; + break; + case 0x10: + di->segment = R_FS; + break; + case 0x20: + di->segment = R_GS; + break; + } + } + else + { + if(defaultSeg == INST_PRE_SS) di->segment = SEGMENT_DEFAULT | R_SS; + else di->segment = SEGMENT_DEFAULT | R_DS; + } +} +/* +operands.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +/* +operands.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef OPERANDS_H +#define OPERANDS_H + + +int operands_extract(_CodeInfo* ci, _DInst* di, _InstInfo* ii, + _iflags instFlags, _OpType type, + unsigned int modrm, _PrefixState* ps, _DecodeType effOpSz, + _DecodeType effAdrSz, _Operand* op); + +#endif /* OPERANDS_H */ +/* +insts.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef INSTS_H +#define INSTS_H + + + +/* Flags Table */ +extern _iflags FlagsTable[]; + +/* Root Trie DB */ +extern _InstSharedInfo InstSharedInfoTable[]; +extern _InstInfo InstInfos[]; +extern _InstInfoEx InstInfosEx[]; +extern _InstNode InstructionsTree[]; + +/* 3DNow! Trie DB */ +extern _InstNode Table_0F_0F; +/* AVX related: */ +extern _InstNode Table_0F, Table_0F_38, Table_0F_3A; + +/* + * The inst_lookup will return on of these two instructions according to the specified decoding mode. + * ARPL or MOVSXD on 64 bits is one byte instruction at index 0x63. + */ +extern _InstInfo II_MOVSXD; + +/* + * The NOP instruction can be prefixed by REX in 64bits, therefore we have to decide in runtime whether it's an XCHG or NOP instruction. + * If 0x90 is prefixed by a usable REX it will become XCHG, otherwise it will become a NOP. + * Also note that if it's prefixed by 0xf3, it becomes a Pause. + */ +extern _InstInfo II_NOP; +extern _InstInfo II_PAUSE; + +/* + * RDRAND and VMPTRLD share same 2.3 bytes opcode, and then alternates on the MOD bits, + * RDRAND is OT_FULL_REG while VMPTRLD is OT_MEM, and there's no such mixed type. + * So a hack into the inst_lookup was added for this decision, the DB isn't flexible enough. :( + */ +extern _InstInfo II_RDRAND; + +/* + * Used for letting the extract operand know the type of operands without knowing the + * instruction itself yet, because of the way those instructions work. + * See function instructions.c!inst_lookup_3dnow. + */ +extern _InstInfo II_3DNOW; + +/* Helper tables for pseudo compare mnemonics. */ +extern uint16_t CmpMnemonicOffsets[8]; /* SSE */ +extern uint16_t VCmpMnemonicOffsets[32]; /* AVX */ + +#endif /* INSTS_H */ + + +/* Maps a register to its register-class mask. */ +uint32_t _REGISTERTORCLASS[] = /* Based on _RegisterType enumeration! */ +{ + RM_AX, RM_CX, RM_DX, RM_BX, RM_SP, RM_BP, RM_SI, RM_DI, RM_R8, RM_R9, RM_R10, RM_R11, RM_R12, RM_R13, RM_R14, RM_R15, + RM_AX, RM_CX, RM_DX, RM_BX, RM_SP, RM_BP, RM_SI, RM_DI, RM_R8, RM_R9, RM_R10, RM_R11, RM_R12, RM_R13, RM_R14, RM_R15, + RM_AX, RM_CX, RM_DX, RM_BX, RM_SP, RM_BP, RM_SI, RM_DI, RM_R8, RM_R9, RM_R10, RM_R11, RM_R12, RM_R13, RM_R14, RM_R15, + RM_AX, RM_CX, RM_DX, RM_BX, RM_AX, RM_CX, RM_DX, RM_BX, RM_R8, RM_R9, RM_R10, RM_R11, RM_R12, RM_R13, RM_R14, RM_R15, + RM_SP, RM_BP, RM_SI, RM_DI, + RM_SEG, RM_SEG, RM_SEG, RM_SEG, RM_SEG, RM_SEG, + 0, + RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, + RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, + RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, + RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, + RM_CR, 0, RM_CR, RM_CR, RM_CR, 0, 0, 0, RM_CR, + RM_DR, RM_DR, RM_DR, RM_DR, 0, 0, RM_DR, RM_DR +}; + +/* A helper function to fix the 8 bits register if REX is used (to support SIL, DIL, etc). */ +_INLINE_ unsigned int _FASTCALL_ operands_fix_8bit_rex_base(unsigned int reg) +{ + if((reg >= 4) && (reg < 8)) return reg + REGS8_REX_BASE - 4; + return reg + REGS8_BASE; +} + +/* A helper function to set operand's type and size. */ +_INLINE_ void operands_set_ts(_Operand* op, _OperandType type, uint16_t size) +{ + op->type = type; + op->size = size; +} + +/* A helper function to set operand's type, size and index. */ +_INLINE_ void operands_set_tsi(_DInst* di, _Operand* op, _OperandType type, uint16_t size, unsigned int index) +{ + op->type = type; + op->index = (uint8_t)index; + op->size = size; + di->usedRegistersMask |= _REGISTERTORCLASS[index]; +} + +/* A helper function to read an unsigned integer from the stream safely. */ +_INLINE_ int read_stream_safe_uint8(_CodeInfo* ci, void* result) +{ + ci->codeLen -= 1; + if(ci->codeLen < 0) return FALSE; + *(uint8_t*)result = *(uint8_t*)ci->code; + ci->code += 1; + return TRUE; +} + +/* A helper function to read an unsigned integer from the stream safely. */ +_INLINE_ int read_stream_safe_uint16(_CodeInfo* ci, void* result) +{ + ci->codeLen -= 2; + if(ci->codeLen < 0) return FALSE; + *(uint16_t*)result = RUSHORT(ci->code); + ci->code += 2; + return TRUE; +} + +/* A helper function to read an unsigned integer from the stream safely. */ +_INLINE_ int read_stream_safe_uint32(_CodeInfo* ci, void* result) +{ + ci->codeLen -= 4; + if(ci->codeLen < 0) return FALSE; + *(uint32_t*)result = RULONG(ci->code); + ci->code += 4; + return TRUE; +} + +/* A helper function to read an unsigned integer from the stream safely. */ +_INLINE_ int read_stream_safe_uint64(_CodeInfo* ci, void* result) +{ + ci->codeLen -= 8; + if(ci->codeLen < 0) return FALSE; + *(uint64_t*)result = RULLONG(ci->code); + ci->code += 8; + return TRUE; +} + +/* A helper function to read a signed integer from the stream safely. */ +_INLINE_ int read_stream_safe_sint8(_CodeInfo* ci, int64_t* result) +{ + ci->codeLen -= 1; + if(ci->codeLen < 0) return FALSE; + *result = *(int8_t*)ci->code; + ci->code += 1; + return TRUE; +} + +/* A helper function to read a signed integer from the stream safely. */ +_INLINE_ int read_stream_safe_sint16(_CodeInfo* ci, int64_t* result) +{ + ci->codeLen -= 2; + if(ci->codeLen < 0) return FALSE; + *result = RSHORT(ci->code); + ci->code += 2; + return TRUE; +} + +/* A helper function to read a signed integer from the stream safely. */ +_INLINE_ int read_stream_safe_sint32(_CodeInfo* ci, int64_t* result) +{ + ci->codeLen -= 4; + if(ci->codeLen < 0) return FALSE; + *result = RLONG(ci->code); + ci->code += 4; + return TRUE; +} + +/* + * SIB decoding is the most confusing part when decoding IA-32 instructions. + * This explanation should clear up some stuff. + * + * ! When base == 5, use EBP as the base register ! + * if (rm == 4) { + * if mod == 01, decode SIB byte and ALSO read a 8 bits displacement. + * if mod == 10, decode SIB byte and ALSO read a 32 bits displacement. + * if mod == 11 <-- EXCEPTION, this is a general-purpose register and mustn't lead to SIB decoding! + * ; So far so good, now the confusing part comes in with mod == 0 and base=5, but no worry. + * if (mod == 00) { + * decode SIB byte WITHOUT any displacement. + * EXCEPTION!!! when base == 5, read a 32 bits displacement, but this time DO NOT use (EBP) BASE at all! + * } + * + * NOTE: base could specify None (no base register) if base==5 and mod==0, but then you also need DISP32. + * } + */ +static void operands_extract_sib(_DInst* di, + _PrefixState* ps, _DecodeType effAdrSz, + unsigned int sib, unsigned int mod, _Operand* op) +{ + unsigned char scale, index, base; + unsigned int vrex = ps->vrex; + uint8_t* pIndex = NULL; + + /* + * SIB bits: + * |7---6-5----3-2---0| + * |SCALE| INDEX| BASE| + * |------------------| + */ + index = (sib >> 3) & 7; + base = sib & 7; + + /* + * The following fields: base/index/scale/disp8/32 are ALL optional by specific rules! + * The idea here is to keep the indirection as a simple-memory type. + * Because the base is optional, and we might be left with only one index. + * So even if there's a base but no index, or vice versa, we end up with one index register. + */ + + /* In 64 bits the REX prefix might affect the index of the SIB byte. */ + if(vrex & PREFIX_EX_X) + { + ps->usedPrefixes |= INST_PRE_REX; + index += EX_GPR_BASE; + } + + if(index == 4) /* No index is used. Use SMEM. */ + { + op->type = O_SMEM; + pIndex = &op->index; + } + else + { + op->type = O_MEM; + pIndex = &di->base; + /* No base, unless it is updated below. E.G: [EAX*4] has no base reg. */ + } + + if(base != 5) + { + if(vrex & PREFIX_EX_B) ps->usedPrefixes |= INST_PRE_REX; + *pIndex = effAdrSz == Decode64Bits ? REGS64_BASE : REGS32_BASE; + *pIndex += (uint8_t)(base + ((vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0)); + + if(di->base != R_NONE) di->usedRegistersMask |= _REGISTERTORCLASS[di->base]; + } + else if(mod != 0) + { + /* + * if base == 5 then you have to decode according to MOD. + * mod(00) - disp32. + * mod(01) - disp8 + rBP + * mod(10) - disp32 + rBP + * mod(11) - not possible, it's a general-purpose register. + */ + + if(vrex & PREFIX_EX_B) ps->usedPrefixes |= INST_PRE_REX; + if(effAdrSz == Decode64Bits) *pIndex = REGS64_BASE + 5 + ((vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0); + else *pIndex = REGS32_BASE + 5 + ((vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0); + + if(di->base != R_NONE) di->usedRegistersMask |= _REGISTERTORCLASS[di->base]; + } + else if(index == 4) + { + /* 32bits displacement only. */ + op->type = O_DISP; + return; + } + + if(index != 4) /* In 64 bits decoding mode, if index == R12, it's valid! */ + { + scale = (sib >> 6) & 3; + if(effAdrSz == Decode64Bits) op->index = (uint8_t)(REGS64_BASE + index); + else op->index = (uint8_t)(REGS32_BASE + index); + di->scale = scale != 0 ? (1 << scale) : 0; + } +} + +/* + * This seems to be the hardest part in decoding the operands. + * If you take a look carefully at Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte, + * you will understand it's easy to decode the operands. + + * First we check the DT, so we can decide according to which Table in the documentation we are supposed to decode. + * Then we follow the specific table whether it's 16 bits or 32/64 bits. + + * Don't forget that Operand Size AND Address Size prefixes may change the decoding! + + * Some instructions force the use of RM16 or other specific types, so take it into account. + */ +static int operands_extract_modrm(_CodeInfo* ci, _PrefixState* ps, _DInst* di, + _DecodeType effAdrSz, unsigned int mod, unsigned int rm, + _iflags instFlags, _Operand* op) +{ + unsigned char sib = 0, base = 0; + + /* Memory indirection decoding ahead:) */ + + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + if((instFlags & INST_PRE_LOCK) && (ps->decodedPrefixes & INST_PRE_LOCK)) + { + ps->usedPrefixes |= INST_PRE_LOCK; + di->flags |= FLAG_LOCK; + } + + if(effAdrSz != Decode16Bits) /* Decode32Bits or Decode64Bits! */ + { + /* Remember that from a 32/64 bits ModR/M byte a SIB byte could follow! */ + if((rm == 5) && (mod == 0)) + { + /* 5 is a special case - only 32 bits displacement, or RIP relative. */ + di->dispSize = 32; + if(!read_stream_safe_sint32(ci, (int64_t*)&di->disp)) return FALSE; + + /* Absolute address: */ + op->type = O_DISP; + + if(ci->dt == Decode64Bits) + { + /* In 64 bits decoding mode depsite of the address size, a RIP-relative address it is. */ + op->type = O_SMEM; + op->index = R_RIP; + di->flags |= FLAG_RIP_RELATIVE; + } + + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + } + else + { + if(rm == 4) + { + /* 4 is a special case - SIB byte + disp8/32 follows! */ + /* Read SIB byte. */ + if(!read_stream_safe_uint8(ci, &sib)) return FALSE; + operands_extract_sib(di, ps, effAdrSz, sib, mod, op); + } + else + { + op->type = O_SMEM; + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + + if(effAdrSz == Decode64Bits) op->index = (uint8_t)(REGS64_BASE + rm); + else op->index = (uint8_t)(REGS32_BASE + rm); + } + + if(mod == 1) + { + di->dispSize = 8; + if(!read_stream_safe_sint8(ci, (int64_t*)&di->disp)) return FALSE; + } + else if((mod == 2) || ((sib & 7) == 5)) /* If there is no BASE, read DISP32! */ + { + di->dispSize = 32; + if(!read_stream_safe_sint32(ci, (int64_t*)&di->disp)) return FALSE; + } + + /* Get the base register. */ + base = op->index; + if(di->base != R_NONE) base = di->base; + else if(di->scale >= 2) base = 0; /* If it's only an index but got scale, it's still DS. */ + /* Default for EBP/ESP is SS segment. 64 bits mode ignores DS anyway. */ + if((base == R_EBP) || (base == R_ESP)) prefixes_use_segment(INST_PRE_SS, ps, ci->dt, di); + else prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + } + } + else /* Decode16Bits */ + { + /* Decoding according to Table 2-1. (16 bits) */ + if((mod == 0) && (rm == 6)) + { + /* 6 is a special case - only 16 bits displacement. */ + op->type = O_DISP; + di->dispSize = 16; + if(!read_stream_safe_sint16(ci, (int64_t*)&di->disp)) return FALSE; + } + else + { + /* + * Create the O_MEM for 16 bits indirection that requires 2 registers, E.G: [BS+SI]. + * or create O_SMEM for a single register indirection, E.G: [BP]. + */ + static uint8_t MODS[] = { R_BX, R_BX, R_BP, R_BP, R_SI, R_DI, R_BP, R_BX }; + static uint8_t MODS2[] = { R_SI, R_DI, R_SI, R_DI }; + if(rm < 4) + { + op->type = O_MEM; + di->base = MODS[rm]; + di->usedRegistersMask |= _REGISTERTORCLASS[MODS[rm]]; + op->index = MODS2[rm]; + } + else + { + op->type = O_SMEM; + op->index = MODS[rm]; + } + + if(mod == 1) /* 8 bits displacement + indirection */ + { + di->dispSize = 8; + if(!read_stream_safe_sint8(ci, (int64_t*)&di->disp)) return FALSE; + } + else if(mod == 2) /* 16 bits displacement + indirection */ + { + di->dispSize = 16; + if(!read_stream_safe_sint16(ci, (int64_t*)&di->disp)) return FALSE; + } + } + + if((rm == 2) || (rm == 3) || ((rm == 6) && (mod != 0))) + { + /* BP's default segment is SS, so ignore it. */ + prefixes_use_segment(INST_PRE_SS, ps, ci->dt, di); + } + else + { + /* Ignore default DS segment. */ + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + } + } + + return TRUE; +} + + +/* + * This function is reponsible to textually format a required operand according to its type. + * It is vital to understand that there are other operands than what the ModR/M byte specifies. + + * Only by decoding the operands of an instruction which got a LOCK prefix, we could tell whether it may use the LOCK prefix. + * According to Intel, LOCK prefix must precede some specific instructions AND in their memory destination operand form (which means first operand). + * LOCK INC EAX, would generate an exception, but LOCK INC [EAX] is alright. + * Also LOCK ADD BX, [BP] would generate an exception. + + * Return code: + * TRUE - continue parsing the instruction and its operands, everything went right 'till now. + * FALSE - not enough bytes, or invalid operands. + */ + +int operands_extract(_CodeInfo* ci, _DInst* di, _InstInfo* ii, + _iflags instFlags, _OpType type, + unsigned int modrm, _PrefixState* ps, _DecodeType effOpSz, + _DecodeType effAdrSz, _Operand* op) +{ + int ret = 0; + unsigned int mod, reg, rm; + unsigned int size = 0; + + /* + * ModRM bits: + * |7-6-5--------3-2-0| + * |MOD|REG/OPCODE|RM | + * |------------------| + */ + /* mod = (modrm >> 6) & 3; */ /* Mode(register-indirection, disp8+reg+indirection, disp16+reg+indirection, general-purpose register) */ + /* reg = (modrm >> 3) & 7; */ /* Register(could be part of the opcode itself or general-purpose register) */ + /* rm = modrm & 7; */ /* Specifies which general-purpose register or disp+reg to use. */ + + /* -- Memory Indirection Operands (that cannot be a general purpose register) -- */ + if((type >= OT_MEM) && (type <= OT_LMEM128_256)) + { + /* All of the above types can't use a general-purpose register (a MOD of 3)!. */ + mod = (modrm >> 6) & 3; + + if(mod == 3) + { + if(type == OT_MEM_OPT) + { + /* Since the MEM is optional, only when mod != 3, then return true as if the operand was alright. */ + return TRUE; + } + return FALSE; + } + + switch(type) + { + case OT_MEM64_128: /* Used only by CMPXCHG8/16B. */ + if(effOpSz == Decode64Bits) + { + ps->usedPrefixes |= INST_PRE_REX; + size = 128; + } + else size = 64; + break; + case OT_MEM32: + size = 32; + break; + case OT_MEM32_64: + /* Used by MOVNTI. Default size is 32bits, 64bits with REX. */ + if(effOpSz == Decode64Bits) + { + ps->usedPrefixes |= INST_PRE_REX; + size = 64; + } + else size = 32; + break; + case OT_MEM64: + size = 64; + break; + case OT_MEM128: + size = 128; + break; + case OT_MEM16_FULL: /* The size indicates about the second item of the pair. */ + switch(effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + size = 16; + break; + case Decode32Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + size = 32; + break; + case Decode64Bits: + /* Mark usage of REX only if it was required. */ + if((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX)) ps->usedPrefixes |= INST_PRE_REX; + size = 64; + break; + } + break; + case OT_MEM16_3264: /* The size indicates about the second item of the pair. */ + if(ci->dt == Decode64Bits) size = 64; + else size = 32; + break; + case OT_FPUM16: + size = 16; + break; + case OT_FPUM32: + size = 32; + break; + case OT_FPUM64: + size = 64; + break; + case OT_FPUM80: + size = 80; + break; + case OT_LMEM128_256: + if(ps->vrex & PREFIX_EX_L) size = 256; + else size = 128; + break; + case OT_MEM_OPT: /* Here we know it's not optional. */ + case OT_MEM: + size = 0; /* Size is unknown, but still handled. */ break; + default: + return FALSE; + } + rm = modrm & 7; + ret = operands_extract_modrm(ci, ps, di, effAdrSz, mod, rm, instFlags, op); + op->size = (uint16_t)size; + if((op->type == O_SMEM) || (op->type == O_MEM)) + { + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + } + return ret; + } + + /* -- Memory Indirection Operands (that can be a register) -- */ + if((type >= OT_RM8) && (type <= OT_LXMM64_128)) + { + mod = (modrm >> 6) & 3; + if(mod != 3) + { + switch(type) + { + case OT_RM_FULL: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* PUSH/JMP/CALL are automatically promoted to 64 bits! */ + if(effOpSz == Decode32Bits) + { + size = 32; + break; + } + else if(effOpSz == Decode64Bits) + { + /* Mark usage of REX only if it was required. */ + if((instFlags & INST_64BITS) == 0) ps->usedPrefixes |= INST_PRE_REX; + size = 64; + break; + } + /* FALL THROUGH BECAUSE dt==Decoded16Bits @-<----*/ + case OT_RM16: + /* If we got here not from OT_RM16, then the prefix was used. */ + if(type != OT_RM16) ps->usedPrefixes |= INST_PRE_OP_SIZE; + size = 16; + break; + case OT_RM32_64: + /* The default size is 32, which can be 64 with a REX only. */ + if(effOpSz == Decode64Bits) + { + size = 64; + /* Mark REX prefix as used if non-promoted instruction. */ + if((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX)) + { + ps->usedPrefixes |= INST_PRE_REX; + } + } + else size = 32; + break; + case OT_RM16_32: + /* Ignore REX, it's either 32 or 16 bits RM. */ + if(ps->decodedPrefixes & INST_PRE_OP_SIZE) + { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* Assume: We are in 64bits when we have this operand used. */ + size = 16; + } + else size = 32; + break; + case OT_WXMM32_64: + case OT_WRM32_64: + if(ps->vrex & PREFIX_EX_W) size = 64; + else size = 32; + break; + case OT_YXMM64_256: + if(ps->vrex & PREFIX_EX_L) size = 256; + else size = 64; + break; + case OT_YXMM128_256: + if(ps->vrex & PREFIX_EX_L) size = 256; + else size = 128; + break; + case OT_LXMM64_128: + if(ps->vrex & PREFIX_EX_L) size = 128; + else size = 64; + break; + case OT_RFULL_M16: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + size = 16; + break; + + case OT_RM8: + case OT_R32_M8: + case OT_R32_64_M8: + case OT_REG32_64_M8: + size = 8; + break; + + case OT_XMM16: + case OT_R32_M16: + case OT_R32_64_M16: + case OT_REG32_64_M16: + size = 16; + break; + + case OT_RM32: + case OT_MM32: + case OT_XMM32: + size = 32; + break; + + case OT_MM64: + case OT_XMM64: + size = 64; + break; + + case OT_XMM128: + size = 128; + break; + case OT_YMM256: + size = 256; + break; + default: + return FALSE; + } + /* Fill size of memory dereference for operand. */ + rm = modrm & 7; + ret = operands_extract_modrm(ci, ps, di, effAdrSz, mod, rm, instFlags, op); + op->size = (uint16_t)size; + if((op->type == O_SMEM) || (op->type == O_MEM)) + { + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + } + return ret; + } + else + { + /* + * General-purpose register is handled the same way in 16/32/64 bits decoding modes. + * NOTE!! that we have to override the size of the register, since it was set earlier as Memory and not Register! + */ + rm = modrm & 7; + size = 0; + switch(type) + { + case OT_RFULL_M16: + case OT_RM_FULL: + switch(effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 16; + rm += REGS16_BASE; + break; + case Decode32Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 32; + rm += REGS32_BASE; + break; + case Decode64Bits: + /* A fix for SMSW RAX which use the REX prefix. */ + if(type == OT_RFULL_M16) ps->usedPrefixes |= INST_PRE_REX; + /* CALL NEAR/PUSH/POP defaults to 64 bits. --> INST_64BITS, REX isn't required, thus ignored anyways. */ + if(instFlags & INST_PRE_REX) ps->usedPrefixes |= INST_PRE_REX; + /* Mark usage of REX only if it was required. */ + if((instFlags & INST_64BITS) == 0) ps->usedPrefixes |= INST_PRE_REX; + /* Include REX if used for REX.B. */ + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 64; + rm += REGS64_BASE; + break; + } + break; + case OT_R32_64_M8: + /* FALL THROUGH, decode 32 or 64 bits register. */ + case OT_R32_64_M16: + /* FALL THROUGH, decode 32 or 64 bits register. */ + case OT_RM32_64: /* Take care specifically in MOVNTI/MOVD/CVT's instructions, making it _REG64 with REX or if they are promoted. */ + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + /* Is it a promoted instruction? (only INST_64BITS is set and REX isn't required.) */ + if((ci->dt == Decode64Bits) && ((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS)) + { + size = 64; + rm += REGS64_BASE; + break; + } + /* Give a chance to REX.W. Because if it was a promoted instruction we don't care about REX.W anyways. */ + if(ps->vrex & PREFIX_EX_W) + { + ps->usedPrefixes |= INST_PRE_REX; + size = 64; + rm += REGS64_BASE; + } + else + { + size = 32; + rm += REGS32_BASE; + } + break; + case OT_RM16_32: /* Used only with MOVZXD instruction to support 16 bits operand. */ + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + /* Is it 16 bits operand size? */ + if(ps->decodedPrefixes & INST_PRE_OP_SIZE) + { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + size = 16; + rm += REGS16_BASE; + } + else + { + size = 32; + rm += REGS32_BASE; + } + break; + case OT_RM16: + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + rm += REGS16_BASE; + size = 16; + break; + case OT_RM8: + if(ps->prefixExtType == PET_REX) + { + ps->usedPrefixes |= INST_PRE_REX; + rm = operands_fix_8bit_rex_base(rm + ((ps->vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0)); + } + else rm += REGS8_BASE; + size = 8; + break; + case OT_MM32: + case OT_MM64: + /* MMX doesn't support extended registers. */ + size = 64; + rm += MMXREGS_BASE; + break; + + case OT_XMM16: + case OT_XMM32: + case OT_XMM64: + case OT_XMM128: + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 128; + rm += SSEREGS_BASE; + break; + + case OT_RM32: + case OT_R32_M8: + case OT_R32_M16: + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 32; + rm += REGS32_BASE; + break; + + case OT_YMM256: + if(ps->vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + rm += AVXREGS_BASE; + size = 256; + break; + case OT_YXMM64_256: + case OT_YXMM128_256: + if(ps->vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + if(ps->vrex & PREFIX_EX_L) + { + size = 256; + rm += AVXREGS_BASE; + } + else + { + size = 128; + rm += SSEREGS_BASE; + } + break; + case OT_WXMM32_64: + case OT_LXMM64_128: + if(ps->vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + size = 128; + rm += SSEREGS_BASE; + break; + + case OT_WRM32_64: + case OT_REG32_64_M8: + case OT_REG32_64_M16: + if(ps->vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + if(ps->vrex & PREFIX_EX_W) + { + size = 64; + rm += REGS64_BASE; + } + else + { + size = 32; + rm += REGS32_BASE; + } + break; + + default: + return FALSE; + } + op->size = (uint16_t)size; + op->index = (uint8_t)rm; + op->type = O_REG; + di->usedRegistersMask |= _REGISTERTORCLASS[rm]; + return TRUE; + } + } + + /* Simple operand type (ModRM reg). */ + reg = (modrm >> 3) & 7; + switch(type) + { + case OT_IMM8: + operands_set_ts(op, O_IMM, 8); + if(!read_stream_safe_uint8(ci, &di->imm.byte)) return FALSE; + break; + case OT_IMM_FULL: /* 16, 32 or 64, depends on prefixes. */ + if(effOpSz == Decode16Bits) + { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* FALL THROUGH */ + case OT_IMM16: /* Force 16 bits imm. */ + operands_set_ts(op, O_IMM, 16); + if(!read_stream_safe_uint16(ci, &di->imm.word)) return FALSE; + break; + /* + * Extension: MOV imm64, requires REX. + * Make sure it needs the REX. + * REX must be present because op size function takes it into consideration. + */ + } + else if((effOpSz == Decode64Bits) && + ((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX))) + { + ps->usedPrefixes |= INST_PRE_REX; + + operands_set_ts(op, O_IMM, 64); + if(!read_stream_safe_uint64(ci, &di->imm.qword)) return FALSE; + break; + } + else ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* FALL THROUGH BECAUSE dt==Decoded32Bits @-<----*/ + case OT_IMM32: + op->type = O_IMM; + if(ci->dt == Decode64Bits) + { + /* + * Imm32 is sign extended to 64 bits! + * Originally the op size was 64, but later was changed to reflect real size of imm. + */ + op->size = 32; + /* Use this as an indicator that it should be signed extended. */ + di->flags |= FLAG_IMM_SIGNED; + if(!read_stream_safe_sint32(ci, &di->imm.sqword)) return FALSE; + } + else + { + op->size = 32; + if(!read_stream_safe_uint32(ci, &di->imm.dword)) return FALSE; + } + break; + case OT_SEIMM8: /* Sign extended immediate. */ + /* + * PUSH SEIMM8 can be prefixed by operand size: + * Input stream: 66, 6a, 55 + * 64bits DT: push small 55 + * 32bits DT: push small 55 + * 16bits DT: push large 55 + * small/large indicates the size of the eSP pointer advancement. + * Check the instFlags (ii->flags) if it can be operand-size-prefixed and if the prefix exists. + */ + op->type = O_IMM; + if((instFlags & INST_PRE_OP_SIZE) && (ps->decodedPrefixes & INST_PRE_OP_SIZE)) + { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + switch(ci->dt) + { + case Decode16Bits: + op->size = 32; + break; + case Decode32Bits: + case Decode64Bits: + op->size = 16; + break; + } + } + else op->size = 8; + di->flags |= FLAG_IMM_SIGNED; + if(!read_stream_safe_sint8(ci, &di->imm.sqword)) return FALSE; + break; + case OT_IMM16_1: + operands_set_ts(op, O_IMM1, 16); + if(!read_stream_safe_uint16(ci, &di->imm.ex.i1)) return FALSE; + break; + case OT_IMM8_1: + operands_set_ts(op, O_IMM1, 8); + if(!read_stream_safe_uint8(ci, &di->imm.ex.i1)) return FALSE; + break; + case OT_IMM8_2: + operands_set_ts(op, O_IMM2, 8); + if(!read_stream_safe_uint8(ci, &di->imm.ex.i2)) return FALSE; + break; + case OT_REG8: + operands_set_ts(op, O_REG, 8); + if(ps->prefixExtType) + { + /* + * If REX prefix is valid then we will have to use low bytes. + * This is a PASSIVE behavior changer of REX prefix, it affects operands even if its value is 0x40 ! + */ + ps->usedPrefixes |= INST_PRE_REX; + op->index = (uint8_t)operands_fix_8bit_rex_base(reg + ((ps->vrex & PREFIX_EX_R) ? EX_GPR_BASE : 0)); + } + else op->index = (uint8_t)(REGS8_BASE + reg); + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + break; + case OT_REG16: + operands_set_tsi(di, op, O_REG, 16, REGS16_BASE + reg); + break; + case OT_REG_FULL: + switch(effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if(ps->vrex & PREFIX_EX_R) + { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(di, op, O_REG, 16, REGS16_BASE + reg); + break; + case Decode32Bits: + if(ps->vrex & PREFIX_EX_R) + { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + else ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(di, op, O_REG, 32, REGS32_BASE + reg); + break; + case Decode64Bits: /* rex must be presented. */ + ps->usedPrefixes |= INST_PRE_REX; + operands_set_tsi(di, op, O_REG, 64, REGS64_BASE + reg + ((ps->vrex & PREFIX_EX_R) ? EX_GPR_BASE : 0)); + break; + } + break; + case OT_REG32: + if(ps->vrex & PREFIX_EX_R) + { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(di, op, O_REG, 32, REGS32_BASE + reg); + break; + case OT_REG32_64: /* Handle CVT's, MOVxX and MOVNTI instructions which could be extended to 64 bits registers with REX. */ + if(ps->vrex & PREFIX_EX_R) + { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + + /* Is it a promoted instruction? (only INST_64BITS is set and REX isn't required.) */ + if((ci->dt == Decode64Bits) && ((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS)) + { + operands_set_tsi(di, op, O_REG, 64, REGS64_BASE + reg); + break; + } + /* Give a chance to REX.W. Because if it was a promoted instruction we don't care about REX.W anyways. */ + if(ps->vrex & PREFIX_EX_W) + { + ps->usedPrefixes |= INST_PRE_REX; + operands_set_tsi(di, op, O_REG, 64, REGS64_BASE + reg); + } + else operands_set_tsi(di, op, O_REG, 32, REGS32_BASE + reg); + break; + case OT_FREG32_64_RM: /* Force decoding mode. Used for MOV CR(n)/DR(n) which defaults to 64 bits operand size in 64 bits. */ + rm = modrm & 7; + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + + if(ci->dt == Decode64Bits) operands_set_tsi(di, op, O_REG, 64, REGS64_BASE + rm); + else operands_set_tsi(di, op, O_REG, 32, REGS32_BASE + rm); + break; + case OT_MM: /* MMX register */ + operands_set_tsi(di, op, O_REG, 64, MMXREGS_BASE + reg); + break; + case OT_MM_RM: /* MMX register, this time from the RM field */ + rm = modrm & 7; + operands_set_tsi(di, op, O_REG, 64, MMXREGS_BASE + rm); + break; + case OT_REGXMM0: /* Implicit XMM0 operand. */ + operands_set_tsi(di, op, O_REG, 128, SSEREGS_BASE + 0); + break; + case OT_XMM: /* SSE register */ + if(ps->vrex & PREFIX_EX_R) + { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(di, op, O_REG, 128, SSEREGS_BASE + reg); + break; + case OT_XMM_RM: /* SSE register, this time from the RM field */ + rm = modrm & 7; + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + operands_set_tsi(di, op, O_REG, 128, SSEREGS_BASE + rm); + break; + case OT_CREG: + /* + * Don't parse if the reg exceeds the bounds of the array. + * Most of the CR's are not implemented, so if there's no matching string, the operand is invalid. + */ + if(ps->vrex & PREFIX_EX_R) + { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + else if((ci->dt == Decode32Bits) && (ps->decodedPrefixes & INST_PRE_LOCK)) + { + /* + * NOTE: In 32 bits decoding mode, + * if the lock prefix is set before MOV CR(n) it will become the 4th bit of the REG field like REX.R in 64 bits. + */ + reg += EX_GPR_BASE; + ps->usedPrefixes |= INST_PRE_LOCK; + } + /* Ignore some registers which do not exist. */ + if((reg >= CREGS_MAX) || (reg == 1) || ((reg >= 5) && (reg <= 7))) return FALSE; + + op->type = O_REG; + if(ci->dt == Decode64Bits) op->size = 64; + else op->size = 32; + op->index = (uint8_t)(CREGS_BASE + reg); + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + break; + case OT_DREG: + /* + * In 64 bits there are 16 debug registers. + * but accessing any of dr8-15 which aren't implemented will cause an #ud. + */ + if((reg == 4) || (reg == 5) || (ps->vrex & PREFIX_EX_R)) return FALSE; + + op->type = O_REG; + if(ci->dt == Decode64Bits) op->size = 64; + else op->size = 32; + op->index = (uint8_t)(DREGS_BASE + reg); + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + break; + case OT_SREG: /* Works with REG16 only! */ + if((&di->ops[0] == op) && (reg == 1)) return FALSE; /* Can't MOV CS, . */ + /*Don't parse if the reg exceeds the bounds of the array. */ + if(reg <= SEG_REGS_MAX - 1) operands_set_tsi(di, op, O_REG, 16, SREGS_BASE + reg); + else return FALSE; + break; + case OT_SEG: + op->type = O_REG; + /* Size of reg is always 16, it's up to caller to zero extend it to operand size. */ + op->size = 16; + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* + * Extract the SEG from ii->flags this time!!! + * Check whether an operand size prefix is used. + */ + switch(instFlags & INST_PRE_SEGOVRD_MASK) + { + case INST_PRE_ES: + op->index = R_ES; + break; + case INST_PRE_CS: + op->index = R_CS; + break; + case INST_PRE_SS: + op->index = R_SS; + break; + case INST_PRE_DS: + op->index = R_DS; + break; + case INST_PRE_FS: + op->index = R_FS; + break; + case INST_PRE_GS: + op->index = R_GS; + break; + } + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + break; + case OT_ACC8: + operands_set_tsi(di, op, O_REG, 8, R_AL); + break; + case OT_ACC16: + operands_set_tsi(di, op, O_REG, 16, R_AX); + break; + case OT_ACC_FULL_NOT64: + /* No REX.W support for IN/OUT. */ + /* FALL THROUGH */ + case OT_ACC_FULL: + if(effOpSz == Decode16Bits) + { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(di, op, O_REG, 16, R_AX); + } + else if((effOpSz == Decode32Bits) || (type == OT_ACC_FULL_NOT64)) + { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(di, op, O_REG, 32, R_EAX); + } + else /* Decode64Bits */ + { + /* Only non-promoted instructions need REX in order to decode in 64 bits. */ + /* MEM-OFFSET MOV's are NOT automatically promoted to 64 bits. */ + if(!(instFlags & INST_64BITS)) + { + ps->usedPrefixes |= INST_PRE_REX; + } + operands_set_tsi(di, op, O_REG, 64, R_RAX); + } + break; + case OT_PTR16_FULL: + /* ptr16:full - full is size of operand size to read, therefore Operand Size Prefix affects this. So we need to handle it. */ + if(effOpSz == Decode16Bits) + { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + ci->codeLen -= sizeof(int16_t) * 2; + if(ci->codeLen < 0) return FALSE; + + operands_set_ts(op, O_PTR, 16); + di->imm.ptr.off = RUSHORT(ci->code); /* Read offset first. */ + di->imm.ptr.seg = RUSHORT((ci->code + sizeof(int16_t))); /* And read segment. */ + + ci->code += sizeof(int16_t) * 2; + } + else /* Decode32Bits, for Decode64Bits this instruction is invalid. */ + { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + ci->codeLen -= sizeof(int32_t) + sizeof(int16_t); + if(ci->codeLen < 0) return FALSE; + + operands_set_ts(op, O_PTR, 32); + di->imm.ptr.off = RULONG(ci->code); /* Read 32bits offset this time. */ + di->imm.ptr.seg = RUSHORT((ci->code + sizeof(int32_t))); /* And read segment, 16 bits. */ + + ci->code += sizeof(int32_t) + sizeof(int16_t); + } + break; + case OT_RELCB: + case OT_RELC_FULL: + + if(type == OT_RELCB) + { + operands_set_ts(op, O_PC, 8); + if(!read_stream_safe_sint8(ci, &di->imm.sqword)) return FALSE; + } + else /* OT_RELC_FULL */ + { + + /* Yep, operand size prefix affects relc also. */ + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if(effOpSz == Decode16Bits) + { + operands_set_ts(op, O_PC, 16); + if(!read_stream_safe_sint16(ci, &di->imm.sqword)) return FALSE; + } + else /* Decode32Bits or Decode64Bits = for now they are the same */ + { + operands_set_ts(op, O_PC, 32); + if(!read_stream_safe_sint32(ci, &di->imm.sqword)) return FALSE; + } + } + + /* Support for hint, see if there's a segment override. */ + if((ii->opcodeId >= I_JO) && (ii->opcodeId <= I_JG)) + { + if(ps->decodedPrefixes & INST_PRE_CS) + { + ps->usedPrefixes |= INST_PRE_CS; + di->flags |= FLAG_HINT_NOT_TAKEN; + } + else if(ps->decodedPrefixes & INST_PRE_DS) + { + ps->usedPrefixes |= INST_PRE_DS; + di->flags |= FLAG_HINT_TAKEN; + } + } + break; + case OT_MOFFS8: + op->size = 8; + /* FALL THROUGH, size won't be changed. */ + case OT_MOFFS_FULL: + op->type = O_DISP; + if(op->size == 0) + { + /* Calculate size of operand (same as ACC size). */ + switch(effOpSz) + { + case Decode16Bits: + op->size = 16; + break; + case Decode32Bits: + op->size = 32; + break; + case Decode64Bits: + op->size = 64; + break; + } + } + + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + + /* + * Just a pointer to a BYTE, WORD, DWORD, QWORD. Works only with ACC8/16/32/64 respectively. + * MOV [0x1234], AL ; MOV AX, [0x1234] ; MOV EAX, [0x1234], note that R/E/AX will be chosen by OT_ACC_FULL. + */ + if(effAdrSz == Decode16Bits) + { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + di->dispSize = 16; + if(!read_stream_safe_uint16(ci, &di->disp)) return FALSE; + } + else if(effAdrSz == Decode32Bits) + { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + di->dispSize = 32; + if(!read_stream_safe_uint32(ci, &di->disp)) return FALSE; + } + else /* Decode64Bits */ + { + di->dispSize = 64; + if(!read_stream_safe_uint64(ci, &di->disp)) return FALSE; + } + break; + case OT_CONST1: + operands_set_ts(op, O_IMM, 8); + di->imm.byte = 1; + break; + case OT_REGCL: + operands_set_tsi(di, op, O_REG, 8, R_CL); + break; + + case OT_FPU_SI: + /* Low 3 bits specify the REG, similar to the MODR/M byte reg. */ + operands_set_tsi(di, op, O_REG, 32, FPUREGS_BASE + (*(ci->code - 1) & 7)); + break; + case OT_FPU_SSI: + operands_set_tsi(di, op, O_REG, 32, R_ST0); + operands_set_tsi(di, op + 1, O_REG, 32, FPUREGS_BASE + (*(ci->code - 1) & 7)); + di->opsNo++; + break; + case OT_FPU_SIS: + operands_set_tsi(di, op, O_REG, 32, FPUREGS_BASE + (*(ci->code - 1) & 7)); + operands_set_tsi(di, op + 1, O_REG, 32, R_ST0); + di->opsNo++; + break; + + /* + * Special treatment for Instructions-Block: + * INC/DEC (only 16/32 bits) /PUSH/POP/XCHG instructions, which get their REG from their own binary code. + + * Notice these instructions are 1 or 2 byte long, + * code points after the byte which represents the instruction itself, + * thus, even if the instructions are 2 bytes long it will read its last byte which contains the REG info. + */ + case OT_IB_RB: + /* Low 3 bits specify the REG, similar to the MODR/M byte reg. */ + operands_set_ts(op, O_REG, 8); + reg = *(ci->code - 1) & 7; + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + op->index = (uint8_t)operands_fix_8bit_rex_base(reg + EX_GPR_BASE); + } + else if(ps->prefixExtType == PET_REX) + { + ps->usedPrefixes |= INST_PRE_REX; + op->index = (uint8_t)operands_fix_8bit_rex_base(reg); + } + else op->index = (uint8_t)(REGS8_BASE + reg); + + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + break; + case OT_IB_R_FULL: + reg = *(ci->code - 1) & 7; + switch(effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(di, op, O_REG, 16, REGS16_BASE + reg); + break; + case Decode32Bits: + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + else ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(di, op, O_REG, 32, REGS32_BASE + reg); + break; + case Decode64Bits: + /* + * Automatically promoted instruction can drop REX prefix if not required. + * PUSH/POP defaults to 64 bits. --> INST_64BITS + * MOV imm64 / BSWAP requires REX.W to be 64 bits --> INST_64BITS | INST_PRE_REX + */ + if((instFlags & INST_64BITS) && ((instFlags & INST_PRE_REX) == 0)) + { + if(ps->vrex & PREFIX_EX_B) + { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + } + else + { + ps->usedPrefixes |= INST_PRE_REX; + reg += (ps->vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0; + } + operands_set_tsi(di, op, O_REG, 64, REGS64_BASE + reg); + break; + } + break; + + /* + * Special treatment for repeatable instructions. + + * We want the following output: + * If there's only the REP/NZ prefix, we won't output anything (All operands are implicit). + * If there's an operand size prefix, we will change the suffix letter of the mnemonic, which specifies the size of operand to the required one. + * If there's a segment override prefix, we will output the segment and the used index register (EDI/ESI). + * If there's an address size prefix, we will output the (segment if needed and) the used and inverted index register (DI/SI). + + * Example: + * :: Decoding in 16 bits mode! :: + * AD ~ LODSW + * 66 AD ~ LODSD + * F3 AC ~ REP LODSB + * F3 66 AD ~ REP LODSD + * F3 3E AC ~ REP LODS BYTE DS:[SI] + * F3 67 AD ~ REP LODS WORD [ESI] + + * The basic form of a repeatable instruction has its operands hidden and has a suffix letter + * which implies on the size of operation being done. + * Therefore, we cannot change the mnemonic here when we encounter another prefix and its not the decoder's responsibility to do so. + * That's why the caller is responsible to add the suffix letter if no other prefixes are used. + * And all we are doing here is formatting the operand correctly. + */ + case OT_REGI_ESI: + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + op->type = O_SMEM; + + /* This might be a 16, 32 or 64 bits instruction, depends on the decoding mode. */ + if(instFlags & INST_16BITS) + { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + + if(effOpSz == Decode16Bits) op->size = 16; + else if((effOpSz == Decode64Bits) && (instFlags & INST_64BITS)) + { + ps->usedPrefixes |= INST_PRE_REX; + op->size = 64; + } + else op->size = 32; + } + else op->size = 8; + + /* + * Clear segment in case OT_REGI_EDI was parsed earlier, + * DS can be overridden and therefore has precedence. + */ + di->segment = R_NONE; + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + + if(effAdrSz == Decode16Bits) op->index = R_SI; + else if(effAdrSz == Decode32Bits) op->index = R_ESI; + else op->index = R_RSI; + + di->usedRegistersMask |= _REGISTERTORCLASS[R_RSI]; /* Maps to RM_SI. */ + break; + case OT_REGI_EDI: + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + op->type = O_SMEM; + + /* This might be a 16 or 32 bits instruction, depends on the decoding mode. */ + if(instFlags & INST_16BITS) + { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + + if(effOpSz == Decode16Bits) op->size = 16; + else if((effOpSz == Decode64Bits) && (instFlags & INST_64BITS)) + { + ps->usedPrefixes |= INST_PRE_REX; + op->size = 64; + } + else op->size = 32; + } + else op->size = 8; + + /* Note: The [rDI] operand can't be prefixed by a segment override, therefore we don't set usedPrefixes. */ + if((di->segment == R_NONE) && (ci->dt != Decode64Bits)) di->segment = R_ES | SEGMENT_DEFAULT; /* No ES in 64 bits mode. */ + + if(effAdrSz == Decode16Bits) op->index = R_DI; + else if(effAdrSz == Decode32Bits) op->index = R_EDI; + else op->index = R_RDI; + + di->usedRegistersMask |= _REGISTERTORCLASS[R_RDI]; /* Maps to RM_DI. */ + break; + + /* Used for In/Out instructions varying forms. */ + case OT_REGDX: + /* Simple single IN/OUT instruction. */ + operands_set_tsi(di, op, O_REG, 16, R_DX); + break; + + /* Used for INVLPGA instruction. */ + case OT_REGECX: + operands_set_tsi(di, op, O_REG, 32, R_ECX); + break; + case OT_REGI_EBXAL: + /* XLAT BYTE [rBX + AL] */ + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + + /* Size of deref is always 8 for xlat. */ + operands_set_tsi(di, op, O_MEM, 8, R_AL); + + if(effAdrSz == Decode16Bits) di->base = R_BX; + else if(effAdrSz == Decode32Bits) di->base = R_EBX; + else + { + ps->usedPrefixes |= INST_PRE_REX; + di->base = R_RBX; + } + + di->usedRegistersMask |= _REGISTERTORCLASS[di->base]; + break; + case OT_REGI_EAX: + /* + * Implicit rAX as memory indirection operand. Used by AMD's SVM instructions. + * Since this is a memory indirection, the default address size in 64bits decoding mode is 64. + */ + + if(effAdrSz == Decode64Bits) operands_set_tsi(di, op, O_SMEM, 64, R_RAX); + else if(effAdrSz == Decode32Bits) + { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + operands_set_tsi(di, op, O_SMEM, 32, R_EAX); + } + else + { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + operands_set_tsi(di, op, O_SMEM, 16, R_AX); + } + break; + case OT_VXMM: + operands_set_tsi(di, op, O_REG, 128, SSEREGS_BASE + ps->vexV); + break; + case OT_XMM_IMM: + ci->codeLen -= sizeof(int8_t); + if(ci->codeLen < 0) return FALSE; + + if(ci->dt == Decode32Bits) reg = (*ci->code >> 4) & 0x7; + else reg = (*ci->code >> 4) & 0xf; + operands_set_tsi(di, op, O_REG, 128, SSEREGS_BASE + reg); + + ci->code += sizeof(int8_t); + break; + case OT_YXMM: + if(ps->vrex & PREFIX_EX_R) reg += EX_GPR_BASE; + if(ps->vrex & PREFIX_EX_L) operands_set_tsi(di, op, O_REG, 256, AVXREGS_BASE + reg); + else operands_set_tsi(di, op, O_REG, 128, SSEREGS_BASE + reg); + break; + case OT_YXMM_IMM: + ci->codeLen -= sizeof(int8_t); + if(ci->codeLen < 0) return FALSE; + + if(ci->dt == Decode32Bits) reg = (*ci->code >> 4) & 0x7; + else reg = (*ci->code >> 4) & 0xf; + + if(ps->vrex & PREFIX_EX_L) operands_set_tsi(di, op, O_REG, 256, AVXREGS_BASE + reg); + else operands_set_tsi(di, op, O_REG, 128, SSEREGS_BASE + reg); + + ci->code += sizeof(int8_t); + break; + case OT_YMM: + if(ps->vrex & PREFIX_EX_R) reg += EX_GPR_BASE; + operands_set_tsi(di, op, O_REG, 256, AVXREGS_BASE + reg); + break; + case OT_VYMM: + operands_set_tsi(di, op, O_REG, 256, AVXREGS_BASE + ps->vexV); + break; + case OT_VYXMM: + if(ps->vrex & PREFIX_EX_L) operands_set_tsi(di, op, O_REG, 256, AVXREGS_BASE + ps->vexV); + else operands_set_tsi(di, op, O_REG, 128, SSEREGS_BASE + ps->vexV); + break; + case OT_WREG32_64: + if(ps->vrex & PREFIX_EX_R) reg += EX_GPR_BASE; + if(ps->vrex & PREFIX_EX_W) operands_set_tsi(di, op, O_REG, 64, REGS64_BASE + reg); + else operands_set_tsi(di, op, O_REG, 32, REGS32_BASE + reg); + break; + default: + return FALSE; + } + return TRUE; +} +/* +insts.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + + + +/* + * GENERATED BY disOps at Fri Dec 17 10:22:38 2021 + */ + +_InstInfo II_MOVSXD = /*II*/ {0x1d7, 10038}; +_InstInfo II_NOP = /*II*/ {0x53, 580}; +_InstInfo II_PAUSE = /*II*/ {0x91, 10046}; +_InstInfo II_WAIT = /*II*/ {0x53, 10053}; +_InstInfo II_RDRAND = /*II*/ {0x1d8, 10059}; +_InstInfo II_3DNOW = /*II*/ {0x1d9, 10067}; + +_iflags FlagsTable[101] = +{ + 0x80000011, + 0x80000000, + 0x800400, + 0x80800400, + 0x800080, + 0x800100, + 0x80800100, + 0x800200, + 0x80800200, + 0x800000, + 0x1, + 0x0, + 0x80800000, + 0x1000000, + 0x81000000, + 0x808000, + 0x800001, + 0x80020001, + 0x1002000, + 0x60, + 0x64, + 0x80000001, + 0x4010000, + 0x1008000, + 0x80000060, + 0x83000064, + 0x3000064, + 0x83000000, + 0x3008000, + 0x200, + 0xc000, + 0x4014000, + 0x8, + 0x81000009, + 0x80000009, + 0x1000808, + 0x81000808, + 0x80020009, + 0x1001008, + 0x81001008, + 0x80000019, + 0x3000009, + 0x83000009, + 0x83000008, + 0xc0000011, + 0x40000001, + 0xc0800011, + 0x40800001, + 0xc0000019, + 0xc1000001, + 0xc0000001, + 0xc0000003, + 0x41000000, + 0x40000000, + 0x40000008, + 0x40000009, + 0x41000001, + 0x43000001, + 0x40000003, + 0x48000000, + 0x200009, + 0x20000009, + 0x60020009, + 0x60000009, + 0x80090009, + 0x200b0009, + 0x20020009, + 0x9, + 0x80100009, + 0x21100009, + 0x87000009, + 0x20009, + 0x20000008, + 0x1000009, + 0x10020009, + 0x160009, + 0x100009, + 0x47000009, + 0x47090009, + 0x40090009, + 0x80002009, + 0xc0000009, + 0x2001, + 0x80002001, + 0x410009, + 0x20420009, + 0x20060009, + 0x120009, + 0x21020009, + 0xc7000019, + 0x20100009, + 0xc0002009, + 0x40002008, + 0xc0000000, + 0xc0002008, + 0x4020009, + 0x40100009, + 0x60120009, + 0x41000009, + 0x83000001, + 0x200001 +}; + +_InstNode Table_0F = 256; +_InstNode Table_0F_0F = 1440; +_InstNode Table_0F_38 = 1896; +_InstNode Table_0F_3A = 2152; + +_InstInfo InstInfos[1248] = +{ + /*II_00*/ {0x0, 11}, + /*II_01*/ {0x1, 11}, + /*II_02*/ {0x2, 11}, + /*II_03*/ {0x3, 11}, + /*II_04*/ {0x4, 11}, + /*II_05*/ {0x5, 11}, + /*II_06*/ {0x6, 16}, + /*II_07*/ {0x7, 22}, + /*II_08*/ {0x8, 27}, + /*II_09*/ {0x9, 27}, + /*II_0A*/ {0xa, 27}, + /*II_0B*/ {0xb, 27}, + /*II_0C*/ {0xc, 27}, + /*II_0D*/ {0xd, 27}, + /*II_0E*/ {0xe, 16}, + /*II_10*/ {0xf, 31}, + /*II_11*/ {0x10, 31}, + /*II_12*/ {0x11, 31}, + /*II_13*/ {0x12, 31}, + /*II_14*/ {0x13, 31}, + /*II_15*/ {0x14, 31}, + /*II_16*/ {0x15, 16}, + /*II_17*/ {0x16, 22}, + /*II_18*/ {0xf, 36}, + /*II_19*/ {0x10, 36}, + /*II_1A*/ {0x11, 36}, + /*II_1B*/ {0x12, 36}, + /*II_1C*/ {0x13, 36}, + /*II_1D*/ {0x14, 36}, + /*II_1E*/ {0x17, 16}, + /*II_1F*/ {0x18, 22}, + /*II_20*/ {0x19, 41}, + /*II_21*/ {0x1a, 41}, + /*II_22*/ {0x1b, 41}, + /*II_23*/ {0x1c, 41}, + /*II_24*/ {0x1d, 41}, + /*II_25*/ {0x1e, 41}, + /*II_27*/ {0x1f, 46}, + /*II_28*/ {0x0, 51}, + /*II_29*/ {0x1, 51}, + /*II_2A*/ {0x2, 51}, + /*II_2B*/ {0x3, 51}, + /*II_2C*/ {0x4, 51}, + /*II_2D*/ {0x5, 51}, + /*II_2F*/ {0x1f, 56}, + /*II_30*/ {0x20, 61}, + /*II_31*/ {0x21, 61}, + /*II_32*/ {0x22, 61}, + /*II_33*/ {0x23, 61}, + /*II_34*/ {0x24, 61}, + /*II_35*/ {0x25, 61}, + /*II_37*/ {0x26, 66}, + /*II_38*/ {0x27, 71}, + /*II_39*/ {0x28, 71}, + /*II_3A*/ {0x29, 71}, + /*II_3B*/ {0x2a, 71}, + /*II_3C*/ {0x2b, 71}, + /*II_3D*/ {0x2c, 71}, + /*II_3F*/ {0x26, 76}, + /*II_40*/ {0x2d, 81}, + /*II_40*/ {0x2d, 81}, + /*II_40*/ {0x2d, 81}, + /*II_40*/ {0x2d, 81}, + /*II_40*/ {0x2d, 81}, + /*II_40*/ {0x2d, 81}, + /*II_40*/ {0x2d, 81}, + /*II_40*/ {0x2d, 81}, + /*II_48*/ {0x2d, 86}, + /*II_48*/ {0x2d, 86}, + /*II_48*/ {0x2d, 86}, + /*II_48*/ {0x2d, 86}, + /*II_48*/ {0x2d, 86}, + /*II_48*/ {0x2d, 86}, + /*II_48*/ {0x2d, 86}, + /*II_48*/ {0x2d, 86}, + /*II_50*/ {0x2e, 16}, + /*II_50*/ {0x2e, 16}, + /*II_50*/ {0x2e, 16}, + /*II_50*/ {0x2e, 16}, + /*II_50*/ {0x2e, 16}, + /*II_50*/ {0x2e, 16}, + /*II_50*/ {0x2e, 16}, + /*II_50*/ {0x2e, 16}, + /*II_58*/ {0x2f, 22}, + /*II_58*/ {0x2f, 22}, + /*II_58*/ {0x2f, 22}, + /*II_58*/ {0x2f, 22}, + /*II_58*/ {0x2f, 22}, + /*II_58*/ {0x2f, 22}, + /*II_58*/ {0x2f, 22}, + /*II_58*/ {0x2f, 22}, + /*II_60*/ {0x30, 91}, + /*II_61*/ {0x30, 98}, + /*II_62*/ {0x31, 104}, + /*II_63*/ {0x32, 111}, + /*II_68*/ {0x33, 16}, + /*II_6A*/ {0x35, 16}, + /*II_6C*/ {0x36, 123}, + /*II_6D*/ {0x37, 123}, + /*II_6E*/ {0x38, 128}, + /*II_6F*/ {0x39, 128}, + /*II_70*/ {0x3a, 134}, + /*II_71*/ {0x3a, 138}, + /*II_72*/ {0x3b, 143}, + /*II_73*/ {0x3b, 147}, + /*II_74*/ {0x3c, 152}, + /*II_75*/ {0x3c, 156}, + /*II_76*/ {0x3d, 161}, + /*II_77*/ {0x3d, 166}, + /*II_78*/ {0x3e, 170}, + /*II_79*/ {0x3e, 174}, + /*II_7A*/ {0x3f, 179}, + /*II_7B*/ {0x3f, 183}, + /*II_7C*/ {0x40, 188}, + /*II_7D*/ {0x40, 192}, + /*II_7E*/ {0x41, 197}, + /*II_7F*/ {0x41, 202}, + /*II_84*/ {0x42, 206}, + /*II_85*/ {0x43, 206}, + /*II_86*/ {0x44, 212}, + /*II_87*/ {0x45, 212}, + /*II_88*/ {0x46, 218}, + /*II_89*/ {0x47, 218}, + /*II_8A*/ {0x48, 218}, + /*II_8B*/ {0x49, 218}, + /*II_8C*/ {0x4a, 218}, + /*II_8D*/ {0x4b, 223}, + /*II_8E*/ {0x4c, 218}, + /*II_90*/ {0x4d, 212}, + /*II_91*/ {0x4d, 212}, + /*II_92*/ {0x4d, 212}, + /*II_93*/ {0x4d, 212}, + /*II_94*/ {0x4d, 212}, + /*II_95*/ {0x4d, 212}, + /*II_96*/ {0x4d, 212}, + /*II_97*/ {0x4d, 212}, + /*II_9A*/ {0x4f, 260}, + /*II_9C*/ {0x50, 270}, + /*II_9D*/ {0x51, 277}, + /*II_9E*/ {0x52, 283}, + /*II_9F*/ {0x53, 289}, + /*II_A0*/ {0x54, 218}, + /*II_A1*/ {0x55, 218}, + /*II_A2*/ {0x56, 218}, + /*II_A3*/ {0x57, 218}, + /*II_A4*/ {0x58, 295}, + /*II_A5*/ {0x59, 295}, + /*II_A6*/ {0x5a, 301}, + /*II_A7*/ {0x5b, 301}, + /*II_A8*/ {0x5c, 206}, + /*II_A9*/ {0x5d, 206}, + /*II_AA*/ {0x5e, 307}, + /*II_AB*/ {0x5f, 307}, + /*II_AC*/ {0x60, 313}, + /*II_AD*/ {0x61, 313}, + /*II_AE*/ {0x62, 319}, + /*II_AF*/ {0x63, 319}, + /*II_B0*/ {0x64, 218}, + /*II_B0*/ {0x64, 218}, + /*II_B0*/ {0x64, 218}, + /*II_B0*/ {0x64, 218}, + /*II_B0*/ {0x64, 218}, + /*II_B0*/ {0x64, 218}, + /*II_B0*/ {0x64, 218}, + /*II_B0*/ {0x64, 218}, + /*II_B8*/ {0x65, 218}, + /*II_B8*/ {0x65, 218}, + /*II_B8*/ {0x65, 218}, + /*II_B8*/ {0x65, 218}, + /*II_B8*/ {0x65, 218}, + /*II_B8*/ {0x65, 218}, + /*II_B8*/ {0x65, 218}, + /*II_B8*/ {0x65, 218}, + /*II_C2*/ {0x66, 325}, + /*II_C3*/ {0x67, 325}, + /*II_C4*/ {0x68, 330}, + /*II_C5*/ {0x68, 335}, + /*II_C8*/ {0x69, 340}, + /*II_C9*/ {0x6a, 347}, + /*II_CA*/ {0x6b, 354}, + /*II_CB*/ {0x6c, 354}, + /*II_CC*/ {0x53, 360}, + /*II_CD*/ {0x6d, 366}, + /*II_CE*/ {0x6e, 371}, + /*II_CF*/ {0x6f, 377}, + /*II_D4*/ {0x70, 383}, + /*II_D5*/ {0x70, 388}, + /*II_D6*/ {0x71, 393}, + /*II_D7*/ {0x72, 399}, + /*II_E0*/ {0x73, 405}, + /*II_E1*/ {0x73, 413}, + /*II_E2*/ {0x74, 420}, + /*II_E4*/ {0x76, 446}, + /*II_E5*/ {0x77, 446}, + /*II_E6*/ {0x78, 450}, + /*II_E7*/ {0x79, 450}, + /*II_E8*/ {0x7a, 455}, + /*II_E9*/ {0x7b, 461}, + /*II_EA*/ {0x7c, 466}, + /*II_EB*/ {0x7d, 461}, + /*II_EC*/ {0x7e, 446}, + /*II_ED*/ {0x7f, 446}, + /*II_EE*/ {0x80, 450}, + /*II_EF*/ {0x81, 450}, + /*II_F1*/ {0x82, 475}, + /*II_F4*/ {0x83, 481}, + /*II_F5*/ {0x84, 486}, + /*II_F8*/ {0x84, 491}, + /*II_F9*/ {0x84, 496}, + /*II_FA*/ {0x85, 501}, + /*II_FB*/ {0x85, 506}, + /*II_FC*/ {0x86, 511}, + /*II_FD*/ {0x86, 516}, + /*II_0F_02*/ {0x87, 521}, + /*II_0F_03*/ {0x87, 526}, + /*II_0F_05*/ {0x88, 531}, + /*II_0F_06*/ {0x89, 540}, + /*II_0F_07*/ {0x88, 546}, + /*II_0F_08*/ {0x89, 554}, + /*II_0F_09*/ {0x89, 560}, + /*II_0F_0B*/ {0x8a, 568}, + /*II_0F_0E*/ {0x8b, 573}, + /*II_0F_1F*/ {0x8c, 580}, + /*II_0F_20*/ {0x8d, 218}, + /*II_0F_21*/ {0x8e, 218}, + /*II_0F_22*/ {0x8f, 218}, + /*II_0F_23*/ {0x90, 218}, + /*II_0F_30*/ {0x89, 585}, + /*II_0F_31*/ {0x89, 592}, + /*II_0F_32*/ {0x89, 599}, + /*II_0F_33*/ {0x89, 606}, + /*II_0F_34*/ {0x88, 613}, + /*II_0F_35*/ {0x88, 623}, + /*II_0F_37*/ {0x91, 632}, + /*II_0F_40*/ {0x92, 640}, + /*II_0F_41*/ {0x92, 647}, + /*II_0F_42*/ {0x93, 655}, + /*II_0F_43*/ {0x93, 662}, + /*II_0F_44*/ {0x94, 670}, + /*II_0F_45*/ {0x94, 677}, + /*II_0F_46*/ {0x95, 685}, + /*II_0F_47*/ {0x95, 693}, + /*II_0F_48*/ {0x96, 700}, + /*II_0F_49*/ {0x96, 707}, + /*II_0F_4A*/ {0x97, 715}, + /*II_0F_4B*/ {0x97, 722}, + /*II_0F_4C*/ {0x98, 730}, + /*II_0F_4D*/ {0x98, 737}, + /*II_0F_4E*/ {0x99, 745}, + /*II_0F_4F*/ {0x99, 753}, + /*II_0F_80*/ {0x9a, 134}, + /*II_0F_81*/ {0x9a, 138}, + /*II_0F_82*/ {0x9b, 143}, + /*II_0F_83*/ {0x9b, 147}, + /*II_0F_84*/ {0x9c, 152}, + /*II_0F_85*/ {0x9c, 156}, + /*II_0F_86*/ {0x9d, 161}, + /*II_0F_87*/ {0x9d, 166}, + /*II_0F_88*/ {0x9e, 170}, + /*II_0F_89*/ {0x9e, 174}, + /*II_0F_8A*/ {0x9f, 179}, + /*II_0F_8B*/ {0x9f, 183}, + /*II_0F_8C*/ {0xa0, 188}, + /*II_0F_8D*/ {0xa0, 192}, + /*II_0F_8E*/ {0xa1, 197}, + /*II_0F_8F*/ {0xa1, 202}, + /*II_0F_90*/ {0xa2, 760}, + /*II_0F_91*/ {0xa2, 766}, + /*II_0F_92*/ {0xa3, 773}, + /*II_0F_93*/ {0xa3, 779}, + /*II_0F_94*/ {0xa4, 786}, + /*II_0F_95*/ {0xa4, 792}, + /*II_0F_96*/ {0xa5, 799}, + /*II_0F_97*/ {0xa5, 806}, + /*II_0F_98*/ {0xa6, 812}, + /*II_0F_99*/ {0xa6, 818}, + /*II_0F_9A*/ {0xa7, 825}, + /*II_0F_9B*/ {0xa7, 831}, + /*II_0F_9C*/ {0xa8, 838}, + /*II_0F_9D*/ {0xa8, 844}, + /*II_0F_9E*/ {0xa9, 851}, + /*II_0F_9F*/ {0xa9, 858}, + /*II_0F_A0*/ {0xaa, 16}, + /*II_0F_A1*/ {0xab, 22}, + /*II_0F_A2*/ {0x91, 864}, + /*II_0F_A3*/ {0xac, 871}, + /*II_0F_A8*/ {0xae, 16}, + /*II_0F_A9*/ {0xaf, 22}, + /*II_0F_AA*/ {0xb0, 881}, + /*II_0F_AB*/ {0xb1, 886}, + /*II_0F_AF*/ {0xb2, 117}, + /*II_0F_B0*/ {0xb3, 897}, + /*II_0F_B1*/ {0xb4, 897}, + /*II_0F_B2*/ {0xb5, 906}, + /*II_0F_B3*/ {0xb1, 911}, + /*II_0F_B4*/ {0xb5, 916}, + /*II_0F_B5*/ {0xb5, 921}, + /*II_0F_B6*/ {0xb6, 926}, + /*II_0F_B7*/ {0xb7, 926}, + /*II_0F_B9*/ {0x8a, 568}, + /*II_0F_BB*/ {0xb1, 933}, + /*II_0F_BE*/ {0xb6, 938}, + /*II_0F_BF*/ {0xb7, 938}, + /*II_0F_C0*/ {0xb3, 945}, + /*II_0F_C1*/ {0xb4, 945}, + /*II_0F_C3*/ {0xb8, 951}, + /*II_0F_C8*/ {0xb9, 959}, + /*II_0F_C8*/ {0xb9, 959}, + /*II_0F_C8*/ {0xb9, 959}, + /*II_0F_C8*/ {0xb9, 959}, + /*II_0F_C8*/ {0xb9, 959}, + /*II_0F_C8*/ {0xb9, 959}, + /*II_0F_C8*/ {0xb9, 959}, + /*II_0F_C8*/ {0xb9, 959}, + /*II_80_00*/ {0xba, 11}, + /*II_80_01*/ {0xbb, 27}, + /*II_80_02*/ {0xbc, 31}, + /*II_80_03*/ {0xbc, 36}, + /*II_80_04*/ {0xbd, 41}, + /*II_80_05*/ {0xba, 51}, + /*II_80_06*/ {0xbe, 61}, + /*II_80_07*/ {0xbf, 71}, + /*II_81_00*/ {0xc0, 11}, + /*II_81_01*/ {0xc1, 27}, + /*II_81_02*/ {0xc2, 31}, + /*II_81_03*/ {0xc2, 36}, + /*II_81_04*/ {0xc3, 41}, + /*II_81_05*/ {0xc0, 51}, + /*II_81_06*/ {0xc4, 61}, + /*II_81_07*/ {0xc5, 71}, + /*II_82_00*/ {0xc6, 11}, + /*II_82_01*/ {0xc7, 27}, + /*II_82_02*/ {0xc8, 31}, + /*II_82_03*/ {0xc8, 36}, + /*II_82_04*/ {0xc9, 41}, + /*II_82_05*/ {0xc6, 51}, + /*II_82_06*/ {0xca, 61}, + /*II_82_07*/ {0xcb, 71}, + /*II_83_00*/ {0xcc, 11}, + /*II_83_01*/ {0xcd, 27}, + /*II_83_02*/ {0xce, 31}, + /*II_83_03*/ {0xce, 36}, + /*II_83_04*/ {0xcf, 41}, + /*II_83_05*/ {0xcc, 51}, + /*II_83_06*/ {0xd0, 61}, + /*II_83_07*/ {0xd1, 71}, + /*II_8F_00*/ {0xd2, 22}, + /*II_C0_00*/ {0xd3, 966}, + /*II_C0_01*/ {0xd3, 971}, + /*II_C0_02*/ {0xd4, 976}, + /*II_C0_03*/ {0xd4, 981}, + /*II_C0_04*/ {0xd5, 986}, + /*II_C0_05*/ {0xd5, 991}, + /*II_C0_06*/ {0xd5, 996}, + /*II_C0_07*/ {0xd5, 1001}, + /*II_C1_00*/ {0xd6, 966}, + /*II_C1_01*/ {0xd6, 971}, + /*II_C1_02*/ {0xd7, 976}, + /*II_C1_03*/ {0xd7, 981}, + /*II_C1_04*/ {0xd8, 986}, + /*II_C1_05*/ {0xd8, 991}, + /*II_C1_06*/ {0xd8, 996}, + /*II_C1_07*/ {0xd8, 1001}, + /*II_C6_00*/ {0xd9, 218}, + /*II_C6_F8*/ {0xda, 1006}, + /*II_C7_00*/ {0xdb, 218}, + /*II_C7_F8*/ {0xdc, 1014}, + /*II_D0_00*/ {0xdd, 966}, + /*II_D0_01*/ {0xdd, 971}, + /*II_D0_02*/ {0xde, 976}, + /*II_D0_03*/ {0xde, 981}, + /*II_D0_04*/ {0xdf, 986}, + /*II_D0_05*/ {0xdf, 991}, + /*II_D0_06*/ {0xdf, 996}, + /*II_D0_07*/ {0xdf, 1001}, + /*II_D1_00*/ {0xe0, 966}, + /*II_D1_01*/ {0xe0, 971}, + /*II_D1_02*/ {0xe1, 976}, + /*II_D1_03*/ {0xe1, 981}, + /*II_D1_04*/ {0xe2, 986}, + /*II_D1_05*/ {0xe2, 991}, + /*II_D1_06*/ {0xe2, 996}, + /*II_D1_07*/ {0xe2, 1001}, + /*II_D2_00*/ {0xe3, 966}, + /*II_D2_01*/ {0xe3, 971}, + /*II_D2_02*/ {0xe4, 976}, + /*II_D2_03*/ {0xe4, 981}, + /*II_D2_04*/ {0xe5, 986}, + /*II_D2_05*/ {0xe5, 991}, + /*II_D2_06*/ {0xe5, 996}, + /*II_D2_07*/ {0xe5, 1001}, + /*II_D3_00*/ {0xe6, 966}, + /*II_D3_01*/ {0xe6, 971}, + /*II_D3_02*/ {0xe7, 976}, + /*II_D3_03*/ {0xe7, 981}, + /*II_D3_04*/ {0xe8, 986}, + /*II_D3_05*/ {0xe8, 991}, + /*II_D3_06*/ {0xe8, 996}, + /*II_D3_07*/ {0xe8, 1001}, + /*II_D8_00*/ {0xe9, 1022}, + /*II_D8_01*/ {0xe9, 1028}, + /*II_D8_02*/ {0xe9, 1034}, + /*II_D8_03*/ {0xe9, 1040}, + /*II_D8_04*/ {0xe9, 1047}, + /*II_D8_05*/ {0xe9, 1053}, + /*II_D8_06*/ {0xe9, 1060}, + /*II_D8_07*/ {0xe9, 1066}, + /*II_D8_C0*/ {0xea, 1022}, + /*II_D8_C0*/ {0xea, 1022}, + /*II_D8_C0*/ {0xea, 1022}, + /*II_D8_C0*/ {0xea, 1022}, + /*II_D8_C0*/ {0xea, 1022}, + /*II_D8_C0*/ {0xea, 1022}, + /*II_D8_C0*/ {0xea, 1022}, + /*II_D8_C0*/ {0xea, 1022}, + /*II_D8_C8*/ {0xea, 1028}, + /*II_D8_C8*/ {0xea, 1028}, + /*II_D8_C8*/ {0xea, 1028}, + /*II_D8_C8*/ {0xea, 1028}, + /*II_D8_C8*/ {0xea, 1028}, + /*II_D8_C8*/ {0xea, 1028}, + /*II_D8_C8*/ {0xea, 1028}, + /*II_D8_C8*/ {0xea, 1028}, + /*II_D8_D0*/ {0xeb, 1034}, + /*II_D8_D0*/ {0xeb, 1034}, + /*II_D8_D0*/ {0xeb, 1034}, + /*II_D8_D0*/ {0xeb, 1034}, + /*II_D8_D0*/ {0xeb, 1034}, + /*II_D8_D0*/ {0xeb, 1034}, + /*II_D8_D0*/ {0xeb, 1034}, + /*II_D8_D0*/ {0xeb, 1034}, + /*II_D8_D8*/ {0xeb, 1040}, + /*II_D8_D9*/ {0xec, 1040}, + /*II_D8_D8*/ {0xeb, 1040}, + /*II_D8_D8*/ {0xeb, 1040}, + /*II_D8_D8*/ {0xeb, 1040}, + /*II_D8_D8*/ {0xeb, 1040}, + /*II_D8_D8*/ {0xeb, 1040}, + /*II_D8_D8*/ {0xeb, 1040}, + /*II_D8_E0*/ {0xea, 1047}, + /*II_D8_E0*/ {0xea, 1047}, + /*II_D8_E0*/ {0xea, 1047}, + /*II_D8_E0*/ {0xea, 1047}, + /*II_D8_E0*/ {0xea, 1047}, + /*II_D8_E0*/ {0xea, 1047}, + /*II_D8_E0*/ {0xea, 1047}, + /*II_D8_E0*/ {0xea, 1047}, + /*II_D8_E8*/ {0xea, 1053}, + /*II_D8_E8*/ {0xea, 1053}, + /*II_D8_E8*/ {0xea, 1053}, + /*II_D8_E8*/ {0xea, 1053}, + /*II_D8_E8*/ {0xea, 1053}, + /*II_D8_E8*/ {0xea, 1053}, + /*II_D8_E8*/ {0xea, 1053}, + /*II_D8_E8*/ {0xea, 1053}, + /*II_D8_F0*/ {0xea, 1060}, + /*II_D8_F0*/ {0xea, 1060}, + /*II_D8_F0*/ {0xea, 1060}, + /*II_D8_F0*/ {0xea, 1060}, + /*II_D8_F0*/ {0xea, 1060}, + /*II_D8_F0*/ {0xea, 1060}, + /*II_D8_F0*/ {0xea, 1060}, + /*II_D8_F0*/ {0xea, 1060}, + /*II_D8_F8*/ {0xea, 1066}, + /*II_D8_F8*/ {0xea, 1066}, + /*II_D8_F8*/ {0xea, 1066}, + /*II_D8_F8*/ {0xea, 1066}, + /*II_D8_F8*/ {0xea, 1066}, + /*II_D8_F8*/ {0xea, 1066}, + /*II_D8_F8*/ {0xea, 1066}, + /*II_D8_F8*/ {0xea, 1066}, + /*II_D9_00*/ {0xe9, 1073}, + /*II_D9_02*/ {0xed, 1078}, + /*II_D9_03*/ {0xed, 1083}, + /*II_D9_04*/ {0xee, 1089}, + /*II_D9_05*/ {0xef, 1097}, + /*II_D9_C0*/ {0xeb, 1073}, + /*II_D9_C0*/ {0xeb, 1073}, + /*II_D9_C0*/ {0xeb, 1073}, + /*II_D9_C0*/ {0xeb, 1073}, + /*II_D9_C0*/ {0xeb, 1073}, + /*II_D9_C0*/ {0xeb, 1073}, + /*II_D9_C0*/ {0xeb, 1073}, + /*II_D9_C0*/ {0xeb, 1073}, + /*II_D9_C8*/ {0xeb, 1104}, + /*II_D9_C9*/ {0xec, 1104}, + /*II_D9_C8*/ {0xeb, 1104}, + /*II_D9_C8*/ {0xeb, 1104}, + /*II_D9_C8*/ {0xeb, 1104}, + /*II_D9_C8*/ {0xeb, 1104}, + /*II_D9_C8*/ {0xeb, 1104}, + /*II_D9_C8*/ {0xeb, 1104}, + /*II_D9_D0*/ {0xec, 1110}, + /*II_D9_E0*/ {0xec, 1116}, + /*II_D9_E1*/ {0xec, 1122}, + /*II_D9_E4*/ {0xec, 1128}, + /*II_D9_E5*/ {0xec, 1134}, + /*II_D9_E8*/ {0xec, 1140}, + /*II_D9_E9*/ {0xec, 1146}, + /*II_D9_EA*/ {0xec, 1154}, + /*II_D9_EB*/ {0xec, 1162}, + /*II_D9_EC*/ {0xec, 1169}, + /*II_D9_ED*/ {0xec, 1177}, + /*II_D9_EE*/ {0xec, 1185}, + /*II_D9_F0*/ {0xec, 1191}, + /*II_D9_F1*/ {0xec, 1198}, + /*II_D9_F2*/ {0xec, 1205}, + /*II_D9_F3*/ {0xec, 1212}, + /*II_D9_F4*/ {0xec, 1220}, + /*II_D9_F5*/ {0xec, 1229}, + /*II_D9_F6*/ {0xec, 1237}, + /*II_D9_F7*/ {0xec, 1246}, + /*II_D9_F8*/ {0xec, 1255}, + /*II_D9_F9*/ {0xec, 1262}, + /*II_D9_FA*/ {0xec, 1271}, + /*II_D9_FB*/ {0xec, 1278}, + /*II_D9_FC*/ {0xec, 1287}, + /*II_D9_FD*/ {0xec, 1296}, + /*II_D9_FE*/ {0xec, 1304}, + /*II_D9_FF*/ {0xec, 1310}, + /*II_DA_00*/ {0xe9, 1316}, + /*II_DA_01*/ {0xe9, 1323}, + /*II_DA_02*/ {0xe9, 1330}, + /*II_DA_03*/ {0xe9, 1337}, + /*II_DA_04*/ {0xe9, 1345}, + /*II_DA_05*/ {0xe9, 1352}, + /*II_DA_06*/ {0xe9, 1360}, + /*II_DA_07*/ {0xe9, 1367}, + /*II_DA_C0*/ {0xf0, 1375}, + /*II_DA_C0*/ {0xf0, 1375}, + /*II_DA_C0*/ {0xf0, 1375}, + /*II_DA_C0*/ {0xf0, 1375}, + /*II_DA_C0*/ {0xf0, 1375}, + /*II_DA_C0*/ {0xf0, 1375}, + /*II_DA_C0*/ {0xf0, 1375}, + /*II_DA_C0*/ {0xf0, 1375}, + /*II_DA_C8*/ {0xf1, 1383}, + /*II_DA_C8*/ {0xf1, 1383}, + /*II_DA_C8*/ {0xf1, 1383}, + /*II_DA_C8*/ {0xf1, 1383}, + /*II_DA_C8*/ {0xf1, 1383}, + /*II_DA_C8*/ {0xf1, 1383}, + /*II_DA_C8*/ {0xf1, 1383}, + /*II_DA_C8*/ {0xf1, 1383}, + /*II_DA_D0*/ {0xf2, 1391}, + /*II_DA_D0*/ {0xf2, 1391}, + /*II_DA_D0*/ {0xf2, 1391}, + /*II_DA_D0*/ {0xf2, 1391}, + /*II_DA_D0*/ {0xf2, 1391}, + /*II_DA_D0*/ {0xf2, 1391}, + /*II_DA_D0*/ {0xf2, 1391}, + /*II_DA_D0*/ {0xf2, 1391}, + /*II_DA_D8*/ {0xf3, 1400}, + /*II_DA_D8*/ {0xf3, 1400}, + /*II_DA_D8*/ {0xf3, 1400}, + /*II_DA_D8*/ {0xf3, 1400}, + /*II_DA_D8*/ {0xf3, 1400}, + /*II_DA_D8*/ {0xf3, 1400}, + /*II_DA_D8*/ {0xf3, 1400}, + /*II_DA_D8*/ {0xf3, 1400}, + /*II_DA_E9*/ {0xec, 1408}, + /*II_DB_00*/ {0xe9, 1417}, + /*II_DB_01*/ {0xf4, 1423}, + /*II_DB_02*/ {0xed, 1431}, + /*II_DB_03*/ {0xed, 1437}, + /*II_DB_05*/ {0xf5, 1073}, + /*II_DB_07*/ {0xf6, 1083}, + /*II_DB_C0*/ {0xf0, 1444}, + /*II_DB_C0*/ {0xf0, 1444}, + /*II_DB_C0*/ {0xf0, 1444}, + /*II_DB_C0*/ {0xf0, 1444}, + /*II_DB_C0*/ {0xf0, 1444}, + /*II_DB_C0*/ {0xf0, 1444}, + /*II_DB_C0*/ {0xf0, 1444}, + /*II_DB_C0*/ {0xf0, 1444}, + /*II_DB_C8*/ {0xf1, 1453}, + /*II_DB_C8*/ {0xf1, 1453}, + /*II_DB_C8*/ {0xf1, 1453}, + /*II_DB_C8*/ {0xf1, 1453}, + /*II_DB_C8*/ {0xf1, 1453}, + /*II_DB_C8*/ {0xf1, 1453}, + /*II_DB_C8*/ {0xf1, 1453}, + /*II_DB_C8*/ {0xf1, 1453}, + /*II_DB_D0*/ {0xf2, 1462}, + /*II_DB_D0*/ {0xf2, 1462}, + /*II_DB_D0*/ {0xf2, 1462}, + /*II_DB_D0*/ {0xf2, 1462}, + /*II_DB_D0*/ {0xf2, 1462}, + /*II_DB_D0*/ {0xf2, 1462}, + /*II_DB_D0*/ {0xf2, 1462}, + /*II_DB_D0*/ {0xf2, 1462}, + /*II_DB_D8*/ {0xf3, 1472}, + /*II_DB_D8*/ {0xf3, 1472}, + /*II_DB_D8*/ {0xf3, 1472}, + /*II_DB_D8*/ {0xf3, 1472}, + /*II_DB_D8*/ {0xf3, 1472}, + /*II_DB_D8*/ {0xf3, 1472}, + /*II_DB_D8*/ {0xf3, 1472}, + /*II_DB_D8*/ {0xf3, 1472}, + /*II_DB_E0*/ {0xec, 1481}, + /*II_DB_E1*/ {0xec, 1487}, + /*II_DB_E4*/ {0xec, 1495}, + /*II_DB_E8*/ {0xf7, 1503}, + /*II_DB_E8*/ {0xf7, 1503}, + /*II_DB_E8*/ {0xf7, 1503}, + /*II_DB_E8*/ {0xf7, 1503}, + /*II_DB_E8*/ {0xf7, 1503}, + /*II_DB_E8*/ {0xf7, 1503}, + /*II_DB_E8*/ {0xf7, 1503}, + /*II_DB_E8*/ {0xf7, 1503}, + /*II_DB_F0*/ {0xf8, 1511}, + /*II_DB_F0*/ {0xf8, 1511}, + /*II_DB_F0*/ {0xf8, 1511}, + /*II_DB_F0*/ {0xf8, 1511}, + /*II_DB_F0*/ {0xf8, 1511}, + /*II_DB_F0*/ {0xf8, 1511}, + /*II_DB_F0*/ {0xf8, 1511}, + /*II_DB_F0*/ {0xf8, 1511}, + /*II_DC_00*/ {0xf9, 1022}, + /*II_DC_01*/ {0xf9, 1028}, + /*II_DC_02*/ {0xf9, 1034}, + /*II_DC_03*/ {0xf9, 1040}, + /*II_DC_04*/ {0xf9, 1047}, + /*II_DC_05*/ {0xf9, 1053}, + /*II_DC_06*/ {0xf9, 1060}, + /*II_DC_07*/ {0xf9, 1066}, + /*II_DC_C0*/ {0xfa, 1022}, + /*II_DC_C0*/ {0xfa, 1022}, + /*II_DC_C0*/ {0xfa, 1022}, + /*II_DC_C0*/ {0xfa, 1022}, + /*II_DC_C0*/ {0xfa, 1022}, + /*II_DC_C0*/ {0xfa, 1022}, + /*II_DC_C0*/ {0xfa, 1022}, + /*II_DC_C0*/ {0xfa, 1022}, + /*II_DC_C8*/ {0xfa, 1028}, + /*II_DC_C8*/ {0xfa, 1028}, + /*II_DC_C8*/ {0xfa, 1028}, + /*II_DC_C8*/ {0xfa, 1028}, + /*II_DC_C8*/ {0xfa, 1028}, + /*II_DC_C8*/ {0xfa, 1028}, + /*II_DC_C8*/ {0xfa, 1028}, + /*II_DC_C8*/ {0xfa, 1028}, + /*II_DC_E0*/ {0xfa, 1053}, + /*II_DC_E0*/ {0xfa, 1053}, + /*II_DC_E0*/ {0xfa, 1053}, + /*II_DC_E0*/ {0xfa, 1053}, + /*II_DC_E0*/ {0xfa, 1053}, + /*II_DC_E0*/ {0xfa, 1053}, + /*II_DC_E0*/ {0xfa, 1053}, + /*II_DC_E0*/ {0xfa, 1053}, + /*II_DC_E8*/ {0xfa, 1047}, + /*II_DC_E8*/ {0xfa, 1047}, + /*II_DC_E8*/ {0xfa, 1047}, + /*II_DC_E8*/ {0xfa, 1047}, + /*II_DC_E8*/ {0xfa, 1047}, + /*II_DC_E8*/ {0xfa, 1047}, + /*II_DC_E8*/ {0xfa, 1047}, + /*II_DC_E8*/ {0xfa, 1047}, + /*II_DC_F0*/ {0xfa, 1066}, + /*II_DC_F0*/ {0xfa, 1066}, + /*II_DC_F0*/ {0xfa, 1066}, + /*II_DC_F0*/ {0xfa, 1066}, + /*II_DC_F0*/ {0xfa, 1066}, + /*II_DC_F0*/ {0xfa, 1066}, + /*II_DC_F0*/ {0xfa, 1066}, + /*II_DC_F0*/ {0xfa, 1066}, + /*II_DC_F8*/ {0xfa, 1060}, + /*II_DC_F8*/ {0xfa, 1060}, + /*II_DC_F8*/ {0xfa, 1060}, + /*II_DC_F8*/ {0xfa, 1060}, + /*II_DC_F8*/ {0xfa, 1060}, + /*II_DC_F8*/ {0xfa, 1060}, + /*II_DC_F8*/ {0xfa, 1060}, + /*II_DC_F8*/ {0xfa, 1060}, + /*II_DD_00*/ {0xf9, 1073}, + /*II_DD_01*/ {0xfb, 1423}, + /*II_DD_02*/ {0xfc, 1078}, + /*II_DD_03*/ {0xfc, 1083}, + /*II_DD_04*/ {0xee, 1518}, + /*II_DD_C0*/ {0xeb, 1526}, + /*II_DD_C0*/ {0xeb, 1526}, + /*II_DD_C0*/ {0xeb, 1526}, + /*II_DD_C0*/ {0xeb, 1526}, + /*II_DD_C0*/ {0xeb, 1526}, + /*II_DD_C0*/ {0xeb, 1526}, + /*II_DD_C0*/ {0xeb, 1526}, + /*II_DD_C0*/ {0xeb, 1526}, + /*II_DD_D0*/ {0xeb, 1078}, + /*II_DD_D0*/ {0xeb, 1078}, + /*II_DD_D0*/ {0xeb, 1078}, + /*II_DD_D0*/ {0xeb, 1078}, + /*II_DD_D0*/ {0xeb, 1078}, + /*II_DD_D0*/ {0xeb, 1078}, + /*II_DD_D0*/ {0xeb, 1078}, + /*II_DD_D0*/ {0xeb, 1078}, + /*II_DD_D8*/ {0xeb, 1083}, + /*II_DD_D8*/ {0xeb, 1083}, + /*II_DD_D8*/ {0xeb, 1083}, + /*II_DD_D8*/ {0xeb, 1083}, + /*II_DD_D8*/ {0xeb, 1083}, + /*II_DD_D8*/ {0xeb, 1083}, + /*II_DD_D8*/ {0xeb, 1083}, + /*II_DD_D8*/ {0xeb, 1083}, + /*II_DD_E0*/ {0xfa, 1533}, + /*II_DD_E1*/ {0xec, 1533}, + /*II_DD_E0*/ {0xfa, 1533}, + /*II_DD_E0*/ {0xfa, 1533}, + /*II_DD_E0*/ {0xfa, 1533}, + /*II_DD_E0*/ {0xfa, 1533}, + /*II_DD_E0*/ {0xfa, 1533}, + /*II_DD_E0*/ {0xfa, 1533}, + /*II_DD_E8*/ {0xeb, 1540}, + /*II_DD_E9*/ {0xec, 1540}, + /*II_DD_E8*/ {0xeb, 1540}, + /*II_DD_E8*/ {0xeb, 1540}, + /*II_DD_E8*/ {0xeb, 1540}, + /*II_DD_E8*/ {0xeb, 1540}, + /*II_DD_E8*/ {0xeb, 1540}, + /*II_DD_E8*/ {0xeb, 1540}, + /*II_DE_00*/ {0xef, 1316}, + /*II_DE_01*/ {0xef, 1323}, + /*II_DE_02*/ {0xef, 1330}, + /*II_DE_03*/ {0xef, 1337}, + /*II_DE_04*/ {0xef, 1345}, + /*II_DE_05*/ {0xef, 1352}, + /*II_DE_06*/ {0xef, 1360}, + /*II_DE_07*/ {0xef, 1367}, + /*II_DE_C0*/ {0xfa, 1548}, + /*II_DE_C1*/ {0xec, 1548}, + /*II_DE_C0*/ {0xfa, 1548}, + /*II_DE_C0*/ {0xfa, 1548}, + /*II_DE_C0*/ {0xfa, 1548}, + /*II_DE_C0*/ {0xfa, 1548}, + /*II_DE_C0*/ {0xfa, 1548}, + /*II_DE_C0*/ {0xfa, 1548}, + /*II_DE_C8*/ {0xfa, 1555}, + /*II_DE_C9*/ {0xec, 1555}, + /*II_DE_C8*/ {0xfa, 1555}, + /*II_DE_C8*/ {0xfa, 1555}, + /*II_DE_C8*/ {0xfa, 1555}, + /*II_DE_C8*/ {0xfa, 1555}, + /*II_DE_C8*/ {0xfa, 1555}, + /*II_DE_C8*/ {0xfa, 1555}, + /*II_DE_D9*/ {0xec, 1562}, + /*II_DE_E0*/ {0xfa, 1570}, + /*II_DE_E1*/ {0xec, 1570}, + /*II_DE_E0*/ {0xfa, 1570}, + /*II_DE_E0*/ {0xfa, 1570}, + /*II_DE_E0*/ {0xfa, 1570}, + /*II_DE_E0*/ {0xfa, 1570}, + /*II_DE_E0*/ {0xfa, 1570}, + /*II_DE_E0*/ {0xfa, 1570}, + /*II_DE_E8*/ {0xfa, 1578}, + /*II_DE_E9*/ {0xec, 1578}, + /*II_DE_E8*/ {0xfa, 1578}, + /*II_DE_E8*/ {0xfa, 1578}, + /*II_DE_E8*/ {0xfa, 1578}, + /*II_DE_E8*/ {0xfa, 1578}, + /*II_DE_E8*/ {0xfa, 1578}, + /*II_DE_E8*/ {0xfa, 1578}, + /*II_DE_F0*/ {0xfa, 1585}, + /*II_DE_F1*/ {0xec, 1585}, + /*II_DE_F0*/ {0xfa, 1585}, + /*II_DE_F0*/ {0xfa, 1585}, + /*II_DE_F0*/ {0xfa, 1585}, + /*II_DE_F0*/ {0xfa, 1585}, + /*II_DE_F0*/ {0xfa, 1585}, + /*II_DE_F0*/ {0xfa, 1585}, + /*II_DE_F8*/ {0xfa, 1593}, + /*II_DE_F9*/ {0xec, 1593}, + /*II_DE_F8*/ {0xfa, 1593}, + /*II_DE_F8*/ {0xfa, 1593}, + /*II_DE_F8*/ {0xfa, 1593}, + /*II_DE_F8*/ {0xfa, 1593}, + /*II_DE_F8*/ {0xfa, 1593}, + /*II_DE_F8*/ {0xfa, 1593}, + /*II_DF_00*/ {0xef, 1417}, + /*II_DF_01*/ {0xfd, 1423}, + /*II_DF_02*/ {0xfe, 1431}, + /*II_DF_03*/ {0xfe, 1437}, + /*II_DF_04*/ {0xf5, 1600}, + /*II_DF_05*/ {0xf9, 1417}, + /*II_DF_06*/ {0xf6, 1606}, + /*II_DF_07*/ {0xfc, 1437}, + /*II_DF_E8*/ {0xf7, 1613}, + /*II_DF_E8*/ {0xf7, 1613}, + /*II_DF_E8*/ {0xf7, 1613}, + /*II_DF_E8*/ {0xf7, 1613}, + /*II_DF_E8*/ {0xf7, 1613}, + /*II_DF_E8*/ {0xf7, 1613}, + /*II_DF_E8*/ {0xf7, 1613}, + /*II_DF_E8*/ {0xf7, 1613}, + /*II_DF_F0*/ {0xf7, 1622}, + /*II_DF_F0*/ {0xf7, 1622}, + /*II_DF_F0*/ {0xf7, 1622}, + /*II_DF_F0*/ {0xf7, 1622}, + /*II_DF_F0*/ {0xf7, 1622}, + /*II_DF_F0*/ {0xf7, 1622}, + /*II_DF_F0*/ {0xf7, 1622}, + /*II_DF_F0*/ {0xf7, 1622}, + /*II_F6_00*/ {0xff, 206}, + /*II_F6_02*/ {0x100, 1630}, + /*II_F6_03*/ {0x101, 1635}, + /*II_F6_04*/ {0x102, 1640}, + /*II_F6_05*/ {0x102, 117}, + /*II_F6_06*/ {0x103, 1645}, + /*II_F6_07*/ {0x103, 1650}, + /*II_F7_00*/ {0x104, 206}, + /*II_F7_02*/ {0x105, 1630}, + /*II_F7_03*/ {0x106, 1635}, + /*II_F7_04*/ {0x107, 1640}, + /*II_F7_05*/ {0x107, 117}, + /*II_F7_06*/ {0x108, 1645}, + /*II_F7_07*/ {0x108, 1650}, + /*II_FE_00*/ {0x109, 81}, + /*II_FE_01*/ {0x109, 86}, + /*II_FF_00*/ {0x10a, 81}, + /*II_FF_01*/ {0x10a, 86}, + /*II_FF_02*/ {0x10b, 455}, + /*II_FF_03*/ {0x10c, 260}, + /*II_FF_04*/ {0x10d, 461}, + /*II_FF_05*/ {0x10e, 466}, + /*II_FF_06*/ {0x10f, 16}, + /*II_0F_00_00*/ {0x110, 1656}, + /*II_0F_00_01*/ {0x111, 1662}, + /*II_0F_00_02*/ {0x112, 1667}, + /*II_0F_00_03*/ {0x113, 1673}, + /*II_0F_00_04*/ {0x114, 1678}, + /*II_0F_00_05*/ {0x114, 1684}, + /*II_0F_01_00*/ {0x115, 1690}, + /*II_0F_01_01*/ {0x115, 1696}, + /*II_0F_01_02*/ {0x116, 1702}, + /*II_0F_01_03*/ {0x116, 1708}, + /*II_0F_01_04*/ {0x117, 1714}, + /*II_0F_01_06*/ {0x118, 1720}, + /*II_0F_01_07*/ {0x119, 1726}, + /*II_0F_01_C1*/ {0x11a, 1734}, + /*II_0F_01_C2*/ {0x11a, 1742}, + /*II_0F_01_C3*/ {0x11a, 1752}, + /*II_0F_01_C4*/ {0x11a, 1762}, + /*II_0F_01_C8*/ {0x11b, 1770}, + /*II_0F_01_C9*/ {0x11b, 1779}, + /*II_0F_01_CA*/ {0x11b, 1786}, + /*II_0F_01_CB*/ {0x11b, 1792}, + /*II_0F_01_D0*/ {0x91, 1798}, + /*II_0F_01_D1*/ {0x91, 1806}, + /*II_0F_01_D4*/ {0x11a, 1814}, + /*II_0F_01_D5*/ {0x11c, 1822}, + /*II_0F_01_D8*/ {0x11d, 1828}, + /*II_0F_01_D9*/ {0x11e, 1835}, + /*II_0F_01_DA*/ {0x11f, 1844}, + /*II_0F_01_DB*/ {0x11f, 1852}, + /*II_0F_01_DC*/ {0x11e, 1860}, + /*II_0F_01_DD*/ {0x11e, 1866}, + /*II_0F_01_DE*/ {0x11f, 1872}, + /*II_0F_01_DF*/ {0x120, 1880}, + /*II_0F_01_F8*/ {0x121, 1889}, + /*II_0F_01_F9*/ {0x121, 1897}, + /*II_0F_0D_00*/ {0x122, 1905}, + /*II_0F_0D_01*/ {0x122, 1915}, + /*II_0F_0F_0C*/ {0x123, 1926}, + /*II_0F_0F_0D*/ {0x124, 1933}, + /*II_0F_0F_1C*/ {0x123, 1940}, + /*II_0F_0F_1D*/ {0x124, 1947}, + /*II_0F_0F_8A*/ {0x123, 1954}, + /*II_0F_0F_8E*/ {0x123, 1962}, + /*II_0F_0F_90*/ {0x124, 1971}, + /*II_0F_0F_94*/ {0x124, 1980}, + /*II_0F_0F_96*/ {0x124, 1987}, + /*II_0F_0F_97*/ {0x124, 1994}, + /*II_0F_0F_9A*/ {0x124, 2003}, + /*II_0F_0F_9E*/ {0x124, 2010}, + /*II_0F_0F_A0*/ {0x124, 2017}, + /*II_0F_0F_A4*/ {0x124, 2026}, + /*II_0F_0F_A6*/ {0x124, 2033}, + /*II_0F_0F_A7*/ {0x124, 2043}, + /*II_0F_0F_AA*/ {0x124, 2053}, + /*II_0F_0F_AE*/ {0x124, 2061}, + /*II_0F_0F_B0*/ {0x124, 2068}, + /*II_0F_0F_B4*/ {0x124, 2077}, + /*II_0F_0F_B6*/ {0x124, 2084}, + /*II_0F_0F_B7*/ {0x124, 2094}, + /*II_0F_0F_BB*/ {0x123, 2103}, + /*II_0F_0F_BF*/ {0x124, 2111}, + /*II_0F_10*/ {0x125, 2120}, + /*II_66_0F_10*/ {0x126, 2128}, + /*II_F3_0F_10*/ {0x127, 2136}, + /*II_F2_0F_10*/ {0x128, 2143}, + /*II_0F_11*/ {0x12d, 2120}, + /*II_66_0F_11*/ {0x12e, 2128}, + /*II_F3_0F_11*/ {0x12f, 2136}, + /*II_F2_0F_11*/ {0x130, 2143}, + /*II_66_0F_12*/ {0x135, 2201}, + /*II_F3_0F_12*/ {0x136, 2209}, + /*II_F2_0F_12*/ {0x136, 2219}, + /*II_0F_13*/ {0x13a, 2193}, + /*II_66_0F_13*/ {0x13b, 2201}, + /*II_0F_14*/ {0x13d, 2277}, + /*II_66_0F_14*/ {0x13e, 2287}, + /*II_0F_15*/ {0x13d, 2319}, + /*II_66_0F_15*/ {0x13e, 2329}, + /*II_66_0F_16*/ {0x135, 2378}, + /*II_F3_0F_16*/ {0x140, 2386}, + /*II_0F_17*/ {0x13a, 2370}, + /*II_66_0F_17*/ {0x13b, 2378}, + /*II_0F_18_00*/ {0x141, 2435}, + /*II_0F_18_01*/ {0x141, 2448}, + /*II_0F_18_02*/ {0x141, 2460}, + /*II_0F_18_03*/ {0x141, 2472}, + /*II_0F_28*/ {0x125, 2484}, + /*II_66_0F_28*/ {0x126, 2492}, + /*II_0F_29*/ {0x12d, 2484}, + /*II_66_0F_29*/ {0x12e, 2492}, + /*II_0F_2A*/ {0x142, 2518}, + /*II_66_0F_2A*/ {0x143, 2528}, + /*II_F3_0F_2A*/ {0x144, 2538}, + /*II_F2_0F_2A*/ {0x145, 2548}, + /*II_0F_2B*/ {0x146, 2580}, + /*II_66_0F_2B*/ {0x147, 2589}, + /*II_F3_0F_2B*/ {0x148, 2598}, + /*II_F2_0F_2B*/ {0x149, 2607}, + /*II_0F_2C*/ {0x14b, 2636}, + /*II_66_0F_2C*/ {0x14c, 2647}, + /*II_F3_0F_2C*/ {0x14d, 2658}, + /*II_F2_0F_2C*/ {0x14e, 2669}, + /*II_0F_2D*/ {0x14b, 2704}, + /*II_66_0F_2D*/ {0x13e, 2714}, + /*II_F3_0F_2D*/ {0x14d, 2724}, + /*II_F2_0F_2D*/ {0x14e, 2734}, + /*II_0F_2E*/ {0x150, 2766}, + /*II_66_0F_2E*/ {0x151, 2775}, + /*II_0F_2F*/ {0x150, 2804}, + /*II_66_0F_2F*/ {0x151, 2812}, + /*II_0F_50*/ {0x154, 2838}, + /*II_66_0F_50*/ {0x155, 2848}, + /*II_0F_51*/ {0x13d, 2880}, + /*II_66_0F_51*/ {0x13e, 2888}, + /*II_F3_0F_51*/ {0x157, 2896}, + /*II_F2_0F_51*/ {0x151, 2904}, + /*II_0F_52*/ {0x13d, 2948}, + /*II_F3_0F_52*/ {0x157, 2957}, + /*II_0F_53*/ {0x13d, 2986}, + /*II_F3_0F_53*/ {0x157, 2993}, + /*II_0F_54*/ {0x13d, 3016}, + /*II_66_0F_54*/ {0x13e, 3023}, + /*II_0F_55*/ {0x13d, 3046}, + /*II_66_0F_55*/ {0x13e, 3054}, + /*II_0F_56*/ {0x13d, 3080}, + /*II_66_0F_56*/ {0x13e, 3086}, + /*II_0F_57*/ {0x13d, 3106}, + /*II_66_0F_57*/ {0x13e, 3113}, + /*II_0F_58*/ {0x13d, 3136}, + /*II_66_0F_58*/ {0x13e, 3143}, + /*II_F3_0F_58*/ {0x157, 3150}, + /*II_F2_0F_58*/ {0x151, 3157}, + /*II_0F_59*/ {0x13d, 3196}, + /*II_66_0F_59*/ {0x13e, 3203}, + /*II_F3_0F_59*/ {0x157, 3210}, + /*II_F2_0F_59*/ {0x151, 3217}, + /*II_0F_5A*/ {0x151, 3256}, + /*II_66_0F_5A*/ {0x13e, 3266}, + /*II_F3_0F_5A*/ {0x158, 3276}, + /*II_F2_0F_5A*/ {0x151, 3286}, + /*II_0F_5B*/ {0x13e, 3340}, + /*II_66_0F_5B*/ {0x13e, 3350}, + /*II_F3_0F_5B*/ {0x13e, 3360}, + /*II_0F_5C*/ {0x13d, 3405}, + /*II_66_0F_5C*/ {0x13e, 3412}, + /*II_F3_0F_5C*/ {0x157, 3419}, + /*II_F2_0F_5C*/ {0x151, 3426}, + /*II_0F_5D*/ {0x13d, 3465}, + /*II_66_0F_5D*/ {0x13e, 3472}, + /*II_F3_0F_5D*/ {0x157, 3479}, + /*II_F2_0F_5D*/ {0x151, 3486}, + /*II_0F_5E*/ {0x13d, 3525}, + /*II_66_0F_5E*/ {0x13e, 3532}, + /*II_F3_0F_5E*/ {0x157, 3539}, + /*II_F2_0F_5E*/ {0x151, 3546}, + /*II_0F_5F*/ {0x13d, 3585}, + /*II_66_0F_5F*/ {0x13e, 3592}, + /*II_F3_0F_5F*/ {0x157, 3599}, + /*II_F2_0F_5F*/ {0x151, 3606}, + /*II_0F_60*/ {0x15b, 3645}, + /*II_66_0F_60*/ {0x13e, 3645}, + /*II_0F_61*/ {0x15b, 3668}, + /*II_66_0F_61*/ {0x13e, 3668}, + /*II_0F_62*/ {0x15b, 3691}, + /*II_66_0F_62*/ {0x13e, 3691}, + /*II_0F_63*/ {0x15c, 3714}, + /*II_66_0F_63*/ {0x13e, 3714}, + /*II_0F_64*/ {0x15c, 3735}, + /*II_66_0F_64*/ {0x13e, 3735}, + /*II_0F_65*/ {0x15c, 3754}, + /*II_66_0F_65*/ {0x13e, 3754}, + /*II_0F_66*/ {0x15c, 3773}, + /*II_66_0F_66*/ {0x13e, 3773}, + /*II_0F_67*/ {0x15c, 3792}, + /*II_66_0F_67*/ {0x13e, 3792}, + /*II_0F_68*/ {0x15c, 3813}, + /*II_66_0F_68*/ {0x13e, 3813}, + /*II_0F_69*/ {0x15c, 3836}, + /*II_66_0F_69*/ {0x13e, 3836}, + /*II_0F_6A*/ {0x15c, 3859}, + /*II_66_0F_6A*/ {0x13e, 3859}, + /*II_0F_6B*/ {0x15c, 3882}, + /*II_66_0F_6B*/ {0x13e, 3882}, + /*II_66_0F_6C*/ {0x13e, 3903}, + /*II_66_0F_6D*/ {0x13e, 3928}, + /*II_0F_6F*/ {0x160, 3959}, + /*II_66_0F_6F*/ {0x126, 3979}, + /*II_F3_0F_6F*/ {0x126, 3987}, + /*II_0F_74*/ {0x15c, 4076}, + /*II_66_0F_74*/ {0x13e, 4076}, + /*II_0F_75*/ {0x15c, 4095}, + /*II_66_0F_75*/ {0x13e, 4095}, + /*II_0F_76*/ {0x15c, 4114}, + /*II_66_0F_76*/ {0x13e, 4114}, + /*II_0F_77*/ {0x164, 4133}, + /*II_0F_78*/ {0x166, 4161}, + /*II_0F_79*/ {0x169, 4185}, + /*II_66_0F_79*/ {0x16a, 4169}, + /*II_F2_0F_79*/ {0x16b, 4176}, + /*II_0F_7A_30*/ {0x16c, 4194}, + /*II_0F_7A_31*/ {0x16d, 4204}, + /*II_66_0F_7C*/ {0x16e, 4214}, + /*II_F2_0F_7C*/ {0x16e, 4222}, + /*II_66_0F_7D*/ {0x16e, 4248}, + /*II_F2_0F_7D*/ {0x16e, 4256}, + /*II_F3_0F_7E*/ {0x128, 3959}, + /*II_0F_7F*/ {0x172, 3959}, + /*II_66_0F_7F*/ {0x12e, 3979}, + /*II_F3_0F_7F*/ {0x12e, 3987}, + /*II_F3_0F_B8*/ {0x176, 4371}, + /*II_0F_BA_04*/ {0x177, 871}, + /*II_0F_BA_05*/ {0x178, 886}, + /*II_0F_BA_06*/ {0x178, 911}, + /*II_0F_BA_07*/ {0x178, 933}, + /*II_0F_BC*/ {0x179, 4379}, + /*II_F3_0F_BC*/ {0x17a, 4384}, + /*II_0F_BD*/ {0x179, 4391}, + /*II_F3_0F_BD*/ {0x17b, 4396}, + /*II_0F_C7_07*/ {0x18b, 6418}, + /*II_66_0F_D0*/ {0x16e, 6427}, + /*II_F2_0F_D0*/ {0x16e, 6437}, + /*II_0F_D1*/ {0x15c, 6469}, + /*II_66_0F_D1*/ {0x13e, 6469}, + /*II_0F_D2*/ {0x15c, 6484}, + /*II_66_0F_D2*/ {0x13e, 6484}, + /*II_0F_D3*/ {0x15c, 6499}, + /*II_66_0F_D3*/ {0x13e, 6499}, + /*II_0F_D4*/ {0x151, 6514}, + /*II_66_0F_D4*/ {0x13e, 6514}, + /*II_0F_D5*/ {0x15c, 6529}, + /*II_66_0F_D5*/ {0x13e, 6529}, + /*II_66_0F_D6*/ {0x130, 3959}, + /*II_F3_0F_D6*/ {0x18c, 6546}, + /*II_F2_0F_D6*/ {0x18d, 6555}, + /*II_0F_D7*/ {0x18f, 6564}, + /*II_66_0F_D7*/ {0x190, 6564}, + /*II_0F_D8*/ {0x15c, 6585}, + /*II_66_0F_D8*/ {0x13e, 6585}, + /*II_0F_D9*/ {0x15c, 6604}, + /*II_66_0F_D9*/ {0x13e, 6604}, + /*II_0F_DA*/ {0x192, 6623}, + /*II_66_0F_DA*/ {0x13e, 6623}, + /*II_0F_DB*/ {0x15c, 6640}, + /*II_66_0F_DB*/ {0x13e, 6640}, + /*II_0F_DC*/ {0x15c, 6653}, + /*II_66_0F_DC*/ {0x13e, 6653}, + /*II_0F_DD*/ {0x15c, 6672}, + /*II_66_0F_DD*/ {0x13e, 6672}, + /*II_0F_DE*/ {0x192, 6681}, + /*II_66_0F_DE*/ {0x13e, 6681}, + /*II_0F_DF*/ {0x15c, 6698}, + /*II_66_0F_DF*/ {0x13e, 6698}, + /*II_0F_E0*/ {0x192, 6713}, + /*II_66_0F_E0*/ {0x13e, 6713}, + /*II_0F_E1*/ {0x15c, 6728}, + /*II_66_0F_E1*/ {0x13e, 6728}, + /*II_0F_E2*/ {0x15c, 6743}, + /*II_66_0F_E2*/ {0x13e, 6743}, + /*II_0F_E3*/ {0x192, 6758}, + /*II_66_0F_E3*/ {0x13e, 6758}, + /*II_0F_E4*/ {0x192, 6773}, + /*II_66_0F_E4*/ {0x13e, 6773}, + /*II_0F_E5*/ {0x15c, 6792}, + /*II_66_0F_E5*/ {0x13e, 6792}, + /*II_66_0F_E6*/ {0x13e, 6809}, + /*II_F3_0F_E6*/ {0x151, 6820}, + /*II_F2_0F_E6*/ {0x13e, 6830}, + /*II_0F_E7*/ {0x193, 6874}, + /*II_66_0F_E7*/ {0x147, 6882}, + /*II_0F_E8*/ {0x15c, 6901}, + /*II_66_0F_E8*/ {0x13e, 6901}, + /*II_0F_E9*/ {0x15c, 6918}, + /*II_66_0F_E9*/ {0x13e, 6918}, + /*II_0F_EA*/ {0x192, 6935}, + /*II_66_0F_EA*/ {0x13e, 6935}, + /*II_0F_EB*/ {0x15c, 6952}, + /*II_66_0F_EB*/ {0x13e, 6952}, + /*II_0F_EC*/ {0x15c, 6963}, + /*II_66_0F_EC*/ {0x13e, 6963}, + /*II_0F_ED*/ {0x15c, 6980}, + /*II_66_0F_ED*/ {0x13e, 6980}, + /*II_0F_EE*/ {0x192, 6997}, + /*II_66_0F_EE*/ {0x13e, 6997}, + /*II_0F_EF*/ {0x15c, 7014}, + /*II_66_0F_EF*/ {0x13e, 7014}, + /*II_F2_0F_F0*/ {0x194, 7027}, + /*II_0F_F1*/ {0x15c, 7042}, + /*II_66_0F_F1*/ {0x13e, 7042}, + /*II_0F_F2*/ {0x15c, 7057}, + /*II_66_0F_F2*/ {0x13e, 7057}, + /*II_0F_F3*/ {0x15c, 7072}, + /*II_66_0F_F3*/ {0x13e, 7072}, + /*II_0F_F4*/ {0x196, 7087}, + /*II_66_0F_F4*/ {0x13e, 7087}, + /*II_0F_F5*/ {0x15c, 7106}, + /*II_66_0F_F5*/ {0x13e, 7106}, + /*II_0F_F6*/ {0x192, 7125}, + /*II_66_0F_F6*/ {0x13e, 7125}, + /*II_0F_F7*/ {0x197, 7142}, + /*II_66_0F_F7*/ {0x198, 7152}, + /*II_0F_F8*/ {0x15c, 7177}, + /*II_66_0F_F8*/ {0x13e, 7177}, + /*II_0F_F9*/ {0x15c, 7192}, + /*II_66_0F_F9*/ {0x13e, 7192}, + /*II_0F_FA*/ {0x15c, 7207}, + /*II_66_0F_FA*/ {0x13e, 7207}, + /*II_0F_FB*/ {0x196, 7222}, + /*II_66_0F_FB*/ {0x13e, 7222}, + /*II_0F_FC*/ {0x15c, 7237}, + /*II_66_0F_FC*/ {0x13e, 7237}, + /*II_0F_FD*/ {0x15c, 7252}, + /*II_66_0F_FD*/ {0x13e, 7252}, + /*II_0F_FE*/ {0x15c, 7267}, + /*II_66_0F_FE*/ {0x13e, 7267}, + /*II_D9_06*/ {0x19a, 7282}, + /*II_9B_D9_06*/ {0x19b, 7291}, + /*II_D9_07*/ {0xfe, 7299}, + /*II_9B_D9_07*/ {0x19c, 7307}, + /*II_DB_E2*/ {0xec, 7314}, + /*II_9B_DB_E2*/ {0x19d, 7322}, + /*II_DB_E3*/ {0xec, 7329}, + /*II_9B_DB_E3*/ {0x19d, 7337}, + /*II_DD_06*/ {0x19a, 7344}, + /*II_9B_DD_06*/ {0x19b, 7352}, + /*II_DD_07*/ {0xfe, 7359}, + /*II_9B_DD_07*/ {0x19c, 7367}, + /*II_DF_E0*/ {0x19e, 7359}, + /*II_9B_DF_E0*/ {0x19f, 7367}, + /*II_0F_38_00*/ {0x1a0, 7374}, + /*II_66_0F_38_00*/ {0x1a1, 7374}, + /*II_0F_38_01*/ {0x1a0, 7391}, + /*II_66_0F_38_01*/ {0x1a1, 7391}, + /*II_0F_38_02*/ {0x1a0, 7408}, + /*II_66_0F_38_02*/ {0x1a1, 7408}, + /*II_0F_38_03*/ {0x1a0, 7425}, + /*II_66_0F_38_03*/ {0x1a1, 7425}, + /*II_0F_38_04*/ {0x1a0, 7444}, + /*II_66_0F_38_04*/ {0x1a1, 7444}, + /*II_0F_38_05*/ {0x1a0, 7467}, + /*II_66_0F_38_05*/ {0x1a1, 7467}, + /*II_0F_38_06*/ {0x1a0, 7484}, + /*II_66_0F_38_06*/ {0x1a1, 7484}, + /*II_0F_38_07*/ {0x1a0, 7501}, + /*II_66_0F_38_07*/ {0x1a1, 7501}, + /*II_0F_38_08*/ {0x1a0, 7520}, + /*II_66_0F_38_08*/ {0x1a1, 7520}, + /*II_0F_38_09*/ {0x1a0, 7537}, + /*II_66_0F_38_09*/ {0x1a1, 7537}, + /*II_0F_38_0A*/ {0x1a0, 7554}, + /*II_66_0F_38_0A*/ {0x1a1, 7554}, + /*II_0F_38_0B*/ {0x1a0, 7571}, + /*II_66_0F_38_0B*/ {0x1a1, 7571}, + /*II_66_0F_38_17*/ {0x1a3, 7662}, + /*II_0F_38_1C*/ {0x1a0, 7721}, + /*II_66_0F_38_1C*/ {0x1a1, 7721}, + /*II_0F_38_1D*/ {0x1a0, 7736}, + /*II_66_0F_38_1D*/ {0x1a1, 7736}, + /*II_0F_38_1E*/ {0x1a0, 7751}, + /*II_66_0F_38_1E*/ {0x1a1, 7751}, + /*II_66_0F_38_20*/ {0x1a8, 7766}, + /*II_66_0F_38_21*/ {0x1a9, 7787}, + /*II_66_0F_38_22*/ {0x1aa, 7808}, + /*II_66_0F_38_23*/ {0x1a8, 7829}, + /*II_66_0F_38_24*/ {0x1a9, 7850}, + /*II_66_0F_38_25*/ {0x1a8, 7871}, + /*II_66_0F_38_28*/ {0x1ac, 7892}, + /*II_66_0F_38_29*/ {0x1ac, 7909}, + /*II_66_0F_38_2A*/ {0x1ad, 7928}, + /*II_66_0F_38_2B*/ {0x1ac, 7949}, + /*II_66_0F_38_30*/ {0x1a8, 7994}, + /*II_66_0F_38_31*/ {0x1a9, 8015}, + /*II_66_0F_38_32*/ {0x1aa, 8036}, + /*II_66_0F_38_33*/ {0x1a8, 8057}, + /*II_66_0F_38_34*/ {0x1a9, 8078}, + /*II_66_0F_38_35*/ {0x1a8, 8099}, + /*II_66_0F_38_37*/ {0x1a3, 8120}, + /*II_66_0F_38_38*/ {0x1ac, 8139}, + /*II_66_0F_38_39*/ {0x1ac, 8156}, + /*II_66_0F_38_3A*/ {0x1ac, 8173}, + /*II_66_0F_38_3B*/ {0x1ac, 8190}, + /*II_66_0F_38_3C*/ {0x1ac, 8207}, + /*II_66_0F_38_3D*/ {0x1ac, 8224}, + /*II_66_0F_38_3E*/ {0x1ac, 8241}, + /*II_66_0F_38_3F*/ {0x1ac, 8258}, + /*II_66_0F_38_40*/ {0x1ac, 8275}, + /*II_66_0F_38_41*/ {0x1ac, 8292}, + /*II_66_0F_38_80*/ {0x1b0, 8317}, + /*II_66_0F_38_81*/ {0x1b0, 8325}, + /*II_66_0F_38_82*/ {0x1b0, 8334}, + /*II_66_0F_38_DB*/ {0x1b3, 9183}, + /*II_66_0F_38_DC*/ {0x1b3, 9200}, + /*II_66_0F_38_DD*/ {0x1b3, 9217}, + /*II_66_0F_38_DE*/ {0x1b3, 9242}, + /*II_66_0F_38_DF*/ {0x1b3, 9259}, + /*II_0F_38_F0*/ {0x1b6, 9284}, + /*II_F2_0F_38_F0*/ {0x1b7, 9291}, + /*II_0F_38_F1*/ {0x1b8, 9284}, + /*II_F2_0F_38_F1*/ {0x1b9, 9291}, + /*II_0F_71_02*/ {0x1d0, 6469}, + /*II_66_0F_71_02*/ {0x1d1, 6469}, + /*II_0F_71_04*/ {0x1d0, 6728}, + /*II_66_0F_71_04*/ {0x1d1, 6728}, + /*II_0F_71_06*/ {0x1d0, 7042}, + /*II_66_0F_71_06*/ {0x1d1, 7042}, + /*II_0F_72_02*/ {0x1d0, 6484}, + /*II_66_0F_72_02*/ {0x1d1, 6484}, + /*II_0F_72_04*/ {0x1d0, 6743}, + /*II_66_0F_72_04*/ {0x1d1, 6743}, + /*II_0F_72_06*/ {0x1d0, 7057}, + /*II_66_0F_72_06*/ {0x1d1, 7057}, + /*II_0F_73_02*/ {0x1d0, 6499}, + /*II_66_0F_73_02*/ {0x1d1, 6499}, + /*II_66_0F_73_03*/ {0x1d1, 9863}, + /*II_0F_73_06*/ {0x1d0, 7072}, + /*II_66_0F_73_06*/ {0x1d1, 7072}, + /*II_66_0F_73_07*/ {0x1d1, 9880}, + /*II_F3_0F_AE_00*/ {0x1d3, 9915}, + /*II_F3_0F_AE_01*/ {0x1d3, 9945}, + /*II_0F_AE_02*/ {0x1d4, 9955}, + /*II_F3_0F_AE_02*/ {0x1d3, 9964}, + /*II_0F_AE_03*/ {0x1d4, 9984}, + /*II_F3_0F_AE_03*/ {0x1d3, 9993}, + /*II_0F_C7_06*/ {0x1d6, 10013}, + /*II_66_0F_C7_06*/ {0x18b, 10022}, + /*II_F3_0F_C7_06*/ {0x18b, 10031} +}; + +_InstInfoEx InstInfosEx[381] = +{ + /*II_69*/ {{0x34, 117}, 0x0, 3, 0, 0, 0}, + /*II_6B*/ {{0x34, 117}, 0x0, 5, 0, 0, 0}, + /*II_98*/ {{0x4e, 228}, 0x0, 0, 0, 233, 239}, + /*II_99*/ {{0x4e, 245}, 0x0, 0, 0, 250, 255}, + /*II_E3*/ {{0x75, 426}, 0x0, 0, 0, 432, 439}, + /*II_0F_A4*/ {{0xad, 875}, 0x0, 1, 0, 0, 0}, + /*II_0F_A5*/ {{0xad, 875}, 0x0, 42, 0, 0, 0}, + /*II_0F_AC*/ {{0xad, 891}, 0x0, 1, 0, 0, 0}, + /*II_0F_AD*/ {{0xad, 891}, 0x0, 42, 0, 0, 0}, + /*II_V_0F_10*/ {{0x129, 2150}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_10*/ {{0x129, 2159}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_10*/ {{0x12a, 2168}, 0x20, 31, 0, 0, 0}, + /*II_V_F2_0F_10*/ {{0x12a, 2176}, 0x20, 31, 0, 0, 0}, + /*II_VRR_F3_0F_10*/ {{0x12b, 2168}, 0x60, 0, 0, 0, 0}, + /*II_VRR_F2_0F_10*/ {{0x12c, 2176}, 0x60, 0, 0, 0, 0}, + /*II_V_0F_11*/ {{0x131, 2150}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_11*/ {{0x131, 2159}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_11*/ {{0x12a, 2168}, 0x20, 31, 0, 0, 0}, + /*II_V_F2_0F_11*/ {{0x12a, 2176}, 0x20, 31, 0, 0, 0}, + /*II_VRR_F3_0F_11*/ {{0x132, 2168}, 0x60, 0, 0, 0, 0}, + /*II_VRR_F2_0F_11*/ {{0x133, 2176}, 0x60, 0, 0, 0, 0}, + /*II_0F_12*/ {{0x134, 2184}, 0x0, 0, 0, 2193, 0}, + /*II_V_0F_12*/ {{0x137, 2228}, 0x0, 86, 0, 2238, 0}, + /*II_V_66_0F_12*/ {{0x138, 2247}, 0x0, 57, 0, 0, 0}, + /*II_V_F3_0F_12*/ {{0x129, 2256}, 0x41, 0, 0, 0, 0}, + /*II_V_F2_0F_12*/ {{0x139, 2267}, 0x41, 0, 0, 0, 0}, + /*II_V_0F_13*/ {{0x13c, 2238}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_13*/ {{0x13c, 2247}, 0x40, 0, 0, 0, 0}, + /*II_V_0F_14*/ {{0x13f, 2297}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_14*/ {{0x13f, 2308}, 0x1, 91, 0, 0, 0}, + /*II_V_0F_15*/ {{0x13f, 2339}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_15*/ {{0x13f, 2350}, 0x1, 91, 0, 0, 0}, + /*II_0F_16*/ {{0x134, 2361}, 0x0, 0, 0, 2370, 0}, + /*II_V_0F_16*/ {{0x137, 2396}, 0x0, 86, 0, 2406, 0}, + /*II_V_66_0F_16*/ {{0x138, 2415}, 0x0, 57, 0, 0, 0}, + /*II_V_F3_0F_16*/ {{0x129, 2424}, 0x41, 0, 0, 0, 0}, + /*II_V_0F_17*/ {{0x13c, 2406}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_17*/ {{0x13c, 2415}, 0x40, 0, 0, 0, 0}, + /*II_V_0F_28*/ {{0x129, 2500}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_28*/ {{0x129, 2509}, 0x41, 0, 0, 0, 0}, + /*II_V_0F_29*/ {{0x131, 2500}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_29*/ {{0x131, 2509}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_2A*/ {{0x138, 2558}, 0x2, 73, 0, 0, 0}, + /*II_V_F2_0F_2A*/ {{0x138, 2569}, 0x2, 73, 0, 0, 0}, + /*II_V_0F_2B*/ {{0x14a, 2616}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_2B*/ {{0x14a, 2626}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_2C*/ {{0x14f, 2680}, 0x42, 0, 0, 0, 0}, + /*II_V_F2_0F_2C*/ {{0x14f, 2692}, 0x42, 0, 0, 0, 0}, + /*II_V_F3_0F_2D*/ {{0x14f, 2744}, 0x42, 0, 0, 0, 0}, + /*II_V_F2_0F_2D*/ {{0x14f, 2755}, 0x42, 0, 0, 0, 0}, + /*II_V_0F_2E*/ {{0x152, 2784}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_2E*/ {{0x153, 2794}, 0x40, 0, 0, 0, 0}, + /*II_V_0F_2F*/ {{0x152, 2820}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_2F*/ {{0x153, 2829}, 0x40, 0, 0, 0, 0}, + /*II_V_0F_50*/ {{0x156, 2858}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_50*/ {{0x156, 2869}, 0x41, 0, 0, 0, 0}, + /*II_V_0F_51*/ {{0x129, 2912}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_51*/ {{0x129, 2921}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_51*/ {{0x138, 2930}, 0x0, 85, 0, 0, 0}, + /*II_V_F2_0F_51*/ {{0x138, 2939}, 0x0, 86, 0, 0, 0}, + /*II_V_0F_52*/ {{0x129, 2966}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_52*/ {{0x138, 2976}, 0x0, 85, 0, 0, 0}, + /*II_V_0F_53*/ {{0x129, 3000}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_53*/ {{0x138, 3008}, 0x0, 85, 0, 0, 0}, + /*II_V_0F_54*/ {{0x13f, 3030}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_54*/ {{0x13f, 3038}, 0x1, 91, 0, 0, 0}, + /*II_V_0F_55*/ {{0x13f, 3062}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_55*/ {{0x13f, 3071}, 0x1, 91, 0, 0, 0}, + /*II_V_0F_56*/ {{0x13f, 3092}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_56*/ {{0x13f, 3099}, 0x1, 91, 0, 0, 0}, + /*II_V_0F_57*/ {{0x13f, 3120}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_57*/ {{0x13f, 3128}, 0x1, 91, 0, 0, 0}, + /*II_V_0F_58*/ {{0x13f, 3164}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_58*/ {{0x13f, 3172}, 0x1, 91, 0, 0, 0}, + /*II_V_F3_0F_58*/ {{0x138, 3180}, 0x0, 85, 0, 0, 0}, + /*II_V_F2_0F_58*/ {{0x138, 3188}, 0x0, 86, 0, 0, 0}, + /*II_V_0F_59*/ {{0x13f, 3224}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_59*/ {{0x13f, 3232}, 0x1, 91, 0, 0, 0}, + /*II_V_F3_0F_59*/ {{0x138, 3240}, 0x0, 85, 0, 0, 0}, + /*II_V_F2_0F_59*/ {{0x138, 3248}, 0x0, 86, 0, 0, 0}, + /*II_V_0F_5A*/ {{0x159, 3296}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_5A*/ {{0x15a, 3307}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_5A*/ {{0x138, 3318}, 0x0, 85, 0, 0, 0}, + /*II_V_F2_0F_5A*/ {{0x138, 3329}, 0x0, 86, 0, 0, 0}, + /*II_V_0F_5B*/ {{0x129, 3371}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_5B*/ {{0x129, 3382}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_5B*/ {{0x129, 3393}, 0x41, 0, 0, 0, 0}, + /*II_V_0F_5C*/ {{0x13f, 3433}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_5C*/ {{0x13f, 3441}, 0x1, 91, 0, 0, 0}, + /*II_V_F3_0F_5C*/ {{0x138, 3449}, 0x0, 85, 0, 0, 0}, + /*II_V_F2_0F_5C*/ {{0x138, 3457}, 0x0, 86, 0, 0, 0}, + /*II_V_0F_5D*/ {{0x13f, 3493}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_5D*/ {{0x13f, 3501}, 0x1, 91, 0, 0, 0}, + /*II_V_F3_0F_5D*/ {{0x138, 3509}, 0x0, 85, 0, 0, 0}, + /*II_V_F2_0F_5D*/ {{0x138, 3517}, 0x0, 86, 0, 0, 0}, + /*II_V_0F_5E*/ {{0x13f, 3553}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_5E*/ {{0x13f, 3561}, 0x1, 91, 0, 0, 0}, + /*II_V_F3_0F_5E*/ {{0x138, 3569}, 0x0, 85, 0, 0, 0}, + /*II_V_F2_0F_5E*/ {{0x138, 3577}, 0x0, 86, 0, 0, 0}, + /*II_V_0F_5F*/ {{0x13f, 3613}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_5F*/ {{0x13f, 3621}, 0x1, 91, 0, 0, 0}, + /*II_V_F3_0F_5F*/ {{0x138, 3629}, 0x0, 85, 0, 0, 0}, + /*II_V_F2_0F_5F*/ {{0x138, 3637}, 0x0, 86, 0, 0, 0}, + /*II_V_66_0F_60*/ {{0x138, 3656}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_61*/ {{0x138, 3679}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_62*/ {{0x138, 3702}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_63*/ {{0x138, 3724}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_64*/ {{0x138, 3744}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_65*/ {{0x138, 3763}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_66*/ {{0x138, 3782}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_67*/ {{0x138, 3802}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_68*/ {{0x138, 3824}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_69*/ {{0x138, 3847}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_6A*/ {{0x138, 3870}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_6B*/ {{0x138, 3892}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_6C*/ {{0x138, 3915}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_6D*/ {{0x138, 3940}, 0x0, 87, 0, 0, 0}, + /*II_0F_6E*/ {{0x15d, 3953}, 0x0, 0, 0, 0, 3959}, + /*II_66_0F_6E*/ {{0x15e, 3953}, 0x0, 0, 0, 0, 3959}, + /*II_V_66_0F_6E*/ {{0x15f, 3965}, 0x46, 0, 0, 3972, 0}, + /*II_V_66_0F_6F*/ {{0x129, 3995}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_6F*/ {{0x129, 4004}, 0x41, 0, 0, 0, 0}, + /*II_0F_70*/ {{0x161, 4013}, 0x0, 1, 0, 0, 0}, + /*II_66_0F_70*/ {{0x162, 4021}, 0x0, 1, 0, 0, 0}, + /*II_F3_0F_70*/ {{0x162, 4029}, 0x0, 1, 0, 0, 0}, + /*II_F2_0F_70*/ {{0x162, 4038}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_70*/ {{0x163, 4047}, 0x40, 1, 0, 0, 0}, + /*II_V_F3_0F_70*/ {{0x163, 4056}, 0x40, 1, 0, 0, 0}, + /*II_V_F2_0F_70*/ {{0x163, 4066}, 0x40, 1, 0, 0, 0}, + /*II_V_66_0F_74*/ {{0x138, 4085}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_75*/ {{0x138, 4104}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_76*/ {{0x138, 4123}, 0x0, 87, 0, 0, 0}, + /*II_V_0F_77*/ {{0x165, 4139}, 0x49, 0, 0, 4151, 0}, + /*II_66_0F_78*/ {{0x167, 4169}, 0x0, 49, 0, 0, 0}, + /*II_F2_0F_78*/ {{0x168, 4176}, 0x0, 48, 49, 0, 0}, + /*II_V_66_0F_7C*/ {{0x13f, 4230}, 0x1, 91, 0, 0, 0}, + /*II_V_F2_0F_7C*/ {{0x13f, 4239}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_7D*/ {{0x13f, 4264}, 0x1, 91, 0, 0, 0}, + /*II_V_F2_0F_7D*/ {{0x13f, 4273}, 0x1, 91, 0, 0, 0}, + /*II_0F_7E*/ {{0x16f, 3953}, 0x0, 0, 0, 0, 3959}, + /*II_66_0F_7E*/ {{0x170, 3953}, 0x0, 0, 0, 0, 3959}, + /*II_V_66_0F_7E*/ {{0x171, 3965}, 0x46, 0, 0, 3972, 0}, + /*II_V_F3_0F_7E*/ {{0x153, 3972}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_7F*/ {{0x131, 3995}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_7F*/ {{0x131, 4004}, 0x41, 0, 0, 0, 0}, + /*II_0F_AE_04*/ {{0x173, 4282}, 0x0, 0, 0, 0, 4289}, + /*II_0F_AE_05*/ {{0x174, 4298}, 0x0, 0, 0, 4306, 4314}, + /*II_0F_AE_06*/ {{0x174, 4324}, 0x0, 0, 0, 4332, 4342}, + /*II_0F_AE_07*/ {{0x175, 4354}, 0x0, 0, 0, 4362, 0}, + /*II_0F_C2*/ {{0x17c, 4403}, 0x0, 0, 0, 4412, 4421}, + /*II_66_0F_C2*/ {{0x17d, 4482}, 0x0, 0, 0, 4491, 4500}, + /*II_F3_0F_C2*/ {{0x17e, 4561}, 0x0, 0, 0, 4570, 4579}, + /*II_F2_0F_C2*/ {{0x17f, 4640}, 0x0, 0, 0, 4649, 4658}, + /*II_V_0F_C2*/ {{0x180, 4719}, 0x1, 91, 0, 4729, 4739}, + /*II_V_66_0F_C2*/ {{0x180, 5121}, 0x1, 91, 0, 5131, 5141}, + /*II_V_F3_0F_C2*/ {{0x181, 5523}, 0x0, 85, 0, 5533, 5543}, + /*II_V_F2_0F_C2*/ {{0x181, 5925}, 0x0, 86, 0, 5935, 5945}, + /*II_0F_C4*/ {{0x182, 6327}, 0x0, 1, 0, 0, 0}, + /*II_66_0F_C4*/ {{0x183, 6327}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_C4*/ {{0x184, 6335}, 0x0, 79, 1, 0, 0}, + /*II_0F_C5*/ {{0x185, 6344}, 0x0, 1, 0, 0, 0}, + /*II_66_0F_C5*/ {{0x186, 6344}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_C5*/ {{0x187, 6352}, 0x40, 1, 0, 0, 0}, + /*II_0F_C6*/ {{0x188, 6361}, 0x0, 1, 0, 0, 0}, + /*II_66_0F_C6*/ {{0x162, 6369}, 0x0, 1, 0, 0, 0}, + /*II_V_0F_C6*/ {{0x189, 6377}, 0x1, 91, 1, 0, 0}, + /*II_V_66_0F_C6*/ {{0x189, 6386}, 0x1, 91, 1, 0, 0}, + /*II_0F_C7_01*/ {{0x18a, 6395}, 0x0, 0, 0, 0, 6406}, + /*II_V_66_0F_D0*/ {{0x13f, 6447}, 0x1, 91, 0, 0, 0}, + /*II_V_F2_0F_D0*/ {{0x13f, 6458}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_D1*/ {{0x138, 6476}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_D2*/ {{0x138, 6491}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_D3*/ {{0x138, 6506}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_D4*/ {{0x138, 6521}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_D5*/ {{0x138, 6537}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_D6*/ {{0x18e, 3972}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_D7*/ {{0x191, 6574}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_D8*/ {{0x138, 6594}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_D9*/ {{0x138, 6613}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_DA*/ {{0x138, 6631}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_DB*/ {{0x138, 6646}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_DC*/ {{0x138, 6662}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_DD*/ {{0x138, 6662}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_DE*/ {{0x138, 6689}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_DF*/ {{0x138, 6705}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_E0*/ {{0x138, 6720}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_E1*/ {{0x138, 6735}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_E2*/ {{0x138, 6750}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_E3*/ {{0x138, 6765}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_E4*/ {{0x138, 6782}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_E5*/ {{0x138, 6800}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_E6*/ {{0x15a, 6840}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_E6*/ {{0x159, 6852}, 0x41, 0, 0, 0, 0}, + /*II_V_F2_0F_E6*/ {{0x15a, 6863}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_E7*/ {{0x14a, 6891}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_E8*/ {{0x138, 6909}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_E9*/ {{0x138, 6926}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_EA*/ {{0x138, 6943}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_EB*/ {{0x138, 6957}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_EC*/ {{0x138, 6971}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_ED*/ {{0x138, 6988}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_EE*/ {{0x138, 7005}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_EF*/ {{0x138, 7020}, 0x0, 87, 0, 0, 0}, + /*II_V_F2_0F_F0*/ {{0x195, 7034}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_F1*/ {{0x138, 7049}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_F2*/ {{0x138, 7064}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_F3*/ {{0x138, 7079}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_F4*/ {{0x138, 7096}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_F5*/ {{0x138, 7115}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_F6*/ {{0x138, 7133}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_F7*/ {{0x199, 7164}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_F8*/ {{0x138, 7184}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_F9*/ {{0x138, 7199}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_FA*/ {{0x138, 7214}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_FB*/ {{0x138, 7229}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_FC*/ {{0x138, 7244}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_FD*/ {{0x138, 7259}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_FE*/ {{0x138, 7274}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_00*/ {{0x138, 7382}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_01*/ {{0x138, 7399}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_02*/ {{0x138, 7416}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_03*/ {{0x138, 7434}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_04*/ {{0x138, 7455}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_05*/ {{0x138, 7475}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_06*/ {{0x138, 7492}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_07*/ {{0x138, 7510}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_08*/ {{0x138, 7528}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_09*/ {{0x138, 7545}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_0A*/ {{0x138, 7562}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_0B*/ {{0x138, 7581}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_0C*/ {{0x13f, 7592}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_38_0D*/ {{0x13f, 7603}, 0x1, 91, 0, 0, 0}, + /*II_V_66_0F_38_0E*/ {{0x129, 7614}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_38_0F*/ {{0x129, 7623}, 0x41, 0, 0, 0, 0}, + /*II_66_0F_38_10*/ {{0x1a2, 7632}, 0x0, 32, 0, 0, 0}, + /*II_66_0F_38_14*/ {{0x1a2, 7642}, 0x0, 32, 0, 0, 0}, + /*II_66_0F_38_15*/ {{0x1a2, 7652}, 0x0, 32, 0, 0, 0}, + /*II_V_66_0F_38_17*/ {{0x129, 7669}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_38_18*/ {{0x1a4, 7677}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_38_19*/ {{0x1a5, 7691}, 0x50, 0, 0, 0, 0}, + /*II_V_66_0F_38_1A*/ {{0x1a6, 7705}, 0x50, 0, 0, 0, 0}, + /*II_V_66_0F_38_1C*/ {{0x1a7, 7728}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_1D*/ {{0x1a7, 7743}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_1E*/ {{0x1a7, 7758}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_20*/ {{0x153, 7776}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_21*/ {{0x152, 7797}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_22*/ {{0x1ab, 7818}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_23*/ {{0x153, 7839}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_24*/ {{0x152, 7860}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_25*/ {{0x153, 7881}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_28*/ {{0x138, 7900}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_29*/ {{0x138, 7918}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_2A*/ {{0x1ae, 7938}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_2B*/ {{0x138, 7959}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_2C*/ {{0x13f, 7970}, 0x1, 67, 0, 0, 0}, + /*II_V_66_0F_38_2D*/ {{0x13f, 7982}, 0x1, 67, 0, 0, 0}, + /*II_V_66_0F_38_2E*/ {{0x1af, 7970}, 0x1, 36, 0, 0, 0}, + /*II_V_66_0F_38_2F*/ {{0x1af, 7982}, 0x1, 36, 0, 0, 0}, + /*II_V_66_0F_38_30*/ {{0x153, 8004}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_31*/ {{0x152, 8025}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_32*/ {{0x1ab, 8046}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_33*/ {{0x153, 8067}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_34*/ {{0x152, 8088}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_35*/ {{0x153, 8109}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_37*/ {{0x138, 8129}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_38*/ {{0x138, 8147}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_39*/ {{0x138, 8164}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_3A*/ {{0x138, 8181}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_3B*/ {{0x138, 8198}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_3C*/ {{0x138, 8215}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_3D*/ {{0x138, 8232}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_3E*/ {{0x138, 8249}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_3F*/ {{0x138, 8266}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_40*/ {{0x138, 8283}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_41*/ {{0x1a7, 8304}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_96*/ {{0x1b1, 8343}, 0x7, 91, 0, 8359, 0}, + /*II_V_66_0F_38_97*/ {{0x1b1, 8375}, 0x7, 91, 0, 8391, 0}, + /*II_V_66_0F_38_98*/ {{0x1b1, 8407}, 0x7, 91, 0, 8420, 0}, + /*II_V_66_0F_38_99*/ {{0x1b2, 8433}, 0x6, 88, 0, 8446, 0}, + /*II_V_66_0F_38_9A*/ {{0x1b1, 8459}, 0x7, 91, 0, 8472, 0}, + /*II_V_66_0F_38_9B*/ {{0x1b2, 8485}, 0x6, 88, 0, 8498, 0}, + /*II_V_66_0F_38_9C*/ {{0x1b1, 8511}, 0x7, 91, 0, 8525, 0}, + /*II_V_66_0F_38_9D*/ {{0x1b2, 8539}, 0x6, 88, 0, 8553, 0}, + /*II_V_66_0F_38_9E*/ {{0x1b1, 8567}, 0x7, 91, 0, 8581, 0}, + /*II_V_66_0F_38_9F*/ {{0x1b2, 8595}, 0x6, 88, 0, 8609, 0}, + /*II_V_66_0F_38_A6*/ {{0x1b1, 8623}, 0x7, 91, 0, 8639, 0}, + /*II_V_66_0F_38_A7*/ {{0x1b1, 8655}, 0x7, 91, 0, 8671, 0}, + /*II_V_66_0F_38_A8*/ {{0x1b1, 8687}, 0x7, 91, 0, 8700, 0}, + /*II_V_66_0F_38_A9*/ {{0x1b2, 8713}, 0x6, 88, 0, 8726, 0}, + /*II_V_66_0F_38_AA*/ {{0x1b1, 8739}, 0x7, 91, 0, 8752, 0}, + /*II_V_66_0F_38_AB*/ {{0x1b2, 8765}, 0x6, 88, 0, 8778, 0}, + /*II_V_66_0F_38_AC*/ {{0x1b1, 8791}, 0x7, 91, 0, 8805, 0}, + /*II_V_66_0F_38_AD*/ {{0x1b2, 8819}, 0x6, 88, 0, 8833, 0}, + /*II_V_66_0F_38_AE*/ {{0x1b1, 8847}, 0x7, 91, 0, 8861, 0}, + /*II_V_66_0F_38_AF*/ {{0x1b2, 8875}, 0x6, 88, 0, 8889, 0}, + /*II_V_66_0F_38_B6*/ {{0x1b1, 8903}, 0x7, 91, 0, 8919, 0}, + /*II_V_66_0F_38_B7*/ {{0x1b1, 8935}, 0x7, 91, 0, 8951, 0}, + /*II_V_66_0F_38_B8*/ {{0x1b1, 8967}, 0x7, 91, 0, 8980, 0}, + /*II_V_66_0F_38_B9*/ {{0x1b2, 8993}, 0x6, 88, 0, 9006, 0}, + /*II_V_66_0F_38_BA*/ {{0x1b1, 9019}, 0x7, 91, 0, 9032, 0}, + /*II_V_66_0F_38_BB*/ {{0x1b2, 9045}, 0x6, 88, 0, 9058, 0}, + /*II_V_66_0F_38_BC*/ {{0x1b1, 9071}, 0x7, 91, 0, 9085, 0}, + /*II_V_66_0F_38_BD*/ {{0x1b2, 9099}, 0x6, 88, 0, 9113, 0}, + /*II_V_66_0F_38_BE*/ {{0x1b1, 9127}, 0x7, 91, 0, 9141, 0}, + /*II_V_66_0F_38_BF*/ {{0x1b2, 9155}, 0x6, 88, 0, 9169, 0}, + /*II_V_66_0F_38_DB*/ {{0x1b4, 9191}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_DC*/ {{0x1b5, 9208}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_DD*/ {{0x1b5, 9229}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_DE*/ {{0x1b5, 9250}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_38_DF*/ {{0x1b5, 9271}, 0x0, 87, 0, 0, 0}, + /*II_V_66_0F_3A_04*/ {{0x1ba, 7592}, 0x41, 1, 0, 0, 0}, + /*II_V_66_0F_3A_05*/ {{0x1ba, 7603}, 0x41, 1, 0, 0, 0}, + /*II_V_66_0F_3A_06*/ {{0x1bb, 9298}, 0x10, 89, 1, 0, 0}, + /*II_66_0F_3A_08*/ {{0x1a2, 9310}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_08*/ {{0x1ba, 9319}, 0x41, 1, 0, 0, 0}, + /*II_66_0F_3A_09*/ {{0x1a2, 9329}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_09*/ {{0x1ba, 9338}, 0x41, 1, 0, 0, 0}, + /*II_66_0F_3A_0A*/ {{0x1bc, 9348}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0A*/ {{0x184, 9357}, 0x0, 85, 1, 0, 0}, + /*II_66_0F_3A_0B*/ {{0x1bd, 9367}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0B*/ {{0x184, 9376}, 0x0, 86, 1, 0, 0}, + /*II_66_0F_3A_0C*/ {{0x1a2, 9386}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0C*/ {{0x189, 9395}, 0x1, 91, 1, 0, 0}, + /*II_66_0F_3A_0D*/ {{0x1a2, 9405}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0D*/ {{0x189, 9414}, 0x1, 91, 1, 0, 0}, + /*II_66_0F_3A_0E*/ {{0x1a2, 9424}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0E*/ {{0x184, 9433}, 0x0, 87, 1, 0, 0}, + /*II_0F_3A_0F*/ {{0x1be, 9443}, 0x0, 1, 0, 0, 0}, + /*II_66_0F_3A_0F*/ {{0x1bf, 9443}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0F*/ {{0x184, 9452}, 0x0, 87, 1, 0, 0}, + /*II_66_0F_3A_14*/ {{0x1c0, 9462}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_14*/ {{0x1c1, 9470}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_15*/ {{0x1c2, 6344}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_15*/ {{0x1c3, 6352}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_16*/ {{0x1c4, 9479}, 0x0, 1, 0, 0, 9487}, + /*II_V_66_0F_3A_16*/ {{0x1c5, 9495}, 0x46, 1, 0, 9504, 0}, + /*II_66_0F_3A_17*/ {{0x1c6, 9513}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_17*/ {{0x1c7, 9524}, 0x40, 1, 0, 0, 0}, + /*II_V_66_0F_3A_18*/ {{0x1bb, 9536}, 0x10, 87, 1, 0, 0}, + /*II_V_66_0F_3A_19*/ {{0x1c8, 9549}, 0x50, 1, 0, 0, 0}, + /*II_66_0F_3A_20*/ {{0x1c9, 9563}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_20*/ {{0x184, 9571}, 0x0, 80, 1, 0, 0}, + /*II_66_0F_3A_21*/ {{0x1bc, 9580}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_21*/ {{0x184, 9590}, 0x0, 85, 1, 0, 0}, + /*II_66_0F_3A_22*/ {{0x1ca, 9601}, 0x0, 1, 0, 0, 9609}, + /*II_V_66_0F_3A_22*/ {{0x184, 9617}, 0x6, 73, 1, 9626, 0}, + /*II_66_0F_3A_40*/ {{0x1a2, 9635}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_40*/ {{0x189, 9641}, 0x1, 91, 1, 0, 0}, + /*II_66_0F_3A_41*/ {{0x1a2, 9648}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_41*/ {{0x184, 9654}, 0x0, 87, 1, 0, 0}, + /*II_66_0F_3A_42*/ {{0x1a2, 9661}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_42*/ {{0x184, 9670}, 0x0, 87, 1, 0, 0}, + /*II_66_0F_3A_44*/ {{0x1cb, 9680}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_44*/ {{0x1cc, 9691}, 0x0, 87, 1, 0, 0}, + /*II_V_66_0F_3A_4A*/ {{0x189, 9703}, 0x1, 91, 37, 0, 0}, + /*II_V_66_0F_3A_4B*/ {{0x189, 9714}, 0x1, 91, 37, 0, 0}, + /*II_V_66_0F_3A_4C*/ {{0x184, 9725}, 0x0, 87, 35, 0, 0}, + /*II_66_0F_3A_60*/ {{0x1cd, 9736}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_60*/ {{0x163, 9747}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_61*/ {{0x1cd, 9759}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_61*/ {{0x163, 9770}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_62*/ {{0x1cd, 9782}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_62*/ {{0x163, 9793}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_63*/ {{0x1cd, 9805}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_63*/ {{0x163, 9816}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_DF*/ {{0x1ce, 9828}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_DF*/ {{0x1cf, 9845}, 0x40, 1, 0, 0, 0}, + /*II_V_66_0F_71_02*/ {{0x1d2, 6476}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_71_04*/ {{0x1d2, 6735}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_71_06*/ {{0x1d2, 7049}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_72_02*/ {{0x1d2, 6491}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_72_04*/ {{0x1d2, 6750}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_72_06*/ {{0x1d2, 7064}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_73_02*/ {{0x1d2, 6506}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_73_03*/ {{0x1d2, 9871}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_73_06*/ {{0x1d2, 7079}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_73_07*/ {{0x1d2, 9888}, 0x0, 1, 0, 0, 0}, + /*II_0F_AE_00*/ {{0x173, 9897}, 0x0, 0, 0, 0, 9905}, + /*II_0F_AE_01*/ {{0x173, 9925}, 0x0, 0, 0, 0, 9934}, + /*II_V_0F_AE_02*/ {{0x1d5, 9974}, 0x40, 0, 0, 0, 0}, + /*II_V_0F_AE_03*/ {{0x1d5, 10003}, 0x40, 0, 0, 0, 0} +}; + +_InstNode InstructionsTree[5688] = +{ + /* 0 - _00 */ 0x2000, + /* 1 - _01 */ 0x2001, + /* 2 - _02 */ 0x2002, + /* 3 - _03 */ 0x2003, + /* 4 - _04 */ 0x2004, + /* 5 - _05 */ 0x2005, + /* 6 - _06 */ 0x2006, + /* 7 - _07 */ 0x2007, + /* 8 - _08 */ 0x2008, + /* 9 - _09 */ 0x2009, + /* a - _0A */ 0x200a, + /* b - _0B */ 0x200b, + /* c - _0C */ 0x200c, + /* d - _0D */ 0x200d, + /* e - _0E */ 0x200e, + /* f - _0F */ 0xa100, + /* 10 - _10 */ 0x200f, + /* 11 - _11 */ 0x2010, + /* 12 - _12 */ 0x2011, + /* 13 - _13 */ 0x2012, + /* 14 - _14 */ 0x2013, + /* 15 - _15 */ 0x2014, + /* 16 - _16 */ 0x2015, + /* 17 - _17 */ 0x2016, + /* 18 - _18 */ 0x2017, + /* 19 - _19 */ 0x2018, + /* 1a - _1A */ 0x2019, + /* 1b - _1B */ 0x201a, + /* 1c - _1C */ 0x201b, + /* 1d - _1D */ 0x201c, + /* 1e - _1E */ 0x201d, + /* 1f - _1F */ 0x201e, + /* 20 - _20 */ 0x201f, + /* 21 - _21 */ 0x2020, + /* 22 - _22 */ 0x2021, + /* 23 - _23 */ 0x2022, + /* 24 - _24 */ 0x2023, + /* 25 - _25 */ 0x2024, + /* 26 - */ 0, + /* 27 - _27 */ 0x2025, + /* 28 - _28 */ 0x2026, + /* 29 - _29 */ 0x2027, + /* 2a - _2A */ 0x2028, + /* 2b - _2B */ 0x2029, + /* 2c - _2C */ 0x202a, + /* 2d - _2D */ 0x202b, + /* 2e - */ 0, + /* 2f - _2F */ 0x202c, + /* 30 - _30 */ 0x202d, + /* 31 - _31 */ 0x202e, + /* 32 - _32 */ 0x202f, + /* 33 - _33 */ 0x2030, + /* 34 - _34 */ 0x2031, + /* 35 - _35 */ 0x2032, + /* 36 - */ 0, + /* 37 - _37 */ 0x2033, + /* 38 - _38 */ 0x2034, + /* 39 - _39 */ 0x2035, + /* 3a - _3A */ 0x2036, + /* 3b - _3B */ 0x2037, + /* 3c - _3C */ 0x2038, + /* 3d - _3D */ 0x2039, + /* 3e - */ 0, + /* 3f - _3F */ 0x203a, + /* 40 - _40 */ 0x203b, + /* 41 - _40 */ 0x203c, + /* 42 - _40 */ 0x203d, + /* 43 - _40 */ 0x203e, + /* 44 - _40 */ 0x203f, + /* 45 - _40 */ 0x2040, + /* 46 - _40 */ 0x2041, + /* 47 - _40 */ 0x2042, + /* 48 - _48 */ 0x2043, + /* 49 - _48 */ 0x2044, + /* 4a - _48 */ 0x2045, + /* 4b - _48 */ 0x2046, + /* 4c - _48 */ 0x2047, + /* 4d - _48 */ 0x2048, + /* 4e - _48 */ 0x2049, + /* 4f - _48 */ 0x204a, + /* 50 - _50 */ 0x204b, + /* 51 - _50 */ 0x204c, + /* 52 - _50 */ 0x204d, + /* 53 - _50 */ 0x204e, + /* 54 - _50 */ 0x204f, + /* 55 - _50 */ 0x2050, + /* 56 - _50 */ 0x2051, + /* 57 - _50 */ 0x2052, + /* 58 - _58 */ 0x2053, + /* 59 - _58 */ 0x2054, + /* 5a - _58 */ 0x2055, + /* 5b - _58 */ 0x2056, + /* 5c - _58 */ 0x2057, + /* 5d - _58 */ 0x2058, + /* 5e - _58 */ 0x2059, + /* 5f - _58 */ 0x205a, + /* 60 - _60 */ 0x205b, + /* 61 - _61 */ 0x205c, + /* 62 - _62 */ 0x205d, + /* 63 - _63 */ 0x605e, + /* 64 - */ 0, + /* 65 - */ 0, + /* 66 - */ 0, + /* 67 - */ 0, + /* 68 - _68 */ 0x205f, + /* 69 - _69 */ 0x4000, + /* 6a - _6A */ 0x2060, + /* 6b - _6B */ 0x4001, + /* 6c - _6C */ 0x2061, + /* 6d - _6D */ 0x2062, + /* 6e - _6E */ 0x2063, + /* 6f - _6F */ 0x2064, + /* 70 - _70 */ 0x2065, + /* 71 - _71 */ 0x2066, + /* 72 - _72 */ 0x2067, + /* 73 - _73 */ 0x2068, + /* 74 - _74 */ 0x2069, + /* 75 - _75 */ 0x206a, + /* 76 - _76 */ 0x206b, + /* 77 - _77 */ 0x206c, + /* 78 - _78 */ 0x206d, + /* 79 - _79 */ 0x206e, + /* 7a - _7A */ 0x206f, + /* 7b - _7B */ 0x2070, + /* 7c - _7C */ 0x2071, + /* 7d - _7D */ 0x2072, + /* 7e - _7E */ 0x2073, + /* 7f - _7F */ 0x2074, + /* 80 - _80 */ 0x8200, + /* 81 - _81 */ 0x8208, + /* 82 - _82 */ 0x8210, + /* 83 - _83 */ 0x8218, + /* 84 - _84 */ 0x2075, + /* 85 - _85 */ 0x2076, + /* 86 - _86 */ 0x2077, + /* 87 - _87 */ 0x2078, + /* 88 - _88 */ 0x2079, + /* 89 - _89 */ 0x207a, + /* 8a - _8A */ 0x207b, + /* 8b - _8B */ 0x207c, + /* 8c - _8C */ 0x207d, + /* 8d - _8D */ 0x607e, + /* 8e - _8E */ 0x207f, + /* 8f - _8F */ 0x8220, + /* 90 - _90 */ 0x6080, + /* 91 - _91 */ 0x2081, + /* 92 - _92 */ 0x2082, + /* 93 - _93 */ 0x2083, + /* 94 - _94 */ 0x2084, + /* 95 - _95 */ 0x2085, + /* 96 - _96 */ 0x2086, + /* 97 - _97 */ 0x2087, + /* 98 - _98 */ 0x4002, + /* 99 - _99 */ 0x4003, + /* 9a - _9A */ 0x2088, + /* 9b - */ 0, + /* 9c - _9C */ 0x2089, + /* 9d - _9D */ 0x208a, + /* 9e - _9E */ 0x208b, + /* 9f - _9F */ 0x208c, + /* a0 - _A0 */ 0x208d, + /* a1 - _A1 */ 0x208e, + /* a2 - _A2 */ 0x208f, + /* a3 - _A3 */ 0x2090, + /* a4 - _A4 */ 0x2091, + /* a5 - _A5 */ 0x2092, + /* a6 - _A6 */ 0x2093, + /* a7 - _A7 */ 0x2094, + /* a8 - _A8 */ 0x2095, + /* a9 - _A9 */ 0x2096, + /* aa - _AA */ 0x2097, + /* ab - _AB */ 0x2098, + /* ac - _AC */ 0x2099, + /* ad - _AD */ 0x209a, + /* ae - _AE */ 0x209b, + /* af - _AF */ 0x209c, + /* b0 - _B0 */ 0x209d, + /* b1 - _B0 */ 0x209e, + /* b2 - _B0 */ 0x209f, + /* b3 - _B0 */ 0x20a0, + /* b4 - _B0 */ 0x20a1, + /* b5 - _B0 */ 0x20a2, + /* b6 - _B0 */ 0x20a3, + /* b7 - _B0 */ 0x20a4, + /* b8 - _B8 */ 0x20a5, + /* b9 - _B8 */ 0x20a6, + /* ba - _B8 */ 0x20a7, + /* bb - _B8 */ 0x20a8, + /* bc - _B8 */ 0x20a9, + /* bd - _B8 */ 0x20aa, + /* be - _B8 */ 0x20ab, + /* bf - _B8 */ 0x20ac, + /* c0 - _C0 */ 0x8228, + /* c1 - _C1 */ 0x8230, + /* c2 - _C2 */ 0x20ad, + /* c3 - _C3 */ 0x20ae, + /* c4 - _C4 */ 0x20af, + /* c5 - _C5 */ 0x20b0, + /* c6 - _C6 */ 0xc238, + /* c7 - _C7 */ 0xc280, + /* c8 - _C8 */ 0x20b1, + /* c9 - _C9 */ 0x20b2, + /* ca - _CA */ 0x20b3, + /* cb - _CB */ 0x20b4, + /* cc - _CC */ 0x20b5, + /* cd - _CD */ 0x20b6, + /* ce - _CE */ 0x20b7, + /* cf - _CF */ 0x20b8, + /* d0 - _D0 */ 0x82c8, + /* d1 - _D1 */ 0x82d0, + /* d2 - _D2 */ 0x82d8, + /* d3 - _D3 */ 0x82e0, + /* d4 - _D4 */ 0x20b9, + /* d5 - _D5 */ 0x20ba, + /* d6 - _D6 */ 0x20bb, + /* d7 - _D7 */ 0x20bc, + /* d8 - _D8 */ 0xc2e8, + /* d9 - _D9 */ 0xc330, + /* da - _DA */ 0xc378, + /* db - _DB */ 0xc3c0, + /* dc - _DC */ 0xc408, + /* dd - _DD */ 0xc450, + /* de - _DE */ 0xc498, + /* df - _DF */ 0xc4e0, + /* e0 - _E0 */ 0x20bd, + /* e1 - _E1 */ 0x20be, + /* e2 - _E2 */ 0x20bf, + /* e3 - _E3 */ 0x4004, + /* e4 - _E4 */ 0x20c0, + /* e5 - _E5 */ 0x20c1, + /* e6 - _E6 */ 0x20c2, + /* e7 - _E7 */ 0x20c3, + /* e8 - _E8 */ 0x20c4, + /* e9 - _E9 */ 0x20c5, + /* ea - _EA */ 0x20c6, + /* eb - _EB */ 0x20c7, + /* ec - _EC */ 0x20c8, + /* ed - _ED */ 0x20c9, + /* ee - _EE */ 0x20ca, + /* ef - _EF */ 0x20cb, + /* f0 - */ 0, + /* f1 - _F1 */ 0x20cc, + /* f2 - */ 0, + /* f3 - */ 0, + /* f4 - _F4 */ 0x20cd, + /* f5 - _F5 */ 0x20ce, + /* f6 - _F6 */ 0x8528, + /* f7 - _F7 */ 0x8530, + /* f8 - _F8 */ 0x20cf, + /* f9 - _F9 */ 0x20d0, + /* fa - _FA */ 0x20d1, + /* fb - _FB */ 0x20d2, + /* fc - _FC */ 0x20d3, + /* fd - _FD */ 0x20d4, + /* fe - _FE */ 0x8538, + /* ff - _FF */ 0x8540, + /* 100 - _0F_00 */ 0x8548, + /* 101 - _0F_01 */ 0xc550, + /* 102 - _0F_02 */ 0x20d5, + /* 103 - _0F_03 */ 0x20d6, + /* 104 - */ 0, + /* 105 - _0F_05 */ 0x20d7, + /* 106 - _0F_06 */ 0x20d8, + /* 107 - _0F_07 */ 0x20d9, + /* 108 - _0F_08 */ 0x20da, + /* 109 - _0F_09 */ 0x20db, + /* 10a - */ 0, + /* 10b - _0F_0B */ 0x20dc, + /* 10c - */ 0, + /* 10d - _0F_0D */ 0x8598, + /* 10e - _0F_0E */ 0x20dd, + /* 10f - _0F_0F */ 0xa5a0, + /* 110 - _0F_10 */ 0xe6a0, + /* 111 - _0F_11 */ 0xe6ac, + /* 112 - _0F_12 */ 0xe6b8, + /* 113 - _0F_13 */ 0xe6c4, + /* 114 - _0F_14 */ 0xe6d0, + /* 115 - _0F_15 */ 0xe6dc, + /* 116 - _0F_16 */ 0xe6e8, + /* 117 - _0F_17 */ 0xe6f4, + /* 118 - _0F_18 */ 0x8700, + /* 119 - */ 0, + /* 11a - */ 0, + /* 11b - */ 0, + /* 11c - */ 0, + /* 11d - */ 0, + /* 11e - */ 0, + /* 11f - _0F_1F */ 0x20de, + /* 120 - _0F_20 */ 0x20df, + /* 121 - _0F_21 */ 0x20e0, + /* 122 - _0F_22 */ 0x20e1, + /* 123 - _0F_23 */ 0x20e2, + /* 124 - */ 0, + /* 125 - */ 0, + /* 126 - */ 0, + /* 127 - */ 0, + /* 128 - _0F_28 */ 0xe708, + /* 129 - _0F_29 */ 0xe714, + /* 12a - _0F_2A */ 0xe720, + /* 12b - _0F_2B */ 0xe72c, + /* 12c - _0F_2C */ 0xe738, + /* 12d - _0F_2D */ 0xe744, + /* 12e - _0F_2E */ 0xe750, + /* 12f - _0F_2F */ 0xe75c, + /* 130 - _0F_30 */ 0x20e3, + /* 131 - _0F_31 */ 0x20e4, + /* 132 - _0F_32 */ 0x20e5, + /* 133 - _0F_33 */ 0x20e6, + /* 134 - _0F_34 */ 0x20e7, + /* 135 - _0F_35 */ 0x20e8, + /* 136 - */ 0, + /* 137 - _0F_37 */ 0x20e9, + /* 138 - _0F_38 */ 0xa768, + /* 139 - */ 0, + /* 13a - _0F_3A */ 0xa868, + /* 13b - */ 0, + /* 13c - */ 0, + /* 13d - */ 0, + /* 13e - */ 0, + /* 13f - */ 0, + /* 140 - _0F_40 */ 0x20ea, + /* 141 - _0F_41 */ 0x20eb, + /* 142 - _0F_42 */ 0x20ec, + /* 143 - _0F_43 */ 0x20ed, + /* 144 - _0F_44 */ 0x20ee, + /* 145 - _0F_45 */ 0x20ef, + /* 146 - _0F_46 */ 0x20f0, + /* 147 - _0F_47 */ 0x20f1, + /* 148 - _0F_48 */ 0x20f2, + /* 149 - _0F_49 */ 0x20f3, + /* 14a - _0F_4A */ 0x20f4, + /* 14b - _0F_4B */ 0x20f5, + /* 14c - _0F_4C */ 0x20f6, + /* 14d - _0F_4D */ 0x20f7, + /* 14e - _0F_4E */ 0x20f8, + /* 14f - _0F_4F */ 0x20f9, + /* 150 - _0F_50 */ 0xe968, + /* 151 - _0F_51 */ 0xe974, + /* 152 - _0F_52 */ 0xe980, + /* 153 - _0F_53 */ 0xe98c, + /* 154 - _0F_54 */ 0xe998, + /* 155 - _0F_55 */ 0xe9a4, + /* 156 - _0F_56 */ 0xe9b0, + /* 157 - _0F_57 */ 0xe9bc, + /* 158 - _0F_58 */ 0xe9c8, + /* 159 - _0F_59 */ 0xe9d4, + /* 15a - _0F_5A */ 0xe9e0, + /* 15b - _0F_5B */ 0xe9ec, + /* 15c - _0F_5C */ 0xe9f8, + /* 15d - _0F_5D */ 0xea04, + /* 15e - _0F_5E */ 0xea10, + /* 15f - _0F_5F */ 0xea1c, + /* 160 - _0F_60 */ 0xea28, + /* 161 - _0F_61 */ 0xea34, + /* 162 - _0F_62 */ 0xea40, + /* 163 - _0F_63 */ 0xea4c, + /* 164 - _0F_64 */ 0xea58, + /* 165 - _0F_65 */ 0xea64, + /* 166 - _0F_66 */ 0xea70, + /* 167 - _0F_67 */ 0xea7c, + /* 168 - _0F_68 */ 0xea88, + /* 169 - _0F_69 */ 0xea94, + /* 16a - _0F_6A */ 0xeaa0, + /* 16b - _0F_6B */ 0xeaac, + /* 16c - _0F_6C */ 0xeab8, + /* 16d - _0F_6D */ 0xeac4, + /* 16e - _0F_6E */ 0xead0, + /* 16f - _0F_6F */ 0xeadc, + /* 170 - _0F_70 */ 0xeae8, + /* 171 - _0F_71 */ 0x8af4, + /* 172 - _0F_72 */ 0x8afc, + /* 173 - _0F_73 */ 0x8b04, + /* 174 - _0F_74 */ 0xeb0c, + /* 175 - _0F_75 */ 0xeb18, + /* 176 - _0F_76 */ 0xeb24, + /* 177 - _0F_77 */ 0xeb30, + /* 178 - _0F_78 */ 0xeb3c, + /* 179 - _0F_79 */ 0xeb48, + /* 17a - _0F_7A */ 0xab54, + /* 17b - */ 0, + /* 17c - _0F_7C */ 0xec54, + /* 17d - _0F_7D */ 0xec60, + /* 17e - _0F_7E */ 0xec6c, + /* 17f - _0F_7F */ 0xec78, + /* 180 - _0F_80 */ 0x20fa, + /* 181 - _0F_81 */ 0x20fb, + /* 182 - _0F_82 */ 0x20fc, + /* 183 - _0F_83 */ 0x20fd, + /* 184 - _0F_84 */ 0x20fe, + /* 185 - _0F_85 */ 0x20ff, + /* 186 - _0F_86 */ 0x2100, + /* 187 - _0F_87 */ 0x2101, + /* 188 - _0F_88 */ 0x2102, + /* 189 - _0F_89 */ 0x2103, + /* 18a - _0F_8A */ 0x2104, + /* 18b - _0F_8B */ 0x2105, + /* 18c - _0F_8C */ 0x2106, + /* 18d - _0F_8D */ 0x2107, + /* 18e - _0F_8E */ 0x2108, + /* 18f - _0F_8F */ 0x2109, + /* 190 - _0F_90 */ 0x210a, + /* 191 - _0F_91 */ 0x210b, + /* 192 - _0F_92 */ 0x210c, + /* 193 - _0F_93 */ 0x210d, + /* 194 - _0F_94 */ 0x210e, + /* 195 - _0F_95 */ 0x210f, + /* 196 - _0F_96 */ 0x2110, + /* 197 - _0F_97 */ 0x2111, + /* 198 - _0F_98 */ 0x2112, + /* 199 - _0F_99 */ 0x2113, + /* 19a - _0F_9A */ 0x2114, + /* 19b - _0F_9B */ 0x2115, + /* 19c - _0F_9C */ 0x2116, + /* 19d - _0F_9D */ 0x2117, + /* 19e - _0F_9E */ 0x2118, + /* 19f - _0F_9F */ 0x2119, + /* 1a0 - _0F_A0 */ 0x211a, + /* 1a1 - _0F_A1 */ 0x211b, + /* 1a2 - _0F_A2 */ 0x211c, + /* 1a3 - _0F_A3 */ 0x211d, + /* 1a4 - _0F_A4 */ 0x4005, + /* 1a5 - _0F_A5 */ 0x4006, + /* 1a6 - */ 0, + /* 1a7 - */ 0, + /* 1a8 - _0F_A8 */ 0x211e, + /* 1a9 - _0F_A9 */ 0x211f, + /* 1aa - _0F_AA */ 0x2120, + /* 1ab - _0F_AB */ 0x2121, + /* 1ac - _0F_AC */ 0x4007, + /* 1ad - _0F_AD */ 0x4008, + /* 1ae - _0F_AE */ 0x8c84, + /* 1af - _0F_AF */ 0x2122, + /* 1b0 - _0F_B0 */ 0x2123, + /* 1b1 - _0F_B1 */ 0x2124, + /* 1b2 - _0F_B2 */ 0x2125, + /* 1b3 - _0F_B3 */ 0x2126, + /* 1b4 - _0F_B4 */ 0x2127, + /* 1b5 - _0F_B5 */ 0x2128, + /* 1b6 - _0F_B6 */ 0x2129, + /* 1b7 - _0F_B7 */ 0x212a, + /* 1b8 - _0F_B8 */ 0xec8c, + /* 1b9 - _0F_B9 */ 0x212b, + /* 1ba - _0F_BA */ 0x8c98, + /* 1bb - _0F_BB */ 0x212c, + /* 1bc - _0F_BC */ 0xeca0, + /* 1bd - _0F_BD */ 0xecac, + /* 1be - _0F_BE */ 0x212d, + /* 1bf - _0F_BF */ 0x212e, + /* 1c0 - _0F_C0 */ 0x212f, + /* 1c1 - _0F_C1 */ 0x2130, + /* 1c2 - _0F_C2 */ 0xecb8, + /* 1c3 - _0F_C3 */ 0x2131, + /* 1c4 - _0F_C4 */ 0xecc4, + /* 1c5 - _0F_C5 */ 0xecd0, + /* 1c6 - _0F_C6 */ 0xecdc, + /* 1c7 - _0F_C7 */ 0x8ce8, + /* 1c8 - _0F_C8 */ 0x2132, + /* 1c9 - _0F_C8 */ 0x2133, + /* 1ca - _0F_C8 */ 0x2134, + /* 1cb - _0F_C8 */ 0x2135, + /* 1cc - _0F_C8 */ 0x2136, + /* 1cd - _0F_C8 */ 0x2137, + /* 1ce - _0F_C8 */ 0x2138, + /* 1cf - _0F_C8 */ 0x2139, + /* 1d0 - _0F_D0 */ 0xecf0, + /* 1d1 - _0F_D1 */ 0xecfc, + /* 1d2 - _0F_D2 */ 0xed08, + /* 1d3 - _0F_D3 */ 0xed14, + /* 1d4 - _0F_D4 */ 0xed20, + /* 1d5 - _0F_D5 */ 0xed2c, + /* 1d6 - _0F_D6 */ 0xed38, + /* 1d7 - _0F_D7 */ 0xed44, + /* 1d8 - _0F_D8 */ 0xed50, + /* 1d9 - _0F_D9 */ 0xed5c, + /* 1da - _0F_DA */ 0xed68, + /* 1db - _0F_DB */ 0xed74, + /* 1dc - _0F_DC */ 0xed80, + /* 1dd - _0F_DD */ 0xed8c, + /* 1de - _0F_DE */ 0xed98, + /* 1df - _0F_DF */ 0xeda4, + /* 1e0 - _0F_E0 */ 0xedb0, + /* 1e1 - _0F_E1 */ 0xedbc, + /* 1e2 - _0F_E2 */ 0xedc8, + /* 1e3 - _0F_E3 */ 0xedd4, + /* 1e4 - _0F_E4 */ 0xede0, + /* 1e5 - _0F_E5 */ 0xedec, + /* 1e6 - _0F_E6 */ 0xedf8, + /* 1e7 - _0F_E7 */ 0xee04, + /* 1e8 - _0F_E8 */ 0xee10, + /* 1e9 - _0F_E9 */ 0xee1c, + /* 1ea - _0F_EA */ 0xee28, + /* 1eb - _0F_EB */ 0xee34, + /* 1ec - _0F_EC */ 0xee40, + /* 1ed - _0F_ED */ 0xee4c, + /* 1ee - _0F_EE */ 0xee58, + /* 1ef - _0F_EF */ 0xee64, + /* 1f0 - _0F_F0 */ 0xee70, + /* 1f1 - _0F_F1 */ 0xee7c, + /* 1f2 - _0F_F2 */ 0xee88, + /* 1f3 - _0F_F3 */ 0xee94, + /* 1f4 - _0F_F4 */ 0xeea0, + /* 1f5 - _0F_F5 */ 0xeeac, + /* 1f6 - _0F_F6 */ 0xeeb8, + /* 1f7 - _0F_F7 */ 0xeec4, + /* 1f8 - _0F_F8 */ 0xeed0, + /* 1f9 - _0F_F9 */ 0xeedc, + /* 1fa - _0F_FA */ 0xeee8, + /* 1fb - _0F_FB */ 0xeef4, + /* 1fc - _0F_FC */ 0xef00, + /* 1fd - _0F_FD */ 0xef0c, + /* 1fe - _0F_FE */ 0xef18, + /* 1ff - */ 0, + /* 200 - _80_00 */ 0x213a, + /* 201 - _80_01 */ 0x213b, + /* 202 - _80_02 */ 0x213c, + /* 203 - _80_03 */ 0x213d, + /* 204 - _80_04 */ 0x213e, + /* 205 - _80_05 */ 0x213f, + /* 206 - _80_06 */ 0x2140, + /* 207 - _80_07 */ 0x2141, + /* 208 - _81_00 */ 0x2142, + /* 209 - _81_01 */ 0x2143, + /* 20a - _81_02 */ 0x2144, + /* 20b - _81_03 */ 0x2145, + /* 20c - _81_04 */ 0x2146, + /* 20d - _81_05 */ 0x2147, + /* 20e - _81_06 */ 0x2148, + /* 20f - _81_07 */ 0x2149, + /* 210 - _82_00 */ 0x214a, + /* 211 - _82_01 */ 0x214b, + /* 212 - _82_02 */ 0x214c, + /* 213 - _82_03 */ 0x214d, + /* 214 - _82_04 */ 0x214e, + /* 215 - _82_05 */ 0x214f, + /* 216 - _82_06 */ 0x2150, + /* 217 - _82_07 */ 0x2151, + /* 218 - _83_00 */ 0x2152, + /* 219 - _83_01 */ 0x2153, + /* 21a - _83_02 */ 0x2154, + /* 21b - _83_03 */ 0x2155, + /* 21c - _83_04 */ 0x2156, + /* 21d - _83_05 */ 0x2157, + /* 21e - _83_06 */ 0x2158, + /* 21f - _83_07 */ 0x2159, + /* 220 - _8F_00 */ 0x215a, + /* 221 - */ 0, + /* 222 - */ 0, + /* 223 - */ 0, + /* 224 - */ 0, + /* 225 - */ 0, + /* 226 - */ 0, + /* 227 - */ 0, + /* 228 - _C0_00 */ 0x215b, + /* 229 - _C0_01 */ 0x215c, + /* 22a - _C0_02 */ 0x215d, + /* 22b - _C0_03 */ 0x215e, + /* 22c - _C0_04 */ 0x215f, + /* 22d - _C0_05 */ 0x2160, + /* 22e - _C0_06 */ 0x2161, + /* 22f - _C0_07 */ 0x2162, + /* 230 - _C1_00 */ 0x2163, + /* 231 - _C1_01 */ 0x2164, + /* 232 - _C1_02 */ 0x2165, + /* 233 - _C1_03 */ 0x2166, + /* 234 - _C1_04 */ 0x2167, + /* 235 - _C1_05 */ 0x2168, + /* 236 - _C1_06 */ 0x2169, + /* 237 - _C1_07 */ 0x216a, + /* 238 - _C6_00 */ 0x216b, + /* 239 - */ 0, + /* 23a - */ 0, + /* 23b - */ 0, + /* 23c - */ 0, + /* 23d - */ 0, + /* 23e - */ 0, + /* 23f - */ 0, + /* 240 - */ 0, + /* 241 - */ 0, + /* 242 - */ 0, + /* 243 - */ 0, + /* 244 - */ 0, + /* 245 - */ 0, + /* 246 - */ 0, + /* 247 - */ 0, + /* 248 - */ 0, + /* 249 - */ 0, + /* 24a - */ 0, + /* 24b - */ 0, + /* 24c - */ 0, + /* 24d - */ 0, + /* 24e - */ 0, + /* 24f - */ 0, + /* 250 - */ 0, + /* 251 - */ 0, + /* 252 - */ 0, + /* 253 - */ 0, + /* 254 - */ 0, + /* 255 - */ 0, + /* 256 - */ 0, + /* 257 - */ 0, + /* 258 - */ 0, + /* 259 - */ 0, + /* 25a - */ 0, + /* 25b - */ 0, + /* 25c - */ 0, + /* 25d - */ 0, + /* 25e - */ 0, + /* 25f - */ 0, + /* 260 - */ 0, + /* 261 - */ 0, + /* 262 - */ 0, + /* 263 - */ 0, + /* 264 - */ 0, + /* 265 - */ 0, + /* 266 - */ 0, + /* 267 - */ 0, + /* 268 - */ 0, + /* 269 - */ 0, + /* 26a - */ 0, + /* 26b - */ 0, + /* 26c - */ 0, + /* 26d - */ 0, + /* 26e - */ 0, + /* 26f - */ 0, + /* 270 - */ 0, + /* 271 - */ 0, + /* 272 - */ 0, + /* 273 - */ 0, + /* 274 - */ 0, + /* 275 - */ 0, + /* 276 - */ 0, + /* 277 - */ 0, + /* 278 - _C6_F8 */ 0x216c, + /* 279 - */ 0, + /* 27a - */ 0, + /* 27b - */ 0, + /* 27c - */ 0, + /* 27d - */ 0, + /* 27e - */ 0, + /* 27f - */ 0, + /* 280 - _C7_00 */ 0x216d, + /* 281 - */ 0, + /* 282 - */ 0, + /* 283 - */ 0, + /* 284 - */ 0, + /* 285 - */ 0, + /* 286 - */ 0, + /* 287 - */ 0, + /* 288 - */ 0, + /* 289 - */ 0, + /* 28a - */ 0, + /* 28b - */ 0, + /* 28c - */ 0, + /* 28d - */ 0, + /* 28e - */ 0, + /* 28f - */ 0, + /* 290 - */ 0, + /* 291 - */ 0, + /* 292 - */ 0, + /* 293 - */ 0, + /* 294 - */ 0, + /* 295 - */ 0, + /* 296 - */ 0, + /* 297 - */ 0, + /* 298 - */ 0, + /* 299 - */ 0, + /* 29a - */ 0, + /* 29b - */ 0, + /* 29c - */ 0, + /* 29d - */ 0, + /* 29e - */ 0, + /* 29f - */ 0, + /* 2a0 - */ 0, + /* 2a1 - */ 0, + /* 2a2 - */ 0, + /* 2a3 - */ 0, + /* 2a4 - */ 0, + /* 2a5 - */ 0, + /* 2a6 - */ 0, + /* 2a7 - */ 0, + /* 2a8 - */ 0, + /* 2a9 - */ 0, + /* 2aa - */ 0, + /* 2ab - */ 0, + /* 2ac - */ 0, + /* 2ad - */ 0, + /* 2ae - */ 0, + /* 2af - */ 0, + /* 2b0 - */ 0, + /* 2b1 - */ 0, + /* 2b2 - */ 0, + /* 2b3 - */ 0, + /* 2b4 - */ 0, + /* 2b5 - */ 0, + /* 2b6 - */ 0, + /* 2b7 - */ 0, + /* 2b8 - */ 0, + /* 2b9 - */ 0, + /* 2ba - */ 0, + /* 2bb - */ 0, + /* 2bc - */ 0, + /* 2bd - */ 0, + /* 2be - */ 0, + /* 2bf - */ 0, + /* 2c0 - _C7_F8 */ 0x216e, + /* 2c1 - */ 0, + /* 2c2 - */ 0, + /* 2c3 - */ 0, + /* 2c4 - */ 0, + /* 2c5 - */ 0, + /* 2c6 - */ 0, + /* 2c7 - */ 0, + /* 2c8 - _D0_00 */ 0x216f, + /* 2c9 - _D0_01 */ 0x2170, + /* 2ca - _D0_02 */ 0x2171, + /* 2cb - _D0_03 */ 0x2172, + /* 2cc - _D0_04 */ 0x2173, + /* 2cd - _D0_05 */ 0x2174, + /* 2ce - _D0_06 */ 0x2175, + /* 2cf - _D0_07 */ 0x2176, + /* 2d0 - _D1_00 */ 0x2177, + /* 2d1 - _D1_01 */ 0x2178, + /* 2d2 - _D1_02 */ 0x2179, + /* 2d3 - _D1_03 */ 0x217a, + /* 2d4 - _D1_04 */ 0x217b, + /* 2d5 - _D1_05 */ 0x217c, + /* 2d6 - _D1_06 */ 0x217d, + /* 2d7 - _D1_07 */ 0x217e, + /* 2d8 - _D2_00 */ 0x217f, + /* 2d9 - _D2_01 */ 0x2180, + /* 2da - _D2_02 */ 0x2181, + /* 2db - _D2_03 */ 0x2182, + /* 2dc - _D2_04 */ 0x2183, + /* 2dd - _D2_05 */ 0x2184, + /* 2de - _D2_06 */ 0x2185, + /* 2df - _D2_07 */ 0x2186, + /* 2e0 - _D3_00 */ 0x2187, + /* 2e1 - _D3_01 */ 0x2188, + /* 2e2 - _D3_02 */ 0x2189, + /* 2e3 - _D3_03 */ 0x218a, + /* 2e4 - _D3_04 */ 0x218b, + /* 2e5 - _D3_05 */ 0x218c, + /* 2e6 - _D3_06 */ 0x218d, + /* 2e7 - _D3_07 */ 0x218e, + /* 2e8 - _D8_00 */ 0x218f, + /* 2e9 - _D8_01 */ 0x2190, + /* 2ea - _D8_02 */ 0x2191, + /* 2eb - _D8_03 */ 0x2192, + /* 2ec - _D8_04 */ 0x2193, + /* 2ed - _D8_05 */ 0x2194, + /* 2ee - _D8_06 */ 0x2195, + /* 2ef - _D8_07 */ 0x2196, + /* 2f0 - _D8_C0 */ 0x2197, + /* 2f1 - _D8_C0 */ 0x2198, + /* 2f2 - _D8_C0 */ 0x2199, + /* 2f3 - _D8_C0 */ 0x219a, + /* 2f4 - _D8_C0 */ 0x219b, + /* 2f5 - _D8_C0 */ 0x219c, + /* 2f6 - _D8_C0 */ 0x219d, + /* 2f7 - _D8_C0 */ 0x219e, + /* 2f8 - _D8_C8 */ 0x219f, + /* 2f9 - _D8_C8 */ 0x21a0, + /* 2fa - _D8_C8 */ 0x21a1, + /* 2fb - _D8_C8 */ 0x21a2, + /* 2fc - _D8_C8 */ 0x21a3, + /* 2fd - _D8_C8 */ 0x21a4, + /* 2fe - _D8_C8 */ 0x21a5, + /* 2ff - _D8_C8 */ 0x21a6, + /* 300 - _D8_D0 */ 0x21a7, + /* 301 - _D8_D0 */ 0x21a8, + /* 302 - _D8_D0 */ 0x21a9, + /* 303 - _D8_D0 */ 0x21aa, + /* 304 - _D8_D0 */ 0x21ab, + /* 305 - _D8_D0 */ 0x21ac, + /* 306 - _D8_D0 */ 0x21ad, + /* 307 - _D8_D0 */ 0x21ae, + /* 308 - _D8_D8 */ 0x21af, + /* 309 - _D8_D9 */ 0x21b0, + /* 30a - _D8_D8 */ 0x21b1, + /* 30b - _D8_D8 */ 0x21b2, + /* 30c - _D8_D8 */ 0x21b3, + /* 30d - _D8_D8 */ 0x21b4, + /* 30e - _D8_D8 */ 0x21b5, + /* 30f - _D8_D8 */ 0x21b6, + /* 310 - _D8_E0 */ 0x21b7, + /* 311 - _D8_E0 */ 0x21b8, + /* 312 - _D8_E0 */ 0x21b9, + /* 313 - _D8_E0 */ 0x21ba, + /* 314 - _D8_E0 */ 0x21bb, + /* 315 - _D8_E0 */ 0x21bc, + /* 316 - _D8_E0 */ 0x21bd, + /* 317 - _D8_E0 */ 0x21be, + /* 318 - _D8_E8 */ 0x21bf, + /* 319 - _D8_E8 */ 0x21c0, + /* 31a - _D8_E8 */ 0x21c1, + /* 31b - _D8_E8 */ 0x21c2, + /* 31c - _D8_E8 */ 0x21c3, + /* 31d - _D8_E8 */ 0x21c4, + /* 31e - _D8_E8 */ 0x21c5, + /* 31f - _D8_E8 */ 0x21c6, + /* 320 - _D8_F0 */ 0x21c7, + /* 321 - _D8_F0 */ 0x21c8, + /* 322 - _D8_F0 */ 0x21c9, + /* 323 - _D8_F0 */ 0x21ca, + /* 324 - _D8_F0 */ 0x21cb, + /* 325 - _D8_F0 */ 0x21cc, + /* 326 - _D8_F0 */ 0x21cd, + /* 327 - _D8_F0 */ 0x21ce, + /* 328 - _D8_F8 */ 0x21cf, + /* 329 - _D8_F8 */ 0x21d0, + /* 32a - _D8_F8 */ 0x21d1, + /* 32b - _D8_F8 */ 0x21d2, + /* 32c - _D8_F8 */ 0x21d3, + /* 32d - _D8_F8 */ 0x21d4, + /* 32e - _D8_F8 */ 0x21d5, + /* 32f - _D8_F8 */ 0x21d6, + /* 330 - _D9_00 */ 0x21d7, + /* 331 - */ 0, + /* 332 - _D9_02 */ 0x21d8, + /* 333 - _D9_03 */ 0x21d9, + /* 334 - _D9_04 */ 0x21da, + /* 335 - _D9_05 */ 0x21db, + /* 336 - _D9_06 */ 0xef24, + /* 337 - _D9_07 */ 0xef30, + /* 338 - _D9_C0 */ 0x21dc, + /* 339 - _D9_C0 */ 0x21dd, + /* 33a - _D9_C0 */ 0x21de, + /* 33b - _D9_C0 */ 0x21df, + /* 33c - _D9_C0 */ 0x21e0, + /* 33d - _D9_C0 */ 0x21e1, + /* 33e - _D9_C0 */ 0x21e2, + /* 33f - _D9_C0 */ 0x21e3, + /* 340 - _D9_C8 */ 0x21e4, + /* 341 - _D9_C9 */ 0x21e5, + /* 342 - _D9_C8 */ 0x21e6, + /* 343 - _D9_C8 */ 0x21e7, + /* 344 - _D9_C8 */ 0x21e8, + /* 345 - _D9_C8 */ 0x21e9, + /* 346 - _D9_C8 */ 0x21ea, + /* 347 - _D9_C8 */ 0x21eb, + /* 348 - _D9_D0 */ 0x21ec, + /* 349 - */ 0, + /* 34a - */ 0, + /* 34b - */ 0, + /* 34c - */ 0, + /* 34d - */ 0, + /* 34e - */ 0, + /* 34f - */ 0, + /* 350 - */ 0, + /* 351 - */ 0, + /* 352 - */ 0, + /* 353 - */ 0, + /* 354 - */ 0, + /* 355 - */ 0, + /* 356 - */ 0, + /* 357 - */ 0, + /* 358 - _D9_E0 */ 0x21ed, + /* 359 - _D9_E1 */ 0x21ee, + /* 35a - */ 0, + /* 35b - */ 0, + /* 35c - _D9_E4 */ 0x21ef, + /* 35d - _D9_E5 */ 0x21f0, + /* 35e - */ 0, + /* 35f - */ 0, + /* 360 - _D9_E8 */ 0x21f1, + /* 361 - _D9_E9 */ 0x21f2, + /* 362 - _D9_EA */ 0x21f3, + /* 363 - _D9_EB */ 0x21f4, + /* 364 - _D9_EC */ 0x21f5, + /* 365 - _D9_ED */ 0x21f6, + /* 366 - _D9_EE */ 0x21f7, + /* 367 - */ 0, + /* 368 - _D9_F0 */ 0x21f8, + /* 369 - _D9_F1 */ 0x21f9, + /* 36a - _D9_F2 */ 0x21fa, + /* 36b - _D9_F3 */ 0x21fb, + /* 36c - _D9_F4 */ 0x21fc, + /* 36d - _D9_F5 */ 0x21fd, + /* 36e - _D9_F6 */ 0x21fe, + /* 36f - _D9_F7 */ 0x21ff, + /* 370 - _D9_F8 */ 0x2200, + /* 371 - _D9_F9 */ 0x2201, + /* 372 - _D9_FA */ 0x2202, + /* 373 - _D9_FB */ 0x2203, + /* 374 - _D9_FC */ 0x2204, + /* 375 - _D9_FD */ 0x2205, + /* 376 - _D9_FE */ 0x2206, + /* 377 - _D9_FF */ 0x2207, + /* 378 - _DA_00 */ 0x2208, + /* 379 - _DA_01 */ 0x2209, + /* 37a - _DA_02 */ 0x220a, + /* 37b - _DA_03 */ 0x220b, + /* 37c - _DA_04 */ 0x220c, + /* 37d - _DA_05 */ 0x220d, + /* 37e - _DA_06 */ 0x220e, + /* 37f - _DA_07 */ 0x220f, + /* 380 - _DA_C0 */ 0x2210, + /* 381 - _DA_C0 */ 0x2211, + /* 382 - _DA_C0 */ 0x2212, + /* 383 - _DA_C0 */ 0x2213, + /* 384 - _DA_C0 */ 0x2214, + /* 385 - _DA_C0 */ 0x2215, + /* 386 - _DA_C0 */ 0x2216, + /* 387 - _DA_C0 */ 0x2217, + /* 388 - _DA_C8 */ 0x2218, + /* 389 - _DA_C8 */ 0x2219, + /* 38a - _DA_C8 */ 0x221a, + /* 38b - _DA_C8 */ 0x221b, + /* 38c - _DA_C8 */ 0x221c, + /* 38d - _DA_C8 */ 0x221d, + /* 38e - _DA_C8 */ 0x221e, + /* 38f - _DA_C8 */ 0x221f, + /* 390 - _DA_D0 */ 0x2220, + /* 391 - _DA_D0 */ 0x2221, + /* 392 - _DA_D0 */ 0x2222, + /* 393 - _DA_D0 */ 0x2223, + /* 394 - _DA_D0 */ 0x2224, + /* 395 - _DA_D0 */ 0x2225, + /* 396 - _DA_D0 */ 0x2226, + /* 397 - _DA_D0 */ 0x2227, + /* 398 - _DA_D8 */ 0x2228, + /* 399 - _DA_D8 */ 0x2229, + /* 39a - _DA_D8 */ 0x222a, + /* 39b - _DA_D8 */ 0x222b, + /* 39c - _DA_D8 */ 0x222c, + /* 39d - _DA_D8 */ 0x222d, + /* 39e - _DA_D8 */ 0x222e, + /* 39f - _DA_D8 */ 0x222f, + /* 3a0 - */ 0, + /* 3a1 - */ 0, + /* 3a2 - */ 0, + /* 3a3 - */ 0, + /* 3a4 - */ 0, + /* 3a5 - */ 0, + /* 3a6 - */ 0, + /* 3a7 - */ 0, + /* 3a8 - */ 0, + /* 3a9 - _DA_E9 */ 0x2230, + /* 3aa - */ 0, + /* 3ab - */ 0, + /* 3ac - */ 0, + /* 3ad - */ 0, + /* 3ae - */ 0, + /* 3af - */ 0, + /* 3b0 - */ 0, + /* 3b1 - */ 0, + /* 3b2 - */ 0, + /* 3b3 - */ 0, + /* 3b4 - */ 0, + /* 3b5 - */ 0, + /* 3b6 - */ 0, + /* 3b7 - */ 0, + /* 3b8 - */ 0, + /* 3b9 - */ 0, + /* 3ba - */ 0, + /* 3bb - */ 0, + /* 3bc - */ 0, + /* 3bd - */ 0, + /* 3be - */ 0, + /* 3bf - */ 0, + /* 3c0 - _DB_00 */ 0x2231, + /* 3c1 - _DB_01 */ 0x2232, + /* 3c2 - _DB_02 */ 0x2233, + /* 3c3 - _DB_03 */ 0x2234, + /* 3c4 - */ 0, + /* 3c5 - _DB_05 */ 0x2235, + /* 3c6 - */ 0, + /* 3c7 - _DB_07 */ 0x2236, + /* 3c8 - _DB_C0 */ 0x2237, + /* 3c9 - _DB_C0 */ 0x2238, + /* 3ca - _DB_C0 */ 0x2239, + /* 3cb - _DB_C0 */ 0x223a, + /* 3cc - _DB_C0 */ 0x223b, + /* 3cd - _DB_C0 */ 0x223c, + /* 3ce - _DB_C0 */ 0x223d, + /* 3cf - _DB_C0 */ 0x223e, + /* 3d0 - _DB_C8 */ 0x223f, + /* 3d1 - _DB_C8 */ 0x2240, + /* 3d2 - _DB_C8 */ 0x2241, + /* 3d3 - _DB_C8 */ 0x2242, + /* 3d4 - _DB_C8 */ 0x2243, + /* 3d5 - _DB_C8 */ 0x2244, + /* 3d6 - _DB_C8 */ 0x2245, + /* 3d7 - _DB_C8 */ 0x2246, + /* 3d8 - _DB_D0 */ 0x2247, + /* 3d9 - _DB_D0 */ 0x2248, + /* 3da - _DB_D0 */ 0x2249, + /* 3db - _DB_D0 */ 0x224a, + /* 3dc - _DB_D0 */ 0x224b, + /* 3dd - _DB_D0 */ 0x224c, + /* 3de - _DB_D0 */ 0x224d, + /* 3df - _DB_D0 */ 0x224e, + /* 3e0 - _DB_D8 */ 0x224f, + /* 3e1 - _DB_D8 */ 0x2250, + /* 3e2 - _DB_D8 */ 0x2251, + /* 3e3 - _DB_D8 */ 0x2252, + /* 3e4 - _DB_D8 */ 0x2253, + /* 3e5 - _DB_D8 */ 0x2254, + /* 3e6 - _DB_D8 */ 0x2255, + /* 3e7 - _DB_D8 */ 0x2256, + /* 3e8 - _DB_E0 */ 0x2257, + /* 3e9 - _DB_E1 */ 0x2258, + /* 3ea - _DB_E2 */ 0xef3c, + /* 3eb - _DB_E3 */ 0xef48, + /* 3ec - _DB_E4 */ 0x2259, + /* 3ed - */ 0, + /* 3ee - */ 0, + /* 3ef - */ 0, + /* 3f0 - _DB_E8 */ 0x225a, + /* 3f1 - _DB_E8 */ 0x225b, + /* 3f2 - _DB_E8 */ 0x225c, + /* 3f3 - _DB_E8 */ 0x225d, + /* 3f4 - _DB_E8 */ 0x225e, + /* 3f5 - _DB_E8 */ 0x225f, + /* 3f6 - _DB_E8 */ 0x2260, + /* 3f7 - _DB_E8 */ 0x2261, + /* 3f8 - _DB_F0 */ 0x2262, + /* 3f9 - _DB_F0 */ 0x2263, + /* 3fa - _DB_F0 */ 0x2264, + /* 3fb - _DB_F0 */ 0x2265, + /* 3fc - _DB_F0 */ 0x2266, + /* 3fd - _DB_F0 */ 0x2267, + /* 3fe - _DB_F0 */ 0x2268, + /* 3ff - _DB_F0 */ 0x2269, + /* 400 - */ 0, + /* 401 - */ 0, + /* 402 - */ 0, + /* 403 - */ 0, + /* 404 - */ 0, + /* 405 - */ 0, + /* 406 - */ 0, + /* 407 - */ 0, + /* 408 - _DC_00 */ 0x226a, + /* 409 - _DC_01 */ 0x226b, + /* 40a - _DC_02 */ 0x226c, + /* 40b - _DC_03 */ 0x226d, + /* 40c - _DC_04 */ 0x226e, + /* 40d - _DC_05 */ 0x226f, + /* 40e - _DC_06 */ 0x2270, + /* 40f - _DC_07 */ 0x2271, + /* 410 - _DC_C0 */ 0x2272, + /* 411 - _DC_C0 */ 0x2273, + /* 412 - _DC_C0 */ 0x2274, + /* 413 - _DC_C0 */ 0x2275, + /* 414 - _DC_C0 */ 0x2276, + /* 415 - _DC_C0 */ 0x2277, + /* 416 - _DC_C0 */ 0x2278, + /* 417 - _DC_C0 */ 0x2279, + /* 418 - _DC_C8 */ 0x227a, + /* 419 - _DC_C8 */ 0x227b, + /* 41a - _DC_C8 */ 0x227c, + /* 41b - _DC_C8 */ 0x227d, + /* 41c - _DC_C8 */ 0x227e, + /* 41d - _DC_C8 */ 0x227f, + /* 41e - _DC_C8 */ 0x2280, + /* 41f - _DC_C8 */ 0x2281, + /* 420 - */ 0, + /* 421 - */ 0, + /* 422 - */ 0, + /* 423 - */ 0, + /* 424 - */ 0, + /* 425 - */ 0, + /* 426 - */ 0, + /* 427 - */ 0, + /* 428 - */ 0, + /* 429 - */ 0, + /* 42a - */ 0, + /* 42b - */ 0, + /* 42c - */ 0, + /* 42d - */ 0, + /* 42e - */ 0, + /* 42f - */ 0, + /* 430 - _DC_E0 */ 0x2282, + /* 431 - _DC_E0 */ 0x2283, + /* 432 - _DC_E0 */ 0x2284, + /* 433 - _DC_E0 */ 0x2285, + /* 434 - _DC_E0 */ 0x2286, + /* 435 - _DC_E0 */ 0x2287, + /* 436 - _DC_E0 */ 0x2288, + /* 437 - _DC_E0 */ 0x2289, + /* 438 - _DC_E8 */ 0x228a, + /* 439 - _DC_E8 */ 0x228b, + /* 43a - _DC_E8 */ 0x228c, + /* 43b - _DC_E8 */ 0x228d, + /* 43c - _DC_E8 */ 0x228e, + /* 43d - _DC_E8 */ 0x228f, + /* 43e - _DC_E8 */ 0x2290, + /* 43f - _DC_E8 */ 0x2291, + /* 440 - _DC_F0 */ 0x2292, + /* 441 - _DC_F0 */ 0x2293, + /* 442 - _DC_F0 */ 0x2294, + /* 443 - _DC_F0 */ 0x2295, + /* 444 - _DC_F0 */ 0x2296, + /* 445 - _DC_F0 */ 0x2297, + /* 446 - _DC_F0 */ 0x2298, + /* 447 - _DC_F0 */ 0x2299, + /* 448 - _DC_F8 */ 0x229a, + /* 449 - _DC_F8 */ 0x229b, + /* 44a - _DC_F8 */ 0x229c, + /* 44b - _DC_F8 */ 0x229d, + /* 44c - _DC_F8 */ 0x229e, + /* 44d - _DC_F8 */ 0x229f, + /* 44e - _DC_F8 */ 0x22a0, + /* 44f - _DC_F8 */ 0x22a1, + /* 450 - _DD_00 */ 0x22a2, + /* 451 - _DD_01 */ 0x22a3, + /* 452 - _DD_02 */ 0x22a4, + /* 453 - _DD_03 */ 0x22a5, + /* 454 - _DD_04 */ 0x22a6, + /* 455 - */ 0, + /* 456 - _DD_06 */ 0xef54, + /* 457 - _DD_07 */ 0xef60, + /* 458 - _DD_C0 */ 0x22a7, + /* 459 - _DD_C0 */ 0x22a8, + /* 45a - _DD_C0 */ 0x22a9, + /* 45b - _DD_C0 */ 0x22aa, + /* 45c - _DD_C0 */ 0x22ab, + /* 45d - _DD_C0 */ 0x22ac, + /* 45e - _DD_C0 */ 0x22ad, + /* 45f - _DD_C0 */ 0x22ae, + /* 460 - */ 0, + /* 461 - */ 0, + /* 462 - */ 0, + /* 463 - */ 0, + /* 464 - */ 0, + /* 465 - */ 0, + /* 466 - */ 0, + /* 467 - */ 0, + /* 468 - _DD_D0 */ 0x22af, + /* 469 - _DD_D0 */ 0x22b0, + /* 46a - _DD_D0 */ 0x22b1, + /* 46b - _DD_D0 */ 0x22b2, + /* 46c - _DD_D0 */ 0x22b3, + /* 46d - _DD_D0 */ 0x22b4, + /* 46e - _DD_D0 */ 0x22b5, + /* 46f - _DD_D0 */ 0x22b6, + /* 470 - _DD_D8 */ 0x22b7, + /* 471 - _DD_D8 */ 0x22b8, + /* 472 - _DD_D8 */ 0x22b9, + /* 473 - _DD_D8 */ 0x22ba, + /* 474 - _DD_D8 */ 0x22bb, + /* 475 - _DD_D8 */ 0x22bc, + /* 476 - _DD_D8 */ 0x22bd, + /* 477 - _DD_D8 */ 0x22be, + /* 478 - _DD_E0 */ 0x22bf, + /* 479 - _DD_E1 */ 0x22c0, + /* 47a - _DD_E0 */ 0x22c1, + /* 47b - _DD_E0 */ 0x22c2, + /* 47c - _DD_E0 */ 0x22c3, + /* 47d - _DD_E0 */ 0x22c4, + /* 47e - _DD_E0 */ 0x22c5, + /* 47f - _DD_E0 */ 0x22c6, + /* 480 - _DD_E8 */ 0x22c7, + /* 481 - _DD_E9 */ 0x22c8, + /* 482 - _DD_E8 */ 0x22c9, + /* 483 - _DD_E8 */ 0x22ca, + /* 484 - _DD_E8 */ 0x22cb, + /* 485 - _DD_E8 */ 0x22cc, + /* 486 - _DD_E8 */ 0x22cd, + /* 487 - _DD_E8 */ 0x22ce, + /* 488 - */ 0, + /* 489 - */ 0, + /* 48a - */ 0, + /* 48b - */ 0, + /* 48c - */ 0, + /* 48d - */ 0, + /* 48e - */ 0, + /* 48f - */ 0, + /* 490 - */ 0, + /* 491 - */ 0, + /* 492 - */ 0, + /* 493 - */ 0, + /* 494 - */ 0, + /* 495 - */ 0, + /* 496 - */ 0, + /* 497 - */ 0, + /* 498 - _DE_00 */ 0x22cf, + /* 499 - _DE_01 */ 0x22d0, + /* 49a - _DE_02 */ 0x22d1, + /* 49b - _DE_03 */ 0x22d2, + /* 49c - _DE_04 */ 0x22d3, + /* 49d - _DE_05 */ 0x22d4, + /* 49e - _DE_06 */ 0x22d5, + /* 49f - _DE_07 */ 0x22d6, + /* 4a0 - _DE_C0 */ 0x22d7, + /* 4a1 - _DE_C1 */ 0x22d8, + /* 4a2 - _DE_C0 */ 0x22d9, + /* 4a3 - _DE_C0 */ 0x22da, + /* 4a4 - _DE_C0 */ 0x22db, + /* 4a5 - _DE_C0 */ 0x22dc, + /* 4a6 - _DE_C0 */ 0x22dd, + /* 4a7 - _DE_C0 */ 0x22de, + /* 4a8 - _DE_C8 */ 0x22df, + /* 4a9 - _DE_C9 */ 0x22e0, + /* 4aa - _DE_C8 */ 0x22e1, + /* 4ab - _DE_C8 */ 0x22e2, + /* 4ac - _DE_C8 */ 0x22e3, + /* 4ad - _DE_C8 */ 0x22e4, + /* 4ae - _DE_C8 */ 0x22e5, + /* 4af - _DE_C8 */ 0x22e6, + /* 4b0 - */ 0, + /* 4b1 - */ 0, + /* 4b2 - */ 0, + /* 4b3 - */ 0, + /* 4b4 - */ 0, + /* 4b5 - */ 0, + /* 4b6 - */ 0, + /* 4b7 - */ 0, + /* 4b8 - */ 0, + /* 4b9 - _DE_D9 */ 0x22e7, + /* 4ba - */ 0, + /* 4bb - */ 0, + /* 4bc - */ 0, + /* 4bd - */ 0, + /* 4be - */ 0, + /* 4bf - */ 0, + /* 4c0 - _DE_E0 */ 0x22e8, + /* 4c1 - _DE_E1 */ 0x22e9, + /* 4c2 - _DE_E0 */ 0x22ea, + /* 4c3 - _DE_E0 */ 0x22eb, + /* 4c4 - _DE_E0 */ 0x22ec, + /* 4c5 - _DE_E0 */ 0x22ed, + /* 4c6 - _DE_E0 */ 0x22ee, + /* 4c7 - _DE_E0 */ 0x22ef, + /* 4c8 - _DE_E8 */ 0x22f0, + /* 4c9 - _DE_E9 */ 0x22f1, + /* 4ca - _DE_E8 */ 0x22f2, + /* 4cb - _DE_E8 */ 0x22f3, + /* 4cc - _DE_E8 */ 0x22f4, + /* 4cd - _DE_E8 */ 0x22f5, + /* 4ce - _DE_E8 */ 0x22f6, + /* 4cf - _DE_E8 */ 0x22f7, + /* 4d0 - _DE_F0 */ 0x22f8, + /* 4d1 - _DE_F1 */ 0x22f9, + /* 4d2 - _DE_F0 */ 0x22fa, + /* 4d3 - _DE_F0 */ 0x22fb, + /* 4d4 - _DE_F0 */ 0x22fc, + /* 4d5 - _DE_F0 */ 0x22fd, + /* 4d6 - _DE_F0 */ 0x22fe, + /* 4d7 - _DE_F0 */ 0x22ff, + /* 4d8 - _DE_F8 */ 0x2300, + /* 4d9 - _DE_F9 */ 0x2301, + /* 4da - _DE_F8 */ 0x2302, + /* 4db - _DE_F8 */ 0x2303, + /* 4dc - _DE_F8 */ 0x2304, + /* 4dd - _DE_F8 */ 0x2305, + /* 4de - _DE_F8 */ 0x2306, + /* 4df - _DE_F8 */ 0x2307, + /* 4e0 - _DF_00 */ 0x2308, + /* 4e1 - _DF_01 */ 0x2309, + /* 4e2 - _DF_02 */ 0x230a, + /* 4e3 - _DF_03 */ 0x230b, + /* 4e4 - _DF_04 */ 0x230c, + /* 4e5 - _DF_05 */ 0x230d, + /* 4e6 - _DF_06 */ 0x230e, + /* 4e7 - _DF_07 */ 0x230f, + /* 4e8 - */ 0, + /* 4e9 - */ 0, + /* 4ea - */ 0, + /* 4eb - */ 0, + /* 4ec - */ 0, + /* 4ed - */ 0, + /* 4ee - */ 0, + /* 4ef - */ 0, + /* 4f0 - */ 0, + /* 4f1 - */ 0, + /* 4f2 - */ 0, + /* 4f3 - */ 0, + /* 4f4 - */ 0, + /* 4f5 - */ 0, + /* 4f6 - */ 0, + /* 4f7 - */ 0, + /* 4f8 - */ 0, + /* 4f9 - */ 0, + /* 4fa - */ 0, + /* 4fb - */ 0, + /* 4fc - */ 0, + /* 4fd - */ 0, + /* 4fe - */ 0, + /* 4ff - */ 0, + /* 500 - */ 0, + /* 501 - */ 0, + /* 502 - */ 0, + /* 503 - */ 0, + /* 504 - */ 0, + /* 505 - */ 0, + /* 506 - */ 0, + /* 507 - */ 0, + /* 508 - _DF_E0 */ 0xef6c, + /* 509 - */ 0, + /* 50a - */ 0, + /* 50b - */ 0, + /* 50c - */ 0, + /* 50d - */ 0, + /* 50e - */ 0, + /* 50f - */ 0, + /* 510 - _DF_E8 */ 0x2310, + /* 511 - _DF_E8 */ 0x2311, + /* 512 - _DF_E8 */ 0x2312, + /* 513 - _DF_E8 */ 0x2313, + /* 514 - _DF_E8 */ 0x2314, + /* 515 - _DF_E8 */ 0x2315, + /* 516 - _DF_E8 */ 0x2316, + /* 517 - _DF_E8 */ 0x2317, + /* 518 - _DF_F0 */ 0x2318, + /* 519 - _DF_F0 */ 0x2319, + /* 51a - _DF_F0 */ 0x231a, + /* 51b - _DF_F0 */ 0x231b, + /* 51c - _DF_F0 */ 0x231c, + /* 51d - _DF_F0 */ 0x231d, + /* 51e - _DF_F0 */ 0x231e, + /* 51f - _DF_F0 */ 0x231f, + /* 520 - */ 0, + /* 521 - */ 0, + /* 522 - */ 0, + /* 523 - */ 0, + /* 524 - */ 0, + /* 525 - */ 0, + /* 526 - */ 0, + /* 527 - */ 0, + /* 528 - _F6_00 */ 0x2320, + /* 529 - */ 0, + /* 52a - _F6_02 */ 0x2321, + /* 52b - _F6_03 */ 0x2322, + /* 52c - _F6_04 */ 0x2323, + /* 52d - _F6_05 */ 0x2324, + /* 52e - _F6_06 */ 0x2325, + /* 52f - _F6_07 */ 0x2326, + /* 530 - _F7_00 */ 0x2327, + /* 531 - */ 0, + /* 532 - _F7_02 */ 0x2328, + /* 533 - _F7_03 */ 0x2329, + /* 534 - _F7_04 */ 0x232a, + /* 535 - _F7_05 */ 0x232b, + /* 536 - _F7_06 */ 0x232c, + /* 537 - _F7_07 */ 0x232d, + /* 538 - _FE_00 */ 0x232e, + /* 539 - _FE_01 */ 0x232f, + /* 53a - */ 0, + /* 53b - */ 0, + /* 53c - */ 0, + /* 53d - */ 0, + /* 53e - */ 0, + /* 53f - */ 0, + /* 540 - _FF_00 */ 0x2330, + /* 541 - _FF_01 */ 0x2331, + /* 542 - _FF_02 */ 0x2332, + /* 543 - _FF_03 */ 0x2333, + /* 544 - _FF_04 */ 0x2334, + /* 545 - _FF_05 */ 0x2335, + /* 546 - _FF_06 */ 0x2336, + /* 547 - */ 0, + /* 548 - _0F_00_00 */ 0x2337, + /* 549 - _0F_00_01 */ 0x2338, + /* 54a - _0F_00_02 */ 0x2339, + /* 54b - _0F_00_03 */ 0x233a, + /* 54c - _0F_00_04 */ 0x233b, + /* 54d - _0F_00_05 */ 0x233c, + /* 54e - */ 0, + /* 54f - */ 0, + /* 550 - _0F_01_00 */ 0x233d, + /* 551 - _0F_01_01 */ 0x233e, + /* 552 - _0F_01_02 */ 0x233f, + /* 553 - _0F_01_03 */ 0x2340, + /* 554 - _0F_01_04 */ 0x2341, + /* 555 - */ 0, + /* 556 - _0F_01_06 */ 0x2342, + /* 557 - _0F_01_07 */ 0x2343, + /* 558 - */ 0, + /* 559 - _0F_01_C1 */ 0x2344, + /* 55a - _0F_01_C2 */ 0x2345, + /* 55b - _0F_01_C3 */ 0x2346, + /* 55c - _0F_01_C4 */ 0x2347, + /* 55d - */ 0, + /* 55e - */ 0, + /* 55f - */ 0, + /* 560 - _0F_01_C8 */ 0x2348, + /* 561 - _0F_01_C9 */ 0x2349, + /* 562 - _0F_01_CA */ 0x234a, + /* 563 - _0F_01_CB */ 0x234b, + /* 564 - */ 0, + /* 565 - */ 0, + /* 566 - */ 0, + /* 567 - */ 0, + /* 568 - _0F_01_D0 */ 0x234c, + /* 569 - _0F_01_D1 */ 0x234d, + /* 56a - */ 0, + /* 56b - */ 0, + /* 56c - _0F_01_D4 */ 0x234e, + /* 56d - _0F_01_D5 */ 0x234f, + /* 56e - */ 0, + /* 56f - */ 0, + /* 570 - _0F_01_D8 */ 0x2350, + /* 571 - _0F_01_D9 */ 0x2351, + /* 572 - _0F_01_DA */ 0x2352, + /* 573 - _0F_01_DB */ 0x2353, + /* 574 - _0F_01_DC */ 0x2354, + /* 575 - _0F_01_DD */ 0x2355, + /* 576 - _0F_01_DE */ 0x2356, + /* 577 - _0F_01_DF */ 0x2357, + /* 578 - */ 0, + /* 579 - */ 0, + /* 57a - */ 0, + /* 57b - */ 0, + /* 57c - */ 0, + /* 57d - */ 0, + /* 57e - */ 0, + /* 57f - */ 0, + /* 580 - */ 0, + /* 581 - */ 0, + /* 582 - */ 0, + /* 583 - */ 0, + /* 584 - */ 0, + /* 585 - */ 0, + /* 586 - */ 0, + /* 587 - */ 0, + /* 588 - */ 0, + /* 589 - */ 0, + /* 58a - */ 0, + /* 58b - */ 0, + /* 58c - */ 0, + /* 58d - */ 0, + /* 58e - */ 0, + /* 58f - */ 0, + /* 590 - _0F_01_F8 */ 0x2358, + /* 591 - _0F_01_F9 */ 0x2359, + /* 592 - */ 0, + /* 593 - */ 0, + /* 594 - */ 0, + /* 595 - */ 0, + /* 596 - */ 0, + /* 597 - */ 0, + /* 598 - _0F_0D_00 */ 0x235a, + /* 599 - _0F_0D_01 */ 0x235b, + /* 59a - */ 0, + /* 59b - */ 0, + /* 59c - */ 0, + /* 59d - */ 0, + /* 59e - */ 0, + /* 59f - */ 0, + /* 5a0 - */ 0, + /* 5a1 - */ 0, + /* 5a2 - */ 0, + /* 5a3 - */ 0, + /* 5a4 - */ 0, + /* 5a5 - */ 0, + /* 5a6 - */ 0, + /* 5a7 - */ 0, + /* 5a8 - */ 0, + /* 5a9 - */ 0, + /* 5aa - */ 0, + /* 5ab - */ 0, + /* 5ac - _0F_0F_0C */ 0x235c, + /* 5ad - _0F_0F_0D */ 0x235d, + /* 5ae - */ 0, + /* 5af - */ 0, + /* 5b0 - */ 0, + /* 5b1 - */ 0, + /* 5b2 - */ 0, + /* 5b3 - */ 0, + /* 5b4 - */ 0, + /* 5b5 - */ 0, + /* 5b6 - */ 0, + /* 5b7 - */ 0, + /* 5b8 - */ 0, + /* 5b9 - */ 0, + /* 5ba - */ 0, + /* 5bb - */ 0, + /* 5bc - _0F_0F_1C */ 0x235e, + /* 5bd - _0F_0F_1D */ 0x235f, + /* 5be - */ 0, + /* 5bf - */ 0, + /* 5c0 - */ 0, + /* 5c1 - */ 0, + /* 5c2 - */ 0, + /* 5c3 - */ 0, + /* 5c4 - */ 0, + /* 5c5 - */ 0, + /* 5c6 - */ 0, + /* 5c7 - */ 0, + /* 5c8 - */ 0, + /* 5c9 - */ 0, + /* 5ca - */ 0, + /* 5cb - */ 0, + /* 5cc - */ 0, + /* 5cd - */ 0, + /* 5ce - */ 0, + /* 5cf - */ 0, + /* 5d0 - */ 0, + /* 5d1 - */ 0, + /* 5d2 - */ 0, + /* 5d3 - */ 0, + /* 5d4 - */ 0, + /* 5d5 - */ 0, + /* 5d6 - */ 0, + /* 5d7 - */ 0, + /* 5d8 - */ 0, + /* 5d9 - */ 0, + /* 5da - */ 0, + /* 5db - */ 0, + /* 5dc - */ 0, + /* 5dd - */ 0, + /* 5de - */ 0, + /* 5df - */ 0, + /* 5e0 - */ 0, + /* 5e1 - */ 0, + /* 5e2 - */ 0, + /* 5e3 - */ 0, + /* 5e4 - */ 0, + /* 5e5 - */ 0, + /* 5e6 - */ 0, + /* 5e7 - */ 0, + /* 5e8 - */ 0, + /* 5e9 - */ 0, + /* 5ea - */ 0, + /* 5eb - */ 0, + /* 5ec - */ 0, + /* 5ed - */ 0, + /* 5ee - */ 0, + /* 5ef - */ 0, + /* 5f0 - */ 0, + /* 5f1 - */ 0, + /* 5f2 - */ 0, + /* 5f3 - */ 0, + /* 5f4 - */ 0, + /* 5f5 - */ 0, + /* 5f6 - */ 0, + /* 5f7 - */ 0, + /* 5f8 - */ 0, + /* 5f9 - */ 0, + /* 5fa - */ 0, + /* 5fb - */ 0, + /* 5fc - */ 0, + /* 5fd - */ 0, + /* 5fe - */ 0, + /* 5ff - */ 0, + /* 600 - */ 0, + /* 601 - */ 0, + /* 602 - */ 0, + /* 603 - */ 0, + /* 604 - */ 0, + /* 605 - */ 0, + /* 606 - */ 0, + /* 607 - */ 0, + /* 608 - */ 0, + /* 609 - */ 0, + /* 60a - */ 0, + /* 60b - */ 0, + /* 60c - */ 0, + /* 60d - */ 0, + /* 60e - */ 0, + /* 60f - */ 0, + /* 610 - */ 0, + /* 611 - */ 0, + /* 612 - */ 0, + /* 613 - */ 0, + /* 614 - */ 0, + /* 615 - */ 0, + /* 616 - */ 0, + /* 617 - */ 0, + /* 618 - */ 0, + /* 619 - */ 0, + /* 61a - */ 0, + /* 61b - */ 0, + /* 61c - */ 0, + /* 61d - */ 0, + /* 61e - */ 0, + /* 61f - */ 0, + /* 620 - */ 0, + /* 621 - */ 0, + /* 622 - */ 0, + /* 623 - */ 0, + /* 624 - */ 0, + /* 625 - */ 0, + /* 626 - */ 0, + /* 627 - */ 0, + /* 628 - */ 0, + /* 629 - */ 0, + /* 62a - _0F_0F_8A */ 0x2360, + /* 62b - */ 0, + /* 62c - */ 0, + /* 62d - */ 0, + /* 62e - _0F_0F_8E */ 0x2361, + /* 62f - */ 0, + /* 630 - _0F_0F_90 */ 0x2362, + /* 631 - */ 0, + /* 632 - */ 0, + /* 633 - */ 0, + /* 634 - _0F_0F_94 */ 0x2363, + /* 635 - */ 0, + /* 636 - _0F_0F_96 */ 0x2364, + /* 637 - _0F_0F_97 */ 0x2365, + /* 638 - */ 0, + /* 639 - */ 0, + /* 63a - _0F_0F_9A */ 0x2366, + /* 63b - */ 0, + /* 63c - */ 0, + /* 63d - */ 0, + /* 63e - _0F_0F_9E */ 0x2367, + /* 63f - */ 0, + /* 640 - _0F_0F_A0 */ 0x2368, + /* 641 - */ 0, + /* 642 - */ 0, + /* 643 - */ 0, + /* 644 - _0F_0F_A4 */ 0x2369, + /* 645 - */ 0, + /* 646 - _0F_0F_A6 */ 0x236a, + /* 647 - _0F_0F_A7 */ 0x236b, + /* 648 - */ 0, + /* 649 - */ 0, + /* 64a - _0F_0F_AA */ 0x236c, + /* 64b - */ 0, + /* 64c - */ 0, + /* 64d - */ 0, + /* 64e - _0F_0F_AE */ 0x236d, + /* 64f - */ 0, + /* 650 - _0F_0F_B0 */ 0x236e, + /* 651 - */ 0, + /* 652 - */ 0, + /* 653 - */ 0, + /* 654 - _0F_0F_B4 */ 0x236f, + /* 655 - */ 0, + /* 656 - _0F_0F_B6 */ 0x2370, + /* 657 - _0F_0F_B7 */ 0x2371, + /* 658 - */ 0, + /* 659 - */ 0, + /* 65a - */ 0, + /* 65b - _0F_0F_BB */ 0x2372, + /* 65c - */ 0, + /* 65d - */ 0, + /* 65e - */ 0, + /* 65f - _0F_0F_BF */ 0x2373, + /* 660 - */ 0, + /* 661 - */ 0, + /* 662 - */ 0, + /* 663 - */ 0, + /* 664 - */ 0, + /* 665 - */ 0, + /* 666 - */ 0, + /* 667 - */ 0, + /* 668 - */ 0, + /* 669 - */ 0, + /* 66a - */ 0, + /* 66b - */ 0, + /* 66c - */ 0, + /* 66d - */ 0, + /* 66e - */ 0, + /* 66f - */ 0, + /* 670 - */ 0, + /* 671 - */ 0, + /* 672 - */ 0, + /* 673 - */ 0, + /* 674 - */ 0, + /* 675 - */ 0, + /* 676 - */ 0, + /* 677 - */ 0, + /* 678 - */ 0, + /* 679 - */ 0, + /* 67a - */ 0, + /* 67b - */ 0, + /* 67c - */ 0, + /* 67d - */ 0, + /* 67e - */ 0, + /* 67f - */ 0, + /* 680 - */ 0, + /* 681 - */ 0, + /* 682 - */ 0, + /* 683 - */ 0, + /* 684 - */ 0, + /* 685 - */ 0, + /* 686 - */ 0, + /* 687 - */ 0, + /* 688 - */ 0, + /* 689 - */ 0, + /* 68a - */ 0, + /* 68b - */ 0, + /* 68c - */ 0, + /* 68d - */ 0, + /* 68e - */ 0, + /* 68f - */ 0, + /* 690 - */ 0, + /* 691 - */ 0, + /* 692 - */ 0, + /* 693 - */ 0, + /* 694 - */ 0, + /* 695 - */ 0, + /* 696 - */ 0, + /* 697 - */ 0, + /* 698 - */ 0, + /* 699 - */ 0, + /* 69a - */ 0, + /* 69b - */ 0, + /* 69c - */ 0, + /* 69d - */ 0, + /* 69e - */ 0, + /* 69f - */ 0, + /* 6a0 - _0F_10 */ 0x2374, + /* 6a1 - _66_0F_10 */ 0x2375, + /* 6a2 - _F3_0F_10 */ 0x2376, + /* 6a3 - _F2_0F_10 */ 0x2377, + /* 6a4 - _V_0F_10 */ 0x4009, + /* 6a5 - _V_66_0F_10 */ 0x400a, + /* 6a6 - _V_F3_0F_10 */ 0x400b, + /* 6a7 - _V_F2_0F_10 */ 0x400c, + /* 6a8 - */ 0, + /* 6a9 - */ 0, + /* 6aa - _VRR_F3_0F_10 */ 0x400d, + /* 6ab - _VRR_F2_0F_10 */ 0x400e, + /* 6ac - _0F_11 */ 0x2378, + /* 6ad - _66_0F_11 */ 0x2379, + /* 6ae - _F3_0F_11 */ 0x237a, + /* 6af - _F2_0F_11 */ 0x237b, + /* 6b0 - _V_0F_11 */ 0x400f, + /* 6b1 - _V_66_0F_11 */ 0x4010, + /* 6b2 - _V_F3_0F_11 */ 0x4011, + /* 6b3 - _V_F2_0F_11 */ 0x4012, + /* 6b4 - */ 0, + /* 6b5 - */ 0, + /* 6b6 - _VRR_F3_0F_11 */ 0x4013, + /* 6b7 - _VRR_F2_0F_11 */ 0x4014, + /* 6b8 - _0F_12 */ 0x4015, + /* 6b9 - _66_0F_12 */ 0x237c, + /* 6ba - _F3_0F_12 */ 0x237d, + /* 6bb - _F2_0F_12 */ 0x237e, + /* 6bc - _V_0F_12 */ 0x4016, + /* 6bd - _V_66_0F_12 */ 0x4017, + /* 6be - _V_F3_0F_12 */ 0x4018, + /* 6bf - _V_F2_0F_12 */ 0x4019, + /* 6c0 - */ 0, + /* 6c1 - */ 0, + /* 6c2 - */ 0, + /* 6c3 - */ 0, + /* 6c4 - _0F_13 */ 0x237f, + /* 6c5 - _66_0F_13 */ 0x2380, + /* 6c6 - */ 0, + /* 6c7 - */ 0, + /* 6c8 - _V_0F_13 */ 0x401a, + /* 6c9 - _V_66_0F_13 */ 0x401b, + /* 6ca - */ 0, + /* 6cb - */ 0, + /* 6cc - */ 0, + /* 6cd - */ 0, + /* 6ce - */ 0, + /* 6cf - */ 0, + /* 6d0 - _0F_14 */ 0x2381, + /* 6d1 - _66_0F_14 */ 0x2382, + /* 6d2 - */ 0, + /* 6d3 - */ 0, + /* 6d4 - _V_0F_14 */ 0x401c, + /* 6d5 - _V_66_0F_14 */ 0x401d, + /* 6d6 - */ 0, + /* 6d7 - */ 0, + /* 6d8 - */ 0, + /* 6d9 - */ 0, + /* 6da - */ 0, + /* 6db - */ 0, + /* 6dc - _0F_15 */ 0x2383, + /* 6dd - _66_0F_15 */ 0x2384, + /* 6de - */ 0, + /* 6df - */ 0, + /* 6e0 - _V_0F_15 */ 0x401e, + /* 6e1 - _V_66_0F_15 */ 0x401f, + /* 6e2 - */ 0, + /* 6e3 - */ 0, + /* 6e4 - */ 0, + /* 6e5 - */ 0, + /* 6e6 - */ 0, + /* 6e7 - */ 0, + /* 6e8 - _0F_16 */ 0x4020, + /* 6e9 - _66_0F_16 */ 0x2385, + /* 6ea - _F3_0F_16 */ 0x2386, + /* 6eb - */ 0, + /* 6ec - _V_0F_16 */ 0x4021, + /* 6ed - _V_66_0F_16 */ 0x4022, + /* 6ee - _V_F3_0F_16 */ 0x4023, + /* 6ef - */ 0, + /* 6f0 - */ 0, + /* 6f1 - */ 0, + /* 6f2 - */ 0, + /* 6f3 - */ 0, + /* 6f4 - _0F_17 */ 0x2387, + /* 6f5 - _66_0F_17 */ 0x2388, + /* 6f6 - */ 0, + /* 6f7 - */ 0, + /* 6f8 - _V_0F_17 */ 0x4024, + /* 6f9 - _V_66_0F_17 */ 0x4025, + /* 6fa - */ 0, + /* 6fb - */ 0, + /* 6fc - */ 0, + /* 6fd - */ 0, + /* 6fe - */ 0, + /* 6ff - */ 0, + /* 700 - _0F_18_00 */ 0x2389, + /* 701 - _0F_18_01 */ 0x238a, + /* 702 - _0F_18_02 */ 0x238b, + /* 703 - _0F_18_03 */ 0x238c, + /* 704 - */ 0, + /* 705 - */ 0, + /* 706 - */ 0, + /* 707 - */ 0, + /* 708 - _0F_28 */ 0x238d, + /* 709 - _66_0F_28 */ 0x238e, + /* 70a - */ 0, + /* 70b - */ 0, + /* 70c - _V_0F_28 */ 0x4026, + /* 70d - _V_66_0F_28 */ 0x4027, + /* 70e - */ 0, + /* 70f - */ 0, + /* 710 - */ 0, + /* 711 - */ 0, + /* 712 - */ 0, + /* 713 - */ 0, + /* 714 - _0F_29 */ 0x238f, + /* 715 - _66_0F_29 */ 0x2390, + /* 716 - */ 0, + /* 717 - */ 0, + /* 718 - _V_0F_29 */ 0x4028, + /* 719 - _V_66_0F_29 */ 0x4029, + /* 71a - */ 0, + /* 71b - */ 0, + /* 71c - */ 0, + /* 71d - */ 0, + /* 71e - */ 0, + /* 71f - */ 0, + /* 720 - _0F_2A */ 0x2391, + /* 721 - _66_0F_2A */ 0x2392, + /* 722 - _F3_0F_2A */ 0x2393, + /* 723 - _F2_0F_2A */ 0x2394, + /* 724 - */ 0, + /* 725 - */ 0, + /* 726 - _V_F3_0F_2A */ 0x402a, + /* 727 - _V_F2_0F_2A */ 0x402b, + /* 728 - */ 0, + /* 729 - */ 0, + /* 72a - */ 0, + /* 72b - */ 0, + /* 72c - _0F_2B */ 0x2395, + /* 72d - _66_0F_2B */ 0x2396, + /* 72e - _F3_0F_2B */ 0x2397, + /* 72f - _F2_0F_2B */ 0x2398, + /* 730 - _V_0F_2B */ 0x402c, + /* 731 - _V_66_0F_2B */ 0x402d, + /* 732 - */ 0, + /* 733 - */ 0, + /* 734 - */ 0, + /* 735 - */ 0, + /* 736 - */ 0, + /* 737 - */ 0, + /* 738 - _0F_2C */ 0x2399, + /* 739 - _66_0F_2C */ 0x239a, + /* 73a - _F3_0F_2C */ 0x239b, + /* 73b - _F2_0F_2C */ 0x239c, + /* 73c - */ 0, + /* 73d - */ 0, + /* 73e - _V_F3_0F_2C */ 0x402e, + /* 73f - _V_F2_0F_2C */ 0x402f, + /* 740 - */ 0, + /* 741 - */ 0, + /* 742 - */ 0, + /* 743 - */ 0, + /* 744 - _0F_2D */ 0x239d, + /* 745 - _66_0F_2D */ 0x239e, + /* 746 - _F3_0F_2D */ 0x239f, + /* 747 - _F2_0F_2D */ 0x23a0, + /* 748 - */ 0, + /* 749 - */ 0, + /* 74a - _V_F3_0F_2D */ 0x4030, + /* 74b - _V_F2_0F_2D */ 0x4031, + /* 74c - */ 0, + /* 74d - */ 0, + /* 74e - */ 0, + /* 74f - */ 0, + /* 750 - _0F_2E */ 0x23a1, + /* 751 - _66_0F_2E */ 0x23a2, + /* 752 - */ 0, + /* 753 - */ 0, + /* 754 - _V_0F_2E */ 0x4032, + /* 755 - _V_66_0F_2E */ 0x4033, + /* 756 - */ 0, + /* 757 - */ 0, + /* 758 - */ 0, + /* 759 - */ 0, + /* 75a - */ 0, + /* 75b - */ 0, + /* 75c - _0F_2F */ 0x23a3, + /* 75d - _66_0F_2F */ 0x23a4, + /* 75e - */ 0, + /* 75f - */ 0, + /* 760 - _V_0F_2F */ 0x4034, + /* 761 - _V_66_0F_2F */ 0x4035, + /* 762 - */ 0, + /* 763 - */ 0, + /* 764 - */ 0, + /* 765 - */ 0, + /* 766 - */ 0, + /* 767 - */ 0, + /* 768 - _0F_38_00 */ 0xef78, + /* 769 - _0F_38_01 */ 0xef84, + /* 76a - _0F_38_02 */ 0xef90, + /* 76b - _0F_38_03 */ 0xef9c, + /* 76c - _0F_38_04 */ 0xefa8, + /* 76d - _0F_38_05 */ 0xefb4, + /* 76e - _0F_38_06 */ 0xefc0, + /* 76f - _0F_38_07 */ 0xefcc, + /* 770 - _0F_38_08 */ 0xefd8, + /* 771 - _0F_38_09 */ 0xefe4, + /* 772 - _0F_38_0A */ 0xeff0, + /* 773 - _0F_38_0B */ 0xeffc, + /* 774 - _0F_38_0C */ 0xf008, + /* 775 - _0F_38_0D */ 0xf014, + /* 776 - _0F_38_0E */ 0xf020, + /* 777 - _0F_38_0F */ 0xf02c, + /* 778 - _0F_38_10 */ 0xf038, + /* 779 - */ 0, + /* 77a - */ 0, + /* 77b - */ 0, + /* 77c - _0F_38_14 */ 0xf044, + /* 77d - _0F_38_15 */ 0xf050, + /* 77e - */ 0, + /* 77f - _0F_38_17 */ 0xf05c, + /* 780 - _0F_38_18 */ 0xf068, + /* 781 - _0F_38_19 */ 0xf074, + /* 782 - _0F_38_1A */ 0xf080, + /* 783 - */ 0, + /* 784 - _0F_38_1C */ 0xf08c, + /* 785 - _0F_38_1D */ 0xf098, + /* 786 - _0F_38_1E */ 0xf0a4, + /* 787 - */ 0, + /* 788 - _0F_38_20 */ 0xf0b0, + /* 789 - _0F_38_21 */ 0xf0bc, + /* 78a - _0F_38_22 */ 0xf0c8, + /* 78b - _0F_38_23 */ 0xf0d4, + /* 78c - _0F_38_24 */ 0xf0e0, + /* 78d - _0F_38_25 */ 0xf0ec, + /* 78e - */ 0, + /* 78f - */ 0, + /* 790 - _0F_38_28 */ 0xf0f8, + /* 791 - _0F_38_29 */ 0xf104, + /* 792 - _0F_38_2A */ 0xf110, + /* 793 - _0F_38_2B */ 0xf11c, + /* 794 - _0F_38_2C */ 0xf128, + /* 795 - _0F_38_2D */ 0xf134, + /* 796 - _0F_38_2E */ 0xf140, + /* 797 - _0F_38_2F */ 0xf14c, + /* 798 - _0F_38_30 */ 0xf158, + /* 799 - _0F_38_31 */ 0xf164, + /* 79a - _0F_38_32 */ 0xf170, + /* 79b - _0F_38_33 */ 0xf17c, + /* 79c - _0F_38_34 */ 0xf188, + /* 79d - _0F_38_35 */ 0xf194, + /* 79e - */ 0, + /* 79f - _0F_38_37 */ 0xf1a0, + /* 7a0 - _0F_38_38 */ 0xf1ac, + /* 7a1 - _0F_38_39 */ 0xf1b8, + /* 7a2 - _0F_38_3A */ 0xf1c4, + /* 7a3 - _0F_38_3B */ 0xf1d0, + /* 7a4 - _0F_38_3C */ 0xf1dc, + /* 7a5 - _0F_38_3D */ 0xf1e8, + /* 7a6 - _0F_38_3E */ 0xf1f4, + /* 7a7 - _0F_38_3F */ 0xf200, + /* 7a8 - _0F_38_40 */ 0xf20c, + /* 7a9 - _0F_38_41 */ 0xf218, + /* 7aa - */ 0, + /* 7ab - */ 0, + /* 7ac - */ 0, + /* 7ad - */ 0, + /* 7ae - */ 0, + /* 7af - */ 0, + /* 7b0 - */ 0, + /* 7b1 - */ 0, + /* 7b2 - */ 0, + /* 7b3 - */ 0, + /* 7b4 - */ 0, + /* 7b5 - */ 0, + /* 7b6 - */ 0, + /* 7b7 - */ 0, + /* 7b8 - */ 0, + /* 7b9 - */ 0, + /* 7ba - */ 0, + /* 7bb - */ 0, + /* 7bc - */ 0, + /* 7bd - */ 0, + /* 7be - */ 0, + /* 7bf - */ 0, + /* 7c0 - */ 0, + /* 7c1 - */ 0, + /* 7c2 - */ 0, + /* 7c3 - */ 0, + /* 7c4 - */ 0, + /* 7c5 - */ 0, + /* 7c6 - */ 0, + /* 7c7 - */ 0, + /* 7c8 - */ 0, + /* 7c9 - */ 0, + /* 7ca - */ 0, + /* 7cb - */ 0, + /* 7cc - */ 0, + /* 7cd - */ 0, + /* 7ce - */ 0, + /* 7cf - */ 0, + /* 7d0 - */ 0, + /* 7d1 - */ 0, + /* 7d2 - */ 0, + /* 7d3 - */ 0, + /* 7d4 - */ 0, + /* 7d5 - */ 0, + /* 7d6 - */ 0, + /* 7d7 - */ 0, + /* 7d8 - */ 0, + /* 7d9 - */ 0, + /* 7da - */ 0, + /* 7db - */ 0, + /* 7dc - */ 0, + /* 7dd - */ 0, + /* 7de - */ 0, + /* 7df - */ 0, + /* 7e0 - */ 0, + /* 7e1 - */ 0, + /* 7e2 - */ 0, + /* 7e3 - */ 0, + /* 7e4 - */ 0, + /* 7e5 - */ 0, + /* 7e6 - */ 0, + /* 7e7 - */ 0, + /* 7e8 - _0F_38_80 */ 0xf224, + /* 7e9 - _0F_38_81 */ 0xf230, + /* 7ea - _0F_38_82 */ 0xf23c, + /* 7eb - */ 0, + /* 7ec - */ 0, + /* 7ed - */ 0, + /* 7ee - */ 0, + /* 7ef - */ 0, + /* 7f0 - */ 0, + /* 7f1 - */ 0, + /* 7f2 - */ 0, + /* 7f3 - */ 0, + /* 7f4 - */ 0, + /* 7f5 - */ 0, + /* 7f6 - */ 0, + /* 7f7 - */ 0, + /* 7f8 - */ 0, + /* 7f9 - */ 0, + /* 7fa - */ 0, + /* 7fb - */ 0, + /* 7fc - */ 0, + /* 7fd - */ 0, + /* 7fe - _0F_38_96 */ 0xf248, + /* 7ff - _0F_38_97 */ 0xf254, + /* 800 - _0F_38_98 */ 0xf260, + /* 801 - _0F_38_99 */ 0xf26c, + /* 802 - _0F_38_9A */ 0xf278, + /* 803 - _0F_38_9B */ 0xf284, + /* 804 - _0F_38_9C */ 0xf290, + /* 805 - _0F_38_9D */ 0xf29c, + /* 806 - _0F_38_9E */ 0xf2a8, + /* 807 - _0F_38_9F */ 0xf2b4, + /* 808 - */ 0, + /* 809 - */ 0, + /* 80a - */ 0, + /* 80b - */ 0, + /* 80c - */ 0, + /* 80d - */ 0, + /* 80e - _0F_38_A6 */ 0xf2c0, + /* 80f - _0F_38_A7 */ 0xf2cc, + /* 810 - _0F_38_A8 */ 0xf2d8, + /* 811 - _0F_38_A9 */ 0xf2e4, + /* 812 - _0F_38_AA */ 0xf2f0, + /* 813 - _0F_38_AB */ 0xf2fc, + /* 814 - _0F_38_AC */ 0xf308, + /* 815 - _0F_38_AD */ 0xf314, + /* 816 - _0F_38_AE */ 0xf320, + /* 817 - _0F_38_AF */ 0xf32c, + /* 818 - */ 0, + /* 819 - */ 0, + /* 81a - */ 0, + /* 81b - */ 0, + /* 81c - */ 0, + /* 81d - */ 0, + /* 81e - _0F_38_B6 */ 0xf338, + /* 81f - _0F_38_B7 */ 0xf344, + /* 820 - _0F_38_B8 */ 0xf350, + /* 821 - _0F_38_B9 */ 0xf35c, + /* 822 - _0F_38_BA */ 0xf368, + /* 823 - _0F_38_BB */ 0xf374, + /* 824 - _0F_38_BC */ 0xf380, + /* 825 - _0F_38_BD */ 0xf38c, + /* 826 - _0F_38_BE */ 0xf398, + /* 827 - _0F_38_BF */ 0xf3a4, + /* 828 - */ 0, + /* 829 - */ 0, + /* 82a - */ 0, + /* 82b - */ 0, + /* 82c - */ 0, + /* 82d - */ 0, + /* 82e - */ 0, + /* 82f - */ 0, + /* 830 - */ 0, + /* 831 - */ 0, + /* 832 - */ 0, + /* 833 - */ 0, + /* 834 - */ 0, + /* 835 - */ 0, + /* 836 - */ 0, + /* 837 - */ 0, + /* 838 - */ 0, + /* 839 - */ 0, + /* 83a - */ 0, + /* 83b - */ 0, + /* 83c - */ 0, + /* 83d - */ 0, + /* 83e - */ 0, + /* 83f - */ 0, + /* 840 - */ 0, + /* 841 - */ 0, + /* 842 - */ 0, + /* 843 - _0F_38_DB */ 0xf3b0, + /* 844 - _0F_38_DC */ 0xf3bc, + /* 845 - _0F_38_DD */ 0xf3c8, + /* 846 - _0F_38_DE */ 0xf3d4, + /* 847 - _0F_38_DF */ 0xf3e0, + /* 848 - */ 0, + /* 849 - */ 0, + /* 84a - */ 0, + /* 84b - */ 0, + /* 84c - */ 0, + /* 84d - */ 0, + /* 84e - */ 0, + /* 84f - */ 0, + /* 850 - */ 0, + /* 851 - */ 0, + /* 852 - */ 0, + /* 853 - */ 0, + /* 854 - */ 0, + /* 855 - */ 0, + /* 856 - */ 0, + /* 857 - */ 0, + /* 858 - _0F_38_F0 */ 0xf3ec, + /* 859 - _0F_38_F1 */ 0xf3f8, + /* 85a - */ 0, + /* 85b - */ 0, + /* 85c - */ 0, + /* 85d - */ 0, + /* 85e - */ 0, + /* 85f - */ 0, + /* 860 - */ 0, + /* 861 - */ 0, + /* 862 - */ 0, + /* 863 - */ 0, + /* 864 - */ 0, + /* 865 - */ 0, + /* 866 - */ 0, + /* 867 - */ 0, + /* 868 - */ 0, + /* 869 - */ 0, + /* 86a - */ 0, + /* 86b - */ 0, + /* 86c - _0F_3A_04 */ 0xf404, + /* 86d - _0F_3A_05 */ 0xf410, + /* 86e - _0F_3A_06 */ 0xf41c, + /* 86f - */ 0, + /* 870 - _0F_3A_08 */ 0xf428, + /* 871 - _0F_3A_09 */ 0xf434, + /* 872 - _0F_3A_0A */ 0xf440, + /* 873 - _0F_3A_0B */ 0xf44c, + /* 874 - _0F_3A_0C */ 0xf458, + /* 875 - _0F_3A_0D */ 0xf464, + /* 876 - _0F_3A_0E */ 0xf470, + /* 877 - _0F_3A_0F */ 0xf47c, + /* 878 - */ 0, + /* 879 - */ 0, + /* 87a - */ 0, + /* 87b - */ 0, + /* 87c - _0F_3A_14 */ 0xf488, + /* 87d - _0F_3A_15 */ 0xf494, + /* 87e - _0F_3A_16 */ 0xf4a0, + /* 87f - _0F_3A_17 */ 0xf4ac, + /* 880 - _0F_3A_18 */ 0xf4b8, + /* 881 - _0F_3A_19 */ 0xf4c4, + /* 882 - */ 0, + /* 883 - */ 0, + /* 884 - */ 0, + /* 885 - */ 0, + /* 886 - */ 0, + /* 887 - */ 0, + /* 888 - _0F_3A_20 */ 0xf4d0, + /* 889 - _0F_3A_21 */ 0xf4dc, + /* 88a - _0F_3A_22 */ 0xf4e8, + /* 88b - */ 0, + /* 88c - */ 0, + /* 88d - */ 0, + /* 88e - */ 0, + /* 88f - */ 0, + /* 890 - */ 0, + /* 891 - */ 0, + /* 892 - */ 0, + /* 893 - */ 0, + /* 894 - */ 0, + /* 895 - */ 0, + /* 896 - */ 0, + /* 897 - */ 0, + /* 898 - */ 0, + /* 899 - */ 0, + /* 89a - */ 0, + /* 89b - */ 0, + /* 89c - */ 0, + /* 89d - */ 0, + /* 89e - */ 0, + /* 89f - */ 0, + /* 8a0 - */ 0, + /* 8a1 - */ 0, + /* 8a2 - */ 0, + /* 8a3 - */ 0, + /* 8a4 - */ 0, + /* 8a5 - */ 0, + /* 8a6 - */ 0, + /* 8a7 - */ 0, + /* 8a8 - _0F_3A_40 */ 0xf4f4, + /* 8a9 - _0F_3A_41 */ 0xf500, + /* 8aa - _0F_3A_42 */ 0xf50c, + /* 8ab - */ 0, + /* 8ac - _0F_3A_44 */ 0xf518, + /* 8ad - */ 0, + /* 8ae - */ 0, + /* 8af - */ 0, + /* 8b0 - */ 0, + /* 8b1 - */ 0, + /* 8b2 - _0F_3A_4A */ 0xf524, + /* 8b3 - _0F_3A_4B */ 0xf530, + /* 8b4 - _0F_3A_4C */ 0xf53c, + /* 8b5 - */ 0, + /* 8b6 - */ 0, + /* 8b7 - */ 0, + /* 8b8 - */ 0, + /* 8b9 - */ 0, + /* 8ba - */ 0, + /* 8bb - */ 0, + /* 8bc - */ 0, + /* 8bd - */ 0, + /* 8be - */ 0, + /* 8bf - */ 0, + /* 8c0 - */ 0, + /* 8c1 - */ 0, + /* 8c2 - */ 0, + /* 8c3 - */ 0, + /* 8c4 - */ 0, + /* 8c5 - */ 0, + /* 8c6 - */ 0, + /* 8c7 - */ 0, + /* 8c8 - _0F_3A_60 */ 0xf548, + /* 8c9 - _0F_3A_61 */ 0xf554, + /* 8ca - _0F_3A_62 */ 0xf560, + /* 8cb - _0F_3A_63 */ 0xf56c, + /* 8cc - */ 0, + /* 8cd - */ 0, + /* 8ce - */ 0, + /* 8cf - */ 0, + /* 8d0 - */ 0, + /* 8d1 - */ 0, + /* 8d2 - */ 0, + /* 8d3 - */ 0, + /* 8d4 - */ 0, + /* 8d5 - */ 0, + /* 8d6 - */ 0, + /* 8d7 - */ 0, + /* 8d8 - */ 0, + /* 8d9 - */ 0, + /* 8da - */ 0, + /* 8db - */ 0, + /* 8dc - */ 0, + /* 8dd - */ 0, + /* 8de - */ 0, + /* 8df - */ 0, + /* 8e0 - */ 0, + /* 8e1 - */ 0, + /* 8e2 - */ 0, + /* 8e3 - */ 0, + /* 8e4 - */ 0, + /* 8e5 - */ 0, + /* 8e6 - */ 0, + /* 8e7 - */ 0, + /* 8e8 - */ 0, + /* 8e9 - */ 0, + /* 8ea - */ 0, + /* 8eb - */ 0, + /* 8ec - */ 0, + /* 8ed - */ 0, + /* 8ee - */ 0, + /* 8ef - */ 0, + /* 8f0 - */ 0, + /* 8f1 - */ 0, + /* 8f2 - */ 0, + /* 8f3 - */ 0, + /* 8f4 - */ 0, + /* 8f5 - */ 0, + /* 8f6 - */ 0, + /* 8f7 - */ 0, + /* 8f8 - */ 0, + /* 8f9 - */ 0, + /* 8fa - */ 0, + /* 8fb - */ 0, + /* 8fc - */ 0, + /* 8fd - */ 0, + /* 8fe - */ 0, + /* 8ff - */ 0, + /* 900 - */ 0, + /* 901 - */ 0, + /* 902 - */ 0, + /* 903 - */ 0, + /* 904 - */ 0, + /* 905 - */ 0, + /* 906 - */ 0, + /* 907 - */ 0, + /* 908 - */ 0, + /* 909 - */ 0, + /* 90a - */ 0, + /* 90b - */ 0, + /* 90c - */ 0, + /* 90d - */ 0, + /* 90e - */ 0, + /* 90f - */ 0, + /* 910 - */ 0, + /* 911 - */ 0, + /* 912 - */ 0, + /* 913 - */ 0, + /* 914 - */ 0, + /* 915 - */ 0, + /* 916 - */ 0, + /* 917 - */ 0, + /* 918 - */ 0, + /* 919 - */ 0, + /* 91a - */ 0, + /* 91b - */ 0, + /* 91c - */ 0, + /* 91d - */ 0, + /* 91e - */ 0, + /* 91f - */ 0, + /* 920 - */ 0, + /* 921 - */ 0, + /* 922 - */ 0, + /* 923 - */ 0, + /* 924 - */ 0, + /* 925 - */ 0, + /* 926 - */ 0, + /* 927 - */ 0, + /* 928 - */ 0, + /* 929 - */ 0, + /* 92a - */ 0, + /* 92b - */ 0, + /* 92c - */ 0, + /* 92d - */ 0, + /* 92e - */ 0, + /* 92f - */ 0, + /* 930 - */ 0, + /* 931 - */ 0, + /* 932 - */ 0, + /* 933 - */ 0, + /* 934 - */ 0, + /* 935 - */ 0, + /* 936 - */ 0, + /* 937 - */ 0, + /* 938 - */ 0, + /* 939 - */ 0, + /* 93a - */ 0, + /* 93b - */ 0, + /* 93c - */ 0, + /* 93d - */ 0, + /* 93e - */ 0, + /* 93f - */ 0, + /* 940 - */ 0, + /* 941 - */ 0, + /* 942 - */ 0, + /* 943 - */ 0, + /* 944 - */ 0, + /* 945 - */ 0, + /* 946 - */ 0, + /* 947 - _0F_3A_DF */ 0xf578, + /* 948 - */ 0, + /* 949 - */ 0, + /* 94a - */ 0, + /* 94b - */ 0, + /* 94c - */ 0, + /* 94d - */ 0, + /* 94e - */ 0, + /* 94f - */ 0, + /* 950 - */ 0, + /* 951 - */ 0, + /* 952 - */ 0, + /* 953 - */ 0, + /* 954 - */ 0, + /* 955 - */ 0, + /* 956 - */ 0, + /* 957 - */ 0, + /* 958 - */ 0, + /* 959 - */ 0, + /* 95a - */ 0, + /* 95b - */ 0, + /* 95c - */ 0, + /* 95d - */ 0, + /* 95e - */ 0, + /* 95f - */ 0, + /* 960 - */ 0, + /* 961 - */ 0, + /* 962 - */ 0, + /* 963 - */ 0, + /* 964 - */ 0, + /* 965 - */ 0, + /* 966 - */ 0, + /* 967 - */ 0, + /* 968 - _0F_50 */ 0x23a5, + /* 969 - _66_0F_50 */ 0x23a6, + /* 96a - */ 0, + /* 96b - */ 0, + /* 96c - _V_0F_50 */ 0x4036, + /* 96d - _V_66_0F_50 */ 0x4037, + /* 96e - */ 0, + /* 96f - */ 0, + /* 970 - */ 0, + /* 971 - */ 0, + /* 972 - */ 0, + /* 973 - */ 0, + /* 974 - _0F_51 */ 0x23a7, + /* 975 - _66_0F_51 */ 0x23a8, + /* 976 - _F3_0F_51 */ 0x23a9, + /* 977 - _F2_0F_51 */ 0x23aa, + /* 978 - _V_0F_51 */ 0x4038, + /* 979 - _V_66_0F_51 */ 0x4039, + /* 97a - _V_F3_0F_51 */ 0x403a, + /* 97b - _V_F2_0F_51 */ 0x403b, + /* 97c - */ 0, + /* 97d - */ 0, + /* 97e - */ 0, + /* 97f - */ 0, + /* 980 - _0F_52 */ 0x23ab, + /* 981 - */ 0, + /* 982 - _F3_0F_52 */ 0x23ac, + /* 983 - */ 0, + /* 984 - _V_0F_52 */ 0x403c, + /* 985 - */ 0, + /* 986 - _V_F3_0F_52 */ 0x403d, + /* 987 - */ 0, + /* 988 - */ 0, + /* 989 - */ 0, + /* 98a - */ 0, + /* 98b - */ 0, + /* 98c - _0F_53 */ 0x23ad, + /* 98d - */ 0, + /* 98e - _F3_0F_53 */ 0x23ae, + /* 98f - */ 0, + /* 990 - _V_0F_53 */ 0x403e, + /* 991 - */ 0, + /* 992 - _V_F3_0F_53 */ 0x403f, + /* 993 - */ 0, + /* 994 - */ 0, + /* 995 - */ 0, + /* 996 - */ 0, + /* 997 - */ 0, + /* 998 - _0F_54 */ 0x23af, + /* 999 - _66_0F_54 */ 0x23b0, + /* 99a - */ 0, + /* 99b - */ 0, + /* 99c - _V_0F_54 */ 0x4040, + /* 99d - _V_66_0F_54 */ 0x4041, + /* 99e - */ 0, + /* 99f - */ 0, + /* 9a0 - */ 0, + /* 9a1 - */ 0, + /* 9a2 - */ 0, + /* 9a3 - */ 0, + /* 9a4 - _0F_55 */ 0x23b1, + /* 9a5 - _66_0F_55 */ 0x23b2, + /* 9a6 - */ 0, + /* 9a7 - */ 0, + /* 9a8 - _V_0F_55 */ 0x4042, + /* 9a9 - _V_66_0F_55 */ 0x4043, + /* 9aa - */ 0, + /* 9ab - */ 0, + /* 9ac - */ 0, + /* 9ad - */ 0, + /* 9ae - */ 0, + /* 9af - */ 0, + /* 9b0 - _0F_56 */ 0x23b3, + /* 9b1 - _66_0F_56 */ 0x23b4, + /* 9b2 - */ 0, + /* 9b3 - */ 0, + /* 9b4 - _V_0F_56 */ 0x4044, + /* 9b5 - _V_66_0F_56 */ 0x4045, + /* 9b6 - */ 0, + /* 9b7 - */ 0, + /* 9b8 - */ 0, + /* 9b9 - */ 0, + /* 9ba - */ 0, + /* 9bb - */ 0, + /* 9bc - _0F_57 */ 0x23b5, + /* 9bd - _66_0F_57 */ 0x23b6, + /* 9be - */ 0, + /* 9bf - */ 0, + /* 9c0 - _V_0F_57 */ 0x4046, + /* 9c1 - _V_66_0F_57 */ 0x4047, + /* 9c2 - */ 0, + /* 9c3 - */ 0, + /* 9c4 - */ 0, + /* 9c5 - */ 0, + /* 9c6 - */ 0, + /* 9c7 - */ 0, + /* 9c8 - _0F_58 */ 0x23b7, + /* 9c9 - _66_0F_58 */ 0x23b8, + /* 9ca - _F3_0F_58 */ 0x23b9, + /* 9cb - _F2_0F_58 */ 0x23ba, + /* 9cc - _V_0F_58 */ 0x4048, + /* 9cd - _V_66_0F_58 */ 0x4049, + /* 9ce - _V_F3_0F_58 */ 0x404a, + /* 9cf - _V_F2_0F_58 */ 0x404b, + /* 9d0 - */ 0, + /* 9d1 - */ 0, + /* 9d2 - */ 0, + /* 9d3 - */ 0, + /* 9d4 - _0F_59 */ 0x23bb, + /* 9d5 - _66_0F_59 */ 0x23bc, + /* 9d6 - _F3_0F_59 */ 0x23bd, + /* 9d7 - _F2_0F_59 */ 0x23be, + /* 9d8 - _V_0F_59 */ 0x404c, + /* 9d9 - _V_66_0F_59 */ 0x404d, + /* 9da - _V_F3_0F_59 */ 0x404e, + /* 9db - _V_F2_0F_59 */ 0x404f, + /* 9dc - */ 0, + /* 9dd - */ 0, + /* 9de - */ 0, + /* 9df - */ 0, + /* 9e0 - _0F_5A */ 0x23bf, + /* 9e1 - _66_0F_5A */ 0x23c0, + /* 9e2 - _F3_0F_5A */ 0x23c1, + /* 9e3 - _F2_0F_5A */ 0x23c2, + /* 9e4 - _V_0F_5A */ 0x4050, + /* 9e5 - _V_66_0F_5A */ 0x4051, + /* 9e6 - _V_F3_0F_5A */ 0x4052, + /* 9e7 - _V_F2_0F_5A */ 0x4053, + /* 9e8 - */ 0, + /* 9e9 - */ 0, + /* 9ea - */ 0, + /* 9eb - */ 0, + /* 9ec - _0F_5B */ 0x23c3, + /* 9ed - _66_0F_5B */ 0x23c4, + /* 9ee - _F3_0F_5B */ 0x23c5, + /* 9ef - */ 0, + /* 9f0 - _V_0F_5B */ 0x4054, + /* 9f1 - _V_66_0F_5B */ 0x4055, + /* 9f2 - _V_F3_0F_5B */ 0x4056, + /* 9f3 - */ 0, + /* 9f4 - */ 0, + /* 9f5 - */ 0, + /* 9f6 - */ 0, + /* 9f7 - */ 0, + /* 9f8 - _0F_5C */ 0x23c6, + /* 9f9 - _66_0F_5C */ 0x23c7, + /* 9fa - _F3_0F_5C */ 0x23c8, + /* 9fb - _F2_0F_5C */ 0x23c9, + /* 9fc - _V_0F_5C */ 0x4057, + /* 9fd - _V_66_0F_5C */ 0x4058, + /* 9fe - _V_F3_0F_5C */ 0x4059, + /* 9ff - _V_F2_0F_5C */ 0x405a, + /* a00 - */ 0, + /* a01 - */ 0, + /* a02 - */ 0, + /* a03 - */ 0, + /* a04 - _0F_5D */ 0x23ca, + /* a05 - _66_0F_5D */ 0x23cb, + /* a06 - _F3_0F_5D */ 0x23cc, + /* a07 - _F2_0F_5D */ 0x23cd, + /* a08 - _V_0F_5D */ 0x405b, + /* a09 - _V_66_0F_5D */ 0x405c, + /* a0a - _V_F3_0F_5D */ 0x405d, + /* a0b - _V_F2_0F_5D */ 0x405e, + /* a0c - */ 0, + /* a0d - */ 0, + /* a0e - */ 0, + /* a0f - */ 0, + /* a10 - _0F_5E */ 0x23ce, + /* a11 - _66_0F_5E */ 0x23cf, + /* a12 - _F3_0F_5E */ 0x23d0, + /* a13 - _F2_0F_5E */ 0x23d1, + /* a14 - _V_0F_5E */ 0x405f, + /* a15 - _V_66_0F_5E */ 0x4060, + /* a16 - _V_F3_0F_5E */ 0x4061, + /* a17 - _V_F2_0F_5E */ 0x4062, + /* a18 - */ 0, + /* a19 - */ 0, + /* a1a - */ 0, + /* a1b - */ 0, + /* a1c - _0F_5F */ 0x23d2, + /* a1d - _66_0F_5F */ 0x23d3, + /* a1e - _F3_0F_5F */ 0x23d4, + /* a1f - _F2_0F_5F */ 0x23d5, + /* a20 - _V_0F_5F */ 0x4063, + /* a21 - _V_66_0F_5F */ 0x4064, + /* a22 - _V_F3_0F_5F */ 0x4065, + /* a23 - _V_F2_0F_5F */ 0x4066, + /* a24 - */ 0, + /* a25 - */ 0, + /* a26 - */ 0, + /* a27 - */ 0, + /* a28 - _0F_60 */ 0x23d6, + /* a29 - _66_0F_60 */ 0x23d7, + /* a2a - */ 0, + /* a2b - */ 0, + /* a2c - */ 0, + /* a2d - _V_66_0F_60 */ 0x4067, + /* a2e - */ 0, + /* a2f - */ 0, + /* a30 - */ 0, + /* a31 - */ 0, + /* a32 - */ 0, + /* a33 - */ 0, + /* a34 - _0F_61 */ 0x23d8, + /* a35 - _66_0F_61 */ 0x23d9, + /* a36 - */ 0, + /* a37 - */ 0, + /* a38 - */ 0, + /* a39 - _V_66_0F_61 */ 0x4068, + /* a3a - */ 0, + /* a3b - */ 0, + /* a3c - */ 0, + /* a3d - */ 0, + /* a3e - */ 0, + /* a3f - */ 0, + /* a40 - _0F_62 */ 0x23da, + /* a41 - _66_0F_62 */ 0x23db, + /* a42 - */ 0, + /* a43 - */ 0, + /* a44 - */ 0, + /* a45 - _V_66_0F_62 */ 0x4069, + /* a46 - */ 0, + /* a47 - */ 0, + /* a48 - */ 0, + /* a49 - */ 0, + /* a4a - */ 0, + /* a4b - */ 0, + /* a4c - _0F_63 */ 0x23dc, + /* a4d - _66_0F_63 */ 0x23dd, + /* a4e - */ 0, + /* a4f - */ 0, + /* a50 - */ 0, + /* a51 - _V_66_0F_63 */ 0x406a, + /* a52 - */ 0, + /* a53 - */ 0, + /* a54 - */ 0, + /* a55 - */ 0, + /* a56 - */ 0, + /* a57 - */ 0, + /* a58 - _0F_64 */ 0x23de, + /* a59 - _66_0F_64 */ 0x23df, + /* a5a - */ 0, + /* a5b - */ 0, + /* a5c - */ 0, + /* a5d - _V_66_0F_64 */ 0x406b, + /* a5e - */ 0, + /* a5f - */ 0, + /* a60 - */ 0, + /* a61 - */ 0, + /* a62 - */ 0, + /* a63 - */ 0, + /* a64 - _0F_65 */ 0x23e0, + /* a65 - _66_0F_65 */ 0x23e1, + /* a66 - */ 0, + /* a67 - */ 0, + /* a68 - */ 0, + /* a69 - _V_66_0F_65 */ 0x406c, + /* a6a - */ 0, + /* a6b - */ 0, + /* a6c - */ 0, + /* a6d - */ 0, + /* a6e - */ 0, + /* a6f - */ 0, + /* a70 - _0F_66 */ 0x23e2, + /* a71 - _66_0F_66 */ 0x23e3, + /* a72 - */ 0, + /* a73 - */ 0, + /* a74 - */ 0, + /* a75 - _V_66_0F_66 */ 0x406d, + /* a76 - */ 0, + /* a77 - */ 0, + /* a78 - */ 0, + /* a79 - */ 0, + /* a7a - */ 0, + /* a7b - */ 0, + /* a7c - _0F_67 */ 0x23e4, + /* a7d - _66_0F_67 */ 0x23e5, + /* a7e - */ 0, + /* a7f - */ 0, + /* a80 - */ 0, + /* a81 - _V_66_0F_67 */ 0x406e, + /* a82 - */ 0, + /* a83 - */ 0, + /* a84 - */ 0, + /* a85 - */ 0, + /* a86 - */ 0, + /* a87 - */ 0, + /* a88 - _0F_68 */ 0x23e6, + /* a89 - _66_0F_68 */ 0x23e7, + /* a8a - */ 0, + /* a8b - */ 0, + /* a8c - */ 0, + /* a8d - _V_66_0F_68 */ 0x406f, + /* a8e - */ 0, + /* a8f - */ 0, + /* a90 - */ 0, + /* a91 - */ 0, + /* a92 - */ 0, + /* a93 - */ 0, + /* a94 - _0F_69 */ 0x23e8, + /* a95 - _66_0F_69 */ 0x23e9, + /* a96 - */ 0, + /* a97 - */ 0, + /* a98 - */ 0, + /* a99 - _V_66_0F_69 */ 0x4070, + /* a9a - */ 0, + /* a9b - */ 0, + /* a9c - */ 0, + /* a9d - */ 0, + /* a9e - */ 0, + /* a9f - */ 0, + /* aa0 - _0F_6A */ 0x23ea, + /* aa1 - _66_0F_6A */ 0x23eb, + /* aa2 - */ 0, + /* aa3 - */ 0, + /* aa4 - */ 0, + /* aa5 - _V_66_0F_6A */ 0x4071, + /* aa6 - */ 0, + /* aa7 - */ 0, + /* aa8 - */ 0, + /* aa9 - */ 0, + /* aaa - */ 0, + /* aab - */ 0, + /* aac - _0F_6B */ 0x23ec, + /* aad - _66_0F_6B */ 0x23ed, + /* aae - */ 0, + /* aaf - */ 0, + /* ab0 - */ 0, + /* ab1 - _V_66_0F_6B */ 0x4072, + /* ab2 - */ 0, + /* ab3 - */ 0, + /* ab4 - */ 0, + /* ab5 - */ 0, + /* ab6 - */ 0, + /* ab7 - */ 0, + /* ab8 - */ 0, + /* ab9 - _66_0F_6C */ 0x23ee, + /* aba - */ 0, + /* abb - */ 0, + /* abc - */ 0, + /* abd - _V_66_0F_6C */ 0x4073, + /* abe - */ 0, + /* abf - */ 0, + /* ac0 - */ 0, + /* ac1 - */ 0, + /* ac2 - */ 0, + /* ac3 - */ 0, + /* ac4 - */ 0, + /* ac5 - _66_0F_6D */ 0x23ef, + /* ac6 - */ 0, + /* ac7 - */ 0, + /* ac8 - */ 0, + /* ac9 - _V_66_0F_6D */ 0x4074, + /* aca - */ 0, + /* acb - */ 0, + /* acc - */ 0, + /* acd - */ 0, + /* ace - */ 0, + /* acf - */ 0, + /* ad0 - _0F_6E */ 0x4075, + /* ad1 - _66_0F_6E */ 0x4076, + /* ad2 - */ 0, + /* ad3 - */ 0, + /* ad4 - */ 0, + /* ad5 - _V_66_0F_6E */ 0x4077, + /* ad6 - */ 0, + /* ad7 - */ 0, + /* ad8 - */ 0, + /* ad9 - */ 0, + /* ada - */ 0, + /* adb - */ 0, + /* adc - _0F_6F */ 0x23f0, + /* add - _66_0F_6F */ 0x23f1, + /* ade - _F3_0F_6F */ 0x23f2, + /* adf - */ 0, + /* ae0 - */ 0, + /* ae1 - _V_66_0F_6F */ 0x4078, + /* ae2 - _V_F3_0F_6F */ 0x4079, + /* ae3 - */ 0, + /* ae4 - */ 0, + /* ae5 - */ 0, + /* ae6 - */ 0, + /* ae7 - */ 0, + /* ae8 - _0F_70 */ 0x407a, + /* ae9 - _66_0F_70 */ 0x407b, + /* aea - _F3_0F_70 */ 0x407c, + /* aeb - _F2_0F_70 */ 0x407d, + /* aec - */ 0, + /* aed - _V_66_0F_70 */ 0x407e, + /* aee - _V_F3_0F_70 */ 0x407f, + /* aef - _V_F2_0F_70 */ 0x4080, + /* af0 - */ 0, + /* af1 - */ 0, + /* af2 - */ 0, + /* af3 - */ 0, + /* af4 - */ 0, + /* af5 - */ 0, + /* af6 - _0F_71_02 */ 0xf584, + /* af7 - */ 0, + /* af8 - _0F_71_04 */ 0xf590, + /* af9 - */ 0, + /* afa - _0F_71_06 */ 0xf59c, + /* afb - */ 0, + /* afc - */ 0, + /* afd - */ 0, + /* afe - _0F_72_02 */ 0xf5a8, + /* aff - */ 0, + /* b00 - _0F_72_04 */ 0xf5b4, + /* b01 - */ 0, + /* b02 - _0F_72_06 */ 0xf5c0, + /* b03 - */ 0, + /* b04 - */ 0, + /* b05 - */ 0, + /* b06 - _0F_73_02 */ 0xf5cc, + /* b07 - _0F_73_03 */ 0xf5d8, + /* b08 - */ 0, + /* b09 - */ 0, + /* b0a - _0F_73_06 */ 0xf5e4, + /* b0b - _0F_73_07 */ 0xf5f0, + /* b0c - _0F_74 */ 0x23f3, + /* b0d - _66_0F_74 */ 0x23f4, + /* b0e - */ 0, + /* b0f - */ 0, + /* b10 - */ 0, + /* b11 - _V_66_0F_74 */ 0x4081, + /* b12 - */ 0, + /* b13 - */ 0, + /* b14 - */ 0, + /* b15 - */ 0, + /* b16 - */ 0, + /* b17 - */ 0, + /* b18 - _0F_75 */ 0x23f5, + /* b19 - _66_0F_75 */ 0x23f6, + /* b1a - */ 0, + /* b1b - */ 0, + /* b1c - */ 0, + /* b1d - _V_66_0F_75 */ 0x4082, + /* b1e - */ 0, + /* b1f - */ 0, + /* b20 - */ 0, + /* b21 - */ 0, + /* b22 - */ 0, + /* b23 - */ 0, + /* b24 - _0F_76 */ 0x23f7, + /* b25 - _66_0F_76 */ 0x23f8, + /* b26 - */ 0, + /* b27 - */ 0, + /* b28 - */ 0, + /* b29 - _V_66_0F_76 */ 0x4083, + /* b2a - */ 0, + /* b2b - */ 0, + /* b2c - */ 0, + /* b2d - */ 0, + /* b2e - */ 0, + /* b2f - */ 0, + /* b30 - _0F_77 */ 0x23f9, + /* b31 - */ 0, + /* b32 - */ 0, + /* b33 - */ 0, + /* b34 - _V_0F_77 */ 0x4084, + /* b35 - */ 0, + /* b36 - */ 0, + /* b37 - */ 0, + /* b38 - */ 0, + /* b39 - */ 0, + /* b3a - */ 0, + /* b3b - */ 0, + /* b3c - _0F_78 */ 0x23fa, + /* b3d - _66_0F_78 */ 0x4085, + /* b3e - */ 0, + /* b3f - _F2_0F_78 */ 0x4086, + /* b40 - */ 0, + /* b41 - */ 0, + /* b42 - */ 0, + /* b43 - */ 0, + /* b44 - */ 0, + /* b45 - */ 0, + /* b46 - */ 0, + /* b47 - */ 0, + /* b48 - _0F_79 */ 0x23fb, + /* b49 - _66_0F_79 */ 0x23fc, + /* b4a - */ 0, + /* b4b - _F2_0F_79 */ 0x23fd, + /* b4c - */ 0, + /* b4d - */ 0, + /* b4e - */ 0, + /* b4f - */ 0, + /* b50 - */ 0, + /* b51 - */ 0, + /* b52 - */ 0, + /* b53 - */ 0, + /* b54 - */ 0, + /* b55 - */ 0, + /* b56 - */ 0, + /* b57 - */ 0, + /* b58 - */ 0, + /* b59 - */ 0, + /* b5a - */ 0, + /* b5b - */ 0, + /* b5c - */ 0, + /* b5d - */ 0, + /* b5e - */ 0, + /* b5f - */ 0, + /* b60 - */ 0, + /* b61 - */ 0, + /* b62 - */ 0, + /* b63 - */ 0, + /* b64 - */ 0, + /* b65 - */ 0, + /* b66 - */ 0, + /* b67 - */ 0, + /* b68 - */ 0, + /* b69 - */ 0, + /* b6a - */ 0, + /* b6b - */ 0, + /* b6c - */ 0, + /* b6d - */ 0, + /* b6e - */ 0, + /* b6f - */ 0, + /* b70 - */ 0, + /* b71 - */ 0, + /* b72 - */ 0, + /* b73 - */ 0, + /* b74 - */ 0, + /* b75 - */ 0, + /* b76 - */ 0, + /* b77 - */ 0, + /* b78 - */ 0, + /* b79 - */ 0, + /* b7a - */ 0, + /* b7b - */ 0, + /* b7c - */ 0, + /* b7d - */ 0, + /* b7e - */ 0, + /* b7f - */ 0, + /* b80 - */ 0, + /* b81 - */ 0, + /* b82 - */ 0, + /* b83 - */ 0, + /* b84 - _0F_7A_30 */ 0x23fe, + /* b85 - _0F_7A_31 */ 0x23ff, + /* b86 - */ 0, + /* b87 - */ 0, + /* b88 - */ 0, + /* b89 - */ 0, + /* b8a - */ 0, + /* b8b - */ 0, + /* b8c - */ 0, + /* b8d - */ 0, + /* b8e - */ 0, + /* b8f - */ 0, + /* b90 - */ 0, + /* b91 - */ 0, + /* b92 - */ 0, + /* b93 - */ 0, + /* b94 - */ 0, + /* b95 - */ 0, + /* b96 - */ 0, + /* b97 - */ 0, + /* b98 - */ 0, + /* b99 - */ 0, + /* b9a - */ 0, + /* b9b - */ 0, + /* b9c - */ 0, + /* b9d - */ 0, + /* b9e - */ 0, + /* b9f - */ 0, + /* ba0 - */ 0, + /* ba1 - */ 0, + /* ba2 - */ 0, + /* ba3 - */ 0, + /* ba4 - */ 0, + /* ba5 - */ 0, + /* ba6 - */ 0, + /* ba7 - */ 0, + /* ba8 - */ 0, + /* ba9 - */ 0, + /* baa - */ 0, + /* bab - */ 0, + /* bac - */ 0, + /* bad - */ 0, + /* bae - */ 0, + /* baf - */ 0, + /* bb0 - */ 0, + /* bb1 - */ 0, + /* bb2 - */ 0, + /* bb3 - */ 0, + /* bb4 - */ 0, + /* bb5 - */ 0, + /* bb6 - */ 0, + /* bb7 - */ 0, + /* bb8 - */ 0, + /* bb9 - */ 0, + /* bba - */ 0, + /* bbb - */ 0, + /* bbc - */ 0, + /* bbd - */ 0, + /* bbe - */ 0, + /* bbf - */ 0, + /* bc0 - */ 0, + /* bc1 - */ 0, + /* bc2 - */ 0, + /* bc3 - */ 0, + /* bc4 - */ 0, + /* bc5 - */ 0, + /* bc6 - */ 0, + /* bc7 - */ 0, + /* bc8 - */ 0, + /* bc9 - */ 0, + /* bca - */ 0, + /* bcb - */ 0, + /* bcc - */ 0, + /* bcd - */ 0, + /* bce - */ 0, + /* bcf - */ 0, + /* bd0 - */ 0, + /* bd1 - */ 0, + /* bd2 - */ 0, + /* bd3 - */ 0, + /* bd4 - */ 0, + /* bd5 - */ 0, + /* bd6 - */ 0, + /* bd7 - */ 0, + /* bd8 - */ 0, + /* bd9 - */ 0, + /* bda - */ 0, + /* bdb - */ 0, + /* bdc - */ 0, + /* bdd - */ 0, + /* bde - */ 0, + /* bdf - */ 0, + /* be0 - */ 0, + /* be1 - */ 0, + /* be2 - */ 0, + /* be3 - */ 0, + /* be4 - */ 0, + /* be5 - */ 0, + /* be6 - */ 0, + /* be7 - */ 0, + /* be8 - */ 0, + /* be9 - */ 0, + /* bea - */ 0, + /* beb - */ 0, + /* bec - */ 0, + /* bed - */ 0, + /* bee - */ 0, + /* bef - */ 0, + /* bf0 - */ 0, + /* bf1 - */ 0, + /* bf2 - */ 0, + /* bf3 - */ 0, + /* bf4 - */ 0, + /* bf5 - */ 0, + /* bf6 - */ 0, + /* bf7 - */ 0, + /* bf8 - */ 0, + /* bf9 - */ 0, + /* bfa - */ 0, + /* bfb - */ 0, + /* bfc - */ 0, + /* bfd - */ 0, + /* bfe - */ 0, + /* bff - */ 0, + /* c00 - */ 0, + /* c01 - */ 0, + /* c02 - */ 0, + /* c03 - */ 0, + /* c04 - */ 0, + /* c05 - */ 0, + /* c06 - */ 0, + /* c07 - */ 0, + /* c08 - */ 0, + /* c09 - */ 0, + /* c0a - */ 0, + /* c0b - */ 0, + /* c0c - */ 0, + /* c0d - */ 0, + /* c0e - */ 0, + /* c0f - */ 0, + /* c10 - */ 0, + /* c11 - */ 0, + /* c12 - */ 0, + /* c13 - */ 0, + /* c14 - */ 0, + /* c15 - */ 0, + /* c16 - */ 0, + /* c17 - */ 0, + /* c18 - */ 0, + /* c19 - */ 0, + /* c1a - */ 0, + /* c1b - */ 0, + /* c1c - */ 0, + /* c1d - */ 0, + /* c1e - */ 0, + /* c1f - */ 0, + /* c20 - */ 0, + /* c21 - */ 0, + /* c22 - */ 0, + /* c23 - */ 0, + /* c24 - */ 0, + /* c25 - */ 0, + /* c26 - */ 0, + /* c27 - */ 0, + /* c28 - */ 0, + /* c29 - */ 0, + /* c2a - */ 0, + /* c2b - */ 0, + /* c2c - */ 0, + /* c2d - */ 0, + /* c2e - */ 0, + /* c2f - */ 0, + /* c30 - */ 0, + /* c31 - */ 0, + /* c32 - */ 0, + /* c33 - */ 0, + /* c34 - */ 0, + /* c35 - */ 0, + /* c36 - */ 0, + /* c37 - */ 0, + /* c38 - */ 0, + /* c39 - */ 0, + /* c3a - */ 0, + /* c3b - */ 0, + /* c3c - */ 0, + /* c3d - */ 0, + /* c3e - */ 0, + /* c3f - */ 0, + /* c40 - */ 0, + /* c41 - */ 0, + /* c42 - */ 0, + /* c43 - */ 0, + /* c44 - */ 0, + /* c45 - */ 0, + /* c46 - */ 0, + /* c47 - */ 0, + /* c48 - */ 0, + /* c49 - */ 0, + /* c4a - */ 0, + /* c4b - */ 0, + /* c4c - */ 0, + /* c4d - */ 0, + /* c4e - */ 0, + /* c4f - */ 0, + /* c50 - */ 0, + /* c51 - */ 0, + /* c52 - */ 0, + /* c53 - */ 0, + /* c54 - */ 0, + /* c55 - _66_0F_7C */ 0x2400, + /* c56 - */ 0, + /* c57 - _F2_0F_7C */ 0x2401, + /* c58 - */ 0, + /* c59 - _V_66_0F_7C */ 0x4087, + /* c5a - */ 0, + /* c5b - _V_F2_0F_7C */ 0x4088, + /* c5c - */ 0, + /* c5d - */ 0, + /* c5e - */ 0, + /* c5f - */ 0, + /* c60 - */ 0, + /* c61 - _66_0F_7D */ 0x2402, + /* c62 - */ 0, + /* c63 - _F2_0F_7D */ 0x2403, + /* c64 - */ 0, + /* c65 - _V_66_0F_7D */ 0x4089, + /* c66 - */ 0, + /* c67 - _V_F2_0F_7D */ 0x408a, + /* c68 - */ 0, + /* c69 - */ 0, + /* c6a - */ 0, + /* c6b - */ 0, + /* c6c - _0F_7E */ 0x408b, + /* c6d - _66_0F_7E */ 0x408c, + /* c6e - _F3_0F_7E */ 0x2404, + /* c6f - */ 0, + /* c70 - */ 0, + /* c71 - _V_66_0F_7E */ 0x408d, + /* c72 - _V_F3_0F_7E */ 0x408e, + /* c73 - */ 0, + /* c74 - */ 0, + /* c75 - */ 0, + /* c76 - */ 0, + /* c77 - */ 0, + /* c78 - _0F_7F */ 0x2405, + /* c79 - _66_0F_7F */ 0x2406, + /* c7a - _F3_0F_7F */ 0x2407, + /* c7b - */ 0, + /* c7c - */ 0, + /* c7d - _V_66_0F_7F */ 0x408f, + /* c7e - _V_F3_0F_7F */ 0x4090, + /* c7f - */ 0, + /* c80 - */ 0, + /* c81 - */ 0, + /* c82 - */ 0, + /* c83 - */ 0, + /* c84 - _0F_AE_00 */ 0xf5fc, + /* c85 - _0F_AE_01 */ 0xf608, + /* c86 - _0F_AE_02 */ 0xf614, + /* c87 - _0F_AE_03 */ 0xf620, + /* c88 - _0F_AE_04 */ 0x4091, + /* c89 - _0F_AE_05 */ 0x4092, + /* c8a - _0F_AE_06 */ 0x4093, + /* c8b - _0F_AE_07 */ 0x4094, + /* c8c - */ 0, + /* c8d - */ 0, + /* c8e - _F3_0F_B8 */ 0x2408, + /* c8f - */ 0, + /* c90 - */ 0, + /* c91 - */ 0, + /* c92 - */ 0, + /* c93 - */ 0, + /* c94 - */ 0, + /* c95 - */ 0, + /* c96 - */ 0, + /* c97 - */ 0, + /* c98 - */ 0, + /* c99 - */ 0, + /* c9a - */ 0, + /* c9b - */ 0, + /* c9c - _0F_BA_04 */ 0x2409, + /* c9d - _0F_BA_05 */ 0x240a, + /* c9e - _0F_BA_06 */ 0x240b, + /* c9f - _0F_BA_07 */ 0x240c, + /* ca0 - _0F_BC */ 0x240d, + /* ca1 - */ 0, + /* ca2 - _F3_0F_BC */ 0x240e, + /* ca3 - */ 0, + /* ca4 - */ 0, + /* ca5 - */ 0, + /* ca6 - */ 0, + /* ca7 - */ 0, + /* ca8 - */ 0, + /* ca9 - */ 0, + /* caa - */ 0, + /* cab - */ 0, + /* cac - _0F_BD */ 0x240f, + /* cad - */ 0, + /* cae - _F3_0F_BD */ 0x2410, + /* caf - */ 0, + /* cb0 - */ 0, + /* cb1 - */ 0, + /* cb2 - */ 0, + /* cb3 - */ 0, + /* cb4 - */ 0, + /* cb5 - */ 0, + /* cb6 - */ 0, + /* cb7 - */ 0, + /* cb8 - _0F_C2 */ 0x4095, + /* cb9 - _66_0F_C2 */ 0x4096, + /* cba - _F3_0F_C2 */ 0x4097, + /* cbb - _F2_0F_C2 */ 0x4098, + /* cbc - _V_0F_C2 */ 0x4099, + /* cbd - _V_66_0F_C2 */ 0x409a, + /* cbe - _V_F3_0F_C2 */ 0x409b, + /* cbf - _V_F2_0F_C2 */ 0x409c, + /* cc0 - */ 0, + /* cc1 - */ 0, + /* cc2 - */ 0, + /* cc3 - */ 0, + /* cc4 - _0F_C4 */ 0x409d, + /* cc5 - _66_0F_C4 */ 0x409e, + /* cc6 - */ 0, + /* cc7 - */ 0, + /* cc8 - */ 0, + /* cc9 - _V_66_0F_C4 */ 0x409f, + /* cca - */ 0, + /* ccb - */ 0, + /* ccc - */ 0, + /* ccd - */ 0, + /* cce - */ 0, + /* ccf - */ 0, + /* cd0 - _0F_C5 */ 0x40a0, + /* cd1 - _66_0F_C5 */ 0x40a1, + /* cd2 - */ 0, + /* cd3 - */ 0, + /* cd4 - */ 0, + /* cd5 - _V_66_0F_C5 */ 0x40a2, + /* cd6 - */ 0, + /* cd7 - */ 0, + /* cd8 - */ 0, + /* cd9 - */ 0, + /* cda - */ 0, + /* cdb - */ 0, + /* cdc - _0F_C6 */ 0x40a3, + /* cdd - _66_0F_C6 */ 0x40a4, + /* cde - */ 0, + /* cdf - */ 0, + /* ce0 - _V_0F_C6 */ 0x40a5, + /* ce1 - _V_66_0F_C6 */ 0x40a6, + /* ce2 - */ 0, + /* ce3 - */ 0, + /* ce4 - */ 0, + /* ce5 - */ 0, + /* ce6 - */ 0, + /* ce7 - */ 0, + /* ce8 - */ 0, + /* ce9 - _0F_C7_01 */ 0x40a7, + /* cea - */ 0, + /* ceb - */ 0, + /* cec - */ 0, + /* ced - */ 0, + /* cee - _0F_C7_06 */ 0xf62c, + /* cef - _0F_C7_07 */ 0x2411, + /* cf0 - */ 0, + /* cf1 - _66_0F_D0 */ 0x2412, + /* cf2 - */ 0, + /* cf3 - _F2_0F_D0 */ 0x2413, + /* cf4 - */ 0, + /* cf5 - _V_66_0F_D0 */ 0x40a8, + /* cf6 - */ 0, + /* cf7 - _V_F2_0F_D0 */ 0x40a9, + /* cf8 - */ 0, + /* cf9 - */ 0, + /* cfa - */ 0, + /* cfb - */ 0, + /* cfc - _0F_D1 */ 0x2414, + /* cfd - _66_0F_D1 */ 0x2415, + /* cfe - */ 0, + /* cff - */ 0, + /* d00 - */ 0, + /* d01 - _V_66_0F_D1 */ 0x40aa, + /* d02 - */ 0, + /* d03 - */ 0, + /* d04 - */ 0, + /* d05 - */ 0, + /* d06 - */ 0, + /* d07 - */ 0, + /* d08 - _0F_D2 */ 0x2416, + /* d09 - _66_0F_D2 */ 0x2417, + /* d0a - */ 0, + /* d0b - */ 0, + /* d0c - */ 0, + /* d0d - _V_66_0F_D2 */ 0x40ab, + /* d0e - */ 0, + /* d0f - */ 0, + /* d10 - */ 0, + /* d11 - */ 0, + /* d12 - */ 0, + /* d13 - */ 0, + /* d14 - _0F_D3 */ 0x2418, + /* d15 - _66_0F_D3 */ 0x2419, + /* d16 - */ 0, + /* d17 - */ 0, + /* d18 - */ 0, + /* d19 - _V_66_0F_D3 */ 0x40ac, + /* d1a - */ 0, + /* d1b - */ 0, + /* d1c - */ 0, + /* d1d - */ 0, + /* d1e - */ 0, + /* d1f - */ 0, + /* d20 - _0F_D4 */ 0x241a, + /* d21 - _66_0F_D4 */ 0x241b, + /* d22 - */ 0, + /* d23 - */ 0, + /* d24 - */ 0, + /* d25 - _V_66_0F_D4 */ 0x40ad, + /* d26 - */ 0, + /* d27 - */ 0, + /* d28 - */ 0, + /* d29 - */ 0, + /* d2a - */ 0, + /* d2b - */ 0, + /* d2c - _0F_D5 */ 0x241c, + /* d2d - _66_0F_D5 */ 0x241d, + /* d2e - */ 0, + /* d2f - */ 0, + /* d30 - */ 0, + /* d31 - _V_66_0F_D5 */ 0x40ae, + /* d32 - */ 0, + /* d33 - */ 0, + /* d34 - */ 0, + /* d35 - */ 0, + /* d36 - */ 0, + /* d37 - */ 0, + /* d38 - */ 0, + /* d39 - _66_0F_D6 */ 0x241e, + /* d3a - _F3_0F_D6 */ 0x241f, + /* d3b - _F2_0F_D6 */ 0x2420, + /* d3c - */ 0, + /* d3d - _V_66_0F_D6 */ 0x40af, + /* d3e - */ 0, + /* d3f - */ 0, + /* d40 - */ 0, + /* d41 - */ 0, + /* d42 - */ 0, + /* d43 - */ 0, + /* d44 - _0F_D7 */ 0x2421, + /* d45 - _66_0F_D7 */ 0x2422, + /* d46 - */ 0, + /* d47 - */ 0, + /* d48 - */ 0, + /* d49 - _V_66_0F_D7 */ 0x40b0, + /* d4a - */ 0, + /* d4b - */ 0, + /* d4c - */ 0, + /* d4d - */ 0, + /* d4e - */ 0, + /* d4f - */ 0, + /* d50 - _0F_D8 */ 0x2423, + /* d51 - _66_0F_D8 */ 0x2424, + /* d52 - */ 0, + /* d53 - */ 0, + /* d54 - */ 0, + /* d55 - _V_66_0F_D8 */ 0x40b1, + /* d56 - */ 0, + /* d57 - */ 0, + /* d58 - */ 0, + /* d59 - */ 0, + /* d5a - */ 0, + /* d5b - */ 0, + /* d5c - _0F_D9 */ 0x2425, + /* d5d - _66_0F_D9 */ 0x2426, + /* d5e - */ 0, + /* d5f - */ 0, + /* d60 - */ 0, + /* d61 - _V_66_0F_D9 */ 0x40b2, + /* d62 - */ 0, + /* d63 - */ 0, + /* d64 - */ 0, + /* d65 - */ 0, + /* d66 - */ 0, + /* d67 - */ 0, + /* d68 - _0F_DA */ 0x2427, + /* d69 - _66_0F_DA */ 0x2428, + /* d6a - */ 0, + /* d6b - */ 0, + /* d6c - */ 0, + /* d6d - _V_66_0F_DA */ 0x40b3, + /* d6e - */ 0, + /* d6f - */ 0, + /* d70 - */ 0, + /* d71 - */ 0, + /* d72 - */ 0, + /* d73 - */ 0, + /* d74 - _0F_DB */ 0x2429, + /* d75 - _66_0F_DB */ 0x242a, + /* d76 - */ 0, + /* d77 - */ 0, + /* d78 - */ 0, + /* d79 - _V_66_0F_DB */ 0x40b4, + /* d7a - */ 0, + /* d7b - */ 0, + /* d7c - */ 0, + /* d7d - */ 0, + /* d7e - */ 0, + /* d7f - */ 0, + /* d80 - _0F_DC */ 0x242b, + /* d81 - _66_0F_DC */ 0x242c, + /* d82 - */ 0, + /* d83 - */ 0, + /* d84 - */ 0, + /* d85 - _V_66_0F_DC */ 0x40b5, + /* d86 - */ 0, + /* d87 - */ 0, + /* d88 - */ 0, + /* d89 - */ 0, + /* d8a - */ 0, + /* d8b - */ 0, + /* d8c - _0F_DD */ 0x242d, + /* d8d - _66_0F_DD */ 0x242e, + /* d8e - */ 0, + /* d8f - */ 0, + /* d90 - */ 0, + /* d91 - _V_66_0F_DD */ 0x40b6, + /* d92 - */ 0, + /* d93 - */ 0, + /* d94 - */ 0, + /* d95 - */ 0, + /* d96 - */ 0, + /* d97 - */ 0, + /* d98 - _0F_DE */ 0x242f, + /* d99 - _66_0F_DE */ 0x2430, + /* d9a - */ 0, + /* d9b - */ 0, + /* d9c - */ 0, + /* d9d - _V_66_0F_DE */ 0x40b7, + /* d9e - */ 0, + /* d9f - */ 0, + /* da0 - */ 0, + /* da1 - */ 0, + /* da2 - */ 0, + /* da3 - */ 0, + /* da4 - _0F_DF */ 0x2431, + /* da5 - _66_0F_DF */ 0x2432, + /* da6 - */ 0, + /* da7 - */ 0, + /* da8 - */ 0, + /* da9 - _V_66_0F_DF */ 0x40b8, + /* daa - */ 0, + /* dab - */ 0, + /* dac - */ 0, + /* dad - */ 0, + /* dae - */ 0, + /* daf - */ 0, + /* db0 - _0F_E0 */ 0x2433, + /* db1 - _66_0F_E0 */ 0x2434, + /* db2 - */ 0, + /* db3 - */ 0, + /* db4 - */ 0, + /* db5 - _V_66_0F_E0 */ 0x40b9, + /* db6 - */ 0, + /* db7 - */ 0, + /* db8 - */ 0, + /* db9 - */ 0, + /* dba - */ 0, + /* dbb - */ 0, + /* dbc - _0F_E1 */ 0x2435, + /* dbd - _66_0F_E1 */ 0x2436, + /* dbe - */ 0, + /* dbf - */ 0, + /* dc0 - */ 0, + /* dc1 - _V_66_0F_E1 */ 0x40ba, + /* dc2 - */ 0, + /* dc3 - */ 0, + /* dc4 - */ 0, + /* dc5 - */ 0, + /* dc6 - */ 0, + /* dc7 - */ 0, + /* dc8 - _0F_E2 */ 0x2437, + /* dc9 - _66_0F_E2 */ 0x2438, + /* dca - */ 0, + /* dcb - */ 0, + /* dcc - */ 0, + /* dcd - _V_66_0F_E2 */ 0x40bb, + /* dce - */ 0, + /* dcf - */ 0, + /* dd0 - */ 0, + /* dd1 - */ 0, + /* dd2 - */ 0, + /* dd3 - */ 0, + /* dd4 - _0F_E3 */ 0x2439, + /* dd5 - _66_0F_E3 */ 0x243a, + /* dd6 - */ 0, + /* dd7 - */ 0, + /* dd8 - */ 0, + /* dd9 - _V_66_0F_E3 */ 0x40bc, + /* dda - */ 0, + /* ddb - */ 0, + /* ddc - */ 0, + /* ddd - */ 0, + /* dde - */ 0, + /* ddf - */ 0, + /* de0 - _0F_E4 */ 0x243b, + /* de1 - _66_0F_E4 */ 0x243c, + /* de2 - */ 0, + /* de3 - */ 0, + /* de4 - */ 0, + /* de5 - _V_66_0F_E4 */ 0x40bd, + /* de6 - */ 0, + /* de7 - */ 0, + /* de8 - */ 0, + /* de9 - */ 0, + /* dea - */ 0, + /* deb - */ 0, + /* dec - _0F_E5 */ 0x243d, + /* ded - _66_0F_E5 */ 0x243e, + /* dee - */ 0, + /* def - */ 0, + /* df0 - */ 0, + /* df1 - _V_66_0F_E5 */ 0x40be, + /* df2 - */ 0, + /* df3 - */ 0, + /* df4 - */ 0, + /* df5 - */ 0, + /* df6 - */ 0, + /* df7 - */ 0, + /* df8 - */ 0, + /* df9 - _66_0F_E6 */ 0x243f, + /* dfa - _F3_0F_E6 */ 0x2440, + /* dfb - _F2_0F_E6 */ 0x2441, + /* dfc - */ 0, + /* dfd - _V_66_0F_E6 */ 0x40bf, + /* dfe - _V_F3_0F_E6 */ 0x40c0, + /* dff - _V_F2_0F_E6 */ 0x40c1, + /* e00 - */ 0, + /* e01 - */ 0, + /* e02 - */ 0, + /* e03 - */ 0, + /* e04 - _0F_E7 */ 0x2442, + /* e05 - _66_0F_E7 */ 0x2443, + /* e06 - */ 0, + /* e07 - */ 0, + /* e08 - */ 0, + /* e09 - _V_66_0F_E7 */ 0x40c2, + /* e0a - */ 0, + /* e0b - */ 0, + /* e0c - */ 0, + /* e0d - */ 0, + /* e0e - */ 0, + /* e0f - */ 0, + /* e10 - _0F_E8 */ 0x2444, + /* e11 - _66_0F_E8 */ 0x2445, + /* e12 - */ 0, + /* e13 - */ 0, + /* e14 - */ 0, + /* e15 - _V_66_0F_E8 */ 0x40c3, + /* e16 - */ 0, + /* e17 - */ 0, + /* e18 - */ 0, + /* e19 - */ 0, + /* e1a - */ 0, + /* e1b - */ 0, + /* e1c - _0F_E9 */ 0x2446, + /* e1d - _66_0F_E9 */ 0x2447, + /* e1e - */ 0, + /* e1f - */ 0, + /* e20 - */ 0, + /* e21 - _V_66_0F_E9 */ 0x40c4, + /* e22 - */ 0, + /* e23 - */ 0, + /* e24 - */ 0, + /* e25 - */ 0, + /* e26 - */ 0, + /* e27 - */ 0, + /* e28 - _0F_EA */ 0x2448, + /* e29 - _66_0F_EA */ 0x2449, + /* e2a - */ 0, + /* e2b - */ 0, + /* e2c - */ 0, + /* e2d - _V_66_0F_EA */ 0x40c5, + /* e2e - */ 0, + /* e2f - */ 0, + /* e30 - */ 0, + /* e31 - */ 0, + /* e32 - */ 0, + /* e33 - */ 0, + /* e34 - _0F_EB */ 0x244a, + /* e35 - _66_0F_EB */ 0x244b, + /* e36 - */ 0, + /* e37 - */ 0, + /* e38 - */ 0, + /* e39 - _V_66_0F_EB */ 0x40c6, + /* e3a - */ 0, + /* e3b - */ 0, + /* e3c - */ 0, + /* e3d - */ 0, + /* e3e - */ 0, + /* e3f - */ 0, + /* e40 - _0F_EC */ 0x244c, + /* e41 - _66_0F_EC */ 0x244d, + /* e42 - */ 0, + /* e43 - */ 0, + /* e44 - */ 0, + /* e45 - _V_66_0F_EC */ 0x40c7, + /* e46 - */ 0, + /* e47 - */ 0, + /* e48 - */ 0, + /* e49 - */ 0, + /* e4a - */ 0, + /* e4b - */ 0, + /* e4c - _0F_ED */ 0x244e, + /* e4d - _66_0F_ED */ 0x244f, + /* e4e - */ 0, + /* e4f - */ 0, + /* e50 - */ 0, + /* e51 - _V_66_0F_ED */ 0x40c8, + /* e52 - */ 0, + /* e53 - */ 0, + /* e54 - */ 0, + /* e55 - */ 0, + /* e56 - */ 0, + /* e57 - */ 0, + /* e58 - _0F_EE */ 0x2450, + /* e59 - _66_0F_EE */ 0x2451, + /* e5a - */ 0, + /* e5b - */ 0, + /* e5c - */ 0, + /* e5d - _V_66_0F_EE */ 0x40c9, + /* e5e - */ 0, + /* e5f - */ 0, + /* e60 - */ 0, + /* e61 - */ 0, + /* e62 - */ 0, + /* e63 - */ 0, + /* e64 - _0F_EF */ 0x2452, + /* e65 - _66_0F_EF */ 0x2453, + /* e66 - */ 0, + /* e67 - */ 0, + /* e68 - */ 0, + /* e69 - _V_66_0F_EF */ 0x40ca, + /* e6a - */ 0, + /* e6b - */ 0, + /* e6c - */ 0, + /* e6d - */ 0, + /* e6e - */ 0, + /* e6f - */ 0, + /* e70 - */ 0, + /* e71 - */ 0, + /* e72 - */ 0, + /* e73 - _F2_0F_F0 */ 0x2454, + /* e74 - */ 0, + /* e75 - */ 0, + /* e76 - */ 0, + /* e77 - _V_F2_0F_F0 */ 0x40cb, + /* e78 - */ 0, + /* e79 - */ 0, + /* e7a - */ 0, + /* e7b - */ 0, + /* e7c - _0F_F1 */ 0x2455, + /* e7d - _66_0F_F1 */ 0x2456, + /* e7e - */ 0, + /* e7f - */ 0, + /* e80 - */ 0, + /* e81 - _V_66_0F_F1 */ 0x40cc, + /* e82 - */ 0, + /* e83 - */ 0, + /* e84 - */ 0, + /* e85 - */ 0, + /* e86 - */ 0, + /* e87 - */ 0, + /* e88 - _0F_F2 */ 0x2457, + /* e89 - _66_0F_F2 */ 0x2458, + /* e8a - */ 0, + /* e8b - */ 0, + /* e8c - */ 0, + /* e8d - _V_66_0F_F2 */ 0x40cd, + /* e8e - */ 0, + /* e8f - */ 0, + /* e90 - */ 0, + /* e91 - */ 0, + /* e92 - */ 0, + /* e93 - */ 0, + /* e94 - _0F_F3 */ 0x2459, + /* e95 - _66_0F_F3 */ 0x245a, + /* e96 - */ 0, + /* e97 - */ 0, + /* e98 - */ 0, + /* e99 - _V_66_0F_F3 */ 0x40ce, + /* e9a - */ 0, + /* e9b - */ 0, + /* e9c - */ 0, + /* e9d - */ 0, + /* e9e - */ 0, + /* e9f - */ 0, + /* ea0 - _0F_F4 */ 0x245b, + /* ea1 - _66_0F_F4 */ 0x245c, + /* ea2 - */ 0, + /* ea3 - */ 0, + /* ea4 - */ 0, + /* ea5 - _V_66_0F_F4 */ 0x40cf, + /* ea6 - */ 0, + /* ea7 - */ 0, + /* ea8 - */ 0, + /* ea9 - */ 0, + /* eaa - */ 0, + /* eab - */ 0, + /* eac - _0F_F5 */ 0x245d, + /* ead - _66_0F_F5 */ 0x245e, + /* eae - */ 0, + /* eaf - */ 0, + /* eb0 - */ 0, + /* eb1 - _V_66_0F_F5 */ 0x40d0, + /* eb2 - */ 0, + /* eb3 - */ 0, + /* eb4 - */ 0, + /* eb5 - */ 0, + /* eb6 - */ 0, + /* eb7 - */ 0, + /* eb8 - _0F_F6 */ 0x245f, + /* eb9 - _66_0F_F6 */ 0x2460, + /* eba - */ 0, + /* ebb - */ 0, + /* ebc - */ 0, + /* ebd - _V_66_0F_F6 */ 0x40d1, + /* ebe - */ 0, + /* ebf - */ 0, + /* ec0 - */ 0, + /* ec1 - */ 0, + /* ec2 - */ 0, + /* ec3 - */ 0, + /* ec4 - _0F_F7 */ 0x2461, + /* ec5 - _66_0F_F7 */ 0x2462, + /* ec6 - */ 0, + /* ec7 - */ 0, + /* ec8 - */ 0, + /* ec9 - _V_66_0F_F7 */ 0x40d2, + /* eca - */ 0, + /* ecb - */ 0, + /* ecc - */ 0, + /* ecd - */ 0, + /* ece - */ 0, + /* ecf - */ 0, + /* ed0 - _0F_F8 */ 0x2463, + /* ed1 - _66_0F_F8 */ 0x2464, + /* ed2 - */ 0, + /* ed3 - */ 0, + /* ed4 - */ 0, + /* ed5 - _V_66_0F_F8 */ 0x40d3, + /* ed6 - */ 0, + /* ed7 - */ 0, + /* ed8 - */ 0, + /* ed9 - */ 0, + /* eda - */ 0, + /* edb - */ 0, + /* edc - _0F_F9 */ 0x2465, + /* edd - _66_0F_F9 */ 0x2466, + /* ede - */ 0, + /* edf - */ 0, + /* ee0 - */ 0, + /* ee1 - _V_66_0F_F9 */ 0x40d4, + /* ee2 - */ 0, + /* ee3 - */ 0, + /* ee4 - */ 0, + /* ee5 - */ 0, + /* ee6 - */ 0, + /* ee7 - */ 0, + /* ee8 - _0F_FA */ 0x2467, + /* ee9 - _66_0F_FA */ 0x2468, + /* eea - */ 0, + /* eeb - */ 0, + /* eec - */ 0, + /* eed - _V_66_0F_FA */ 0x40d5, + /* eee - */ 0, + /* eef - */ 0, + /* ef0 - */ 0, + /* ef1 - */ 0, + /* ef2 - */ 0, + /* ef3 - */ 0, + /* ef4 - _0F_FB */ 0x2469, + /* ef5 - _66_0F_FB */ 0x246a, + /* ef6 - */ 0, + /* ef7 - */ 0, + /* ef8 - */ 0, + /* ef9 - _V_66_0F_FB */ 0x40d6, + /* efa - */ 0, + /* efb - */ 0, + /* efc - */ 0, + /* efd - */ 0, + /* efe - */ 0, + /* eff - */ 0, + /* f00 - _0F_FC */ 0x246b, + /* f01 - _66_0F_FC */ 0x246c, + /* f02 - */ 0, + /* f03 - */ 0, + /* f04 - */ 0, + /* f05 - _V_66_0F_FC */ 0x40d7, + /* f06 - */ 0, + /* f07 - */ 0, + /* f08 - */ 0, + /* f09 - */ 0, + /* f0a - */ 0, + /* f0b - */ 0, + /* f0c - _0F_FD */ 0x246d, + /* f0d - _66_0F_FD */ 0x246e, + /* f0e - */ 0, + /* f0f - */ 0, + /* f10 - */ 0, + /* f11 - _V_66_0F_FD */ 0x40d8, + /* f12 - */ 0, + /* f13 - */ 0, + /* f14 - */ 0, + /* f15 - */ 0, + /* f16 - */ 0, + /* f17 - */ 0, + /* f18 - _0F_FE */ 0x246f, + /* f19 - _66_0F_FE */ 0x2470, + /* f1a - */ 0, + /* f1b - */ 0, + /* f1c - */ 0, + /* f1d - _V_66_0F_FE */ 0x40d9, + /* f1e - */ 0, + /* f1f - */ 0, + /* f20 - */ 0, + /* f21 - */ 0, + /* f22 - */ 0, + /* f23 - */ 0, + /* f24 - _D9_06 */ 0x2471, + /* f25 - _9B_D9_06 */ 0x2472, + /* f26 - */ 0, + /* f27 - */ 0, + /* f28 - */ 0, + /* f29 - */ 0, + /* f2a - */ 0, + /* f2b - */ 0, + /* f2c - */ 0, + /* f2d - */ 0, + /* f2e - */ 0, + /* f2f - */ 0, + /* f30 - _D9_07 */ 0x2473, + /* f31 - _9B_D9_07 */ 0x2474, + /* f32 - */ 0, + /* f33 - */ 0, + /* f34 - */ 0, + /* f35 - */ 0, + /* f36 - */ 0, + /* f37 - */ 0, + /* f38 - */ 0, + /* f39 - */ 0, + /* f3a - */ 0, + /* f3b - */ 0, + /* f3c - _DB_E2 */ 0x2475, + /* f3d - _9B_DB_E2 */ 0x2476, + /* f3e - */ 0, + /* f3f - */ 0, + /* f40 - */ 0, + /* f41 - */ 0, + /* f42 - */ 0, + /* f43 - */ 0, + /* f44 - */ 0, + /* f45 - */ 0, + /* f46 - */ 0, + /* f47 - */ 0, + /* f48 - _DB_E3 */ 0x2477, + /* f49 - _9B_DB_E3 */ 0x2478, + /* f4a - */ 0, + /* f4b - */ 0, + /* f4c - */ 0, + /* f4d - */ 0, + /* f4e - */ 0, + /* f4f - */ 0, + /* f50 - */ 0, + /* f51 - */ 0, + /* f52 - */ 0, + /* f53 - */ 0, + /* f54 - _DD_06 */ 0x2479, + /* f55 - _9B_DD_06 */ 0x247a, + /* f56 - */ 0, + /* f57 - */ 0, + /* f58 - */ 0, + /* f59 - */ 0, + /* f5a - */ 0, + /* f5b - */ 0, + /* f5c - */ 0, + /* f5d - */ 0, + /* f5e - */ 0, + /* f5f - */ 0, + /* f60 - _DD_07 */ 0x247b, + /* f61 - _9B_DD_07 */ 0x247c, + /* f62 - */ 0, + /* f63 - */ 0, + /* f64 - */ 0, + /* f65 - */ 0, + /* f66 - */ 0, + /* f67 - */ 0, + /* f68 - */ 0, + /* f69 - */ 0, + /* f6a - */ 0, + /* f6b - */ 0, + /* f6c - _DF_E0 */ 0x247d, + /* f6d - _9B_DF_E0 */ 0x247e, + /* f6e - */ 0, + /* f6f - */ 0, + /* f70 - */ 0, + /* f71 - */ 0, + /* f72 - */ 0, + /* f73 - */ 0, + /* f74 - */ 0, + /* f75 - */ 0, + /* f76 - */ 0, + /* f77 - */ 0, + /* f78 - _0F_38_00 */ 0x247f, + /* f79 - _66_0F_38_00 */ 0x2480, + /* f7a - */ 0, + /* f7b - */ 0, + /* f7c - */ 0, + /* f7d - _V_66_0F_38_00 */ 0x40da, + /* f7e - */ 0, + /* f7f - */ 0, + /* f80 - */ 0, + /* f81 - */ 0, + /* f82 - */ 0, + /* f83 - */ 0, + /* f84 - _0F_38_01 */ 0x2481, + /* f85 - _66_0F_38_01 */ 0x2482, + /* f86 - */ 0, + /* f87 - */ 0, + /* f88 - */ 0, + /* f89 - _V_66_0F_38_01 */ 0x40db, + /* f8a - */ 0, + /* f8b - */ 0, + /* f8c - */ 0, + /* f8d - */ 0, + /* f8e - */ 0, + /* f8f - */ 0, + /* f90 - _0F_38_02 */ 0x2483, + /* f91 - _66_0F_38_02 */ 0x2484, + /* f92 - */ 0, + /* f93 - */ 0, + /* f94 - */ 0, + /* f95 - _V_66_0F_38_02 */ 0x40dc, + /* f96 - */ 0, + /* f97 - */ 0, + /* f98 - */ 0, + /* f99 - */ 0, + /* f9a - */ 0, + /* f9b - */ 0, + /* f9c - _0F_38_03 */ 0x2485, + /* f9d - _66_0F_38_03 */ 0x2486, + /* f9e - */ 0, + /* f9f - */ 0, + /* fa0 - */ 0, + /* fa1 - _V_66_0F_38_03 */ 0x40dd, + /* fa2 - */ 0, + /* fa3 - */ 0, + /* fa4 - */ 0, + /* fa5 - */ 0, + /* fa6 - */ 0, + /* fa7 - */ 0, + /* fa8 - _0F_38_04 */ 0x2487, + /* fa9 - _66_0F_38_04 */ 0x2488, + /* faa - */ 0, + /* fab - */ 0, + /* fac - */ 0, + /* fad - _V_66_0F_38_04 */ 0x40de, + /* fae - */ 0, + /* faf - */ 0, + /* fb0 - */ 0, + /* fb1 - */ 0, + /* fb2 - */ 0, + /* fb3 - */ 0, + /* fb4 - _0F_38_05 */ 0x2489, + /* fb5 - _66_0F_38_05 */ 0x248a, + /* fb6 - */ 0, + /* fb7 - */ 0, + /* fb8 - */ 0, + /* fb9 - _V_66_0F_38_05 */ 0x40df, + /* fba - */ 0, + /* fbb - */ 0, + /* fbc - */ 0, + /* fbd - */ 0, + /* fbe - */ 0, + /* fbf - */ 0, + /* fc0 - _0F_38_06 */ 0x248b, + /* fc1 - _66_0F_38_06 */ 0x248c, + /* fc2 - */ 0, + /* fc3 - */ 0, + /* fc4 - */ 0, + /* fc5 - _V_66_0F_38_06 */ 0x40e0, + /* fc6 - */ 0, + /* fc7 - */ 0, + /* fc8 - */ 0, + /* fc9 - */ 0, + /* fca - */ 0, + /* fcb - */ 0, + /* fcc - _0F_38_07 */ 0x248d, + /* fcd - _66_0F_38_07 */ 0x248e, + /* fce - */ 0, + /* fcf - */ 0, + /* fd0 - */ 0, + /* fd1 - _V_66_0F_38_07 */ 0x40e1, + /* fd2 - */ 0, + /* fd3 - */ 0, + /* fd4 - */ 0, + /* fd5 - */ 0, + /* fd6 - */ 0, + /* fd7 - */ 0, + /* fd8 - _0F_38_08 */ 0x248f, + /* fd9 - _66_0F_38_08 */ 0x2490, + /* fda - */ 0, + /* fdb - */ 0, + /* fdc - */ 0, + /* fdd - _V_66_0F_38_08 */ 0x40e2, + /* fde - */ 0, + /* fdf - */ 0, + /* fe0 - */ 0, + /* fe1 - */ 0, + /* fe2 - */ 0, + /* fe3 - */ 0, + /* fe4 - _0F_38_09 */ 0x2491, + /* fe5 - _66_0F_38_09 */ 0x2492, + /* fe6 - */ 0, + /* fe7 - */ 0, + /* fe8 - */ 0, + /* fe9 - _V_66_0F_38_09 */ 0x40e3, + /* fea - */ 0, + /* feb - */ 0, + /* fec - */ 0, + /* fed - */ 0, + /* fee - */ 0, + /* fef - */ 0, + /* ff0 - _0F_38_0A */ 0x2493, + /* ff1 - _66_0F_38_0A */ 0x2494, + /* ff2 - */ 0, + /* ff3 - */ 0, + /* ff4 - */ 0, + /* ff5 - _V_66_0F_38_0A */ 0x40e4, + /* ff6 - */ 0, + /* ff7 - */ 0, + /* ff8 - */ 0, + /* ff9 - */ 0, + /* ffa - */ 0, + /* ffb - */ 0, + /* ffc - _0F_38_0B */ 0x2495, + /* ffd - _66_0F_38_0B */ 0x2496, + /* ffe - */ 0, + /* fff - */ 0, + /* 1000 - */ 0, + /* 1001 - _V_66_0F_38_0B */ 0x40e5, + /* 1002 - */ 0, + /* 1003 - */ 0, + /* 1004 - */ 0, + /* 1005 - */ 0, + /* 1006 - */ 0, + /* 1007 - */ 0, + /* 1008 - */ 0, + /* 1009 - */ 0, + /* 100a - */ 0, + /* 100b - */ 0, + /* 100c - */ 0, + /* 100d - _V_66_0F_38_0C */ 0x40e6, + /* 100e - */ 0, + /* 100f - */ 0, + /* 1010 - */ 0, + /* 1011 - */ 0, + /* 1012 - */ 0, + /* 1013 - */ 0, + /* 1014 - */ 0, + /* 1015 - */ 0, + /* 1016 - */ 0, + /* 1017 - */ 0, + /* 1018 - */ 0, + /* 1019 - _V_66_0F_38_0D */ 0x40e7, + /* 101a - */ 0, + /* 101b - */ 0, + /* 101c - */ 0, + /* 101d - */ 0, + /* 101e - */ 0, + /* 101f - */ 0, + /* 1020 - */ 0, + /* 1021 - */ 0, + /* 1022 - */ 0, + /* 1023 - */ 0, + /* 1024 - */ 0, + /* 1025 - _V_66_0F_38_0E */ 0x40e8, + /* 1026 - */ 0, + /* 1027 - */ 0, + /* 1028 - */ 0, + /* 1029 - */ 0, + /* 102a - */ 0, + /* 102b - */ 0, + /* 102c - */ 0, + /* 102d - */ 0, + /* 102e - */ 0, + /* 102f - */ 0, + /* 1030 - */ 0, + /* 1031 - _V_66_0F_38_0F */ 0x40e9, + /* 1032 - */ 0, + /* 1033 - */ 0, + /* 1034 - */ 0, + /* 1035 - */ 0, + /* 1036 - */ 0, + /* 1037 - */ 0, + /* 1038 - */ 0, + /* 1039 - _66_0F_38_10 */ 0x40ea, + /* 103a - */ 0, + /* 103b - */ 0, + /* 103c - */ 0, + /* 103d - */ 0, + /* 103e - */ 0, + /* 103f - */ 0, + /* 1040 - */ 0, + /* 1041 - */ 0, + /* 1042 - */ 0, + /* 1043 - */ 0, + /* 1044 - */ 0, + /* 1045 - _66_0F_38_14 */ 0x40eb, + /* 1046 - */ 0, + /* 1047 - */ 0, + /* 1048 - */ 0, + /* 1049 - */ 0, + /* 104a - */ 0, + /* 104b - */ 0, + /* 104c - */ 0, + /* 104d - */ 0, + /* 104e - */ 0, + /* 104f - */ 0, + /* 1050 - */ 0, + /* 1051 - _66_0F_38_15 */ 0x40ec, + /* 1052 - */ 0, + /* 1053 - */ 0, + /* 1054 - */ 0, + /* 1055 - */ 0, + /* 1056 - */ 0, + /* 1057 - */ 0, + /* 1058 - */ 0, + /* 1059 - */ 0, + /* 105a - */ 0, + /* 105b - */ 0, + /* 105c - */ 0, + /* 105d - _66_0F_38_17 */ 0x2497, + /* 105e - */ 0, + /* 105f - */ 0, + /* 1060 - */ 0, + /* 1061 - _V_66_0F_38_17 */ 0x40ed, + /* 1062 - */ 0, + /* 1063 - */ 0, + /* 1064 - */ 0, + /* 1065 - */ 0, + /* 1066 - */ 0, + /* 1067 - */ 0, + /* 1068 - */ 0, + /* 1069 - */ 0, + /* 106a - */ 0, + /* 106b - */ 0, + /* 106c - */ 0, + /* 106d - _V_66_0F_38_18 */ 0x40ee, + /* 106e - */ 0, + /* 106f - */ 0, + /* 1070 - */ 0, + /* 1071 - */ 0, + /* 1072 - */ 0, + /* 1073 - */ 0, + /* 1074 - */ 0, + /* 1075 - */ 0, + /* 1076 - */ 0, + /* 1077 - */ 0, + /* 1078 - */ 0, + /* 1079 - _V_66_0F_38_19 */ 0x40ef, + /* 107a - */ 0, + /* 107b - */ 0, + /* 107c - */ 0, + /* 107d - */ 0, + /* 107e - */ 0, + /* 107f - */ 0, + /* 1080 - */ 0, + /* 1081 - */ 0, + /* 1082 - */ 0, + /* 1083 - */ 0, + /* 1084 - */ 0, + /* 1085 - _V_66_0F_38_1A */ 0x40f0, + /* 1086 - */ 0, + /* 1087 - */ 0, + /* 1088 - */ 0, + /* 1089 - */ 0, + /* 108a - */ 0, + /* 108b - */ 0, + /* 108c - _0F_38_1C */ 0x2498, + /* 108d - _66_0F_38_1C */ 0x2499, + /* 108e - */ 0, + /* 108f - */ 0, + /* 1090 - */ 0, + /* 1091 - _V_66_0F_38_1C */ 0x40f1, + /* 1092 - */ 0, + /* 1093 - */ 0, + /* 1094 - */ 0, + /* 1095 - */ 0, + /* 1096 - */ 0, + /* 1097 - */ 0, + /* 1098 - _0F_38_1D */ 0x249a, + /* 1099 - _66_0F_38_1D */ 0x249b, + /* 109a - */ 0, + /* 109b - */ 0, + /* 109c - */ 0, + /* 109d - _V_66_0F_38_1D */ 0x40f2, + /* 109e - */ 0, + /* 109f - */ 0, + /* 10a0 - */ 0, + /* 10a1 - */ 0, + /* 10a2 - */ 0, + /* 10a3 - */ 0, + /* 10a4 - _0F_38_1E */ 0x249c, + /* 10a5 - _66_0F_38_1E */ 0x249d, + /* 10a6 - */ 0, + /* 10a7 - */ 0, + /* 10a8 - */ 0, + /* 10a9 - _V_66_0F_38_1E */ 0x40f3, + /* 10aa - */ 0, + /* 10ab - */ 0, + /* 10ac - */ 0, + /* 10ad - */ 0, + /* 10ae - */ 0, + /* 10af - */ 0, + /* 10b0 - */ 0, + /* 10b1 - _66_0F_38_20 */ 0x249e, + /* 10b2 - */ 0, + /* 10b3 - */ 0, + /* 10b4 - */ 0, + /* 10b5 - _V_66_0F_38_20 */ 0x40f4, + /* 10b6 - */ 0, + /* 10b7 - */ 0, + /* 10b8 - */ 0, + /* 10b9 - */ 0, + /* 10ba - */ 0, + /* 10bb - */ 0, + /* 10bc - */ 0, + /* 10bd - _66_0F_38_21 */ 0x249f, + /* 10be - */ 0, + /* 10bf - */ 0, + /* 10c0 - */ 0, + /* 10c1 - _V_66_0F_38_21 */ 0x40f5, + /* 10c2 - */ 0, + /* 10c3 - */ 0, + /* 10c4 - */ 0, + /* 10c5 - */ 0, + /* 10c6 - */ 0, + /* 10c7 - */ 0, + /* 10c8 - */ 0, + /* 10c9 - _66_0F_38_22 */ 0x24a0, + /* 10ca - */ 0, + /* 10cb - */ 0, + /* 10cc - */ 0, + /* 10cd - _V_66_0F_38_22 */ 0x40f6, + /* 10ce - */ 0, + /* 10cf - */ 0, + /* 10d0 - */ 0, + /* 10d1 - */ 0, + /* 10d2 - */ 0, + /* 10d3 - */ 0, + /* 10d4 - */ 0, + /* 10d5 - _66_0F_38_23 */ 0x24a1, + /* 10d6 - */ 0, + /* 10d7 - */ 0, + /* 10d8 - */ 0, + /* 10d9 - _V_66_0F_38_23 */ 0x40f7, + /* 10da - */ 0, + /* 10db - */ 0, + /* 10dc - */ 0, + /* 10dd - */ 0, + /* 10de - */ 0, + /* 10df - */ 0, + /* 10e0 - */ 0, + /* 10e1 - _66_0F_38_24 */ 0x24a2, + /* 10e2 - */ 0, + /* 10e3 - */ 0, + /* 10e4 - */ 0, + /* 10e5 - _V_66_0F_38_24 */ 0x40f8, + /* 10e6 - */ 0, + /* 10e7 - */ 0, + /* 10e8 - */ 0, + /* 10e9 - */ 0, + /* 10ea - */ 0, + /* 10eb - */ 0, + /* 10ec - */ 0, + /* 10ed - _66_0F_38_25 */ 0x24a3, + /* 10ee - */ 0, + /* 10ef - */ 0, + /* 10f0 - */ 0, + /* 10f1 - _V_66_0F_38_25 */ 0x40f9, + /* 10f2 - */ 0, + /* 10f3 - */ 0, + /* 10f4 - */ 0, + /* 10f5 - */ 0, + /* 10f6 - */ 0, + /* 10f7 - */ 0, + /* 10f8 - */ 0, + /* 10f9 - _66_0F_38_28 */ 0x24a4, + /* 10fa - */ 0, + /* 10fb - */ 0, + /* 10fc - */ 0, + /* 10fd - _V_66_0F_38_28 */ 0x40fa, + /* 10fe - */ 0, + /* 10ff - */ 0, + /* 1100 - */ 0, + /* 1101 - */ 0, + /* 1102 - */ 0, + /* 1103 - */ 0, + /* 1104 - */ 0, + /* 1105 - _66_0F_38_29 */ 0x24a5, + /* 1106 - */ 0, + /* 1107 - */ 0, + /* 1108 - */ 0, + /* 1109 - _V_66_0F_38_29 */ 0x40fb, + /* 110a - */ 0, + /* 110b - */ 0, + /* 110c - */ 0, + /* 110d - */ 0, + /* 110e - */ 0, + /* 110f - */ 0, + /* 1110 - */ 0, + /* 1111 - _66_0F_38_2A */ 0x24a6, + /* 1112 - */ 0, + /* 1113 - */ 0, + /* 1114 - */ 0, + /* 1115 - _V_66_0F_38_2A */ 0x40fc, + /* 1116 - */ 0, + /* 1117 - */ 0, + /* 1118 - */ 0, + /* 1119 - */ 0, + /* 111a - */ 0, + /* 111b - */ 0, + /* 111c - */ 0, + /* 111d - _66_0F_38_2B */ 0x24a7, + /* 111e - */ 0, + /* 111f - */ 0, + /* 1120 - */ 0, + /* 1121 - _V_66_0F_38_2B */ 0x40fd, + /* 1122 - */ 0, + /* 1123 - */ 0, + /* 1124 - */ 0, + /* 1125 - */ 0, + /* 1126 - */ 0, + /* 1127 - */ 0, + /* 1128 - */ 0, + /* 1129 - */ 0, + /* 112a - */ 0, + /* 112b - */ 0, + /* 112c - */ 0, + /* 112d - _V_66_0F_38_2C */ 0x40fe, + /* 112e - */ 0, + /* 112f - */ 0, + /* 1130 - */ 0, + /* 1131 - */ 0, + /* 1132 - */ 0, + /* 1133 - */ 0, + /* 1134 - */ 0, + /* 1135 - */ 0, + /* 1136 - */ 0, + /* 1137 - */ 0, + /* 1138 - */ 0, + /* 1139 - _V_66_0F_38_2D */ 0x40ff, + /* 113a - */ 0, + /* 113b - */ 0, + /* 113c - */ 0, + /* 113d - */ 0, + /* 113e - */ 0, + /* 113f - */ 0, + /* 1140 - */ 0, + /* 1141 - */ 0, + /* 1142 - */ 0, + /* 1143 - */ 0, + /* 1144 - */ 0, + /* 1145 - _V_66_0F_38_2E */ 0x4100, + /* 1146 - */ 0, + /* 1147 - */ 0, + /* 1148 - */ 0, + /* 1149 - */ 0, + /* 114a - */ 0, + /* 114b - */ 0, + /* 114c - */ 0, + /* 114d - */ 0, + /* 114e - */ 0, + /* 114f - */ 0, + /* 1150 - */ 0, + /* 1151 - _V_66_0F_38_2F */ 0x4101, + /* 1152 - */ 0, + /* 1153 - */ 0, + /* 1154 - */ 0, + /* 1155 - */ 0, + /* 1156 - */ 0, + /* 1157 - */ 0, + /* 1158 - */ 0, + /* 1159 - _66_0F_38_30 */ 0x24a8, + /* 115a - */ 0, + /* 115b - */ 0, + /* 115c - */ 0, + /* 115d - _V_66_0F_38_30 */ 0x4102, + /* 115e - */ 0, + /* 115f - */ 0, + /* 1160 - */ 0, + /* 1161 - */ 0, + /* 1162 - */ 0, + /* 1163 - */ 0, + /* 1164 - */ 0, + /* 1165 - _66_0F_38_31 */ 0x24a9, + /* 1166 - */ 0, + /* 1167 - */ 0, + /* 1168 - */ 0, + /* 1169 - _V_66_0F_38_31 */ 0x4103, + /* 116a - */ 0, + /* 116b - */ 0, + /* 116c - */ 0, + /* 116d - */ 0, + /* 116e - */ 0, + /* 116f - */ 0, + /* 1170 - */ 0, + /* 1171 - _66_0F_38_32 */ 0x24aa, + /* 1172 - */ 0, + /* 1173 - */ 0, + /* 1174 - */ 0, + /* 1175 - _V_66_0F_38_32 */ 0x4104, + /* 1176 - */ 0, + /* 1177 - */ 0, + /* 1178 - */ 0, + /* 1179 - */ 0, + /* 117a - */ 0, + /* 117b - */ 0, + /* 117c - */ 0, + /* 117d - _66_0F_38_33 */ 0x24ab, + /* 117e - */ 0, + /* 117f - */ 0, + /* 1180 - */ 0, + /* 1181 - _V_66_0F_38_33 */ 0x4105, + /* 1182 - */ 0, + /* 1183 - */ 0, + /* 1184 - */ 0, + /* 1185 - */ 0, + /* 1186 - */ 0, + /* 1187 - */ 0, + /* 1188 - */ 0, + /* 1189 - _66_0F_38_34 */ 0x24ac, + /* 118a - */ 0, + /* 118b - */ 0, + /* 118c - */ 0, + /* 118d - _V_66_0F_38_34 */ 0x4106, + /* 118e - */ 0, + /* 118f - */ 0, + /* 1190 - */ 0, + /* 1191 - */ 0, + /* 1192 - */ 0, + /* 1193 - */ 0, + /* 1194 - */ 0, + /* 1195 - _66_0F_38_35 */ 0x24ad, + /* 1196 - */ 0, + /* 1197 - */ 0, + /* 1198 - */ 0, + /* 1199 - _V_66_0F_38_35 */ 0x4107, + /* 119a - */ 0, + /* 119b - */ 0, + /* 119c - */ 0, + /* 119d - */ 0, + /* 119e - */ 0, + /* 119f - */ 0, + /* 11a0 - */ 0, + /* 11a1 - _66_0F_38_37 */ 0x24ae, + /* 11a2 - */ 0, + /* 11a3 - */ 0, + /* 11a4 - */ 0, + /* 11a5 - _V_66_0F_38_37 */ 0x4108, + /* 11a6 - */ 0, + /* 11a7 - */ 0, + /* 11a8 - */ 0, + /* 11a9 - */ 0, + /* 11aa - */ 0, + /* 11ab - */ 0, + /* 11ac - */ 0, + /* 11ad - _66_0F_38_38 */ 0x24af, + /* 11ae - */ 0, + /* 11af - */ 0, + /* 11b0 - */ 0, + /* 11b1 - _V_66_0F_38_38 */ 0x4109, + /* 11b2 - */ 0, + /* 11b3 - */ 0, + /* 11b4 - */ 0, + /* 11b5 - */ 0, + /* 11b6 - */ 0, + /* 11b7 - */ 0, + /* 11b8 - */ 0, + /* 11b9 - _66_0F_38_39 */ 0x24b0, + /* 11ba - */ 0, + /* 11bb - */ 0, + /* 11bc - */ 0, + /* 11bd - _V_66_0F_38_39 */ 0x410a, + /* 11be - */ 0, + /* 11bf - */ 0, + /* 11c0 - */ 0, + /* 11c1 - */ 0, + /* 11c2 - */ 0, + /* 11c3 - */ 0, + /* 11c4 - */ 0, + /* 11c5 - _66_0F_38_3A */ 0x24b1, + /* 11c6 - */ 0, + /* 11c7 - */ 0, + /* 11c8 - */ 0, + /* 11c9 - _V_66_0F_38_3A */ 0x410b, + /* 11ca - */ 0, + /* 11cb - */ 0, + /* 11cc - */ 0, + /* 11cd - */ 0, + /* 11ce - */ 0, + /* 11cf - */ 0, + /* 11d0 - */ 0, + /* 11d1 - _66_0F_38_3B */ 0x24b2, + /* 11d2 - */ 0, + /* 11d3 - */ 0, + /* 11d4 - */ 0, + /* 11d5 - _V_66_0F_38_3B */ 0x410c, + /* 11d6 - */ 0, + /* 11d7 - */ 0, + /* 11d8 - */ 0, + /* 11d9 - */ 0, + /* 11da - */ 0, + /* 11db - */ 0, + /* 11dc - */ 0, + /* 11dd - _66_0F_38_3C */ 0x24b3, + /* 11de - */ 0, + /* 11df - */ 0, + /* 11e0 - */ 0, + /* 11e1 - _V_66_0F_38_3C */ 0x410d, + /* 11e2 - */ 0, + /* 11e3 - */ 0, + /* 11e4 - */ 0, + /* 11e5 - */ 0, + /* 11e6 - */ 0, + /* 11e7 - */ 0, + /* 11e8 - */ 0, + /* 11e9 - _66_0F_38_3D */ 0x24b4, + /* 11ea - */ 0, + /* 11eb - */ 0, + /* 11ec - */ 0, + /* 11ed - _V_66_0F_38_3D */ 0x410e, + /* 11ee - */ 0, + /* 11ef - */ 0, + /* 11f0 - */ 0, + /* 11f1 - */ 0, + /* 11f2 - */ 0, + /* 11f3 - */ 0, + /* 11f4 - */ 0, + /* 11f5 - _66_0F_38_3E */ 0x24b5, + /* 11f6 - */ 0, + /* 11f7 - */ 0, + /* 11f8 - */ 0, + /* 11f9 - _V_66_0F_38_3E */ 0x410f, + /* 11fa - */ 0, + /* 11fb - */ 0, + /* 11fc - */ 0, + /* 11fd - */ 0, + /* 11fe - */ 0, + /* 11ff - */ 0, + /* 1200 - */ 0, + /* 1201 - _66_0F_38_3F */ 0x24b6, + /* 1202 - */ 0, + /* 1203 - */ 0, + /* 1204 - */ 0, + /* 1205 - _V_66_0F_38_3F */ 0x4110, + /* 1206 - */ 0, + /* 1207 - */ 0, + /* 1208 - */ 0, + /* 1209 - */ 0, + /* 120a - */ 0, + /* 120b - */ 0, + /* 120c - */ 0, + /* 120d - _66_0F_38_40 */ 0x24b7, + /* 120e - */ 0, + /* 120f - */ 0, + /* 1210 - */ 0, + /* 1211 - _V_66_0F_38_40 */ 0x4111, + /* 1212 - */ 0, + /* 1213 - */ 0, + /* 1214 - */ 0, + /* 1215 - */ 0, + /* 1216 - */ 0, + /* 1217 - */ 0, + /* 1218 - */ 0, + /* 1219 - _66_0F_38_41 */ 0x24b8, + /* 121a - */ 0, + /* 121b - */ 0, + /* 121c - */ 0, + /* 121d - _V_66_0F_38_41 */ 0x4112, + /* 121e - */ 0, + /* 121f - */ 0, + /* 1220 - */ 0, + /* 1221 - */ 0, + /* 1222 - */ 0, + /* 1223 - */ 0, + /* 1224 - */ 0, + /* 1225 - _66_0F_38_80 */ 0x24b9, + /* 1226 - */ 0, + /* 1227 - */ 0, + /* 1228 - */ 0, + /* 1229 - */ 0, + /* 122a - */ 0, + /* 122b - */ 0, + /* 122c - */ 0, + /* 122d - */ 0, + /* 122e - */ 0, + /* 122f - */ 0, + /* 1230 - */ 0, + /* 1231 - _66_0F_38_81 */ 0x24ba, + /* 1232 - */ 0, + /* 1233 - */ 0, + /* 1234 - */ 0, + /* 1235 - */ 0, + /* 1236 - */ 0, + /* 1237 - */ 0, + /* 1238 - */ 0, + /* 1239 - */ 0, + /* 123a - */ 0, + /* 123b - */ 0, + /* 123c - */ 0, + /* 123d - _66_0F_38_82 */ 0x24bb, + /* 123e - */ 0, + /* 123f - */ 0, + /* 1240 - */ 0, + /* 1241 - */ 0, + /* 1242 - */ 0, + /* 1243 - */ 0, + /* 1244 - */ 0, + /* 1245 - */ 0, + /* 1246 - */ 0, + /* 1247 - */ 0, + /* 1248 - */ 0, + /* 1249 - */ 0, + /* 124a - */ 0, + /* 124b - */ 0, + /* 124c - */ 0, + /* 124d - _V_66_0F_38_96 */ 0x4113, + /* 124e - */ 0, + /* 124f - */ 0, + /* 1250 - */ 0, + /* 1251 - */ 0, + /* 1252 - */ 0, + /* 1253 - */ 0, + /* 1254 - */ 0, + /* 1255 - */ 0, + /* 1256 - */ 0, + /* 1257 - */ 0, + /* 1258 - */ 0, + /* 1259 - _V_66_0F_38_97 */ 0x4114, + /* 125a - */ 0, + /* 125b - */ 0, + /* 125c - */ 0, + /* 125d - */ 0, + /* 125e - */ 0, + /* 125f - */ 0, + /* 1260 - */ 0, + /* 1261 - */ 0, + /* 1262 - */ 0, + /* 1263 - */ 0, + /* 1264 - */ 0, + /* 1265 - _V_66_0F_38_98 */ 0x4115, + /* 1266 - */ 0, + /* 1267 - */ 0, + /* 1268 - */ 0, + /* 1269 - */ 0, + /* 126a - */ 0, + /* 126b - */ 0, + /* 126c - */ 0, + /* 126d - */ 0, + /* 126e - */ 0, + /* 126f - */ 0, + /* 1270 - */ 0, + /* 1271 - _V_66_0F_38_99 */ 0x4116, + /* 1272 - */ 0, + /* 1273 - */ 0, + /* 1274 - */ 0, + /* 1275 - */ 0, + /* 1276 - */ 0, + /* 1277 - */ 0, + /* 1278 - */ 0, + /* 1279 - */ 0, + /* 127a - */ 0, + /* 127b - */ 0, + /* 127c - */ 0, + /* 127d - _V_66_0F_38_9A */ 0x4117, + /* 127e - */ 0, + /* 127f - */ 0, + /* 1280 - */ 0, + /* 1281 - */ 0, + /* 1282 - */ 0, + /* 1283 - */ 0, + /* 1284 - */ 0, + /* 1285 - */ 0, + /* 1286 - */ 0, + /* 1287 - */ 0, + /* 1288 - */ 0, + /* 1289 - _V_66_0F_38_9B */ 0x4118, + /* 128a - */ 0, + /* 128b - */ 0, + /* 128c - */ 0, + /* 128d - */ 0, + /* 128e - */ 0, + /* 128f - */ 0, + /* 1290 - */ 0, + /* 1291 - */ 0, + /* 1292 - */ 0, + /* 1293 - */ 0, + /* 1294 - */ 0, + /* 1295 - _V_66_0F_38_9C */ 0x4119, + /* 1296 - */ 0, + /* 1297 - */ 0, + /* 1298 - */ 0, + /* 1299 - */ 0, + /* 129a - */ 0, + /* 129b - */ 0, + /* 129c - */ 0, + /* 129d - */ 0, + /* 129e - */ 0, + /* 129f - */ 0, + /* 12a0 - */ 0, + /* 12a1 - _V_66_0F_38_9D */ 0x411a, + /* 12a2 - */ 0, + /* 12a3 - */ 0, + /* 12a4 - */ 0, + /* 12a5 - */ 0, + /* 12a6 - */ 0, + /* 12a7 - */ 0, + /* 12a8 - */ 0, + /* 12a9 - */ 0, + /* 12aa - */ 0, + /* 12ab - */ 0, + /* 12ac - */ 0, + /* 12ad - _V_66_0F_38_9E */ 0x411b, + /* 12ae - */ 0, + /* 12af - */ 0, + /* 12b0 - */ 0, + /* 12b1 - */ 0, + /* 12b2 - */ 0, + /* 12b3 - */ 0, + /* 12b4 - */ 0, + /* 12b5 - */ 0, + /* 12b6 - */ 0, + /* 12b7 - */ 0, + /* 12b8 - */ 0, + /* 12b9 - _V_66_0F_38_9F */ 0x411c, + /* 12ba - */ 0, + /* 12bb - */ 0, + /* 12bc - */ 0, + /* 12bd - */ 0, + /* 12be - */ 0, + /* 12bf - */ 0, + /* 12c0 - */ 0, + /* 12c1 - */ 0, + /* 12c2 - */ 0, + /* 12c3 - */ 0, + /* 12c4 - */ 0, + /* 12c5 - _V_66_0F_38_A6 */ 0x411d, + /* 12c6 - */ 0, + /* 12c7 - */ 0, + /* 12c8 - */ 0, + /* 12c9 - */ 0, + /* 12ca - */ 0, + /* 12cb - */ 0, + /* 12cc - */ 0, + /* 12cd - */ 0, + /* 12ce - */ 0, + /* 12cf - */ 0, + /* 12d0 - */ 0, + /* 12d1 - _V_66_0F_38_A7 */ 0x411e, + /* 12d2 - */ 0, + /* 12d3 - */ 0, + /* 12d4 - */ 0, + /* 12d5 - */ 0, + /* 12d6 - */ 0, + /* 12d7 - */ 0, + /* 12d8 - */ 0, + /* 12d9 - */ 0, + /* 12da - */ 0, + /* 12db - */ 0, + /* 12dc - */ 0, + /* 12dd - _V_66_0F_38_A8 */ 0x411f, + /* 12de - */ 0, + /* 12df - */ 0, + /* 12e0 - */ 0, + /* 12e1 - */ 0, + /* 12e2 - */ 0, + /* 12e3 - */ 0, + /* 12e4 - */ 0, + /* 12e5 - */ 0, + /* 12e6 - */ 0, + /* 12e7 - */ 0, + /* 12e8 - */ 0, + /* 12e9 - _V_66_0F_38_A9 */ 0x4120, + /* 12ea - */ 0, + /* 12eb - */ 0, + /* 12ec - */ 0, + /* 12ed - */ 0, + /* 12ee - */ 0, + /* 12ef - */ 0, + /* 12f0 - */ 0, + /* 12f1 - */ 0, + /* 12f2 - */ 0, + /* 12f3 - */ 0, + /* 12f4 - */ 0, + /* 12f5 - _V_66_0F_38_AA */ 0x4121, + /* 12f6 - */ 0, + /* 12f7 - */ 0, + /* 12f8 - */ 0, + /* 12f9 - */ 0, + /* 12fa - */ 0, + /* 12fb - */ 0, + /* 12fc - */ 0, + /* 12fd - */ 0, + /* 12fe - */ 0, + /* 12ff - */ 0, + /* 1300 - */ 0, + /* 1301 - _V_66_0F_38_AB */ 0x4122, + /* 1302 - */ 0, + /* 1303 - */ 0, + /* 1304 - */ 0, + /* 1305 - */ 0, + /* 1306 - */ 0, + /* 1307 - */ 0, + /* 1308 - */ 0, + /* 1309 - */ 0, + /* 130a - */ 0, + /* 130b - */ 0, + /* 130c - */ 0, + /* 130d - _V_66_0F_38_AC */ 0x4123, + /* 130e - */ 0, + /* 130f - */ 0, + /* 1310 - */ 0, + /* 1311 - */ 0, + /* 1312 - */ 0, + /* 1313 - */ 0, + /* 1314 - */ 0, + /* 1315 - */ 0, + /* 1316 - */ 0, + /* 1317 - */ 0, + /* 1318 - */ 0, + /* 1319 - _V_66_0F_38_AD */ 0x4124, + /* 131a - */ 0, + /* 131b - */ 0, + /* 131c - */ 0, + /* 131d - */ 0, + /* 131e - */ 0, + /* 131f - */ 0, + /* 1320 - */ 0, + /* 1321 - */ 0, + /* 1322 - */ 0, + /* 1323 - */ 0, + /* 1324 - */ 0, + /* 1325 - _V_66_0F_38_AE */ 0x4125, + /* 1326 - */ 0, + /* 1327 - */ 0, + /* 1328 - */ 0, + /* 1329 - */ 0, + /* 132a - */ 0, + /* 132b - */ 0, + /* 132c - */ 0, + /* 132d - */ 0, + /* 132e - */ 0, + /* 132f - */ 0, + /* 1330 - */ 0, + /* 1331 - _V_66_0F_38_AF */ 0x4126, + /* 1332 - */ 0, + /* 1333 - */ 0, + /* 1334 - */ 0, + /* 1335 - */ 0, + /* 1336 - */ 0, + /* 1337 - */ 0, + /* 1338 - */ 0, + /* 1339 - */ 0, + /* 133a - */ 0, + /* 133b - */ 0, + /* 133c - */ 0, + /* 133d - _V_66_0F_38_B6 */ 0x4127, + /* 133e - */ 0, + /* 133f - */ 0, + /* 1340 - */ 0, + /* 1341 - */ 0, + /* 1342 - */ 0, + /* 1343 - */ 0, + /* 1344 - */ 0, + /* 1345 - */ 0, + /* 1346 - */ 0, + /* 1347 - */ 0, + /* 1348 - */ 0, + /* 1349 - _V_66_0F_38_B7 */ 0x4128, + /* 134a - */ 0, + /* 134b - */ 0, + /* 134c - */ 0, + /* 134d - */ 0, + /* 134e - */ 0, + /* 134f - */ 0, + /* 1350 - */ 0, + /* 1351 - */ 0, + /* 1352 - */ 0, + /* 1353 - */ 0, + /* 1354 - */ 0, + /* 1355 - _V_66_0F_38_B8 */ 0x4129, + /* 1356 - */ 0, + /* 1357 - */ 0, + /* 1358 - */ 0, + /* 1359 - */ 0, + /* 135a - */ 0, + /* 135b - */ 0, + /* 135c - */ 0, + /* 135d - */ 0, + /* 135e - */ 0, + /* 135f - */ 0, + /* 1360 - */ 0, + /* 1361 - _V_66_0F_38_B9 */ 0x412a, + /* 1362 - */ 0, + /* 1363 - */ 0, + /* 1364 - */ 0, + /* 1365 - */ 0, + /* 1366 - */ 0, + /* 1367 - */ 0, + /* 1368 - */ 0, + /* 1369 - */ 0, + /* 136a - */ 0, + /* 136b - */ 0, + /* 136c - */ 0, + /* 136d - _V_66_0F_38_BA */ 0x412b, + /* 136e - */ 0, + /* 136f - */ 0, + /* 1370 - */ 0, + /* 1371 - */ 0, + /* 1372 - */ 0, + /* 1373 - */ 0, + /* 1374 - */ 0, + /* 1375 - */ 0, + /* 1376 - */ 0, + /* 1377 - */ 0, + /* 1378 - */ 0, + /* 1379 - _V_66_0F_38_BB */ 0x412c, + /* 137a - */ 0, + /* 137b - */ 0, + /* 137c - */ 0, + /* 137d - */ 0, + /* 137e - */ 0, + /* 137f - */ 0, + /* 1380 - */ 0, + /* 1381 - */ 0, + /* 1382 - */ 0, + /* 1383 - */ 0, + /* 1384 - */ 0, + /* 1385 - _V_66_0F_38_BC */ 0x412d, + /* 1386 - */ 0, + /* 1387 - */ 0, + /* 1388 - */ 0, + /* 1389 - */ 0, + /* 138a - */ 0, + /* 138b - */ 0, + /* 138c - */ 0, + /* 138d - */ 0, + /* 138e - */ 0, + /* 138f - */ 0, + /* 1390 - */ 0, + /* 1391 - _V_66_0F_38_BD */ 0x412e, + /* 1392 - */ 0, + /* 1393 - */ 0, + /* 1394 - */ 0, + /* 1395 - */ 0, + /* 1396 - */ 0, + /* 1397 - */ 0, + /* 1398 - */ 0, + /* 1399 - */ 0, + /* 139a - */ 0, + /* 139b - */ 0, + /* 139c - */ 0, + /* 139d - _V_66_0F_38_BE */ 0x412f, + /* 139e - */ 0, + /* 139f - */ 0, + /* 13a0 - */ 0, + /* 13a1 - */ 0, + /* 13a2 - */ 0, + /* 13a3 - */ 0, + /* 13a4 - */ 0, + /* 13a5 - */ 0, + /* 13a6 - */ 0, + /* 13a7 - */ 0, + /* 13a8 - */ 0, + /* 13a9 - _V_66_0F_38_BF */ 0x4130, + /* 13aa - */ 0, + /* 13ab - */ 0, + /* 13ac - */ 0, + /* 13ad - */ 0, + /* 13ae - */ 0, + /* 13af - */ 0, + /* 13b0 - */ 0, + /* 13b1 - _66_0F_38_DB */ 0x24bc, + /* 13b2 - */ 0, + /* 13b3 - */ 0, + /* 13b4 - */ 0, + /* 13b5 - _V_66_0F_38_DB */ 0x4131, + /* 13b6 - */ 0, + /* 13b7 - */ 0, + /* 13b8 - */ 0, + /* 13b9 - */ 0, + /* 13ba - */ 0, + /* 13bb - */ 0, + /* 13bc - */ 0, + /* 13bd - _66_0F_38_DC */ 0x24bd, + /* 13be - */ 0, + /* 13bf - */ 0, + /* 13c0 - */ 0, + /* 13c1 - _V_66_0F_38_DC */ 0x4132, + /* 13c2 - */ 0, + /* 13c3 - */ 0, + /* 13c4 - */ 0, + /* 13c5 - */ 0, + /* 13c6 - */ 0, + /* 13c7 - */ 0, + /* 13c8 - */ 0, + /* 13c9 - _66_0F_38_DD */ 0x24be, + /* 13ca - */ 0, + /* 13cb - */ 0, + /* 13cc - */ 0, + /* 13cd - _V_66_0F_38_DD */ 0x4133, + /* 13ce - */ 0, + /* 13cf - */ 0, + /* 13d0 - */ 0, + /* 13d1 - */ 0, + /* 13d2 - */ 0, + /* 13d3 - */ 0, + /* 13d4 - */ 0, + /* 13d5 - _66_0F_38_DE */ 0x24bf, + /* 13d6 - */ 0, + /* 13d7 - */ 0, + /* 13d8 - */ 0, + /* 13d9 - _V_66_0F_38_DE */ 0x4134, + /* 13da - */ 0, + /* 13db - */ 0, + /* 13dc - */ 0, + /* 13dd - */ 0, + /* 13de - */ 0, + /* 13df - */ 0, + /* 13e0 - */ 0, + /* 13e1 - _66_0F_38_DF */ 0x24c0, + /* 13e2 - */ 0, + /* 13e3 - */ 0, + /* 13e4 - */ 0, + /* 13e5 - _V_66_0F_38_DF */ 0x4135, + /* 13e6 - */ 0, + /* 13e7 - */ 0, + /* 13e8 - */ 0, + /* 13e9 - */ 0, + /* 13ea - */ 0, + /* 13eb - */ 0, + /* 13ec - _0F_38_F0 */ 0x24c1, + /* 13ed - */ 0, + /* 13ee - */ 0, + /* 13ef - _F2_0F_38_F0 */ 0x24c2, + /* 13f0 - */ 0, + /* 13f1 - */ 0, + /* 13f2 - */ 0, + /* 13f3 - */ 0, + /* 13f4 - */ 0, + /* 13f5 - */ 0, + /* 13f6 - */ 0, + /* 13f7 - */ 0, + /* 13f8 - _0F_38_F1 */ 0x24c3, + /* 13f9 - */ 0, + /* 13fa - */ 0, + /* 13fb - _F2_0F_38_F1 */ 0x24c4, + /* 13fc - */ 0, + /* 13fd - */ 0, + /* 13fe - */ 0, + /* 13ff - */ 0, + /* 1400 - */ 0, + /* 1401 - */ 0, + /* 1402 - */ 0, + /* 1403 - */ 0, + /* 1404 - */ 0, + /* 1405 - */ 0, + /* 1406 - */ 0, + /* 1407 - */ 0, + /* 1408 - */ 0, + /* 1409 - _V_66_0F_3A_04 */ 0x4136, + /* 140a - */ 0, + /* 140b - */ 0, + /* 140c - */ 0, + /* 140d - */ 0, + /* 140e - */ 0, + /* 140f - */ 0, + /* 1410 - */ 0, + /* 1411 - */ 0, + /* 1412 - */ 0, + /* 1413 - */ 0, + /* 1414 - */ 0, + /* 1415 - _V_66_0F_3A_05 */ 0x4137, + /* 1416 - */ 0, + /* 1417 - */ 0, + /* 1418 - */ 0, + /* 1419 - */ 0, + /* 141a - */ 0, + /* 141b - */ 0, + /* 141c - */ 0, + /* 141d - */ 0, + /* 141e - */ 0, + /* 141f - */ 0, + /* 1420 - */ 0, + /* 1421 - _V_66_0F_3A_06 */ 0x4138, + /* 1422 - */ 0, + /* 1423 - */ 0, + /* 1424 - */ 0, + /* 1425 - */ 0, + /* 1426 - */ 0, + /* 1427 - */ 0, + /* 1428 - */ 0, + /* 1429 - _66_0F_3A_08 */ 0x4139, + /* 142a - */ 0, + /* 142b - */ 0, + /* 142c - */ 0, + /* 142d - _V_66_0F_3A_08 */ 0x413a, + /* 142e - */ 0, + /* 142f - */ 0, + /* 1430 - */ 0, + /* 1431 - */ 0, + /* 1432 - */ 0, + /* 1433 - */ 0, + /* 1434 - */ 0, + /* 1435 - _66_0F_3A_09 */ 0x413b, + /* 1436 - */ 0, + /* 1437 - */ 0, + /* 1438 - */ 0, + /* 1439 - _V_66_0F_3A_09 */ 0x413c, + /* 143a - */ 0, + /* 143b - */ 0, + /* 143c - */ 0, + /* 143d - */ 0, + /* 143e - */ 0, + /* 143f - */ 0, + /* 1440 - */ 0, + /* 1441 - _66_0F_3A_0A */ 0x413d, + /* 1442 - */ 0, + /* 1443 - */ 0, + /* 1444 - */ 0, + /* 1445 - _V_66_0F_3A_0A */ 0x413e, + /* 1446 - */ 0, + /* 1447 - */ 0, + /* 1448 - */ 0, + /* 1449 - */ 0, + /* 144a - */ 0, + /* 144b - */ 0, + /* 144c - */ 0, + /* 144d - _66_0F_3A_0B */ 0x413f, + /* 144e - */ 0, + /* 144f - */ 0, + /* 1450 - */ 0, + /* 1451 - _V_66_0F_3A_0B */ 0x4140, + /* 1452 - */ 0, + /* 1453 - */ 0, + /* 1454 - */ 0, + /* 1455 - */ 0, + /* 1456 - */ 0, + /* 1457 - */ 0, + /* 1458 - */ 0, + /* 1459 - _66_0F_3A_0C */ 0x4141, + /* 145a - */ 0, + /* 145b - */ 0, + /* 145c - */ 0, + /* 145d - _V_66_0F_3A_0C */ 0x4142, + /* 145e - */ 0, + /* 145f - */ 0, + /* 1460 - */ 0, + /* 1461 - */ 0, + /* 1462 - */ 0, + /* 1463 - */ 0, + /* 1464 - */ 0, + /* 1465 - _66_0F_3A_0D */ 0x4143, + /* 1466 - */ 0, + /* 1467 - */ 0, + /* 1468 - */ 0, + /* 1469 - _V_66_0F_3A_0D */ 0x4144, + /* 146a - */ 0, + /* 146b - */ 0, + /* 146c - */ 0, + /* 146d - */ 0, + /* 146e - */ 0, + /* 146f - */ 0, + /* 1470 - */ 0, + /* 1471 - _66_0F_3A_0E */ 0x4145, + /* 1472 - */ 0, + /* 1473 - */ 0, + /* 1474 - */ 0, + /* 1475 - _V_66_0F_3A_0E */ 0x4146, + /* 1476 - */ 0, + /* 1477 - */ 0, + /* 1478 - */ 0, + /* 1479 - */ 0, + /* 147a - */ 0, + /* 147b - */ 0, + /* 147c - _0F_3A_0F */ 0x4147, + /* 147d - _66_0F_3A_0F */ 0x4148, + /* 147e - */ 0, + /* 147f - */ 0, + /* 1480 - */ 0, + /* 1481 - _V_66_0F_3A_0F */ 0x4149, + /* 1482 - */ 0, + /* 1483 - */ 0, + /* 1484 - */ 0, + /* 1485 - */ 0, + /* 1486 - */ 0, + /* 1487 - */ 0, + /* 1488 - */ 0, + /* 1489 - _66_0F_3A_14 */ 0x414a, + /* 148a - */ 0, + /* 148b - */ 0, + /* 148c - */ 0, + /* 148d - _V_66_0F_3A_14 */ 0x414b, + /* 148e - */ 0, + /* 148f - */ 0, + /* 1490 - */ 0, + /* 1491 - */ 0, + /* 1492 - */ 0, + /* 1493 - */ 0, + /* 1494 - */ 0, + /* 1495 - _66_0F_3A_15 */ 0x414c, + /* 1496 - */ 0, + /* 1497 - */ 0, + /* 1498 - */ 0, + /* 1499 - _V_66_0F_3A_15 */ 0x414d, + /* 149a - */ 0, + /* 149b - */ 0, + /* 149c - */ 0, + /* 149d - */ 0, + /* 149e - */ 0, + /* 149f - */ 0, + /* 14a0 - */ 0, + /* 14a1 - _66_0F_3A_16 */ 0x414e, + /* 14a2 - */ 0, + /* 14a3 - */ 0, + /* 14a4 - */ 0, + /* 14a5 - _V_66_0F_3A_16 */ 0x414f, + /* 14a6 - */ 0, + /* 14a7 - */ 0, + /* 14a8 - */ 0, + /* 14a9 - */ 0, + /* 14aa - */ 0, + /* 14ab - */ 0, + /* 14ac - */ 0, + /* 14ad - _66_0F_3A_17 */ 0x4150, + /* 14ae - */ 0, + /* 14af - */ 0, + /* 14b0 - */ 0, + /* 14b1 - _V_66_0F_3A_17 */ 0x4151, + /* 14b2 - */ 0, + /* 14b3 - */ 0, + /* 14b4 - */ 0, + /* 14b5 - */ 0, + /* 14b6 - */ 0, + /* 14b7 - */ 0, + /* 14b8 - */ 0, + /* 14b9 - */ 0, + /* 14ba - */ 0, + /* 14bb - */ 0, + /* 14bc - */ 0, + /* 14bd - _V_66_0F_3A_18 */ 0x4152, + /* 14be - */ 0, + /* 14bf - */ 0, + /* 14c0 - */ 0, + /* 14c1 - */ 0, + /* 14c2 - */ 0, + /* 14c3 - */ 0, + /* 14c4 - */ 0, + /* 14c5 - */ 0, + /* 14c6 - */ 0, + /* 14c7 - */ 0, + /* 14c8 - */ 0, + /* 14c9 - _V_66_0F_3A_19 */ 0x4153, + /* 14ca - */ 0, + /* 14cb - */ 0, + /* 14cc - */ 0, + /* 14cd - */ 0, + /* 14ce - */ 0, + /* 14cf - */ 0, + /* 14d0 - */ 0, + /* 14d1 - _66_0F_3A_20 */ 0x4154, + /* 14d2 - */ 0, + /* 14d3 - */ 0, + /* 14d4 - */ 0, + /* 14d5 - _V_66_0F_3A_20 */ 0x4155, + /* 14d6 - */ 0, + /* 14d7 - */ 0, + /* 14d8 - */ 0, + /* 14d9 - */ 0, + /* 14da - */ 0, + /* 14db - */ 0, + /* 14dc - */ 0, + /* 14dd - _66_0F_3A_21 */ 0x4156, + /* 14de - */ 0, + /* 14df - */ 0, + /* 14e0 - */ 0, + /* 14e1 - _V_66_0F_3A_21 */ 0x4157, + /* 14e2 - */ 0, + /* 14e3 - */ 0, + /* 14e4 - */ 0, + /* 14e5 - */ 0, + /* 14e6 - */ 0, + /* 14e7 - */ 0, + /* 14e8 - */ 0, + /* 14e9 - _66_0F_3A_22 */ 0x4158, + /* 14ea - */ 0, + /* 14eb - */ 0, + /* 14ec - */ 0, + /* 14ed - _V_66_0F_3A_22 */ 0x4159, + /* 14ee - */ 0, + /* 14ef - */ 0, + /* 14f0 - */ 0, + /* 14f1 - */ 0, + /* 14f2 - */ 0, + /* 14f3 - */ 0, + /* 14f4 - */ 0, + /* 14f5 - _66_0F_3A_40 */ 0x415a, + /* 14f6 - */ 0, + /* 14f7 - */ 0, + /* 14f8 - */ 0, + /* 14f9 - _V_66_0F_3A_40 */ 0x415b, + /* 14fa - */ 0, + /* 14fb - */ 0, + /* 14fc - */ 0, + /* 14fd - */ 0, + /* 14fe - */ 0, + /* 14ff - */ 0, + /* 1500 - */ 0, + /* 1501 - _66_0F_3A_41 */ 0x415c, + /* 1502 - */ 0, + /* 1503 - */ 0, + /* 1504 - */ 0, + /* 1505 - _V_66_0F_3A_41 */ 0x415d, + /* 1506 - */ 0, + /* 1507 - */ 0, + /* 1508 - */ 0, + /* 1509 - */ 0, + /* 150a - */ 0, + /* 150b - */ 0, + /* 150c - */ 0, + /* 150d - _66_0F_3A_42 */ 0x415e, + /* 150e - */ 0, + /* 150f - */ 0, + /* 1510 - */ 0, + /* 1511 - _V_66_0F_3A_42 */ 0x415f, + /* 1512 - */ 0, + /* 1513 - */ 0, + /* 1514 - */ 0, + /* 1515 - */ 0, + /* 1516 - */ 0, + /* 1517 - */ 0, + /* 1518 - */ 0, + /* 1519 - _66_0F_3A_44 */ 0x4160, + /* 151a - */ 0, + /* 151b - */ 0, + /* 151c - */ 0, + /* 151d - _V_66_0F_3A_44 */ 0x4161, + /* 151e - */ 0, + /* 151f - */ 0, + /* 1520 - */ 0, + /* 1521 - */ 0, + /* 1522 - */ 0, + /* 1523 - */ 0, + /* 1524 - */ 0, + /* 1525 - */ 0, + /* 1526 - */ 0, + /* 1527 - */ 0, + /* 1528 - */ 0, + /* 1529 - _V_66_0F_3A_4A */ 0x4162, + /* 152a - */ 0, + /* 152b - */ 0, + /* 152c - */ 0, + /* 152d - */ 0, + /* 152e - */ 0, + /* 152f - */ 0, + /* 1530 - */ 0, + /* 1531 - */ 0, + /* 1532 - */ 0, + /* 1533 - */ 0, + /* 1534 - */ 0, + /* 1535 - _V_66_0F_3A_4B */ 0x4163, + /* 1536 - */ 0, + /* 1537 - */ 0, + /* 1538 - */ 0, + /* 1539 - */ 0, + /* 153a - */ 0, + /* 153b - */ 0, + /* 153c - */ 0, + /* 153d - */ 0, + /* 153e - */ 0, + /* 153f - */ 0, + /* 1540 - */ 0, + /* 1541 - _V_66_0F_3A_4C */ 0x4164, + /* 1542 - */ 0, + /* 1543 - */ 0, + /* 1544 - */ 0, + /* 1545 - */ 0, + /* 1546 - */ 0, + /* 1547 - */ 0, + /* 1548 - */ 0, + /* 1549 - _66_0F_3A_60 */ 0x4165, + /* 154a - */ 0, + /* 154b - */ 0, + /* 154c - */ 0, + /* 154d - _V_66_0F_3A_60 */ 0x4166, + /* 154e - */ 0, + /* 154f - */ 0, + /* 1550 - */ 0, + /* 1551 - */ 0, + /* 1552 - */ 0, + /* 1553 - */ 0, + /* 1554 - */ 0, + /* 1555 - _66_0F_3A_61 */ 0x4167, + /* 1556 - */ 0, + /* 1557 - */ 0, + /* 1558 - */ 0, + /* 1559 - _V_66_0F_3A_61 */ 0x4168, + /* 155a - */ 0, + /* 155b - */ 0, + /* 155c - */ 0, + /* 155d - */ 0, + /* 155e - */ 0, + /* 155f - */ 0, + /* 1560 - */ 0, + /* 1561 - _66_0F_3A_62 */ 0x4169, + /* 1562 - */ 0, + /* 1563 - */ 0, + /* 1564 - */ 0, + /* 1565 - _V_66_0F_3A_62 */ 0x416a, + /* 1566 - */ 0, + /* 1567 - */ 0, + /* 1568 - */ 0, + /* 1569 - */ 0, + /* 156a - */ 0, + /* 156b - */ 0, + /* 156c - */ 0, + /* 156d - _66_0F_3A_63 */ 0x416b, + /* 156e - */ 0, + /* 156f - */ 0, + /* 1570 - */ 0, + /* 1571 - _V_66_0F_3A_63 */ 0x416c, + /* 1572 - */ 0, + /* 1573 - */ 0, + /* 1574 - */ 0, + /* 1575 - */ 0, + /* 1576 - */ 0, + /* 1577 - */ 0, + /* 1578 - */ 0, + /* 1579 - _66_0F_3A_DF */ 0x416d, + /* 157a - */ 0, + /* 157b - */ 0, + /* 157c - */ 0, + /* 157d - _V_66_0F_3A_DF */ 0x416e, + /* 157e - */ 0, + /* 157f - */ 0, + /* 1580 - */ 0, + /* 1581 - */ 0, + /* 1582 - */ 0, + /* 1583 - */ 0, + /* 1584 - _0F_71_02 */ 0x24c5, + /* 1585 - _66_0F_71_02 */ 0x24c6, + /* 1586 - */ 0, + /* 1587 - */ 0, + /* 1588 - */ 0, + /* 1589 - _V_66_0F_71_02 */ 0x416f, + /* 158a - */ 0, + /* 158b - */ 0, + /* 158c - */ 0, + /* 158d - */ 0, + /* 158e - */ 0, + /* 158f - */ 0, + /* 1590 - _0F_71_04 */ 0x24c7, + /* 1591 - _66_0F_71_04 */ 0x24c8, + /* 1592 - */ 0, + /* 1593 - */ 0, + /* 1594 - */ 0, + /* 1595 - _V_66_0F_71_04 */ 0x4170, + /* 1596 - */ 0, + /* 1597 - */ 0, + /* 1598 - */ 0, + /* 1599 - */ 0, + /* 159a - */ 0, + /* 159b - */ 0, + /* 159c - _0F_71_06 */ 0x24c9, + /* 159d - _66_0F_71_06 */ 0x24ca, + /* 159e - */ 0, + /* 159f - */ 0, + /* 15a0 - */ 0, + /* 15a1 - _V_66_0F_71_06 */ 0x4171, + /* 15a2 - */ 0, + /* 15a3 - */ 0, + /* 15a4 - */ 0, + /* 15a5 - */ 0, + /* 15a6 - */ 0, + /* 15a7 - */ 0, + /* 15a8 - _0F_72_02 */ 0x24cb, + /* 15a9 - _66_0F_72_02 */ 0x24cc, + /* 15aa - */ 0, + /* 15ab - */ 0, + /* 15ac - */ 0, + /* 15ad - _V_66_0F_72_02 */ 0x4172, + /* 15ae - */ 0, + /* 15af - */ 0, + /* 15b0 - */ 0, + /* 15b1 - */ 0, + /* 15b2 - */ 0, + /* 15b3 - */ 0, + /* 15b4 - _0F_72_04 */ 0x24cd, + /* 15b5 - _66_0F_72_04 */ 0x24ce, + /* 15b6 - */ 0, + /* 15b7 - */ 0, + /* 15b8 - */ 0, + /* 15b9 - _V_66_0F_72_04 */ 0x4173, + /* 15ba - */ 0, + /* 15bb - */ 0, + /* 15bc - */ 0, + /* 15bd - */ 0, + /* 15be - */ 0, + /* 15bf - */ 0, + /* 15c0 - _0F_72_06 */ 0x24cf, + /* 15c1 - _66_0F_72_06 */ 0x24d0, + /* 15c2 - */ 0, + /* 15c3 - */ 0, + /* 15c4 - */ 0, + /* 15c5 - _V_66_0F_72_06 */ 0x4174, + /* 15c6 - */ 0, + /* 15c7 - */ 0, + /* 15c8 - */ 0, + /* 15c9 - */ 0, + /* 15ca - */ 0, + /* 15cb - */ 0, + /* 15cc - _0F_73_02 */ 0x24d1, + /* 15cd - _66_0F_73_02 */ 0x24d2, + /* 15ce - */ 0, + /* 15cf - */ 0, + /* 15d0 - */ 0, + /* 15d1 - _V_66_0F_73_02 */ 0x4175, + /* 15d2 - */ 0, + /* 15d3 - */ 0, + /* 15d4 - */ 0, + /* 15d5 - */ 0, + /* 15d6 - */ 0, + /* 15d7 - */ 0, + /* 15d8 - */ 0, + /* 15d9 - _66_0F_73_03 */ 0x24d3, + /* 15da - */ 0, + /* 15db - */ 0, + /* 15dc - */ 0, + /* 15dd - _V_66_0F_73_03 */ 0x4176, + /* 15de - */ 0, + /* 15df - */ 0, + /* 15e0 - */ 0, + /* 15e1 - */ 0, + /* 15e2 - */ 0, + /* 15e3 - */ 0, + /* 15e4 - _0F_73_06 */ 0x24d4, + /* 15e5 - _66_0F_73_06 */ 0x24d5, + /* 15e6 - */ 0, + /* 15e7 - */ 0, + /* 15e8 - */ 0, + /* 15e9 - _V_66_0F_73_06 */ 0x4177, + /* 15ea - */ 0, + /* 15eb - */ 0, + /* 15ec - */ 0, + /* 15ed - */ 0, + /* 15ee - */ 0, + /* 15ef - */ 0, + /* 15f0 - */ 0, + /* 15f1 - _66_0F_73_07 */ 0x24d6, + /* 15f2 - */ 0, + /* 15f3 - */ 0, + /* 15f4 - */ 0, + /* 15f5 - _V_66_0F_73_07 */ 0x4178, + /* 15f6 - */ 0, + /* 15f7 - */ 0, + /* 15f8 - */ 0, + /* 15f9 - */ 0, + /* 15fa - */ 0, + /* 15fb - */ 0, + /* 15fc - _0F_AE_00 */ 0x4179, + /* 15fd - */ 0, + /* 15fe - _F3_0F_AE_00 */ 0x24d7, + /* 15ff - */ 0, + /* 1600 - */ 0, + /* 1601 - */ 0, + /* 1602 - */ 0, + /* 1603 - */ 0, + /* 1604 - */ 0, + /* 1605 - */ 0, + /* 1606 - */ 0, + /* 1607 - */ 0, + /* 1608 - _0F_AE_01 */ 0x417a, + /* 1609 - */ 0, + /* 160a - _F3_0F_AE_01 */ 0x24d8, + /* 160b - */ 0, + /* 160c - */ 0, + /* 160d - */ 0, + /* 160e - */ 0, + /* 160f - */ 0, + /* 1610 - */ 0, + /* 1611 - */ 0, + /* 1612 - */ 0, + /* 1613 - */ 0, + /* 1614 - _0F_AE_02 */ 0x24d9, + /* 1615 - */ 0, + /* 1616 - _F3_0F_AE_02 */ 0x24da, + /* 1617 - */ 0, + /* 1618 - _V_0F_AE_02 */ 0x417b, + /* 1619 - */ 0, + /* 161a - */ 0, + /* 161b - */ 0, + /* 161c - */ 0, + /* 161d - */ 0, + /* 161e - */ 0, + /* 161f - */ 0, + /* 1620 - _0F_AE_03 */ 0x24db, + /* 1621 - */ 0, + /* 1622 - _F3_0F_AE_03 */ 0x24dc, + /* 1623 - */ 0, + /* 1624 - _V_0F_AE_03 */ 0x417c, + /* 1625 - */ 0, + /* 1626 - */ 0, + /* 1627 - */ 0, + /* 1628 - */ 0, + /* 1629 - */ 0, + /* 162a - */ 0, + /* 162b - */ 0, + /* 162c - _0F_C7_06 */ 0x24dd, + /* 162d - _66_0F_C7_06 */ 0x24de, + /* 162e - _F3_0F_C7_06 */ 0x24df, + /* 162f - */ 0, + /* 1630 - */ 0, + /* 1631 - */ 0, + /* 1632 - */ 0, + /* 1633 - */ 0, + /* 1634 - */ 0, + /* 1635 - */ 0, + /* 1636 - */ 0, + /* 1637 - */ 0 +}; + +_InstSharedInfo InstSharedInfoTable[474] = +{ + {0, 6, 68, 245, 0, 0, 256}, + {0, 8, 72, 245, 0, 0, 256}, + {0, 68, 6, 245, 0, 0, 256}, + {0, 72, 8, 245, 0, 0, 256}, + {1, 1, 11, 245, 0, 0, 256}, + {1, 3, 13, 245, 0, 0, 256}, + {2, 0, 46, 0, 0, 0, 256}, + {3, 0, 46, 0, 0, 0, 256}, + {0, 6, 68, 196, 16, 0, 256}, + {0, 8, 72, 196, 16, 0, 256}, + {0, 68, 6, 196, 16, 0, 256}, + {0, 72, 8, 196, 16, 0, 256}, + {1, 1, 11, 196, 16, 0, 256}, + {1, 3, 13, 196, 16, 0, 256}, + {4, 0, 46, 0, 0, 0, 256}, + {0, 6, 68, 245, 1, 0, 256}, + {0, 8, 72, 245, 1, 0, 256}, + {0, 68, 6, 245, 1, 0, 256}, + {0, 72, 8, 245, 1, 0, 256}, + {1, 1, 11, 245, 1, 0, 256}, + {1, 3, 13, 245, 1, 0, 256}, + {5, 0, 46, 0, 0, 0, 256}, + {6, 0, 46, 0, 0, 0, 256}, + {7, 0, 46, 0, 0, 0, 256}, + {8, 0, 46, 0, 0, 0, 256}, + {0, 6, 68, 229, 0, 16, 256}, + {0, 8, 72, 229, 0, 16, 256}, + {0, 68, 6, 229, 0, 16, 256}, + {0, 72, 8, 229, 0, 16, 256}, + {1, 1, 11, 229, 0, 16, 256}, + {1, 3, 13, 229, 0, 16, 256}, + {9, 0, 0, 213, 17, 32, 256}, + {0, 6, 68, 196, 0, 16, 256}, + {0, 8, 72, 196, 0, 16, 256}, + {0, 68, 6, 196, 0, 16, 256}, + {0, 72, 8, 196, 0, 16, 256}, + {1, 1, 11, 196, 0, 16, 256}, + {1, 3, 13, 196, 0, 16, 256}, + {9, 0, 0, 17, 16, 228, 256}, + {10, 6, 68, 245, 0, 0, 256}, + {10, 8, 72, 245, 0, 0, 256}, + {10, 68, 6, 245, 0, 0, 256}, + {10, 72, 8, 245, 0, 0, 256}, + {11, 1, 11, 245, 0, 0, 256}, + {11, 3, 13, 245, 0, 0, 256}, + {12, 0, 18, 244, 0, 0, 256}, + {13, 0, 18, 0, 0, 0, 256}, + {14, 0, 18, 0, 0, 0, 256}, + {15, 0, 0, 0, 0, 0, 256}, + {16, 54, 8, 0, 0, 0, 256}, + {10, 7, 69, 64, 0, 0, 256}, + {13, 0, 3, 0, 0, 0, 256}, + {17, 72, 8, 33, 0, 212, 256}, + {18, 0, 5, 0, 0, 0, 256}, + {19, 25, 22, 0, 8, 0, 33024}, + {20, 25, 22, 0, 8, 0, 33024}, + {19, 21, 25, 0, 8, 0, 33024}, + {20, 21, 25, 0, 8, 0, 33024}, + {13, 0, 15, 0, 32, 0, 261}, + {13, 0, 15, 0, 1, 0, 261}, + {13, 0, 15, 0, 64, 0, 261}, + {13, 0, 15, 0, 65, 0, 261}, + {13, 0, 15, 0, 128, 0, 261}, + {13, 0, 15, 0, 4, 0, 261}, + {13, 0, 15, 0, 160, 0, 261}, + {13, 0, 15, 0, 224, 0, 261}, + {10, 6, 68, 196, 0, 16, 256}, + {10, 8, 72, 196, 0, 16, 256}, + {0, 6, 68, 0, 0, 0, 256}, + {0, 8, 72, 0, 0, 0, 256}, + {21, 6, 68, 0, 0, 0, 256}, + {21, 8, 72, 0, 0, 0, 256}, + {21, 68, 6, 0, 0, 0, 256}, + {21, 72, 8, 0, 0, 0, 256}, + {21, 45, 71, 0, 0, 0, 256}, + {21, 54, 8, 0, 0, 0, 256}, + {21, 71, 45, 0, 0, 0, 256}, + {1, 13, 18, 0, 0, 0, 256}, + {22, 0, 0, 0, 0, 0, 256}, + {9, 0, 50, 0, 0, 0, 257}, + {23, 0, 0, 0, 0, 0, 256}, + {23, 0, 0, 255, 0, 0, 256}, + {11, 0, 0, 213, 0, 0, 256}, + {11, 0, 0, 0, 0, 0, 256}, + {1, 19, 11, 0, 0, 0, 256}, + {1, 20, 13, 0, 0, 0, 256}, + {1, 11, 19, 0, 0, 0, 256}, + {1, 13, 20, 0, 0, 0, 256}, + {24, 21, 22, 0, 8, 0, 256}, + {25, 21, 22, 0, 8, 0, 256}, + {19, 22, 21, 245, 8, 0, 256}, + {26, 22, 21, 245, 8, 0, 256}, + {11, 1, 11, 196, 0, 16, 256}, + {11, 3, 13, 196, 0, 16, 256}, + {19, 11, 22, 0, 8, 0, 256}, + {26, 13, 22, 0, 8, 0, 256}, + {19, 21, 11, 0, 8, 0, 256}, + {26, 21, 13, 0, 8, 0, 256}, + {19, 11, 22, 245, 8, 0, 256}, + {26, 13, 22, 245, 8, 0, 256}, + {1, 1, 17, 0, 0, 0, 256}, + {27, 3, 18, 0, 0, 0, 256}, + {13, 0, 2, 0, 0, 0, 258}, + {13, 0, 0, 0, 0, 0, 258}, + {16, 60, 8, 0, 0, 0, 256}, + {13, 49, 47, 0, 0, 0, 256}, + {13, 0, 0, 0, 0, 0, 256}, + {28, 0, 2, 0, 0, 0, 258}, + {28, 0, 0, 0, 0, 0, 258}, + {11, 0, 1, 0, 0, 0, 262}, + {9, 0, 0, 0, 0, 0, 262}, + {28, 0, 0, 255, 0, 0, 33026}, + {9, 0, 1, 196, 0, 49, 256}, + {9, 0, 0, 0, 0, 0, 256}, + {29, 0, 23, 0, 0, 0, 256}, + {30, 0, 15, 0, 64, 0, 261}, + {30, 0, 15, 0, 0, 0, 261}, + {31, 0, 15, 0, 0, 0, 261}, + {1, 1, 11, 0, 0, 0, 33024}, + {1, 1, 14, 0, 0, 0, 33024}, + {11, 11, 1, 0, 0, 0, 33024}, + {11, 14, 1, 0, 0, 0, 33024}, + {13, 0, 16, 0, 0, 0, 257}, + {13, 0, 16, 0, 0, 0, 260}, + {9, 0, 50, 0, 0, 0, 260}, + {13, 0, 15, 0, 0, 0, 260}, + {1, 25, 11, 0, 0, 0, 33024}, + {1, 25, 14, 0, 0, 0, 33024}, + {11, 11, 25, 0, 0, 0, 33024}, + {11, 14, 25, 0, 0, 0, 33024}, + {11, 0, 0, 0, 0, 0, 262}, + {11, 0, 0, 0, 0, 0, 33032}, + {11, 0, 0, 1, 0, 0, 256}, + {11, 0, 0, 2, 0, 0, 33024}, + {11, 0, 0, 8, 0, 0, 256}, + {10, 69, 8, 64, 0, 0, 256}, + {32, 0, 0, 0, 0, 0, 771}, + {32, 0, 0, 0, 0, 0, 33024}, + {32, 0, 0, 0, 0, 0, 262}, + {11, 0, 0, 0, 0, 0, 3072}, + {10, 0, 72, 0, 0, 0, 256}, + {33, 43, 51, 0, 0, 0, 33024}, + {33, 44, 51, 0, 0, 0, 33024}, + {33, 51, 43, 0, 0, 0, 33024}, + {33, 51, 44, 0, 0, 0, 33024}, + {32, 0, 0, 0, 0, 0, 256}, + {34, 72, 8, 0, 32, 0, 775}, + {34, 72, 8, 0, 1, 0, 775}, + {34, 72, 8, 0, 64, 0, 775}, + {34, 72, 8, 0, 65, 0, 775}, + {34, 72, 8, 0, 128, 0, 775}, + {34, 72, 8, 0, 4, 0, 775}, + {34, 72, 8, 0, 160, 0, 775}, + {34, 72, 8, 0, 224, 0, 775}, + {32, 0, 16, 0, 32, 0, 261}, + {32, 0, 16, 0, 1, 0, 261}, + {32, 0, 16, 0, 64, 0, 261}, + {32, 0, 16, 0, 65, 0, 261}, + {32, 0, 16, 0, 128, 0, 261}, + {32, 0, 16, 0, 4, 0, 261}, + {32, 0, 16, 0, 160, 0, 261}, + {32, 0, 16, 0, 224, 0, 261}, + {34, 0, 68, 0, 32, 0, 256}, + {34, 0, 68, 0, 1, 0, 256}, + {34, 0, 68, 0, 64, 0, 256}, + {34, 0, 68, 0, 65, 0, 256}, + {34, 0, 68, 0, 128, 0, 256}, + {34, 0, 68, 0, 4, 0, 256}, + {34, 0, 68, 0, 160, 0, 256}, + {34, 0, 68, 0, 224, 0, 256}, + {35, 0, 46, 0, 0, 0, 256}, + {36, 0, 46, 0, 0, 0, 256}, + {34, 8, 72, 1, 0, 244, 256}, + {37, 8, 72, 197, 0, 48, 256}, + {38, 0, 46, 0, 0, 0, 256}, + {39, 0, 46, 0, 0, 0, 256}, + {32, 0, 0, 255, 0, 0, 256}, + {40, 8, 72, 1, 0, 244, 256}, + {34, 72, 8, 33, 0, 212, 256}, + {40, 6, 68, 245, 0, 0, 256}, + {40, 8, 72, 245, 0, 0, 256}, + {41, 60, 8, 0, 0, 0, 256}, + {34, 68, 8, 0, 0, 0, 256}, + {42, 69, 8, 0, 0, 0, 256}, + {42, 10, 56, 0, 0, 0, 1536}, + {43, 0, 18, 0, 0, 0, 256}, + {44, 1, 68, 245, 0, 0, 256}, + {44, 1, 68, 196, 16, 0, 256}, + {44, 1, 68, 245, 1, 0, 256}, + {44, 1, 68, 229, 0, 16, 256}, + {44, 1, 68, 196, 0, 16, 256}, + {45, 1, 68, 245, 0, 0, 256}, + {44, 3, 72, 245, 0, 0, 256}, + {44, 3, 72, 196, 16, 0, 256}, + {44, 3, 72, 245, 1, 0, 256}, + {44, 3, 72, 229, 0, 16, 256}, + {44, 3, 72, 196, 0, 16, 256}, + {45, 3, 72, 245, 0, 0, 256}, + {46, 1, 68, 245, 0, 0, 256}, + {46, 1, 68, 196, 16, 0, 256}, + {46, 1, 68, 245, 1, 0, 256}, + {46, 1, 68, 229, 0, 16, 256}, + {46, 1, 68, 196, 0, 16, 256}, + {47, 1, 68, 245, 0, 0, 256}, + {44, 5, 72, 245, 0, 0, 256}, + {48, 5, 72, 196, 16, 0, 256}, + {44, 5, 72, 245, 1, 0, 256}, + {48, 5, 72, 229, 0, 16, 256}, + {48, 5, 72, 196, 0, 16, 256}, + {45, 5, 72, 245, 0, 0, 256}, + {49, 0, 72, 0, 0, 0, 256}, + {50, 1, 68, 1, 0, 32, 256}, + {50, 1, 68, 1, 1, 32, 256}, + {50, 1, 68, 197, 0, 48, 256}, + {50, 1, 72, 1, 0, 32, 256}, + {50, 1, 72, 1, 1, 32, 256}, + {50, 1, 72, 197, 0, 48, 256}, + {51, 1, 68, 0, 0, 0, 256}, + {52, 0, 1, 0, 0, 0, 768}, + {51, 3, 72, 0, 0, 0, 256}, + {52, 0, 16, 0, 0, 0, 768}, + {50, 41, 68, 33, 0, 0, 256}, + {50, 41, 68, 33, 1, 0, 256}, + {50, 41, 68, 229, 0, 16, 256}, + {50, 41, 72, 33, 0, 0, 256}, + {50, 41, 72, 33, 1, 0, 256}, + {50, 41, 72, 229, 0, 16, 256}, + {50, 42, 68, 1, 0, 32, 256}, + {50, 42, 68, 1, 1, 32, 256}, + {50, 42, 68, 197, 0, 48, 256}, + {50, 42, 72, 1, 0, 32, 256}, + {50, 42, 72, 1, 1, 32, 256}, + {50, 42, 72, 197, 0, 48, 256}, + {45, 0, 64, 0, 0, 0, 512}, + {53, 0, 28, 0, 0, 0, 512}, + {53, 0, 27, 0, 0, 0, 512}, + {53, 0, 0, 0, 0, 0, 512}, + {50, 0, 64, 0, 0, 0, 512}, + {45, 0, 54, 0, 0, 0, 512}, + {45, 0, 63, 0, 0, 0, 512}, + {54, 0, 28, 0, 1, 0, 768}, + {54, 0, 28, 0, 64, 0, 768}, + {54, 0, 28, 0, 65, 0, 768}, + {54, 0, 28, 0, 4, 0, 768}, + {55, 0, 64, 0, 0, 0, 1792}, + {45, 0, 66, 0, 0, 0, 512}, + {50, 0, 66, 0, 0, 0, 512}, + {54, 0, 28, 69, 0, 0, 512}, + {54, 0, 28, 69, 0, 0, 768}, + {45, 0, 65, 0, 0, 0, 512}, + {53, 0, 29, 0, 0, 0, 512}, + {55, 0, 65, 0, 0, 0, 1792}, + {50, 0, 65, 0, 0, 0, 512}, + {55, 0, 63, 0, 0, 0, 1792}, + {50, 0, 63, 0, 0, 0, 512}, + {45, 1, 68, 196, 0, 16, 256}, + {44, 0, 68, 0, 0, 0, 256}, + {44, 0, 68, 245, 0, 0, 256}, + {50, 0, 68, 33, 0, 212, 256}, + {50, 0, 68, 0, 0, 245, 256}, + {45, 3, 72, 196, 0, 16, 256}, + {44, 0, 72, 0, 0, 0, 256}, + {44, 0, 72, 245, 0, 0, 256}, + {50, 0, 72, 33, 0, 212, 256}, + {50, 0, 72, 0, 0, 245, 256}, + {44, 0, 68, 244, 0, 0, 256}, + {44, 0, 72, 244, 0, 0, 256}, + {56, 0, 72, 0, 0, 0, 257}, + {57, 0, 60, 0, 0, 0, 257}, + {56, 0, 72, 0, 0, 0, 260}, + {57, 0, 60, 0, 0, 0, 260}, + {56, 0, 72, 0, 0, 0, 256}, + {45, 0, 72, 0, 0, 0, 256}, + {45, 0, 69, 0, 0, 0, 256}, + {45, 0, 69, 0, 0, 0, 33024}, + {55, 0, 69, 0, 0, 0, 33024}, + {45, 0, 69, 64, 0, 0, 256}, + {56, 0, 61, 0, 0, 0, 256}, + {56, 0, 61, 0, 0, 0, 33024}, + {51, 0, 71, 0, 0, 0, 256}, + {58, 0, 69, 0, 0, 0, 33024}, + {55, 0, 54, 0, 0, 0, 33024}, + {54, 0, 0, 0, 0, 0, 3584}, + {54, 0, 0, 0, 0, 0, 256}, + {13, 0, 0, 0, 0, 0, 768}, + {55, 0, 24, 0, 0, 0, 3840}, + {54, 0, 0, 0, 0, 0, 3840}, + {54, 0, 24, 0, 0, 0, 3840}, + {54, 26, 24, 0, 0, 0, 3840}, + {59, 0, 0, 0, 0, 0, 256}, + {55, 0, 54, 0, 0, 0, 3072}, + {60, 83, 52, 0, 0, 0, 3328}, + {60, 83, 52, 0, 0, 0, 3072}, + {34, 87, 30, 0, 0, 0, 1280}, + {34, 87, 30, 0, 0, 0, 1536}, + {34, 85, 30, 0, 0, 0, 1280}, + {34, 86, 30, 0, 0, 0, 1536}, + {61, 91, 36, 0, 0, 0, 4096}, + {62, 34, 30, 0, 0, 0, 4096}, + {63, 55, 30, 0, 0, 0, 4096}, + {63, 57, 30, 0, 0, 0, 4096}, + {34, 30, 87, 0, 0, 0, 1280}, + {34, 30, 87, 0, 0, 0, 1536}, + {34, 30, 85, 0, 0, 0, 1280}, + {34, 30, 86, 0, 0, 0, 1536}, + {61, 36, 91, 0, 0, 0, 4096}, + {63, 30, 55, 0, 0, 0, 4096}, + {63, 30, 57, 0, 0, 0, 4096}, + {64, 86, 30, 0, 0, 0, 1280}, + {34, 57, 30, 0, 0, 0, 1536}, + {34, 86, 30, 0, 0, 0, 1792}, + {65, 34, 30, 0, 0, 0, 4096}, + {66, 34, 30, 0, 0, 0, 4096}, + {61, 90, 36, 0, 0, 0, 4096}, + {34, 30, 57, 0, 0, 0, 1280}, + {34, 30, 57, 0, 0, 0, 1536}, + {61, 30, 57, 0, 0, 0, 4096}, + {67, 87, 30, 0, 0, 0, 1280}, + {67, 87, 30, 0, 0, 0, 1536}, + {66, 40, 36, 0, 0, 0, 4096}, + {34, 87, 30, 0, 0, 0, 1792}, + {55, 0, 54, 0, 0, 0, 1280}, + {67, 83, 30, 0, 0, 0, 1280}, + {67, 83, 30, 0, 0, 0, 1536}, + {41, 76, 30, 0, 0, 0, 1280}, + {41, 76, 30, 0, 0, 0, 1536}, + {34, 30, 59, 0, 0, 0, 1280}, + {34, 30, 59, 0, 0, 0, 1536}, + {34, 30, 55, 0, 0, 0, 2816}, + {34, 30, 57, 0, 0, 0, 2816}, + {61, 36, 67, 0, 0, 0, 4096}, + {67, 86, 52, 0, 0, 0, 1280}, + {67, 87, 52, 0, 0, 0, 1536}, + {41, 85, 10, 0, 0, 0, 1280}, + {41, 86, 10, 0, 0, 0, 1536}, + {61, 88, 33, 0, 0, 0, 4096}, + {67, 85, 30, 69, 0, 0, 1280}, + {67, 86, 30, 0, 0, 0, 1536}, + {61, 85, 30, 0, 0, 0, 4096}, + {61, 86, 30, 0, 0, 0, 4096}, + {68, 31, 9, 0, 0, 0, 1280}, + {68, 31, 9, 0, 0, 0, 1536}, + {69, 36, 10, 0, 0, 0, 4096}, + {67, 85, 30, 0, 0, 0, 1280}, + {67, 85, 30, 0, 0, 0, 1536}, + {61, 92, 36, 0, 0, 0, 4096}, + {61, 91, 30, 0, 0, 0, 4096}, + {67, 82, 52, 0, 0, 0, 1024}, + {67, 83, 52, 0, 0, 0, 1024}, + {70, 76, 52, 0, 0, 0, 1024}, + {70, 76, 30, 0, 0, 0, 1536}, + {61, 73, 30, 0, 0, 0, 4096}, + {34, 83, 52, 0, 0, 0, 1024}, + {71, 83, 52, 0, 0, 0, 1280}, + {71, 87, 30, 0, 0, 0, 1536}, + {66, 87, 30, 0, 0, 0, 4096}, + {32, 0, 0, 0, 0, 0, 1024}, + {72, 0, 0, 0, 0, 0, 4096}, + {73, 10, 76, 0, 0, 0, 3584}, + {74, 48, 31, 0, 0, 0, 2816}, + {75, 31, 30, 0, 0, 0, 2816}, + {73, 76, 10, 0, 0, 0, 3584}, + {67, 31, 30, 0, 0, 0, 2816}, + {76, 31, 30, 0, 0, 0, 2816}, + {32, 86, 30, 0, 0, 0, 3584}, + {32, 30, 86, 0, 0, 0, 3584}, + {67, 87, 30, 0, 0, 0, 1792}, + {70, 52, 76, 0, 0, 0, 1024}, + {70, 30, 76, 0, 0, 0, 1536}, + {61, 30, 73, 0, 0, 0, 4096}, + {34, 52, 83, 0, 0, 0, 1024}, + {77, 0, 54, 0, 0, 0, 256}, + {78, 0, 62, 0, 0, 0, 256}, + {79, 0, 62, 0, 0, 0, 256}, + {80, 72, 8, 64, 0, 0, 2560}, + {81, 1, 72, 1, 0, 244, 256}, + {48, 1, 72, 1, 0, 244, 256}, + {67, 72, 8, 64, 0, 245, 256}, + {82, 72, 8, 0, 0, 0, 3584}, + {83, 72, 8, 65, 0, 180, 256}, + {84, 87, 30, 0, 0, 0, 1280}, + {84, 87, 30, 0, 0, 0, 1536}, + {84, 85, 30, 0, 0, 0, 1280}, + {84, 86, 30, 0, 0, 0, 1536}, + {85, 40, 36, 0, 0, 0, 4096}, + {85, 34, 30, 0, 0, 0, 4096}, + {71, 79, 52, 0, 0, 0, 1280}, + {71, 79, 30, 0, 0, 0, 1536}, + {86, 34, 30, 0, 0, 0, 4096}, + {87, 53, 9, 0, 0, 0, 1280}, + {71, 31, 9, 0, 0, 0, 1536}, + {88, 30, 10, 0, 0, 0, 4096}, + {71, 87, 30, 0, 0, 0, 1280}, + {86, 40, 36, 0, 0, 0, 4096}, + {89, 0, 58, 64, 0, 0, 256}, + {55, 0, 57, 0, 0, 0, 3584}, + {68, 53, 30, 0, 0, 0, 1536}, + {68, 31, 52, 0, 0, 0, 1536}, + {61, 30, 86, 0, 0, 0, 4096}, + {76, 53, 9, 0, 0, 0, 1280}, + {76, 31, 9, 0, 0, 0, 1536}, + {69, 30, 10, 0, 0, 0, 4096}, + {67, 83, 52, 0, 0, 0, 1280}, + {34, 52, 57, 0, 0, 0, 1280}, + {67, 54, 30, 0, 0, 0, 1792}, + {61, 67, 36, 0, 0, 0, 4096}, + {67, 83, 52, 0, 0, 0, 1536}, + {76, 53, 52, 0, 0, 0, 1280}, + {76, 31, 30, 0, 0, 0, 1536}, + {90, 31, 30, 0, 0, 0, 4096}, + {50, 0, 54, 0, 0, 0, 512}, + {91, 0, 54, 0, 0, 0, 512}, + {91, 0, 63, 0, 0, 0, 512}, + {92, 0, 0, 0, 0, 0, 512}, + {93, 0, 12, 0, 0, 0, 512}, + {94, 0, 12, 0, 0, 0, 512}, + {67, 83, 52, 0, 0, 0, 2048}, + {67, 87, 30, 0, 0, 0, 2048}, + {71, 87, 30, 0, 0, 0, 2304}, + {67, 87, 30, 0, 0, 0, 2560}, + {61, 55, 36, 0, 0, 0, 4096}, + {61, 57, 38, 0, 0, 0, 4096}, + {61, 59, 38, 0, 0, 0, 4096}, + {61, 87, 30, 0, 0, 0, 4096}, + {67, 86, 30, 0, 0, 0, 2304}, + {67, 85, 30, 0, 0, 0, 2304}, + {67, 84, 30, 0, 0, 0, 2304}, + {61, 84, 30, 0, 0, 0, 4096}, + {67, 87, 30, 0, 0, 0, 2304}, + {34, 59, 30, 0, 0, 0, 2304}, + {61, 59, 30, 0, 0, 0, 4096}, + {66, 40, 67, 0, 0, 0, 4096}, + {73, 59, 10, 0, 0, 0, 3584}, + {66, 40, 36, 0, 0, 0, 4352}, + {66, 34, 30, 0, 0, 0, 4352}, + {67, 87, 30, 0, 0, 0, 4864}, + {61, 87, 30, 0, 0, 0, 4864}, + {66, 34, 30, 0, 0, 0, 4864}, + {34, 72, 8, 0, 0, 0, 256}, + {34, 68, 10, 0, 0, 0, 2560}, + {34, 8, 72, 0, 0, 0, 256}, + {34, 72, 10, 0, 0, 0, 2560}, + {66, 91, 36, 0, 0, 0, 4096}, + {86, 39, 38, 0, 0, 0, 4096}, + {71, 85, 30, 0, 0, 0, 2304}, + {71, 86, 30, 0, 0, 0, 2304}, + {71, 83, 52, 0, 0, 0, 2048}, + {71, 87, 30, 0, 0, 0, 2048}, + {71, 30, 74, 0, 0, 0, 2304}, + {88, 30, 80, 0, 0, 0, 4096}, + {71, 30, 75, 0, 0, 0, 2304}, + {88, 30, 81, 0, 0, 0, 4096}, + {95, 30, 76, 0, 0, 0, 2304}, + {66, 30, 73, 0, 0, 0, 4096}, + {71, 30, 76, 0, 0, 0, 2304}, + {66, 30, 70, 0, 0, 0, 4096}, + {66, 38, 87, 0, 0, 0, 4096}, + {71, 78, 30, 0, 0, 0, 2304}, + {95, 76, 30, 0, 0, 0, 2304}, + {71, 87, 30, 0, 0, 0, 4608}, + {86, 34, 30, 0, 0, 0, 4608}, + {71, 87, 30, 0, 0, 0, 2560}, + {71, 87, 30, 0, 0, 0, 4864}, + {66, 87, 30, 0, 0, 0, 4864}, + {96, 1, 53, 0, 0, 0, 1024}, + {55, 1, 31, 0, 0, 0, 1536}, + {97, 31, 34, 0, 0, 0, 4096}, + {98, 0, 10, 0, 0, 0, 3584}, + {55, 0, 55, 0, 0, 0, 256}, + {63, 0, 55, 0, 0, 0, 4096}, + {55, 0, 54, 0, 0, 0, 3584}, + {99, 70, 10, 0, 0, 0, 256}, + {98, 0, 72, 0, 0, 0, 256}, + {100, 83, 52, 0, 0, 0, 3072} +}; + +uint16_t CmpMnemonicOffsets[8] = +{ + 0, 9, 18, 27, 39, 49, 59, 69 +}; +uint16_t VCmpMnemonicOffsets[32] = +{ + 0, 10, 20, 30, 43, 54, 65, 76, 87, 100, 111, 122, 135, 149, 159, 169, 181, 194, 207, 220, 235, 249, 263, 277, 290, 303, 317, 331, 347, 361, 374, 387 +};/* +instructions.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + + + + +/* Helper macros to extract the type or index from an inst-node value. */ +#define INST_NODE_INDEX(n) ((n) & 0x1fff) +#define INST_NODE_TYPE(n) ((n) >> 13) + +/* Helper macro to read the actual flags that are associated with an inst-info. */ +#define INST_INFO_FLAGS(ii) (FlagsTable[InstSharedInfoTable[(ii)->sharedIndex].flagsIndex]) + +/* +I use the trie data structure as I found it most fitting to a disassembler mechanism. +When you read a byte and have to decide if it's enough or you should read more bytes, 'till you get to the instruction information. +It's really fast because you POP the instruction info in top 3 iterates on the DB, because an instruction can be formed from two bytes + 3 bits reg from the ModR/M byte. +For a simple explanation, check this out: +http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Tree/Trie/ +Further reading: http://en.wikipedia.org/wiki/Trie + +The first GATE (array you read off a trie data structure), as I call them, is statically allocated by the compiler. +The second and third gates if used are being allocated dynamically by the instructions-insertion functionality. + +How would such a thing look in memory, say we support 4 instructions with 3 bytes top (means 2 dynamically allocated gates). + +-> +|-------| 0, +|0| -------------------------------> |-------| +|1|RET | 1, |0|AND | +|2| -----> |-------| |1|XOR | +|3|INT3 | |0|PUSH | |2|OR | 0,3, +|-------| |1|POP | |3| --------->|-------| + |2|PUSHF| |-------| |0|ROR | + |3|POPF | |1|ROL | + |-------| |2|SHR | + |3|SHL | + |-------| + +Of course, this is NOT how Intel instructions set looks!!! +but I just wanted to give a small demonstration. +Now the instructions you get from such a trie DB goes like this: + +0, 0 - AND +0, 1 - XOR +0, 2 - OR +0, 3, 0, ROR +0, 3, 1, ROL +0, 3, 2, SHR +0, 3, 3, SHL +1 - RET +2, 0 - PUSH +2, 1 - POP +2, 2 - PUSHF +2, 3 - POPF +3 - INT3 + +I guess it's clear by now. +So now, if you read 0, you know that you have to enter the second gate(list) with the second byte specifying the index. +But if you read 1, you know that you go to an instruction (in this case, a RET). +That's why there's an Instruction-Node structure, it tells you whether you got to an instruction or another list +so you should keep on reading byte). + +In Intel, you could go through 4 gates at top, because there are instructions which are built from 2 bytes and another smaller list +for the REG part, or newest SSE4 instructions which use 4 bytes for opcode. +Therefore, Intel's first gate is 256 long, and other gates are 256 (/72) or 8 long, yes, it costs pretty much a lot of memory +for non-used defined instructions, but I think that it still rocks. +*/ + +/* + * A helper function to look up the correct inst-info structure. + * It does one fetch from the index-table, and then another to get the inst-info. + * Note that it takes care about basic inst-info or inst-info-ex. + * The caller should worry about boundary checks and whether it accesses a last-level table. + */ +static _InstInfo* inst_get_info(_InstNode in, int index) +{ + int instIndex = 0; + + in = InstructionsTree[INST_NODE_INDEX(in) + index]; + if(in == INT_NOTEXISTS) return NULL; + + instIndex = INST_NODE_INDEX(in); + return INST_NODE_TYPE(in) == INT_INFO ? &InstInfos[instIndex] : (_InstInfo*)&InstInfosEx[instIndex]; +} + +/* + * This function is responsible to return the instruction information of the first found in code. + * It returns the _InstInfo of the found instruction, otherwise NULL. + * code should point to the ModR/M byte upon exit (if used), or after the instruction binary code itself. + * This function is NOT decoding-type dependant, it is up to the caller to see whether the instruction is valid. + * Get the instruction info, using a Trie data structure. + * + * Sometimes normal prefixes become mandatory prefixes, which means they are now part of the instruction opcode bytes. + + * This is a bit tricky now, + * if the first byte is a REP (F3) prefix, we will have to give a chance to an SSE instruction. + * If an instruction doesn't exist, we will make it as a prefix and re-locateinst. + * A case such that a REP prefix is being changed into an instruction byte and also an SSE instruction will not be found can't happen, + * simply because there are no collisions between string instruction and SSE instructions (they are escaped). + + * As for S/SSE2/3, check for F2 and 66 as well. + + * In 64 bits, we have to make sure that we will skip the REX prefix, if it exists. + * There's a specific case, where a 66 is mandatory but it was dropped because REG.W was used, + * but it doesn't behave as an operand size prefix but as a mandatory, so we will have to take it into account. + + * For example (64 bits decoding mode): + * 66 98 CBW + * 48 98 CDQE + * 66 48 98: db 0x66; CDQE + * Shows that operand size is dropped. + + * Now, it's a mandatory prefix and NOT an operand size one. + * 66480f2dc0 db 0x48; CVTPD2PI XMM0, XMM0 + * Although this instruction doesn't require a REX.W, it just shows, that even if it did - it doesn't matter. + * REX.W is dropped because it's not required, but the decode function disabled the operand size even so. + */ +static _InstInfo* inst_lookup_prefixed(_InstNode in, _PrefixState* ps) +{ + int checkOpSize = FALSE; + int index = 0; + _InstInfo* ii = NULL; + + /* Check prefixes of current decoded instruction (None, 0x66, 0xf3, 0xf2). */ + switch(ps->decodedPrefixes & (INST_PRE_OP_SIZE | INST_PRE_REPS)) + { + case 0: + /* Non-prefixed, index = 0. */ + index = 0; + break; + case INST_PRE_OP_SIZE: + /* 0x66, index = 1. */ + index = 1; + /* Mark that we used it as a mandatory prefix. */ + ps->isOpSizeMandatory = TRUE; + ps->decodedPrefixes &= ~INST_PRE_OP_SIZE; + break; + case INST_PRE_REP: + /* 0xf3, index = 2. */ + index = 2; + ps->decodedPrefixes &= ~INST_PRE_REP; + break; + case INST_PRE_REPNZ: + /* 0xf2, index = 3. */ + index = 3; + ps->decodedPrefixes &= ~INST_PRE_REPNZ; + break; + default: + /* + * Now we got a problem, since there are a few mandatory prefixes at once. + * There is only one case when it's ok, when the operand size prefix is for real (not mandatory). + * Otherwise we will have to return NULL, since the instruction is illegal. + * Therefore we will start with REPNZ and REP prefixes, + * try to get the instruction and only then check for the operand size prefix. + */ + + /* If both REPNZ and REP are together, it's illegal for sure. */ + if((ps->decodedPrefixes & INST_PRE_REPS) == INST_PRE_REPS) return NULL; + + /* Now we know it's either REPNZ+OPSIZE or REP+OPSIZE, so examine the instruction. */ + if(ps->decodedPrefixes & INST_PRE_REPNZ) + { + index = 3; + ps->decodedPrefixes &= ~INST_PRE_REPNZ; + } + else if(ps->decodedPrefixes & INST_PRE_REP) + { + index = 2; + ps->decodedPrefixes &= ~INST_PRE_REP; + } + /* Mark to verify the operand-size prefix of the fetched instruction below. */ + checkOpSize = TRUE; + break; + } + + /* Fetch the inst-info from the index. */ + ii = inst_get_info(in, index); + + if(checkOpSize) + { + /* If the instruction doesn't support operand size prefix, then it's illegal. */ + if((ii == NULL) || (~INST_INFO_FLAGS(ii) & INST_PRE_OP_SIZE)) return NULL; + } + + /* If there was a prefix, but the instruction wasn't found. Try to fall back to use the normal instruction. */ + if(ii == NULL) ii = inst_get_info(in, 0); + return ii; +} + +/* A helper function to look up special VEX instructions. + * See if it's a MOD based instruction and fix index if required. + * Only after a first lookup (that was done by caller), we can tell if we need to fix the index. + * Because these are coupled instructions + * (which means that the base instruction hints about the other instruction). + * Note that caller should check if it's a MOD dependent instruction before getting in here. + */ +static _InstInfo* inst_vex_mod_lookup(_CodeInfo* ci, _InstNode in, _InstInfo* ii, unsigned int index) +{ + /* Advance to read the MOD from ModRM byte. */ + ci->code += 1; + ci->codeLen -= 1; + if(ci->codeLen < 0) return NULL; + if(*ci->code < INST_DIVIDED_MODRM) + { + /* MOD is not 11, therefore change the index to 8 - 12 range in the prefixed table. */ + index += 4; + /* Make a second lookup for this special instruction. */ + return inst_get_info(in, index); + } + /* Return the original one, in case we didn't find a suited instruction. */ + return ii; +} + +static _InstInfo* inst_vex_lookup(_CodeInfo* ci, _PrefixState* ps) +{ + _InstNode in = 0; + unsigned int pp = 0, start = 0; + unsigned int index = 4; /* VEX instructions start at index 4 in the Prefixed table. */ + uint8_t vex = *ps->vexPos, vex2 = 0, v = 0; + int instType = 0, instIndex = 0; + + /* The VEX instruction will #ud if any of 66, f0, f2, f3, REX prefixes precede. */ + _iflags illegal = (INST_PRE_OP_SIZE | INST_PRE_LOCK | INST_PRE_REP | INST_PRE_REPNZ | INST_PRE_REX); + if((ps->decodedPrefixes & illegal) != 0) return NULL; + + /* Read the some fields from the VEX prefix we need to extract the instruction. */ + if(ps->prefixExtType == PET_VEX2BYTES) + { + ps->vexV = v = (~vex >> 3) & 0xf; + pp = vex & 3; + /* Implied leading 0x0f byte by default for 2 bytes VEX prefix. */ + start = 1; + } + else /* PET_VEX3BYTES */ + { + start = vex & 0x1f; + vex2 = *(ps->vexPos + 1); + ps->vexV = v = (~vex2 >> 3) & 0xf; + pp = vex2 & 3; + } + + /* start can be either 1 (0x0f), 2 (0x0f, 0x038) or 3 (0x0f, 0x3a), otherwise it's illegal. */ + switch(start) + { + case 1: + in = Table_0F; + break; + case 2: + in = Table_0F_38; + break; + case 3: + in = Table_0F_3A; + break; + default: + return NULL; + } + + /* pp is actually the implied mandatory prefix, apply it to the index. */ + index += pp; /* (None, 0x66, 0xf3, 0xf2) */ + + /* Read a byte from the stream. */ + ci->codeLen -= 1; + if(ci->codeLen < 0) return NULL; + + in = InstructionsTree[INST_NODE_INDEX(in) + *ci->code]; + if(in == INT_NOTEXISTS) return NULL; + + instType = INST_NODE_TYPE(in); + instIndex = INST_NODE_INDEX(in); + + /* + * If we started with 0f38 or 0f3a so it's a prefixed table, + * therefore it's surely a VEXed instruction (because of a high index). + * However, starting with 0f, could also lead immediately to a prefixed table for some bytes. + * it might return NULL, if the index is invalid. + */ + if(instType == INT_LIST_PREFIXED) + { + _InstInfo* ii = inst_get_info(in, index); + /* See if the instruction is dependent on MOD. */ + if((ii != NULL) && (((_InstInfoEx*)ii)->flagsEx & INST_MODRR_BASED)) + { + ii = inst_vex_mod_lookup(ci, in, ii, index); + } + return ii; + } + + /* + * If we reached here, obviously we started with 0f. VEXed instructions must be nodes of a prefixed table. + * But since we found an instruction (or divided one), just return NULL. + * They cannot lead to a VEXed instruction. + */ + if((instType == INT_INFO) || (instType == INT_INFOEX) || (instType == INT_LIST_DIVIDED)) return NULL; + + /* Now we are left with handling either GROUP or FULL tables, therefore we will read another byte from the stream. */ + ci->code += 1; + ci->codeLen -= 1; + if(ci->codeLen < 0) return NULL; + + if(instType == INT_LIST_GROUP) + { + in = InstructionsTree[instIndex + ((*ci->code >> 3) & 7)]; + /* Continue below to check prefixed table. */ + } + else if(instType == INT_LIST_FULL) + { + in = InstructionsTree[instIndex + *ci->code]; + /* Continue below to check prefixed table. */ + } + + /* Now that we got to the last table in the trie, check for a prefixed table. */ + if(INST_NODE_TYPE(in) == INT_LIST_PREFIXED) + { + _InstInfo* ii = inst_get_info(in, index); + /* See if the instruction is dependent on MOD. */ + if((ii != NULL) && (((_InstInfoEx*)ii)->flagsEx & INST_MODRR_BASED)) + { + ii = inst_vex_mod_lookup(ci, in, ii, index); + } + return ii; + } + + /* No VEXed instruction was found. */ + return NULL; +} + +_InstInfo* inst_lookup(_CodeInfo* ci, _PrefixState* ps, int* isPrefixed) +{ + unsigned int tmpIndex0, tmpIndex1, tmpIndex2; + int instType; + _InstNode in; + _InstInfo* ii = NULL; + int isWaitIncluded = FALSE; + + /* Always safe to read first byte codeLen > 0. */ + tmpIndex0 = *ci->code; + + if(prefixes_is_valid((unsigned char)tmpIndex0, ci->dt)) + { + *isPrefixed = TRUE; + prefixes_decode(ci, ps); + if(ci->codeLen < 1) return NULL; /* No more bytes for opcode, halt. */ + tmpIndex0 = *ci->code; /* Reload. */ + + /* If there are too many prefixes, it will be checked later in decode_inst. */ + + /* See whether we have to handle a VEX prefixed instruction. */ + if(ps->decodedPrefixes & INST_PRE_VEX) + { + ii = inst_vex_lookup(ci, ps); + if(ii != NULL) + { + /* Make sure that VEX.L exists when forced. */ + if((((_InstInfoEx*)ii)->flagsEx & INST_FORCE_VEXL) && (~ps->vrex & PREFIX_EX_L)) return NULL; + /* If the instruction doesn't use VEX.vvvv it must be zero. */ + if((((_InstInfoEx*)ii)->flagsEx & INST_VEX_V_UNUSED) && ps->vexV) return NULL; + } + return ii; + } + } + + /* Account first byte, we know it's safe to read. */ + ci->codeLen -= 1; + + /* Check for special 0x9b, WAIT instruction, which can be part of some instructions(x87). */ + if(tmpIndex0 == INST_WAIT_INDEX) + { + /* Only OCST_1dBYTES get a chance to include this byte as part of the opcode. */ + isWaitIncluded = TRUE; + + /* Ignore all prefixes, since they are useless and operate on the WAIT instruction itself. */ + prefixes_ignore_all(ps); + + /* Move to next code byte as a new whole instruction. */ + ci->code += 1; + ci->codeLen -= 1; + if(ci->codeLen < 0) return NULL; /* Faster to return NULL, it will be detected as WAIT later anyway. */ + /* Since we got a WAIT prefix, we re-read the first byte. */ + tmpIndex0 = *ci->code; + } + + /* Walk first byte in InstructionsTree root. */ + in = InstructionsTree[tmpIndex0]; + if((uint32_t)in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + /* Single byte instruction (OCST_1BYTE). */ + if((instType < INT_INFOS) && (!isWaitIncluded)) + { + /* Some single byte instructions need extra treatment. */ + if(instType == INT_INFO_TREAT) + { + if(tmpIndex0 == INST_NOP_INDEX) /* Nopnopnop */ + { + /* Check for Pause, since it's prefixed with 0xf3, which is not a real mandatory prefix. */ + if(ps->decodedPrefixes & INST_PRE_REP) + { + /* Flag this prefix as used. */ + ps->usedPrefixes |= INST_PRE_REP; + return &II_PAUSE; + } + + /* + * Treat NOP/XCHG specially. + * If we're not in 64bits restore XCHG to NOP, since in the DB it's XCHG. + * Else if we're in 64bits examine REX, if exists, and decide which instruction should go to output. + * 48 90 XCHG RAX, RAX is a true NOP (eat REX in this case because it's valid). + * 90 XCHG EAX, EAX is a true NOP (and not high dword of RAX = 0 although it should be a 32 bits operation). + * Note that if the REX.B is used, then the register is not RAX anymore but R8, which means it's not a NOP. + */ + if(ps->vrex & PREFIX_EX_W) ps->usedPrefixes |= INST_PRE_REX; + if((ci->dt != Decode64Bits) || (~ps->vrex & PREFIX_EX_B)) return &II_NOP; + } + else if(tmpIndex0 == INST_LEA_INDEX) + { + /* Ignore segment override prefixes for LEA instruction. */ + ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK; + /* Update unused mask for ignoring segment prefix. */ + prefixes_ignore(ps, PFXIDX_SEG); + } + else if(tmpIndex0 == INST_ARPL_INDEX) + { + /* + * ARPL/MOVSXD share the same opcode, and both have different operands and mnemonics, of course. + * Practically, I couldn't come up with a comfortable way to merge the operands' types of ARPL/MOVSXD. + * And since the DB can't be patched dynamically, because the DB has to be multi-threaded compliant, + * I have no choice but to check for ARPL/MOVSXD right here - "right about now, the funk soul brother, check it out now, the funk soul brother...", fatboy slim + */ + if(ci->dt == Decode64Bits) + { + return &II_MOVSXD; + } /* else ARPL will be returned because its defined in the DB already. */ + } + } + /* + * Return the 1 byte instruction we found. + * We can have three node types here: infoex, info_treat and info. + * The latter two are really the same basic structure. + */ + return instType == INT_INFOEX ? (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)] : &InstInfos[INST_NODE_INDEX(in)]; + } + + /* Read second byte, still doesn't mean all of its bits are used (I.E: ModRM). */ + ci->code += 1; + ci->codeLen -= 1; + if(ci->codeLen < 0) return NULL; + tmpIndex1 = *ci->code; + + /* Try single byte instruction + reg bits (OCST_13BYTES). */ + if((instType == INT_LIST_GROUP) && (!isWaitIncluded)) return inst_get_info(in, (tmpIndex1 >> 3) & 7); + + /* Try single byte instruction + reg byte OR one whole byte (OCST_1dBYTES). */ + if(instType == INT_LIST_DIVIDED) + { + + /* Checking for inst by REG bits is higher priority if it's found not to be divided instruction. */ + { + _InstNode in2 = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex1 >> 3) & 7)]; + /* + * Do NOT check for NULL here, since we do a bit of a guess work, + * hence we don't override 'in', cause we might still need it. + */ + instType = INST_NODE_TYPE(in2); + + if(instType == INT_INFO) ii = &InstInfos[INST_NODE_INDEX(in2)]; + else if(instType == INT_INFOEX) ii = (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in2)]; + if((ii != NULL) && (INST_INFO_FLAGS(ii) & INST_NOT_DIVIDED)) return ii; + /* ii is reset below. */ + } + + /* Continue normally because of wait prefix. */ + if(tmpIndex1 < INST_DIVIDED_MODRM) + { + /* An instruction which requires a ModR/M byte. Thus it's 1.3 bytes long instruction. */ + tmpIndex1 = (tmpIndex1 >> 3) & 7; /* Isolate the 3 REG/OPCODE bits. */ + } + else /* Normal 2 bytes instruction. */ + { + /* + * Divided instructions can't be in the range of 0x8-0xc0. + * That's because 0-8 are used for 3 bits group. + * And 0xc0-0xff are used for not-divided instruction. + * So the in between range is omitted, thus saving some more place in the tables. + */ + tmpIndex1 -= INST_DIVIDED_MODRM - 8; + } + + in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex1]; + if(in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + if(instType < INT_INFOS) + { + /* If the instruction doesn't support the wait (marked as opsize) as part of the opcode, it's illegal. */ + ii = instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + if((~INST_INFO_FLAGS(ii) & INST_PRE_OP_SIZE) && (isWaitIncluded)) return NULL; + return ii; + } + /* + * If we got here the instruction can support the wait prefix, so see if it was part of the stream. + * Examine prefixed table, specially used for 0x9b, since it's optional. + * No Wait: index = 0. + * Wait Exists, index = 1. + */ + return inst_get_info(in, isWaitIncluded); + } + + /* Don't allow to continue if WAIT is part of the opcode, because there are no instructions that include it. */ + if(isWaitIncluded) return NULL; + + /* Try 2 bytes long instruction (doesn't include ModRM byte). */ + if(instType == INT_LIST_FULL) + { + in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex1]; + if(in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + /* This is where we check if we just read two escape bytes in a row, which means it is a 3DNow! instruction. */ + if((tmpIndex0 == _3DNOW_ESCAPE_BYTE) && (tmpIndex1 == _3DNOW_ESCAPE_BYTE)) return &II_3DNOW; + + /* 2 bytes instruction (OCST_2BYTES). */ + if(instType < INT_INFOS) + return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + + /* + * 2 bytes + mandatory prefix. + * Mandatory prefixes can be anywhere in the prefixes. + * There cannot be more than one mandatory prefix, unless it's a normal operand size prefix. + */ + if(instType == INT_LIST_PREFIXED) return inst_lookup_prefixed(in, ps); + } + + /* Read third byte, still doesn't mean all of its bits are used (I.E: ModRM). */ + ci->code += 1; + ci->codeLen -= 1; + if(ci->codeLen < 0) return NULL; + tmpIndex2 = *ci->code; + + /* Try 2 bytes + reg instruction (OCST_23BYTES). */ + if(instType == INT_LIST_GROUP) + { + in = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex2 >> 3) & 7)]; + if(in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + if(instType < INT_INFOS) + return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + + /* It has to be a prefixed table then. */ + ii = inst_lookup_prefixed(in, ps); + /* RDRAND and VMPTRLD share same 2.3 bytes opcode, and alternate on the MOD bits. See insts.h for more info. */ + if((ii != NULL) && (ii->opcodeId == I_VMPTRLD) && (tmpIndex1 >= INST_DIVIDED_MODRM)) return &II_RDRAND; + return ii; + } + + /* Try 2 bytes + divided range (OCST_2dBYTES). */ + if(instType == INT_LIST_DIVIDED) + { + _InstNode in2 = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex2 >> 3) & 7)]; + /* + * Do NOT check for NULL here, since we do a bit of a guess work, + * hence we don't override 'in', cause we might still need it. + */ + instType = INST_NODE_TYPE(in2); + + if(instType == INT_INFO) ii = &InstInfos[INST_NODE_INDEX(in2)]; + else if(instType == INT_INFOEX) ii = (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in2)]; + + /* + * OCST_2dBYTES is complex, because there are a few instructions which are not divided in some special cases. + * If the instruction wasn't divided (but still it must be a 2.3 because we are in divided category) + * or it was an official 2.3 (because its index was less than 0xc0) - + * Then it means the instruction should be using the REG bits, otherwise give a chance to range 0xc0-0xff. + */ + /* If we found an instruction only by its REG bits, AND it is not divided, then return it. */ + if((ii != NULL) && (INST_INFO_FLAGS(ii) & INST_NOT_DIVIDED)) return ii; + /* Otherwise, if the range is above 0xc0, try the special divided range (range 0x8-0xc0 is omitted). */ + if(tmpIndex2 >= INST_DIVIDED_MODRM) return inst_get_info(in, tmpIndex2 - INST_DIVIDED_MODRM + 8); + + /* It might be that we got here without touching ii in the above if statements, then it becomes an invalid instruction prolly. */ + return ii; + } + + /* Try 3 full bytes (OCST_3BYTES - no ModRM byte). */ + if(instType == INT_LIST_FULL) + { + /* OCST_3BYTES. */ + in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex2]; + if(in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + if(instType < INT_INFOS) + return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + + if(instType == INT_LIST_PREFIXED) return inst_lookup_prefixed(in, ps); + } + + /* Kahtchinggg, damn. */ + return NULL; +} + +/* +* 3DNow! instruction handling: + +* This is used when we encounter a 3DNow! instruction. +* We can't really locate a 3DNow! instruction before we see two escaped bytes, +* 0x0f, 0x0f. Then we have to extract operands which are, dest=mmx register, src=mmx register or quadword indirection. +* When we are finished with the extraction of operands we can resume to locate the instruction by reading another byte +* which tells us which 3DNow instruction we really tracked down... +* So in order to tell the extract operands function which operands the 3DNow! instruction require, we need to set up some +* generic instruction info for 3DNow! instructions. + +* In the inst_lookup itself, when we read an OCST_3BYTES which the two first bytes are 0x0f and 0x0f. +* we will return this special generic II for the specific operands we are interested in (MM, MM64). +* Then after extracting the operand, we'll call a completion routine for locating the instruction +* which will be called only for 3DNow! instructions, distinguished by a flag, and it will read the last byte of the 3 bytes. +* +* The id of this opcode should not be used, the following function should change it anyway. +*/ +_InstInfo* inst_lookup_3dnow(_CodeInfo* ci) +{ + /* Start off from the two escape bytes gates... which is 3DNow! table.*/ + _InstNode in = Table_0F_0F; + + int index; + + /* Make sure we can read a byte off the stream. */ + if(ci->codeLen < 1) return NULL; + + index = *ci->code; + + ci->codeLen -= 1; + ci->code += 1; + return inst_get_info(in, index); +} +/* +distorm.c + +diStorm3 C Library Interface +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + + +/* C DLL EXPORTS */ +#ifdef SUPPORT_64BIT_OFFSET +_DLLEXPORT_ _DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#else +_DLLEXPORT_ _DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#endif +{ + if(usedInstructionsCount == NULL) + { + return DECRES_SUCCESS; + } + + if((ci == NULL) || + (ci->codeLen < 0) || + ((unsigned)ci->dt > (unsigned)Decode64Bits) || + (ci->code == NULL) || + (result == NULL) || + (maxInstructions == 0) || + ((ci->features & (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32)) == (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32))) + { + return DECRES_INPUTERR; + } + + return decode_internal(ci, FALSE, result, maxInstructions, usedInstructionsCount); +} + +#ifndef DISTORM_LIGHT + +/* Helper function to concatenate an explicit size when it's unknown from the operands. */ +static void distorm_format_size(unsigned char** str, const _DInst* di, int opNum) +{ + int isSizingRequired = 0; + /* + * We only have to output the size explicitly if it's not clear from the operands. + * For example: + * mov al, [0x1234] -> The size is 8, we know it from the AL register operand. + * mov [0x1234], 0x11 -> Now we don't know the size. Pam pam pam + * + * If given operand number is higher than 2, then output the size anyways. + */ + isSizingRequired = ((opNum >= 2) || ((opNum == 0) && (di->ops[0].type != O_REG) && (di->ops[1].type != O_REG))); + + /* Still not sure? Try some special instructions. */ + if(!isSizingRequired) + { + /* + * INS/OUTS are exception, because DX is a port specifier and not a real src/dst register. + * A few exceptions that always requires sizing: + * MOVZX, MOVSX, MOVSXD. + * ROL, ROR, RCL, RCR, SHL, SHR, SAL, SAR. + * SHLD, SHRD. + * CVTSI2SS is also an exception. + */ + switch(di->opcode) + { + case I_INS: + case I_OUTS: + case I_MOVZX: + case I_MOVSX: + case I_MOVSXD: + case I_ROL: + case I_ROR: + case I_RCL: + case I_RCR: + case I_SHL: + case I_SHR: + case I_SAL: + case I_SAR: + case I_SHLD: + case I_SHRD: + case I_CVTSI2SS: + isSizingRequired = 1; + break; + default: /* Instruction doesn't require sizing. */ + break; + } + } + + if(isSizingRequired) + { + /*case 0: break; OT_MEM's unknown size. */ + switch(di->ops[opNum].size / 8) + { + case 1: + strcat_WS(*str, "BYTE ", 8, 5); + break; + case 2: + strcat_WS(*str, "WORD ", 8, 5); + break; + case 4: + strcat_WS(*str, "DWORD ", 8, 6); + break; + case 8: + strcat_WS(*str, "QWORD ", 8, 6); + break; + case 10: + strcat_WS(*str, "TBYTE ", 8, 6); + break; + case 16: + strcat_WS(*str, "DQWORD ", 8, 7); + break; + case 32: + strcat_WS(*str, "YWORD ", 8, 6); + break; + } + } +} + +static void distorm_format_signed_disp(unsigned char** str, const _DInst* di, uint64_t addrMask) +{ + int64_t tmpDisp64; + + if(di->dispSize) + { + if(((int64_t)di->disp < 0)) + { + chrcat_WS(*str, MINUS_DISP_CHR); + tmpDisp64 = -(int64_t)di->disp; + tmpDisp64 &= addrMask; /* Verify only for neg numbers. */ + } + else + { + chrcat_WS(*str, PLUS_DISP_CHR); + tmpDisp64 = di->disp; + } + str_int(str, tmpDisp64); + } +} + +static uint8_t prefixTable[6][8] = { "", "LOCK ", "REPNZ ", "REPNZ ", "REP ", "REPZ " }; +static unsigned int prefixSizesTable[6] = { 0, 5, 6, 6, 4, 5 }; +static uint8_t suffixTable[10] = { 0, 'B', 'W', 0, 'D', 0, 0, 0, 'Q' }; + +/* WARNING: This function is written carefully to be able to work with same input and output buffer in-place! */ +#ifdef SUPPORT_64BIT_OFFSET +_DLLEXPORT_ void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result) +#else +_DLLEXPORT_ void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result) +#endif +{ + unsigned char* str; + int64_t tmpDisp64; + uint64_t addrMask = (uint64_t) - 1; + const _WMnemonic* mnemonic; + int suffixSize = -1; + unsigned int i; + + /* Set address mask, when default is for 64bits addresses. */ + if(ci->features & DF_USE_ADDR_MASK) addrMask = ci->addrMask; + else + { + if(ci->features & DF_MAXIMUM_ADDR32) addrMask = 0xffffffff; + else if(ci->features & DF_MAXIMUM_ADDR16) addrMask = 0xffff; + } + + /* Gotta have full address for (di->addr - ci->codeOffset) to work in all modes. */ + str_hex(&result->instructionHex, (const uint8_t*)&ci->code[(unsigned int)(di->addr - ci->codeOffset)], di->size); + + if((int)((int16_t)di->flags) == -1) + { + /* In-place considerations: DI is RESULT. Deref fields first. */ + unsigned int size = di->size; + unsigned int byte = di->imm.byte; + _OffsetType offset = di->addr & addrMask; + + result->offset = offset; + result->size = size; + str = (unsigned char*)&result->mnemonic.p; + strcat_WS(str, "DB ", 4, 3); + str_int(&str, byte); + strfinalize_WS(result->mnemonic, str); + *(uint64_t*)&result->operands = 0; /* Clears length and the string at once. */ + return; /* Skip to next instruction. */ + } + + str = (unsigned char*)&result->operands.p; + + /* Special treatment for String (movs, cmps, stos, lods, scas) instructions. */ + if((di->opcode >= I_MOVS) && (di->opcode <= I_SCAS)) + { + /* + * No operands are needed if the address size is the default one, + * and no segment is overridden, so add the suffix letter, + * to indicate size of operation and continue to next instruction. + */ + if((SEGMENT_IS_DEFAULT_OR_NONE(di->segment)) && (FLAG_GET_ADDRSIZE(di->flags) == ci->dt)) + { + suffixSize = di->ops[0].size / 8; + goto skipOperands; + } + suffixSize = 0; /* Marks it's a string instruction. */ + } + + for(i = 0; i < di->opsNo; i++) + { + unsigned int type = di->ops[i].type; + if(i > 0) strcat_WS(str, ", ", 2, 2); + if(type == O_REG) + { + strcat_WSR(&str, &_REGISTERS[di->ops[i].index]); + } + else if(type == O_IMM) + { + /* If the instruction is 'push', show explicit size (except byte imm). */ + if((di->opcode == I_PUSH) && (di->ops[i].size != 8)) distorm_format_size(&str, di, i); + /* Special fix for negative sign extended immediates. */ + if((di->flags & FLAG_IMM_SIGNED) && (di->ops[i].size == 8) && (di->imm.sbyte < 0)) + { + chrcat_WS(str, MINUS_DISP_CHR); + tmpDisp64 = -di->imm.sbyte; + str_int(&str, tmpDisp64); + } + else + { + /* Notice signedness and size of the immediate. */ + if(di->ops[i].size == 0x20) str_int(&str, di->imm.dword); + else str_int(&str, di->imm.qword); + } + } + else if(type == O_PC) + { +#ifdef SUPPORT_64BIT_OFFSET + str_int(&str, (di->size + di->imm.sqword + di->addr) & addrMask); +#else + tmpDisp64 = ((_OffsetType)di->imm.sdword + di->addr + di->size) & (uint32_t)addrMask; + str_int(&str, tmpDisp64); +#endif + } + else if(type == O_DISP) + { + distorm_format_size(&str, di, i); + chrcat_WS(str, OPEN_CHR); + if(!SEGMENT_IS_DEFAULT_OR_NONE(di->segment)) + { + strcat_WSR(&str, &_REGISTERS[SEGMENT_GET_UNSAFE(di->segment)]); + chrcat_WS(str, SEG_OFF_CHR); + } + tmpDisp64 = di->disp & addrMask; + str_int(&str, tmpDisp64); + chrcat_WS(str, CLOSE_CHR); + } + else if(type == O_SMEM) + { + int isDefault; + int segment; + distorm_format_size(&str, di, i); + chrcat_WS(str, OPEN_CHR); + + segment = SEGMENT_GET(di->segment); + isDefault = SEGMENT_IS_DEFAULT(di->segment); + + /* + * This is where we need to take special care for String instructions. + * If we got here, it means we need to explicitly show their operands. + * The problem with CMPS and MOVS is that they have two(!) memory operands. + * So we have to complement(!) them ourselves, since the isntruction structure supplies only the segment that can be overridden. + * And make the rest of the String operations explicit. + * We ignore default ES/DS in 64 bits. + * ["MOVS"], [OPT.REGI_EDI, OPT.REGI_ESI] -- DS can be overridden. + * ["CMPS"], [OPT.REGI_ESI, OPT.REGI_EDI] -- DS can be overriden. + * + * suffixSize == 0 was set above for string opcode already. + */ + if(suffixSize == 0) + { + if(((di->opcode == I_MOVS) && (i == 0)) || ((di->opcode == I_CMPS) && (i == 1))) + { + if(ci->dt != Decode64Bits) + { + segment = R_ES; + isDefault = FALSE; + } + else isDefault = TRUE; + } + else if(isDefault && ((di->opcode == I_MOVS) || (di->opcode == I_CMPS))) + { + if(ci->dt != Decode64Bits) + { + segment = R_DS; + isDefault = FALSE; + } + } + } + if(!isDefault && (segment != R_NONE)) + { + strcat_WSR(&str, &_REGISTERS[segment]); + chrcat_WS(str, SEG_OFF_CHR); + } + + strcat_WSR(&str, &_REGISTERS[di->ops[i].index]); + + distorm_format_signed_disp(&str, di, addrMask); + chrcat_WS(str, CLOSE_CHR); + } + else if(type == O_MEM) + { + distorm_format_size(&str, di, i); + chrcat_WS(str, OPEN_CHR); + if(!SEGMENT_IS_DEFAULT_OR_NONE(di->segment)) + { + strcat_WSR(&str, &_REGISTERS[SEGMENT_GET_UNSAFE(di->segment)]); + chrcat_WS(str, SEG_OFF_CHR); + } + if(di->base != R_NONE) + { + strcat_WSR(&str, &_REGISTERS[di->base]); + chrcat_WS(str, PLUS_DISP_CHR); + } + strcat_WSR(&str, &_REGISTERS[di->ops[i].index]); + if(di->scale != 0) + { + switch(di->scale) + { + case 2: + strcat_WS(str, "*2", 2, 2); + break; + case 4: + strcat_WS(str, "*4", 2, 2); + break; + case 8: + strcat_WS(str, "*8", 2, 2); + break; + } + } + distorm_format_signed_disp(&str, di, addrMask); + chrcat_WS(str, CLOSE_CHR); + } + else if(type == O_PTR) + { + str_int(&str, di->imm.ptr.seg); + chrcat_WS(str, SEG_OFF_CHR); + str_int(&str, di->imm.ptr.off); + } + else if(type == O_IMM1) + { + str_int(&str, di->imm.ex.i1); + } + else if(type == O_IMM2) + { + str_int(&str, di->imm.ex.i2); + } + } + +skipOperands: + + /* Finalize the operands string. */ + strfinalize_WS(result->operands, str); + + /* Not used anymore. + if (di->flags & FLAG_HINT_TAKEN) strcat_WSN(str, " ;TAKEN"); + else if (di->flags & FLAG_HINT_NOT_TAKEN) strcat_WSN(str, " ;NOT TAKEN"); + */ + { + /* In-place considerations: DI is RESULT. Deref fields first. */ + unsigned int opcode = di->opcode; + unsigned int prefix = FLAG_GET_PREFIX(di->flags); + unsigned int size = di->size; + _OffsetType offset = di->addr & addrMask; + str = (unsigned char*)&result->mnemonic.p; + mnemonic = (const _WMnemonic*)&_MNEMONICS[opcode]; + + if(prefix) + { + /* REP prefix for CMPS and SCAS is really a REPZ. */ + prefix += (opcode == I_CMPS); + prefix += (opcode == I_SCAS); + memcpy(str, &prefixTable[prefix][0], 8); + str += prefixSizesTable[prefix]; + } + + /* + * Always copy 16 bytes from the mnemonic, we have a sentinel padding so we can read past. + * This helps the compiler to remove the call to memcpy and therefore makes this copying much faster. + * The longest instruction is exactly 16 chars long, so we null terminate the string below. + */ + memcpy((int8_t*)str, mnemonic->p, 16); + str += mnemonic->length; + + if(suffixSize > 0) + { + *str++ = suffixTable[suffixSize]; + } + strfinalize_WS(result->mnemonic, str); + + result->offset = offset; + result->size = size; + } +} + +#ifdef SUPPORT_64BIT_OFFSET +_DLLEXPORT_ _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#else +_DLLEXPORT_ _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#endif +{ + _DecodeResult res; + _CodeInfo ci; + unsigned int i, instsCount; + + *usedInstructionsCount = 0; + + /* I use codeLen as a signed variable in order to ease detection of underflow... and besides - */ + if(codeLen < 0) + { + return DECRES_INPUTERR; + } + + if((unsigned)dt > (unsigned)Decode64Bits) + { + return DECRES_INPUTERR; + } + + /* Make sure there's at least one instruction in the result buffer. */ + if((code == NULL) || (result == NULL) || (maxInstructions == 0)) + { + return DECRES_INPUTERR; + } + + /* + * We have to format the result into text. But the interal decoder works with the new structure of _DInst. + * Therefore, we will pass the result array(!) from the caller and the interal decoder will fill it in with _DInst's. + * Then we will copy each result to a temporary structure, and use it to reformat that specific result. + * + * This is all done to save memory allocation and to work on the same result array in-place!!! + * It's a bit ugly, I have to admit, but worth it. + */ + + ci.codeOffset = codeOffset; + ci.code = code; + ci.codeLen = codeLen; + ci.dt = dt; + ci.features = DF_USE_ADDR_MASK; + if(dt == Decode16Bits) ci.addrMask = 0xffff; + else if(dt == Decode32Bits) ci.addrMask = 0xffffffff; + else ci.addrMask = (_OffsetType) - 1; + + res = decode_internal(&ci, TRUE, (_DInst*)result, maxInstructions, usedInstructionsCount); + instsCount = *usedInstructionsCount; + for(i = 0; i < instsCount; i++) + { + /* distorm_format is optimized and can work with same input/output buffer in-place. */ +#ifdef SUPPORT_64BIT_OFFSET + distorm_format64(&ci, (_DInst*)&result[i], &result[i]); +#else + distorm_format32(&ci, (_DInst*)&result[i], &result[i]); +#endif + } + + return res; +} + +#endif /* DISTORM_LIGHT */ + +_DLLEXPORT_ unsigned int distorm_version(void) +{ + return __DISTORMV__; +} +/* +decoder.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2021 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + + + +/* Instruction Prefixes - Opcode - ModR/M - SIB - Displacement - Immediate */ + +static _DecodeType decode_get_effective_addr_size(_DecodeType dt, _iflags decodedPrefixes) +{ + /* + * Map from the current decoding mode to an effective address size: + * Decode16 -> Decode32 + * Decode32 -> Decode16 + * Decode64 -> Decode32 + */ + + /* Switch to non default mode if prefix exists, only for ADDRESS SIZE. */ + if(decodedPrefixes & INST_PRE_ADDR_SIZE) + { + if(dt == Decode32Bits) return Decode16Bits; + return Decode32Bits; + } + return dt; +} + +static _DecodeType decode_get_effective_op_size(_DecodeType dt, _iflags decodedPrefixes, unsigned int rex, _iflags instFlags) +{ + /* + * Map from the current decoding mode to an effective operand size: + * Decode16 -> Decode32 + * Decode32 -> Decode16 + * Decode64 -> Decode16 + * Not that in 64bits it's a bit more complicated, because of REX and promoted instructions. + */ + + if(decodedPrefixes & INST_PRE_OP_SIZE) + { + if(dt == Decode16Bits) return Decode32Bits; + return Decode16Bits; + } + + if(dt == Decode64Bits) + { + /* + * REX Prefix toggles data size to 64 bits. + * Operand size prefix toggles data size to 16. + * Default data size is 32 bits. + * Promoted instructions are 64 bits if they don't require a REX perfix. + * Non promoted instructions are 64 bits if the REX prefix exists. + */ + /* Automatically promoted instructions have only INST_64BITS SET! */ + if(((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS) || + /* Other instructions in 64 bits can be promoted only with a REX prefix. */ + ((decodedPrefixes & INST_PRE_REX) && (rex & PREFIX_EX_W))) return Decode64Bits; + return Decode32Bits; /* Default. */ + } + + return dt; +} + +/* + * A helper macro to convert from diStorm's CPU flags to EFLAGS. + * Copy eflags from compact version (8 bits) to eflags compatible (16 bits). + * From D_COMPACT_IF to D_IF, bit index 1 to 9. + * From D_COMPACT_DF to D_DF, bit index 3 to 10. + * From D_COMPACT_OF to D_OF, bit index 5 to 11. + */ +#define CONVERT_FLAGS_TO_EFLAGS(dst, src, field) dst->field = ((src->field & D_COMPACT_SAME_FLAGS) | \ + ((src->field & D_COMPACT_IF) << (9 - 1)) | \ + ((src->field & D_COMPACT_DF) << (10 - 3)) | \ + ((src->field & D_COMPACT_OF) << (11 - 5))); + +/* If DECRES_SUCCESS is returned, CI is in sync, otherwise it loses sync. */ +/* Important note: CI is keeping track only for code and codeLen, in case of a failure caller has to restart on their own. */ +static _DecodeResult decode_inst(_CodeInfo* ci, _PrefixState* ps, const uint8_t* startCode, _DInst* di) +{ + /* Holds the info about the current found instruction. */ + _InstInfo* ii; + _InstSharedInfo* isi; + + /* Calculate (and cache) effective-operand-size and effective-address-size only once. */ + _DecodeType effOpSz, effAdrSz; + _iflags instFlags; + + /* The ModR/M byte of the current instruction. */ + unsigned int modrm = 0; + int isPrefixed = 0; + + ii = inst_lookup(ci, ps, &isPrefixed); + if(ii == NULL) goto _Undecodable; + + isi = &InstSharedInfoTable[ii->sharedIndex]; + instFlags = FlagsTable[isi->flagsIndex]; + + /* Cache the effective operand-size and address-size. */ + if(isPrefixed) + { + + /* + * If both REX and OpSize are available we will have to disable the OpSize, because REX has precedence. + * However, only if REX.W is set! + * We had to wait with this test, since the operand size may be a mandatory prefix, + * and we know it only after fetching opcode. + */ + if((ps->decodedPrefixes & INST_PRE_OP_SIZE) && + (ps->prefixExtType == PET_REX) && + (ps->vrex & PREFIX_EX_W) && + (!ps->isOpSizeMandatory)) + { + ps->decodedPrefixes &= ~INST_PRE_OP_SIZE; + prefixes_ignore(ps, PFXIDX_OP_SIZE); + } + + effAdrSz = decode_get_effective_addr_size(ci->dt, ps->decodedPrefixes); + effOpSz = decode_get_effective_op_size(ci->dt, ps->decodedPrefixes, ps->vrex, instFlags); + } + else + { + effAdrSz = ci->dt; /* Default is current decoding type since there's no prefix. */ + effOpSz = decode_get_effective_op_size(ci->dt, 0, 0, instFlags); + } + + /* + * In this point we know the instruction we are about to decode and its operands (unless, it's an invalid one!), + * so it makes it the right time for decoding-type suitability testing. + * Which practically means, don't allow 32 bits instructions in 16 bits decoding mode, but do allow + * 16 bits instructions in 32 bits decoding mode, of course... + + * NOTE: Make sure the instruction set for 32 bits has explicitly this specific flag set. + * NOTE2: Make sure the instruction set for 64 bits has explicitly this specific flag set. + + * If this is the case, drop what we've got and restart all over after DB'ing that byte. + + * Though, don't drop an instruction which is also supported in 16 and 32 bits. + */ + + /* ! ! ! DISABLED UNTIL FURTHER NOTICE ! ! ! Decode16Bits CAN NOW DECODE 32 BITS INSTRUCTIONS ! ! !*/ + /* if (ii && (dt == Decode16Bits) && (instFlags & INST_32BITS) && (~instFlags & INST_16BITS)) ii = NULL; */ + + memset(di, 0, sizeof(_DInst)); + + if(instFlags & INST_MODRM_REQUIRED) + { + /* If the ModRM byte is not part of the opcode, skip the last byte code, so code points now to ModRM. */ + if(!(instFlags & INST_MODRM_INCLUDED)) + { + ci->code++; + if(--ci->codeLen < 0) goto _Undecodable; + } + modrm = *ci->code; + } + + ci->code++; /* Skip the last byte we just read (either last opcode's byte code or a ModRM). */ + + di->addr = ci->codeOffset & ci->addrMask; + di->opcode = ii->opcodeId; + di->flags = isi->meta & META_INST_PRIVILEGED; + + /* + * Store the address size inside the flags. + * This is necessary for the caller to know the size of rSP when using PUSHA for example. + */ + di->base = R_NONE; + di->segment = R_NONE; + + FLAG_SET_ADDRSIZE(di, effAdrSz); + + /* Try to extract the next operand only if the latter exists. */ + if(isi->d != OT_NONE) + { + unsigned int opsNo = 1; + _Operand* op = &di->ops[0]; + if(instFlags & (INST_MODRR_REQUIRED | INST_FORCE_REG0)) + { + /* Some instructions enforce that mod=11, so validate that. */ + if((modrm < INST_DIVIDED_MODRM) && (instFlags & INST_MODRR_REQUIRED)) goto _Undecodable; + /* Some instructions enforce that reg=000, so validate that. (Specifically EXTRQ). */ + if((instFlags & INST_FORCE_REG0) && (((modrm >> 3) & 7) != 0)) goto _Undecodable; + } + if(!operands_extract(ci, di, ii, instFlags, (_OpType)isi->d, modrm, ps, effOpSz, effAdrSz, op++)) goto _Undecodable; + + if(isi->s != OT_NONE) + { + if(!operands_extract(ci, di, ii, instFlags, (_OpType)isi->s, modrm, ps, effOpSz, effAdrSz, op++)) goto _Undecodable; + opsNo++; + /* Use third operand, only if the flags says this InstInfo requires it. */ + if(instFlags & INST_USE_OP3) + { + if(!operands_extract(ci, di, ii, instFlags, (_OpType)((_InstInfoEx*)ii)->op3, modrm, ps, effOpSz, effAdrSz, op++)) goto _Undecodable; + opsNo++; + /* Support for a fourth operand is added for (e.g:) INSERTQ instruction. */ + if(instFlags & INST_USE_OP4) + { + if(!operands_extract(ci, di, ii, instFlags, (_OpType)((_InstInfoEx*)ii)->op4, modrm, ps, effOpSz, effAdrSz, op++)) goto _Undecodable; + opsNo++; + } + } + } + + /* Copy DST_WR flag. */ + di->flags |= (instFlags & INST_DST_WR) >> (31 - 6); /* Copy bit from INST_DST_WR (bit 31) to FLAG_DST_WR (bit 6). */ + /* operands_extract may touched it for FPU operands, so add on top. */ + di->opsNo += (uint8_t)opsNo; + } + + if(instFlags & (INST_3DNOW_FETCH | + INST_PSEUDO_OPCODE | + INST_NATIVE | + INST_PRE_REPNZ | + INST_PRE_REP | + INST_PRE_ADDR_SIZE | + INST_INVALID_64BITS | + INST_64BITS_FETCH)) /* 8 for 1! */ + { + + /* If it's a native instruction copy OpSize Prefix. */ + if(ps && instFlags & INST_NATIVE) ps->usedPrefixes |= (ps->decodedPrefixes & INST_PRE_OP_SIZE); + + if(ci->dt != Decode64Bits) + { + /* If it's only a 64 bits instruction drop it in other decoding modes. */ + if(instFlags & INST_64BITS_FETCH) goto _Undecodable; + } + else + { + /* Drop instructions which are invalid in 64 bits. */ + if(instFlags & INST_INVALID_64BITS) goto _Undecodable; + } + + /* If it were a 3DNow! instruction, we will have to find the instruction itself now that we got its operands extracted. */ + if(instFlags & INST_3DNOW_FETCH) + { + ii = inst_lookup_3dnow(ci); + if(ii == NULL) goto _Undecodable; + isi = &InstSharedInfoTable[ii->sharedIndex]; + instFlags = FlagsTable[isi->flagsIndex]; + di->opcode = ii->opcodeId; + } + + /* Check whether pseudo opcode is needed, only for CMP instructions: */ + if(instFlags & INST_PSEUDO_OPCODE) + { + /* Used only for special CMP instructions which have pseudo opcodes suffix. */ + unsigned int cmpType; + + if(--ci->codeLen < 0) goto _Undecodable; + cmpType = *ci->code; + ci->code++; + + /* + * The opcodeId is the offset to the FIRST pseudo compare mnemonic, + * we will have to fix it so it offsets into the corrected mnemonic. + * Therefore, we use another table to fix the offset. + */ + if(instFlags & INST_PRE_VEX) + { + /* AVX Comparison type must be between 0 to 32, otherwise Reserved. */ + if(cmpType >= INST_VCMP_MAX_RANGE) goto _Undecodable; + + /* Use the AVX pseudo compare mnemonics table. */ + di->opcode = ii->opcodeId + VCmpMnemonicOffsets[cmpType]; + } + else + { + /* SSE Comparison type must be between 0 to 8, otherwise Reserved. */ + if(cmpType >= INST_CMP_MAX_RANGE) goto _Undecodable; + di->opcode = ii->opcodeId + CmpMnemonicOffsets[cmpType]; + } + + goto _SkipOpcoding; + } + + /* Start with prefix REP/N/Z. */ + if(isPrefixed && (instFlags & (INST_PRE_REPNZ | INST_PRE_REP))) + { + if((instFlags & INST_PRE_REPNZ) && (ps->decodedPrefixes & INST_PRE_REPNZ)) + { + ps->usedPrefixes |= INST_PRE_REPNZ; + di->flags |= FLAG_REPNZ; + } + else if((instFlags & INST_PRE_REP) && (ps->decodedPrefixes & INST_PRE_REP)) + { + ps->usedPrefixes |= INST_PRE_REP; + di->flags |= FLAG_REP; + } + } + + if(instFlags & INST_PRE_ADDR_SIZE) + { + /* If it's JeCXZ the ADDR_SIZE prefix affects them. */ + if(instFlags & INST_USE_EXMNEMONIC) + { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + if(effAdrSz == Decode16Bits) di->opcode = ii->opcodeId; + else if(effAdrSz == Decode32Bits) di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + /* Ignore REX.W in 64bits, JECXZ is promoted. */ + else /* Decode64Bits */ di->opcode = ((_InstInfoEx*)ii)->opcodeId3; + } + + /* LOOPxx instructions are also native instruction, but they are special case ones, ADDR_SIZE prefix affects them. */ + else if(instFlags & INST_NATIVE) + { + di->opcode = ii->opcodeId; + + /* If LOOPxx gets here from 64bits, it must be Decode32Bits because Address Size prefix is set. */ + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + } + + goto _SkipOpcoding; + } + } + + /* + * If we reached here the instruction was fully decoded, we located the instruction in the DB and extracted operands. + * Use the correct mnemonic according to the DT. + * If we are in 32 bits decoding mode it doesn't necessarily mean we will choose mnemonic2, alas, + * it means that if there is a mnemonic2, it will be used. + * Note: + * If the instruction is prefixed by operand size we will format it in the non-default decoding mode! + * So there might be a situation that an instruction of 32 bit gets formatted in 16 bits decoding mode. + * Both ways should end up with a correct and expected formatting of the text. + */ + if(effOpSz == Decode32Bits) /* Decode32Bits */ + { + + /* Set operand size. */ + FLAG_SET_OPSIZE(di, Decode32Bits); + + /* Give a chance for special mnemonic instruction in 32 bits decoding. */ + if(instFlags & INST_USE_EXMNEMONIC) + { + /* Is it a special instruction which has another mnemonic for mod=11 ? */ + if(instFlags & INST_MNEMONIC_MODRM_BASED) + { + if(modrm < INST_DIVIDED_MODRM) di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + } + else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + ps->usedPrefixes |= INST_PRE_OP_SIZE; + } + } + else if(effOpSz == Decode64Bits) /* Decode64Bits, note that some instructions might be decoded in Decode32Bits above. */ + { + + /* Set operand size. */ + FLAG_SET_OPSIZE(di, Decode64Bits); + + if(instFlags & (INST_USE_EXMNEMONIC | INST_USE_EXMNEMONIC2)) + { + /* + * We shouldn't be here for MODRM based mnemonics with a MOD=11, + * because they must not use REX (otherwise it will get to the wrong instruction which share same opcode). + * See XRSTOR and XSAVEOPT. + */ + if((modrm >= INST_DIVIDED_MODRM) && (instFlags & INST_MNEMONIC_MODRM_BASED)) goto _Undecodable; + + /* Use third mnemonic, for 64 bits. */ + if((instFlags & INST_USE_EXMNEMONIC2) && (ps->vrex & PREFIX_EX_W)) + { + ps->usedPrefixes |= INST_PRE_REX; + di->opcode = ((_InstInfoEx*)ii)->opcodeId3; + } + else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; /* Use second mnemonic. */ + } + } + else /* Decode16Bits */ + { + + /* Set operand size. */ + FLAG_SET_OPSIZE(di, Decode16Bits); + + /* + * If it's a special instruction which has two mnemonics, then use the 16 bits one + update usedPrefixes. + * Note: use 16 bits mnemonic if that instruction supports 32 bit or 64 bit explicitly. + */ + if((instFlags & (INST_USE_EXMNEMONIC | INST_32BITS | INST_64BITS)) == INST_USE_EXMNEMONIC) ps->usedPrefixes |= INST_PRE_OP_SIZE; + } + +_SkipOpcoding: + + /* Check VEX mnemonics: */ + if(isPrefixed && (instFlags & INST_PRE_VEX) && + (((((_InstInfoEx*)ii)->flagsEx & INST_MNEMONIC_VEXW_BASED) && (ps->vrex & PREFIX_EX_W)) || + ((((_InstInfoEx*)ii)->flagsEx & INST_MNEMONIC_VEXL_BASED) && (ps->vrex & PREFIX_EX_L)))) + { + di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + } + + /* Instruction's size should include prefixes too if exist. */ + di->size = (uint8_t)(ci->code - startCode); + /* + * There's a limit of 15 bytes on instruction length. The only way to violate + * this limit is by putting redundant prefixes before an instruction. + * start points to first prefix if any, otherwise it points to instruction first byte. + */ + if(di->size > INST_MAXIMUM_SIZE) goto _Undecodable; + + /* Set the unused prefixes mask, if any prefixes (not) used at all. */ + if(isPrefixed) di->unusedPrefixesMask = prefixes_set_unused_mask(ps); + + /* Copy instruction meta. */ + di->meta = isi->meta; + + if(ci->features & DF_FILL_EFLAGS) + { + /* Copy CPU affected flags. */ + if(isi->testedFlagsMask) CONVERT_FLAGS_TO_EFLAGS(di, isi, testedFlagsMask); + if(isi->modifiedFlagsMask) CONVERT_FLAGS_TO_EFLAGS(di, isi, modifiedFlagsMask); + if(isi->undefinedFlagsMask) CONVERT_FLAGS_TO_EFLAGS(di, isi, undefinedFlagsMask); + } + + /* + * Instruction can still be invalid if it's total length is over 15 bytes with prefixes. + * Up to the caller to check that. + */ + return DECRES_SUCCESS; + +_Undecodable: /* If the instruction couldn't be decoded for some reason, fail. */ + /* Special case for WAIT instruction: If it's dropped as a prefix, we have to return a valid instruction! */ + if(*startCode == INST_WAIT_INDEX) + { + int delta; + memset(di, 0, sizeof(_DInst)); + di->addr = ci->codeOffset & ci->addrMask; + di->imm.byte = INST_WAIT_INDEX; + di->segment = R_NONE; + di->base = R_NONE; + di->size = 1; + di->opcode = I_WAIT; + META_SET_ISC(di, ISC_INTEGER); + + /* Fix ci because WAIT could be a prefix that failed, and ci->code is now out of sync. */ + delta = (int)(ci->code - startCode); /* How many bytes we read so far. */ + ci->codeLen += delta - 1; + ci->code = startCode + 1; + /* codeOffset is fixed outside. */ + + return DECRES_SUCCESS; + } + + /* Mark that we didn't manage to decode the instruction well, caller will drop it. */ + return DECRES_INPUTERR; +} + +/* + * decode_internal + * + * supportOldIntr - Since now we work with new structure instead of the old _DecodedInst, we are still interested in backward compatibility. + * So although, the array is now of type _DInst, we want to read it in jumps of the old array element's size. + * This is in order to save memory allocation for conversion between the new and the old structures. + * It really means we can do the conversion in-place now. + */ +_DecodeResult decode_internal(_CodeInfo* _ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount) +{ + _CodeInfo ci = *_ci; /* A working copy, we don't touch user's _ci except OUT params. */ + _PrefixState ps; + /* Bookkeep these from ci below, as it makes things way simpler. */ + const uint8_t* code; + int codeLen; + _OffsetType codeOffset; + + _DecodeResult ret = DECRES_SUCCESS; + + /* Current working decoded instruction in results. */ + _DInst* pdi = (_DInst*)&result[0]; /* There's always a room for at least one slot, checked earlier. */ + _DInst* maxResultAddr; + + unsigned int features = ci.features; + + unsigned int diStructSize; + /* Use next entry. */ +#ifndef DISTORM_LIGHT + if(supportOldIntr) + { + diStructSize = sizeof(_DecodedInst); + maxResultAddr = (_DInst*)((size_t)&result[0] + (maxResultCount * sizeof(_DecodedInst))); + } + else +#endif /* DISTORM_LIGHT */ + { + diStructSize = sizeof(_DInst); + maxResultAddr = &result[maxResultCount]; + } + + ci.addrMask = (_OffsetType) - 1; + +#ifdef DISTORM_LIGHT + supportOldIntr; /* Unreferenced. */ + + /* + * Only truncate address if we are using the decompose interface. + * Otherwise, we use the textual interface which needs full addresses for formatting bytes output. + * So distorm_format will truncate later. + */ + if(features & DF_MAXIMUM_ADDR32) ci.addrMask = 0xffffffff; + else if(features & DF_MAXIMUM_ADDR16) ci.addrMask = 0xffff; +#endif + + ps.count = 1; /* Force zero'ing ps below. */ + + /* Decode instructions as long as we have what to decode/enough room in entries. */ + while(ci.codeLen > 0) + { + code = ci.code; + codeLen = ci.codeLen; + codeOffset = ci.codeOffset; + + if(ps.count) memset(&ps, 0, sizeof(ps)); + + /**** INSTRUCTION DECODING NEXT: ****/ + + /* Make sure we didn't run out of output entries. */ + if(pdi >= maxResultAddr) + { + ret = DECRES_MEMORYERR; + break; + } + + ret = decode_inst(&ci, &ps, code, pdi); + /* decode_inst keeps track (only if successful!) for code and codeLen but ignores codeOffset, fix it here. */ + ci.codeOffset += pdi->size; + + if(ret == DECRES_SUCCESS) + { + + if(features & (DF_SINGLE_BYTE_STEP | DF_RETURN_FC_ONLY | DF_STOP_ON_PRIVILEGED | DF_STOP_ON_FLOW_CONTROL)) + { + + /* Sync codeinfo, remember that currently it points to beginning of the instruction and prefixes if any. */ + if(features & DF_SINGLE_BYTE_STEP) + { + ci.code = code + 1; + ci.codeLen = codeLen - 1; + ci.codeOffset = codeOffset + 1; + } + + /* See if we need to filter this instruction. */ + if((features & DF_RETURN_FC_ONLY) && (META_GET_FC(pdi->meta) == FC_NONE)) + { + continue; + } + + /* Check whether we need to stop on any feature. */ + if((features & DF_STOP_ON_PRIVILEGED) && (FLAG_GET_PRIVILEGED(pdi->flags))) + { + pdi = (_DInst*)((char*)pdi + diStructSize); + break; /* ret = DECRES_SUCCESS; */ + } + + if(features & DF_STOP_ON_FLOW_CONTROL) + { + unsigned int mfc = META_GET_FC(pdi->meta); + if(mfc && (((features & DF_STOP_ON_CALL) && (mfc == FC_CALL)) || + ((features & DF_STOP_ON_RET) && (mfc == FC_RET)) || + ((features & DF_STOP_ON_SYS) && (mfc == FC_SYS)) || + ((features & DF_STOP_ON_UNC_BRANCH) && (mfc == FC_UNC_BRANCH)) || + ((features & DF_STOP_ON_CND_BRANCH) && (mfc == FC_CND_BRANCH)) || + ((features & DF_STOP_ON_INT) && (mfc == FC_INT)) || + ((features & DF_STOP_ON_CMOV) && (mfc == FC_CMOV)) || + ((features & DF_STOP_ON_HLT) && (mfc == FC_HLT)))) + { + pdi = (_DInst*)((char*)pdi + diStructSize); + break; /* ret = DECRES_SUCCESS; */ + } + } + } + + /* Allocate at least one more entry to use, for the next instruction. */ + pdi = (_DInst*)((char*)pdi + diStructSize); + } + else /* ret == DECRES_INPUTERR */ + { + + /* Handle failure of decoding last instruction. */ + if((!(features & DF_RETURN_FC_ONLY))) + { + memset(pdi, 0, sizeof(_DInst)); + pdi->flags = FLAG_NOT_DECODABLE; + pdi->imm.byte = *code; + pdi->size = 1; + pdi->addr = codeOffset & ci.addrMask; + pdi = (_DInst*)((char*)pdi + diStructSize); + + /* If an instruction wasn't decoded then stop on undecodeable if set. */ + if(features & DF_STOP_ON_UNDECODEABLE) + { + ret = DECRES_SUCCESS; + break; + } + } + + /* Skip a single byte in case of a failure and retry instruction. */ + ci.code = code + 1; + ci.codeLen = codeLen - 1; + ci.codeOffset = codeOffset + 1; + + /* Reset return value. */ + ret = DECRES_SUCCESS; + } + } + + /* Set OUT params. */ + *usedInstructionsCount = (unsigned int)(((size_t)pdi - (size_t)result) / (size_t)diStructSize); + _ci->nextOffset = ci.codeOffset; + + return ret; +} diff --git a/release.bat b/release.bat index f7f846a..aaf42ed 100644 --- a/release.bat +++ b/release.bat @@ -1,9 +1,16 @@ @echo off setlocal enableextensions + +set "SRC32=bin\Release\Win32" +if not exist "%SRC32%\TitanEngine.dll" set "SRC32=Release\x32" + +set "SRC64=bin\Release\x64" +if not exist "%SRC64%\TitanEngine.dll" set "SRC64=Release\x64" + if exist deps rmdir /s /q deps mkdir deps\x32 mkdir deps\x64 -copy /y Release\x32\TitanEngine.dll deps\x32\TitanEngine.dll -copy /y Release\x32\TitanEngine.pdb deps\x32\TitanEngine.pdb -copy /y Release\x64\TitanEngine.dll deps\x64\TitanEngine.dll -copy /y Release\x64\TitanEngine.pdb deps\x64\TitanEngine.pdb +copy /y "%SRC32%\TitanEngine.dll" deps\x32\TitanEngine.dll +copy /y "%SRC32%\TitanEngine.pdb" deps\x32\TitanEngine.pdb +copy /y "%SRC64%\TitanEngine.dll" deps\x64\TitanEngine.dll +copy /y "%SRC64%\TitanEngine.pdb" deps\x64\TitanEngine.pdb diff --git a/scylla_wrapper/ApiReader.cpp b/scylla_wrapper/ApiReader.cpp new file mode 100644 index 0000000..0ce7288 --- /dev/null +++ b/scylla_wrapper/ApiReader.cpp @@ -0,0 +1,1218 @@ +#include "stdafx.h" +#include "ApiReader.h" +#include "Architecture.h" +#include "SystemInformation.h" +#include "StringConversion.h" +#include "PeParser.h" + +std::unordered_multimap ApiReader::apiList; //api look up table +std::map* ApiReader::moduleThunkList; //store found apis + +DWORD_PTR ApiReader::minApiAddress = 0xFFFFFFFF; +DWORD_PTR ApiReader::maxApiAddress = 0; + +//#define DEBUG_COMMENTS + +void ApiReader::readApisFromModuleList() +{ + + readExportTableAlwaysFromDisk = true; + + for(unsigned int i = 0; i < moduleList.size(); i++) + { + setModulePriority(&moduleList[i]); + + if(moduleList[i].modBaseAddr + moduleList[i].modBaseSize > maxValidAddress) + { + maxValidAddress = moduleList[i].modBaseAddr + moduleList[i].modBaseSize; + } + + // Scylla::windowLog.log(L"Module parsing: %s",moduleList[i].fullPath); + + if(!moduleList[i].isAlreadyParsed) + { + parseModule(&moduleList[i]); + } + } + +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"Address Min " PRINTF_DWORD_PTR_FULL L" Max " PRINTF_DWORD_PTR_FULL L"\nimagebase " PRINTF_DWORD_PTR_FULL L" maxValidAddress " PRINTF_DWORD_PTR_FULL, minApiAddress, maxApiAddress, targetImageBase, maxValidAddress); +#endif +} + +void ApiReader::parseModule(ModuleInfo* module) +{ + module->parsing = true; + + if(isWinSxSModule(module)) + { + parseModuleWithMapping(module); + } + else if(isModuleLoadedInOwnProcess(module)) + { + parseModuleWithOwnProcess(module); + } + else + { + if(readExportTableAlwaysFromDisk) + { + parseModuleWithMapping(module); + } + else + { + parseModuleWithProcess(module); + } + } + + module->isAlreadyParsed = true; +} + +void ApiReader::parseModuleWithMapping(ModuleInfo* moduleInfo) +{ + LPVOID fileMapping = 0; + PIMAGE_NT_HEADERS pNtHeader = 0; + PIMAGE_DOS_HEADER pDosHeader = 0; + + fileMapping = createFileMappingViewRead(moduleInfo->fullPath); + + if(fileMapping == 0) + return; + + pDosHeader = (PIMAGE_DOS_HEADER)fileMapping; + pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileMapping + (DWORD_PTR)(pDosHeader->e_lfanew)); + + if(isPeAndExportTableValid(pNtHeader)) + { + parseExportTable(moduleInfo, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)fileMapping + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), (DWORD_PTR)fileMapping); + } + + + UnmapViewOfFile(fileMapping); + +} + +inline bool ApiReader::isApiForwarded(DWORD_PTR rva, PIMAGE_NT_HEADERS pNtHeader) +{ + if((rva > pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) && (rva < (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size))) + { + return true; + } + else + { + return false; + } +} + +void ApiReader::handleForwardedApi(DWORD_PTR vaStringPointer, char* functionNameParent, DWORD_PTR rvaParent, WORD ordinalParent, ModuleInfo* moduleParent) +{ + size_t dllNameLength = 0; + WORD ordinal = 0; + ModuleInfo* module = 0; + DWORD_PTR vaApi = 0; + DWORD_PTR rvaApi = 0; + char dllName[100] = {0}; + WCHAR dllNameW[100] = {0}; + char* fordwardedString = (char*)vaStringPointer; + char* searchFunctionName = strchr(fordwardedString, '.'); + + + if(!searchFunctionName) + return; + + dllNameLength = searchFunctionName - fordwardedString; + + if(dllNameLength >= 99) + { + return; + } + else + { + strncpy_s(dllName, fordwardedString, dllNameLength); + } + + searchFunctionName++; + + //Since Windows 7 + if(!_strnicmp(dllName, "API-", 4) || !_strnicmp(dllName, "EXT-", 4)) //API_SET_PREFIX_NAME, API_SET_EXTENSION + { + /* + Info: http://www.nirsoft.net/articles/windows_7_kernel_architecture_changes.html + */ + + FARPROC addy = GetProcAddress(GetModuleHandleA(dllName), searchFunctionName); + + if(addy != 0) + { + addApi(functionNameParent, 0, ordinalParent, (DWORD_PTR)addy, (DWORD_PTR)addy - (DWORD_PTR)GetModuleHandleA(dllName), true, moduleParent); + } + + return; + } + + strcat_s(dllName, ".dll"); + + StringConversion::ToUTF16(dllName, dllNameW, _countof(dllNameW)); + + if(!_wcsicmp(dllNameW, moduleParent->getFilename())) + { + module = moduleParent; + } + else + { + module = findModuleByName(dllNameW); + } + + if(module != 0) // module == 0 -> can be ignored + { + /*if ((module->isAlreadyParsed == false) && (module != moduleParent)) + { + //do API extract + + if (module->parsing == true) + { + //some stupid circle dependency + printf("stupid circle dependency %s\n",module->getFilename()); + } + else + { + parseModule(module); + } + }*/ + + if(strchr(searchFunctionName, '#')) + { + //forwarding by ordinal + searchFunctionName++; + ordinal = (WORD)atoi(searchFunctionName); + findApiByModuleAndOrdinal(module, ordinal, &vaApi, &rvaApi); + } + else + { + findApiByModuleAndName(module, searchFunctionName, &vaApi, &rvaApi); + } + + if(rvaApi == 0) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"handleForwardedApi :: Api not found, this is really BAD! %S", fordwardedString); +#endif + } + else + { + addApi(functionNameParent, 0, ordinalParent, vaApi, rvaApi, true, moduleParent); + } + } + +} + +ModuleInfo* ApiReader::findModuleByName(WCHAR* name) +{ + for(unsigned int i = 0; i < moduleList.size(); i++) + { + if(!_wcsicmp(moduleList[i].getFilename(), name)) + { + return &moduleList[i]; + } + } + + return 0; +} + +void ApiReader::addApiWithoutName(WORD ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo* moduleInfo) +{ + addApi(0, 0, ordinal, va, rva, isForwarded, moduleInfo); +} + +void ApiReader::addApi(char* functionName, WORD hint, WORD ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo* moduleInfo) +{ + ApiInfo* apiInfo = new ApiInfo(); + + if((functionName != 0) && (strlen(functionName) < _countof(apiInfo->name))) + { + strcpy_s(apiInfo->name, functionName); + } + else + { + apiInfo->name[0] = 0x00; + } + + apiInfo->ordinal = ordinal; + apiInfo->isForwarded = isForwarded; + apiInfo->module = moduleInfo; + apiInfo->rva = rva; + apiInfo->va = va; + apiInfo->hint = hint; + + setMinMaxApiAddress(va); + + moduleInfo->apiList.push_back(apiInfo); + + apiList.insert(API_Pair(va, apiInfo)); +} + +BYTE* ApiReader::getHeaderFromProcess(ModuleInfo* module) +{ + BYTE* bufferHeader = 0; + DWORD readSize = 0; + + if(module->modBaseSize < PE_HEADER_BYTES_COUNT) + { + readSize = module->modBaseSize; + } + else + { + readSize = PE_HEADER_BYTES_COUNT; + } + + bufferHeader = new BYTE[readSize]; + + if(!readMemoryFromProcess(module->modBaseAddr, readSize, bufferHeader)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"getHeaderFromProcess :: Error reading header"); +#endif + delete[] bufferHeader; + return 0; + } + else + { + return bufferHeader; + } +} + +BYTE* ApiReader::getExportTableFromProcess(ModuleInfo* module, PIMAGE_NT_HEADERS pNtHeader) +{ + DWORD readSize = 0; + BYTE* bufferExportTable = 0; + + readSize = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; + + if(readSize < (sizeof(IMAGE_EXPORT_DIRECTORY) + 8)) + { + //Something is wrong with the PE Header +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"Something is wrong with the PE Header here Export table size %d", readSize); +#endif + readSize = sizeof(IMAGE_EXPORT_DIRECTORY) + 100; + } + + if(readSize) + { + bufferExportTable = new BYTE[readSize]; + + if(!bufferExportTable) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"Something is wrong with the PE Header here Export table size %d", readSize); +#endif + return 0; + } + + if(!readMemoryFromProcess(module->modBaseAddr + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, readSize, bufferExportTable)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"getExportTableFromProcess :: Error reading export table from process"); +#endif + delete[] bufferExportTable; + return 0; + } + else + { + return bufferExportTable; + } + } + else + { + return 0; + } +} + +void ApiReader::parseModuleWithProcess(ModuleInfo* module) +{ + PIMAGE_NT_HEADERS pNtHeader = 0; + PIMAGE_DOS_HEADER pDosHeader = 0; + BYTE* bufferHeader = 0; + BYTE* bufferExportTable = 0; + PeParser peParser(module->modBaseAddr, false); + + if(!peParser.isValidPeFile()) + return; + + pNtHeader = peParser.getCurrentNtHeader(); + + if(peParser.hasExportDirectory()) + { + bufferExportTable = getExportTableFromProcess(module, pNtHeader); + + if(bufferExportTable) + { + parseExportTable(module, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)bufferExportTable, (DWORD_PTR)bufferExportTable - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + delete[] bufferExportTable; + } + } +} + +void ApiReader::parseExportTable(ModuleInfo* module, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress) +{ + DWORD* addressOfFunctionsArray = 0, *addressOfNamesArray = 0; + WORD* addressOfNameOrdinalsArray = 0; + char* functionName = 0; + DWORD_PTR RVA = 0, VA = 0; + WORD ordinal = 0; + WORD i = 0, j = 0; + bool withoutName; + + + addressOfFunctionsArray = (DWORD*)((DWORD_PTR)pExportDir->AddressOfFunctions + deltaAddress); + addressOfNamesArray = (DWORD*)((DWORD_PTR)pExportDir->AddressOfNames + deltaAddress); + addressOfNameOrdinalsArray = (WORD*)((DWORD_PTR)pExportDir->AddressOfNameOrdinals + deltaAddress); + +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"parseExportTable :: module %s NumberOfNames %X", module->fullPath, pExportDir->NumberOfNames); +#endif + + for(i = 0; i < pExportDir->NumberOfNames; i++) + { + functionName = (char*)(addressOfNamesArray[i] + deltaAddress); + ordinal = (WORD)(addressOfNameOrdinalsArray[i] + pExportDir->Base); + RVA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]]; + VA = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + module->modBaseAddr; + +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"parseExportTable :: api %S ordinal %d imagebase " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" VA " PRINTF_DWORD_PTR_FULL, functionName, ordinal, module->modBaseAddr, RVA, VA); +#endif + if(!isApiBlacklisted(functionName)) + { + if(!isApiForwarded(RVA, pNtHeader)) + { + addApi(functionName, i, ordinal, VA, RVA, false, module); + } + else + { + //printf("Forwarded: %s\n",functionName); + handleForwardedApi(RVA + deltaAddress, functionName, RVA, ordinal, module); + } + } + + } + + /*Exports without name*/ + if(pExportDir->NumberOfNames != pExportDir->NumberOfFunctions) + { + for(i = 0; i < pExportDir->NumberOfFunctions; i++) + { + withoutName = true; + for(j = 0; j < pExportDir->NumberOfNames; j++) + { + if(addressOfNameOrdinalsArray[j] == i) + { + withoutName = false; + break; + } + } + if(withoutName && addressOfFunctionsArray[i] != 0) + { + ordinal = (WORD)(i + pExportDir->Base); + RVA = addressOfFunctionsArray[i]; + VA = (addressOfFunctionsArray[i] + module->modBaseAddr); + + + if(!isApiForwarded(RVA, pNtHeader)) + { + addApiWithoutName(ordinal, VA, RVA, false, module); + } + else + { + handleForwardedApi(RVA + deltaAddress, 0, RVA, ordinal, module); + } + + } + } + } +} + +void ApiReader::findApiByModuleAndOrdinal(ModuleInfo* module, WORD ordinal, DWORD_PTR* vaApi, DWORD_PTR* rvaApi) +{ + findApiByModule(module, 0, ordinal, vaApi, rvaApi); +} + +void ApiReader::findApiByModuleAndName(ModuleInfo* module, char* searchFunctionName, DWORD_PTR* vaApi, DWORD_PTR* rvaApi) +{ + findApiByModule(module, searchFunctionName, 0, vaApi, rvaApi); +} + +void ApiReader::findApiByModule(ModuleInfo* module, char* searchFunctionName, WORD ordinal, DWORD_PTR* vaApi, DWORD_PTR* rvaApi) +{ + if(isModuleLoadedInOwnProcess(module)) + { + HMODULE hModule = GetModuleHandle(module->getFilename()); + + if(hModule) + { + if(vaApi) + { + if(ordinal) + { + *vaApi = (DWORD_PTR)GetProcAddress(hModule, (LPCSTR)ordinal); + } + else + { + *vaApi = (DWORD_PTR)GetProcAddress(hModule, searchFunctionName); + } + + *rvaApi = (*vaApi) - (DWORD_PTR)hModule; + *vaApi = (*rvaApi) + module->modBaseAddr; + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"findApiByModule :: vaApi == NULL, should never happen %S", searchFunctionName); +#endif + } + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"findApiByModule :: hModule == NULL, should never happen %s", module->getFilename()); +#endif + } + } + else + { + //search api in extern process + findApiInProcess(module, searchFunctionName, ordinal, vaApi, rvaApi); + } +} + +bool ApiReader::isModuleLoadedInOwnProcess(ModuleInfo* module) +{ + for(unsigned int i = 0; i < ownModuleList.size(); i++) + { + if(!_wcsicmp(module->fullPath, ownModuleList[i].fullPath)) + { + //printf("isModuleLoadedInOwnProcess :: %s %s\n",module->fullPath,ownModuleList[i].fullPath); + return true; + } + } + return false; +} + +void ApiReader::parseModuleWithOwnProcess(ModuleInfo* module) +{ + PIMAGE_NT_HEADERS pNtHeader = 0; + PIMAGE_DOS_HEADER pDosHeader = 0; + HMODULE hModule = GetModuleHandle(module->getFilename()); + + if(hModule) + { + pDosHeader = (PIMAGE_DOS_HEADER)hModule; + pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + (DWORD_PTR)(pDosHeader->e_lfanew)); + + if(isPeAndExportTableValid(pNtHeader)) + { + parseExportTable(module, pNtHeader, (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)hModule + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), (DWORD_PTR)hModule); + } + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"parseModuleWithOwnProcess :: hModule is NULL"); +#endif + } +} + +bool ApiReader::isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader) +{ + if(pNtHeader->Signature != IMAGE_NT_SIGNATURE) + { + // Scylla::windowLog.log(L"-> IMAGE_NT_SIGNATURE doesn't match."); + return false; + } + else if((pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0) || (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size == 0)) + { + // Scylla::windowLog.log(L"-> No export table."); + return false; + } + else + { + return true; + } +} + +void ApiReader::findApiInProcess(ModuleInfo* module, char* searchFunctionName, WORD ordinal, DWORD_PTR* vaApi, DWORD_PTR* rvaApi) +{ + PIMAGE_NT_HEADERS pNtHeader = 0; + PIMAGE_DOS_HEADER pDosHeader = 0; + BYTE* bufferHeader = 0; + BYTE* bufferExportTable = 0; + + + bufferHeader = getHeaderFromProcess(module); + + if(bufferHeader == 0) + return; + + pDosHeader = (PIMAGE_DOS_HEADER)bufferHeader; + pNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)bufferHeader + (DWORD_PTR)(pDosHeader->e_lfanew)); + + if(isPeAndExportTableValid(pNtHeader)) + { + bufferExportTable = getExportTableFromProcess(module, pNtHeader); + + if(bufferExportTable) + { + findApiInExportTable(module, (PIMAGE_EXPORT_DIRECTORY)bufferExportTable, (DWORD_PTR)bufferExportTable - pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, searchFunctionName, ordinal, vaApi, rvaApi); + delete[] bufferExportTable; + } + } + + delete[] bufferHeader; +} + +bool ApiReader::findApiInExportTable(ModuleInfo* module, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress, char* searchFunctionName, WORD ordinal, DWORD_PTR* vaApi, DWORD_PTR* rvaApi) +{ + DWORD* addressOfFunctionsArray = 0, *addressOfNamesArray = 0; + WORD* addressOfNameOrdinalsArray = 0; + char* functionName = 0; + DWORD i = 0, j = 0; + + addressOfFunctionsArray = (DWORD*)((DWORD_PTR)pExportDir->AddressOfFunctions + deltaAddress); + addressOfNamesArray = (DWORD*)((DWORD_PTR)pExportDir->AddressOfNames + deltaAddress); + addressOfNameOrdinalsArray = (WORD*)((DWORD_PTR)pExportDir->AddressOfNameOrdinals + deltaAddress); + + if(searchFunctionName) + { + for(i = 0; i < pExportDir->NumberOfNames; i++) + { + functionName = (char*)(addressOfNamesArray[i] + deltaAddress); + + if(!strcmp(functionName, searchFunctionName)) + { + *rvaApi = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]]; + *vaApi = addressOfFunctionsArray[addressOfNameOrdinalsArray[i]] + module->modBaseAddr; + return true; + } + } + } + else + { + for(i = 0; i < pExportDir->NumberOfFunctions; i++) + { + if(ordinal == (i + pExportDir->Base)) + { + *rvaApi = addressOfFunctionsArray[i]; + *vaApi = (addressOfFunctionsArray[i] + module->modBaseAddr); + return true; + } + } + } + + return false; +} + + +void ApiReader::setModulePriority(ModuleInfo* module) +{ + const WCHAR* moduleFileName = module->getFilename(); + + //imports by kernelbase don't exist + if(!_wcsicmp(moduleFileName, L"kernelbase.dll")) + { + module->priority = -1; + } + else if(!_wcsicmp(moduleFileName, L"ntdll.dll")) + { + module->priority = 0; + } + else if(!_wcsicmp(moduleFileName, L"shlwapi.dll")) + { + module->priority = 0; + } + else if(!_wcsicmp(moduleFileName, L"ShimEng.dll")) + { + module->priority = 0; + } + else if(!_wcsicmp(moduleFileName, L"kernel32.dll")) + { + module->priority = 2; + } + else if(!_wcsnicmp(moduleFileName, L"API-", 4) || !_wcsnicmp(moduleFileName, L"EXT-", 4)) //API_SET_PREFIX_NAME, API_SET_EXTENSION + { + module->priority = 0; + } + else + { + module->priority = 1; + } +} + +bool ApiReader::isApiAddressValid(DWORD_PTR virtualAddress) +{ + return apiList.count(virtualAddress) > 0; +} + +ApiInfo* ApiReader::getApiByVirtualAddress(DWORD_PTR virtualAddress, bool* isSuspect) +{ + std::unordered_multimap::iterator it1, it2; + size_t c = 0; + size_t countDuplicates = apiList.count(virtualAddress); + int countHighPriority = 0; + ApiInfo* apiFound = 0; + + + if(countDuplicates == 0) + { + return 0; + } + else if(countDuplicates == 1) + { + //API is 100% correct + *isSuspect = false; + it1 = apiList.find(virtualAddress); // Find first match. + return (ApiInfo*)((*it1).second); + } + else + { + it1 = apiList.find(virtualAddress); // Find first match. + + //any high priority with a name + apiFound = getScoredApi(it1, countDuplicates, true, false, false, true, false, false, false, false); + + if(apiFound) + return apiFound; + + *isSuspect = true; + + //high priority with a name and ansi/unicode name + apiFound = getScoredApi(it1, countDuplicates, true, true, false, true, false, false, false, false); + + if(apiFound) + return apiFound; + + //priority 2 with no underline in name + apiFound = getScoredApi(it1, countDuplicates, true, false, true, false, false, false, true, false); + + if(apiFound) + return apiFound; + + //priority 1 with a name + apiFound = getScoredApi(it1, countDuplicates, true, false, false, false, false, true, false, false); + + if(apiFound) + return apiFound; + + //With a name + apiFound = getScoredApi(it1, countDuplicates, true, false, false, false, false, false, false, false); + + if(apiFound) + return apiFound; + + //any with priority, name, ansi/unicode + apiFound = getScoredApi(it1, countDuplicates, true, true, false, true, false, false, false, true); + + if(apiFound) + return apiFound; + + //any with priority + apiFound = getScoredApi(it1, countDuplicates, false, false, false, true, false, false, false, true); + + if(apiFound) + return apiFound; + + //has prio 0 and name + apiFound = getScoredApi(it1, countDuplicates, false, false, false, false, true, false, false, true); + + if(apiFound) + return apiFound; + } + + //is never reached + // Scylla::windowLog.log(L"getApiByVirtualAddress :: There is a api resolving bug, VA: " PRINTF_DWORD_PTR_FULL, virtualAddress); + for(size_t c = 0; c < countDuplicates; c++, it1++) + { + apiFound = (ApiInfo*)((*it1).second); + // Scylla::windowLog.log(L"-> Possible API: %S ord: %d ", apiFound->name, apiFound->ordinal); + } + return (ApiInfo*) 1; +} + +ApiInfo* ApiReader::getScoredApi(std::unordered_multimap::iterator it1, size_t countDuplicates, bool hasName, bool hasUnicodeAnsiName, bool hasNoUnderlineInName, bool hasPrioDll, bool hasPrio0Dll, bool hasPrio1Dll, bool hasPrio2Dll, bool firstWin) +{ + ApiInfo* foundApi = 0; + ApiInfo* foundMatchingApi = 0; + int countFoundApis = 0; + int scoreNeeded = 0; + int scoreValue = 0; + size_t apiNameLength = 0; + + if(hasUnicodeAnsiName || hasNoUnderlineInName) + { + hasName = true; + } + + if(hasName) + scoreNeeded++; + + if(hasUnicodeAnsiName) + scoreNeeded++; + + if(hasNoUnderlineInName) + scoreNeeded++; + + if(hasPrioDll) + scoreNeeded++; + + if(hasPrio0Dll) + scoreNeeded++; + + if(hasPrio1Dll) + scoreNeeded++; + + if(hasPrio2Dll) + scoreNeeded++; + + for(size_t c = 0; c < countDuplicates; c++, it1++) + { + foundApi = (ApiInfo*)((*it1).second); + scoreValue = 0; + + if(hasName) + { + if(foundApi->name[0] != 0x00) + { + scoreValue++; + + if(hasUnicodeAnsiName) + { + apiNameLength = strlen(foundApi->name); + + if((foundApi->name[apiNameLength - 1] == 'W') || (foundApi->name[apiNameLength - 1] == 'A')) + { + scoreValue++; + } + } + + if(hasNoUnderlineInName) + { + if(!strrchr(foundApi->name, '_')) + { + scoreValue++; + } + } + } + } + + if(hasPrioDll) + { + if(foundApi->module->priority >= 1) + { + scoreValue++; + } + } + + if(hasPrio0Dll) + { + if(foundApi->module->priority == 0) + { + scoreValue++; + } + } + + if(hasPrio1Dll) + { + if(foundApi->module->priority == 1) + { + scoreValue++; + } + } + + if(hasPrio2Dll) + { + if(foundApi->module->priority == 2) + { + scoreValue++; + } + } + + + if(scoreValue == scoreNeeded) + { + foundMatchingApi = foundApi; + countFoundApis++; + + if(firstWin) + { + return foundMatchingApi; + } + } + } + + if(countFoundApis == 1) + { + return foundMatchingApi; + } + else + { + return (ApiInfo*)0; + } + +} + +void ApiReader::setMinMaxApiAddress(DWORD_PTR virtualAddress) +{ + if(virtualAddress < minApiAddress) + { + minApiAddress = virtualAddress - 1; + } + if(virtualAddress > maxApiAddress) + { + maxApiAddress = virtualAddress + 1; + } +} + +void ApiReader::readAndParseIAT(DWORD_PTR addressIAT, DWORD sizeIAT, std::map & moduleListNew) +{ + moduleThunkList = &moduleListNew; + BYTE* dataIat = new BYTE[sizeIAT]; + if(readMemoryFromProcess(addressIAT, sizeIAT, dataIat)) + { + parseIAT(addressIAT, dataIat, sizeIAT); + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"ApiReader::readAndParseIAT :: error reading iat " PRINTF_DWORD_PTR_FULL, addressIAT); +#endif + } + + delete[] dataIat; +} + +void ApiReader::parseIAT(DWORD_PTR addressIAT, BYTE* iatBuffer, SIZE_T size) +{ + ApiInfo* apiFound = 0; + ModuleInfo* module = 0; + bool isSuspect = false; + int countApiFound = 0, countApiNotFound = 0; + DWORD_PTR* pIATAddress = (DWORD_PTR*)iatBuffer; + SIZE_T sizeIAT = size / sizeof(DWORD_PTR); + + for(SIZE_T i = 0; i < sizeIAT; i++) + { + //Scylla::windowLog.log(L"%08X %08X %d von %d", addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i],i,sizeIAT); + + if(!isInvalidMemoryForIat(pIATAddress[i])) + { + if((pIATAddress[i] > minApiAddress) && (pIATAddress[i] < maxApiAddress)) + { + + apiFound = getApiByVirtualAddress(pIATAddress[i], &isSuspect); + if(apiFound == 0) + { + //Scylla::windowLog.log(L"getApiByVirtualAddress :: No Api found " PRINTF_DWORD_PTR_FULL, pIATAddress[i]); + } + if(apiFound == (ApiInfo*)1) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"apiFound == (ApiInfo *)1 -> " PRINTF_DWORD_PTR_FULL, pIATAddress[i]); +#endif + } + else if(apiFound) + { + countApiFound++; +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(PRINTF_DWORD_PTR_FULL L" %s %d %s", apiFound->va, apiFound->module->getFilename(), apiFound->ordinal, apiFound->name); +#endif + if(module != apiFound->module) + { + module = apiFound->module; + addFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, apiFound, true, isSuspect); + } + else + { + addFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, apiFound, false, isSuspect); + } + + } + else + { + countApiNotFound++; + addNotFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i]); + //printf("parseIAT :: API not found %08X\n", pIATAddress[i]); + } + } + else + { + //printf("parseIAT :: API not found %08X\n", pIATAddress[i]); + countApiNotFound++; + addNotFoundApiToModuleList(addressIAT + (DWORD_PTR)&pIATAddress[i] - (DWORD_PTR)iatBuffer, pIATAddress[i]); + } + } + + } + + //Scylla::windowLog.log(L"IAT parsing finished, found %d valid APIs, missed %d APIs", countApiFound, countApiNotFound); +} + +void ApiReader::addFoundApiToModuleList(DWORD_PTR iatAddressVA, ApiInfo* apiFound, bool isNewModule, bool isSuspect) +{ + if(isNewModule) + { + addModuleToModuleList(apiFound->module->getFilename(), iatAddressVA - targetImageBase); + } + addFunctionToModuleList(apiFound, iatAddressVA, iatAddressVA - targetImageBase, apiFound->ordinal, true, isSuspect); +} + +bool ApiReader::addModuleToModuleList(const WCHAR* moduleName, DWORD_PTR firstThunk) +{ + ImportModuleThunk module; + + module.firstThunk = firstThunk; + wcscpy_s(module.moduleName, moduleName); + + (*moduleThunkList).insert(std::pair(firstThunk, module)); + + return true; +} + +void ApiReader::addUnknownModuleToModuleList(DWORD_PTR firstThunk) +{ + ImportModuleThunk module; + + module.firstThunk = firstThunk; + wcscpy_s(module.moduleName, L"?"); + + (*moduleThunkList).insert(std::pair(firstThunk, module)); +} + +bool ApiReader::addFunctionToModuleList(ApiInfo* apiFound, DWORD_PTR va, DWORD_PTR rva, WORD ordinal, bool valid, bool suspect) +{ + ImportThunk import; + ImportModuleThunk* module = 0; + std::map::iterator iterator1; + + if((*moduleThunkList).size() > 1) + { + iterator1 = (*moduleThunkList).begin(); + while(iterator1 != (*moduleThunkList).end()) + { + if(rva >= iterator1->second.firstThunk) + { + iterator1++; + if(iterator1 == (*moduleThunkList).end()) + { + iterator1--; + module = &(iterator1->second); + break; + } + else if(rva < iterator1->second.firstThunk) + { + iterator1--; + module = &(iterator1->second); + break; + } + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"Error iterator1 != (*moduleThunkList).end()"); +#endif + break; + } + } + } + else + { + iterator1 = (*moduleThunkList).begin(); + module = &(iterator1->second); + } + + if(!module) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL, rva); +#endif + return false; + } + + + import.suspect = suspect; + import.valid = valid; + import.va = va; + import.rva = rva; + import.apiAddressVA = apiFound->va; + import.ordinal = ordinal; + import.hint = (WORD)apiFound->hint; + + wcscpy_s(import.moduleName, apiFound->module->getFilename()); + strcpy_s(import.name, apiFound->name); + + module->thunkList.insert(std::pair(import.rva, import)); + + return true; +} + +void ApiReader::clearAll() +{ + minApiAddress = -1; + maxApiAddress = 0; + + for(std::unordered_map::iterator it = apiList.begin(); it != apiList.end(); ++it) + { + delete it->second; + } + apiList.clear(); + + if(moduleThunkList != 0) + { + (*moduleThunkList).clear(); + } +} + +bool ApiReader::addNotFoundApiToModuleList(DWORD_PTR iatAddressVA, DWORD_PTR apiAddress) +{ + ImportThunk import; + ImportModuleThunk* module = 0; + std::map::iterator iterator1; + DWORD_PTR rva = iatAddressVA - targetImageBase; + + if((*moduleThunkList).size() > 0) + { + iterator1 = (*moduleThunkList).begin(); + while(iterator1 != (*moduleThunkList).end()) + { + if(rva >= iterator1->second.firstThunk) + { + iterator1++; + if(iterator1 == (*moduleThunkList).end()) + { + iterator1--; + //new unknown module + if(iterator1->second.moduleName[0] == L'?') + { + module = &(iterator1->second); + } + else + { + addUnknownModuleToModuleList(rva); + module = &((*moduleThunkList).find(rva)->second); + } + + break; + } + else if(rva < iterator1->second.firstThunk) + { + iterator1--; + module = &(iterator1->second); + break; + } + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"Error iterator1 != (*moduleThunkList).end()\r\n"); +#endif + break; + } + } + } + else + { + //new unknown module + addUnknownModuleToModuleList(rva); + module = &((*moduleThunkList).find(rva)->second); + } + + if(!module) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"ImportsHandling::addFunction module not found rva " PRINTF_DWORD_PTR_FULL, rva); +#endif + return false; + } + + + import.suspect = true; + import.valid = false; + import.va = iatAddressVA; + import.rva = rva; + import.apiAddressVA = apiAddress; + import.ordinal = 0; + + wcscpy_s(import.moduleName, L"?"); + strcpy_s(import.name, "?"); + + module->thunkList.insert(std::pair(import.rva, import)); + + return true; +} + +bool ApiReader::isApiBlacklisted(const char* functionName) +{ + if(SystemInformation::currenOS < WIN_VISTA_32) + { + if(!strcmp(functionName, "RestoreLastError")) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } + + + /*#ifdef _WIN64 + else if (SystemInformation::currenOS == WIN_XP_64 && !strcmp(functionName, "DecodePointer")) + { + return true; + } + #endif*/ +} + +bool ApiReader::isWinSxSModule(ModuleInfo* module) +{ + if(wcsstr(module->fullPath, L"\\WinSxS\\")) + { + return true; + } + else if(wcsstr(module->fullPath, L"\\winsxs\\")) + { + return true; + } + else + { + return false; + } +} + +bool ApiReader::isInvalidMemoryForIat(DWORD_PTR address) +{ + if(address == 0) + return true; + + if(address == -1) + return true; + + MEMORY_BASIC_INFORMATION memBasic = {0}; + + if(VirtualQueryEx(ProcessAccessHelp::hProcess, (LPCVOID)address, &memBasic, sizeof(MEMORY_BASIC_INFORMATION))) + { + if((memBasic.State == MEM_COMMIT) && ProcessAccessHelp::isPageAccessable(memBasic.Protect)) + { + return false; + } + else + { + return true; + } + } + else + { + return true; + } +} diff --git a/scylla_wrapper/ApiReader.h b/scylla_wrapper/ApiReader.h new file mode 100644 index 0000000..a0d61c8 --- /dev/null +++ b/scylla_wrapper/ApiReader.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include +#include +#include "ProcessAccessHelp.h" +#include "Thunks.h" + +typedef std::pair API_Pair; + +class ApiReader : public ProcessAccessHelp +{ +public: + static std::unordered_multimap apiList; //api look up table + + static std::map* moduleThunkList; //store found apis + + static DWORD_PTR minApiAddress; + static DWORD_PTR maxApiAddress; + + /* + * Read all APIs from target process + */ + void readApisFromModuleList(); + + bool isApiAddressValid(DWORD_PTR virtualAddress); + ApiInfo* getApiByVirtualAddress(DWORD_PTR virtualAddress, bool* isSuspect); + void readAndParseIAT(DWORD_PTR addressIAT, DWORD sizeIAT, std::map & moduleListNew); + void addFoundApiToModuleList(DWORD_PTR iatAddress, ApiInfo* apiFound, bool isNewModule, bool isSuspect); + bool addModuleToModuleList(const WCHAR* moduleName, DWORD_PTR firstThunk); + void clearAll(); + bool isInvalidMemoryForIat(DWORD_PTR address); + +private: + bool readExportTableAlwaysFromDisk; + void parseIAT(DWORD_PTR addressIAT, BYTE* iatBuffer, SIZE_T size); + + void addApi(char* functionName, WORD hint, WORD ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo* moduleInfo); + void addApiWithoutName(WORD ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo* moduleInfo); + inline bool isApiForwarded(DWORD_PTR rva, PIMAGE_NT_HEADERS pNtHeader); + void handleForwardedApi(DWORD_PTR vaStringPointer, char* functionNameParent, DWORD_PTR rvaParent, WORD ordinalParent, ModuleInfo* moduleParent); + void parseModule(ModuleInfo* module); + void parseModuleWithProcess(ModuleInfo* module); + + void parseExportTable(ModuleInfo* module, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress); + + ModuleInfo* findModuleByName(WCHAR* name); + + void findApiByModuleAndOrdinal(ModuleInfo* module, WORD ordinal, DWORD_PTR* vaApi, DWORD_PTR* rvaApi); + void findApiByModuleAndName(ModuleInfo* module, char* searchFunctionName, DWORD_PTR* vaApi, DWORD_PTR* rvaApi); + void findApiByModule(ModuleInfo* module, char* searchFunctionName, WORD ordinal, DWORD_PTR* vaApi, DWORD_PTR* rvaApi); + + bool isModuleLoadedInOwnProcess(ModuleInfo* module); + void parseModuleWithOwnProcess(ModuleInfo* module); + bool isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader); + void findApiInProcess(ModuleInfo* module, char* searchFunctionName, WORD ordinal, DWORD_PTR* vaApi, DWORD_PTR* rvaApi); + bool findApiInExportTable(ModuleInfo* module, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress, char* searchFunctionName, WORD ordinal, DWORD_PTR* vaApi, DWORD_PTR* rvaApi); + + BYTE* getHeaderFromProcess(ModuleInfo* module); + BYTE* getExportTableFromProcess(ModuleInfo* module, PIMAGE_NT_HEADERS pNtHeader); + + void setModulePriority(ModuleInfo* module); + void setMinMaxApiAddress(DWORD_PTR virtualAddress); + + void parseModuleWithMapping(ModuleInfo* moduleInfo); //not used + bool addFunctionToModuleList(ApiInfo* apiFound, DWORD_PTR va, DWORD_PTR rva, WORD ordinal, bool valid, bool suspect); + bool addNotFoundApiToModuleList(DWORD_PTR iatAddressVA, DWORD_PTR apiAddress); + + void addUnknownModuleToModuleList(DWORD_PTR firstThunk); + bool isApiBlacklisted(const char* functionName); + bool isWinSxSModule(ModuleInfo* module); + + ApiInfo* getScoredApi(std::unordered_map::iterator it1, size_t countDuplicates, bool hasName, bool hasUnicodeAnsiName, bool hasNoUnderlineInName, bool hasPrioDll, bool hasPrio0Dll, bool hasPrio1Dll, bool hasPrio2Dll, bool firstWin); +}; diff --git a/scylla_wrapper/Architecture.cpp b/scylla_wrapper/Architecture.cpp new file mode 100644 index 0000000..2e52cb1 --- /dev/null +++ b/scylla_wrapper/Architecture.cpp @@ -0,0 +1,24 @@ +#include "stdafx.h" +#include "Architecture.h" + +/* +#ifdef _WIN64 + +const WCHAR Architecture::NAME[] = L"x64"; + +const WCHAR Architecture::PRINTF_DWORD_PTR[] = L"%I64X"; +const WCHAR Architecture::PRINTF_DWORD_PTR_FULL[] = L"%016I64X"; +const WCHAR Architecture::PRINTF_DWORD_PTR_HALF[] = L"%08I64X"; +const WCHAR Architecture::PRINTF_INTEGER[] = L"%I64u"; + +#else + +const WCHAR Architecture::NAME[] = L"x86"; + +const WCHAR Architecture::PRINTF_DWORD_PTR[] = L"%X"; +const WCHAR Architecture::PRINTF_DWORD_PTR_FULL[] = L"%08X"; +const WCHAR Architecture::PRINTF_DWORD_PTR_HALF[] = L"%08X"; +const WCHAR Architecture::PRINTF_INTEGER[] = L"%u"; + +#endif +*/ diff --git a/scylla_wrapper/Architecture.h b/scylla_wrapper/Architecture.h new file mode 100644 index 0000000..4baad94 --- /dev/null +++ b/scylla_wrapper/Architecture.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#ifdef _WIN64 + +#define ARCHITECTURE_S "x64" +#define PRINTF_DWORD_PTR_S "%I64X" +#define PRINTF_DWORD_PTR_FULL_S "%016I64X" +#define PRINTF_DWORD_PTR_HALF_S "%08I64X" +#define PRINTF_INTEGER_S "%I64u" + +#else + +#define ARCHITECTURE_S "x86" +#define PRINTF_DWORD_PTR_S "%X" +#define PRINTF_DWORD_PTR_FULL_S "%08X" +#define PRINTF_DWORD_PTR_HALF_S "%08X" +#define PRINTF_INTEGER_S "%u" + +#endif + +#define ARCHITECTURE TEXT(ARCHITECTURE_S) +#define PRINTF_DWORD_PTR TEXT(PRINTF_DWORD_PTR_S) +#define PRINTF_DWORD_PTR_FULL TEXT(PRINTF_DWORD_PTR_FULL_S) +#define PRINTF_DWORD_PTR_HALF TEXT(PRINTF_DWORD_PTR_HALF_S) +#define PRINTF_INTEGER TEXT(PRINTF_INTEGER_S) diff --git a/scylla_wrapper/DeviceNameResolver.cpp b/scylla_wrapper/DeviceNameResolver.cpp new file mode 100644 index 0000000..11a1bbf --- /dev/null +++ b/scylla_wrapper/DeviceNameResolver.cpp @@ -0,0 +1,102 @@ +#include "stdafx.h" +#include "DeviceNameResolver.h" +#include "NativeWinApi.h" + +DeviceNameResolver::DeviceNameResolver() +{ + NativeWinApi::initialize(); + initDeviceNameList(); +} + +DeviceNameResolver::~DeviceNameResolver() +{ + deviceNameList.clear(); +} + +void DeviceNameResolver::initDeviceNameList() +{ + TCHAR shortName[3] = {0}; + TCHAR longName[MAX_PATH] = {0}; + HardDisk hardDisk; + + shortName[1] = TEXT(':'); + + deviceNameList.reserve(3); + + for(TCHAR shortD = TEXT('a'); shortD < TEXT('z'); shortD++) + { + shortName[0] = shortD; + if(QueryDosDevice(shortName, longName, MAX_PATH) > 0) + { + hardDisk.shortName[0] = _totupper(shortD); + hardDisk.shortName[1] = TEXT(':'); + hardDisk.shortName[2] = 0; + + hardDisk.longNameLength = _tcslen(longName); + + + _tcscpy_s(hardDisk.longName, longName); + deviceNameList.push_back(hardDisk); + } + } + + fixVirtualDevices(); +} + +bool DeviceNameResolver::resolveDeviceLongNameToShort(const TCHAR* sourcePath, TCHAR* targetPath) +{ + for(unsigned int i = 0; i < deviceNameList.size(); i++) + { + if(!_tcsnicmp(deviceNameList[i].longName, sourcePath, deviceNameList[i].longNameLength)) + { + _tcscpy_s(targetPath, MAX_PATH, deviceNameList[i].shortName); + _tcscat_s(targetPath, MAX_PATH, sourcePath + deviceNameList[i].longNameLength); + return true; + } + } + + return false; +} + +void DeviceNameResolver::fixVirtualDevices() +{ + const USHORT BufferSize = MAX_PATH * 2 * sizeof(WCHAR); + WCHAR longCopy[MAX_PATH] = {0}; + OBJECT_ATTRIBUTES oa = {0}; + UNICODE_STRING unicodeInput = {0}; + UNICODE_STRING unicodeOutput = {0}; + HANDLE hFile = 0; + ULONG retLen = 0; + HardDisk hardDisk; + + unicodeOutput.Buffer = (PWSTR)malloc(BufferSize); + if(!unicodeOutput.Buffer) + return; + + for(unsigned int i = 0; i < deviceNameList.size(); i++) + { + wcscpy_s(longCopy, deviceNameList[i].longName); + + NativeWinApi::RtlInitUnicodeString(&unicodeInput, longCopy); + InitializeObjectAttributes(&oa, &unicodeInput, 0, 0, 0); + + if(NT_SUCCESS(NativeWinApi::NtOpenSymbolicLinkObject(&hFile, SYMBOLIC_LINK_QUERY, &oa))) + { + unicodeOutput.Length = BufferSize; + unicodeOutput.MaximumLength = unicodeOutput.Length; + ZeroMemory(unicodeOutput.Buffer, unicodeOutput.Length); + + if(NT_SUCCESS(NativeWinApi::NtQuerySymbolicLinkObject(hFile, &unicodeOutput, &retLen))) + { + hardDisk.longNameLength = wcslen(unicodeOutput.Buffer); + wcscpy_s(hardDisk.shortName, deviceNameList[i].shortName); + wcscpy_s(hardDisk.longName, unicodeOutput.Buffer); + deviceNameList.push_back(hardDisk); + } + + NativeWinApi::NtClose(hFile); + } + } + + free(unicodeOutput.Buffer); +} diff --git a/scylla_wrapper/DeviceNameResolver.h b/scylla_wrapper/DeviceNameResolver.h new file mode 100644 index 0000000..d46ffe5 --- /dev/null +++ b/scylla_wrapper/DeviceNameResolver.h @@ -0,0 +1,31 @@ +#include + + +#pragma once + +#include +#include +#include + +class HardDisk +{ +public: + TCHAR shortName[3]; + TCHAR longName[MAX_PATH]; + size_t longNameLength; +}; + +class DeviceNameResolver +{ +public: + DeviceNameResolver(); + ~DeviceNameResolver(); + bool resolveDeviceLongNameToShort(const TCHAR* sourcePath, TCHAR* targetPath); +private: + std::vector deviceNameList; + + void initDeviceNameList(); + void fixVirtualDevices(); +}; + + diff --git a/scylla_wrapper/IATReferenceScan.cpp b/scylla_wrapper/IATReferenceScan.cpp new file mode 100644 index 0000000..01ce9fd --- /dev/null +++ b/scylla_wrapper/IATReferenceScan.cpp @@ -0,0 +1,738 @@ +#include "stdafx.h" +#include "IATReferenceScan.h" +#include "Architecture.h" +#include + +//#define DEBUG_COMMENTS + + +//FileLog IATReferenceScan::directImportLog(L"Scylla_direct_imports.log"); + +int IATReferenceScan::numberOfFoundDirectImports() +{ + return (int)iatDirectImportList.size(); +} + +int IATReferenceScan::numberOfFoundUniqueDirectImports() +{ + std::set apiPointers; + for(std::vector::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++) + { + IATReference* ref = &(*iter); + apiPointers.insert(ref->targetAddressInIat); + } + + return (int)apiPointers.size(); +} + +int IATReferenceScan::numberOfDirectImportApisNotInIat() +{ + std::set apiPointers; + for(std::vector::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++) + { + IATReference* ref = &(*iter); + + if(ref->targetPointer == 0) + { + apiPointers.insert(ref->targetAddressInIat); + } + } + + return (int)apiPointers.size(); +} + +int IATReferenceScan::getSizeInBytesOfJumpTableInSection() +{ + return (numberOfFoundUniqueDirectImports() * 6); //for x86 and x64 the same size, FF25 00000000 +} + +void IATReferenceScan::startScan(DWORD_PTR imageBase, DWORD imageSize, DWORD_PTR iatAddress, DWORD iatSize) +{ + MEMORY_BASIC_INFORMATION memBasic = {0}; + + IatAddressVA = iatAddress; + IatSize = iatSize; + ImageBase = imageBase; + ImageSize = imageSize; + + if(ScanForNormalImports) + { + iatReferenceList.clear(); + iatReferenceList.reserve(200); + } + if(ScanForDirectImports) + { + iatDirectImportList.clear(); + iatDirectImportList.reserve(50); + } + + + + DWORD_PTR section = imageBase; + + do + { + if(!VirtualQueryEx(ProcessAccessHelp::hProcess, (LPCVOID)section, &memBasic, sizeof(MEMORY_BASIC_INFORMATION))) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"VirtualQueryEx failed %d", GetLastError()); +#endif + + break; + } + else + { + if(ProcessAccessHelp::isPageExecutable(memBasic.Protect)) + { + //do read and scan + scanMemoryPage(memBasic.BaseAddress, memBasic.RegionSize); + } + } + + section = (DWORD_PTR)((SIZE_T)section + memBasic.RegionSize); + + } + while(section < (imageBase + imageSize)); + + +} + +//void IATReferenceScan::patchNewIatBaseMemory(DWORD_PTR newIatBaseAddress) +//{ +// NewIatAddressVA = newIatBaseAddress; +// +// for (std::vector::iterator iter = iatReferenceList.begin(); iter != iatReferenceList.end(); iter++) +// { +// patchReferenceInMemory(&(*iter)); +// } +//} +// +//void IATReferenceScan::patchNewIatBaseFile(DWORD_PTR newIatBaseAddress) +//{ +// NewIatAddressVA = newIatBaseAddress; +// +// for (std::vector::iterator iter = iatReferenceList.begin(); iter != iatReferenceList.end(); iter++) +// { +// patchReferenceInFile(&(*iter)); +// } +//} + +void IATReferenceScan::patchDirectImportsMemory(bool junkByteAfterInstruction) +{ + JunkByteAfterInstruction = junkByteAfterInstruction; + for(std::vector::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++) + { + patchDirectImportInMemory(&(*iter)); + } +} + + +void IATReferenceScan::scanMemoryPage(PVOID BaseAddress, SIZE_T RegionSize) +{ + BYTE* dataBuffer = (BYTE*)calloc(RegionSize, 1); + BYTE* currentPos = dataBuffer; + int currentSize = (int)RegionSize; + DWORD_PTR currentOffset = (DWORD_PTR)BaseAddress; + _DecodeResult res; + unsigned int instructionsCount = 0, next = 0; + + if(!dataBuffer) + return; + + if(ProcessAccessHelp::readMemoryFromProcess((DWORD_PTR)BaseAddress, RegionSize, (LPVOID)dataBuffer)) + { + while(1) + { + ZeroMemory(&ProcessAccessHelp::decomposerCi, sizeof(_CodeInfo)); + ProcessAccessHelp::decomposerCi.code = currentPos; + ProcessAccessHelp::decomposerCi.codeLen = currentSize; + ProcessAccessHelp::decomposerCi.dt = ProcessAccessHelp::dt; + ProcessAccessHelp::decomposerCi.codeOffset = currentOffset; + + instructionsCount = 0; + + res = distorm_decompose(&ProcessAccessHelp::decomposerCi, ProcessAccessHelp::decomposerResult, sizeof(ProcessAccessHelp::decomposerResult) / sizeof(ProcessAccessHelp::decomposerResult[0]), &instructionsCount); + + if(res == DECRES_INPUTERR) + { + break; + } + + for(unsigned int i = 0; i < instructionsCount; i++) + { + if(ProcessAccessHelp::decomposerResult[i].flags != FLAG_NOT_DECODABLE) + { + analyzeInstruction(&ProcessAccessHelp::decomposerResult[i]); + } + } + + if(res == DECRES_SUCCESS) break; // All instructions were decoded. + else if(instructionsCount == 0) break; + + next = (unsigned long)(ProcessAccessHelp::decomposerResult[instructionsCount - 1].addr - ProcessAccessHelp::decomposerResult[0].addr); + + if(ProcessAccessHelp::decomposerResult[instructionsCount - 1].flags != FLAG_NOT_DECODABLE) + { + next += ProcessAccessHelp::decomposerResult[instructionsCount - 1].size; + } + + currentPos += next; + currentOffset += next; + currentSize -= next; + } + } + + free(dataBuffer); +} + +void IATReferenceScan::analyzeInstruction(_DInst* instruction) +{ + if(ScanForNormalImports) + { + findNormalIatReference(instruction); + } + + if(ScanForDirectImports) + { + findDirectIatReferenceMov(instruction); + +#ifndef _WIN64 + findDirectIatReferenceCallJmp(instruction); + findDirectIatReferenceLea(instruction); + findDirectIatReferencePush(instruction); +#endif + } +} + +void IATReferenceScan::findNormalIatReference(_DInst* instruction) +{ +#ifdef DEBUG_COMMENTS + _DecodedInst inst; +#endif + + IATReference ref; + + + if(META_GET_FC(instruction->meta) == FC_CALL || META_GET_FC(instruction->meta) == FC_UNC_BRANCH) + { + if(instruction->size >= 5) + { + if(META_GET_FC(instruction->meta) == FC_CALL) + { + ref.type = IAT_REFERENCE_PTR_CALL; + } + else + { + ref.type = IAT_REFERENCE_PTR_JMP; + } + ref.addressVA = (DWORD_PTR)instruction->addr; + ref.instructionSize = instruction->size; + +#ifdef _WIN64 + if(instruction->flags & FLAG_RIP_RELATIVE) + { + +#ifdef DEBUG_COMMENTS + distorm_format(&ProcessAccessHelp::decomposerCi, instruction, &inst); + Scylla::debugLog.log(PRINTF_DWORD_PTR_FULL L" " PRINTF_DWORD_PTR_FULL L" %S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, (DWORD_PTR)instruction->addr, ImageBase, inst.mnemonic.p, inst.operands.p, instruction->ops[0].type, instruction->size, INSTRUCTION_GET_RIP_TARGET(instruction)); +#endif + + if(INSTRUCTION_GET_RIP_TARGET(instruction) >= IatAddressVA && INSTRUCTION_GET_RIP_TARGET(instruction) < (IatAddressVA + IatSize)) + { + ref.targetPointer = INSTRUCTION_GET_RIP_TARGET(instruction); + + getIatEntryAddress(&ref); + + //Scylla::debugLog.log(L"iat entry "PRINTF_DWORD_PTR_FULL,ref.targetAddressInIat); + + iatReferenceList.push_back(ref); + } + } +#else + + if(instruction->ops[0].type == O_DISP) + { + //jmp dword ptr || call dword ptr +#ifdef DEBUG_COMMENTS + distorm_format(&ProcessAccessHelp::decomposerCi, instruction, &inst); + Scylla::debugLog.log(PRINTF_DWORD_PTR_FULL L" " PRINTF_DWORD_PTR_FULL L" %S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, (DWORD_PTR)instruction->addr, ImageBase, inst.mnemonic.p, inst.operands.p, instruction->ops[0].type, instruction->size, instruction->disp); +#endif + + if(instruction->disp >= IatAddressVA && instruction->disp < (IatAddressVA + IatSize)) + { + ref.targetPointer = (DWORD_PTR)instruction->disp; + + getIatEntryAddress(&ref); + + //Scylla::debugLog.log(L"iat entry "PRINTF_DWORD_PTR_FULL,ref.targetAddressInIat); + + iatReferenceList.push_back(ref); + } + } +#endif + } + } +} + +void IATReferenceScan::getIatEntryAddress(IATReference* ref) +{ + if(!ProcessAccessHelp::readMemoryFromProcess(ref->targetPointer, sizeof(DWORD_PTR), &ref->targetAddressInIat)) + { + ref->targetAddressInIat = 0; + } +} + +bool IATReferenceScan::isAddressValidImageMemory(DWORD_PTR address) +{ + MEMORY_BASIC_INFORMATION memBasic = {0}; + + if(!VirtualQueryEx(ProcessAccessHelp::hProcess, (LPCVOID)address, &memBasic, sizeof(MEMORY_BASIC_INFORMATION))) + { + return false; + } + + return (memBasic.Type == MEM_IMAGE && ProcessAccessHelp::isPageExecutable(memBasic.Protect)); +} + +void IATReferenceScan::patchReferenceInMemory(IATReference* ref) +{ + DWORD_PTR newIatAddressPointer = ref->targetPointer - IatAddressVA + NewIatAddressRVA; + + DWORD patchBytes = 0; + +#ifdef _WIN64 + patchBytes = (DWORD)(newIatAddressPointer - ref->addressVA - 6); +#else + patchBytes = newIatAddressPointer; +#endif + ProcessAccessHelp::writeMemoryToProcess(ref->addressVA + 2, sizeof(DWORD), &patchBytes); +} + +void IATReferenceScan::patchDirectImportInMemory(IATReference* ref) +{ + DWORD patchBytes = 0; + BYTE patchPreBytes[2]; + + if(ref->targetPointer) + { + patchPreBytes[0] = 0xFF; + + if(ref->type == IAT_REFERENCE_DIRECT_CALL) //FF15 + { + patchPreBytes[1] = 0x15; + } + else if(ref->type == IAT_REFERENCE_DIRECT_JMP) //FF25 + { + patchPreBytes[1] = 0x25; + } + else + { + return; + } + + if(!JunkByteAfterInstruction) + { + ref->addressVA -= 1; + } + + ProcessAccessHelp::writeMemoryToProcess(ref->addressVA, 2, patchPreBytes); + +#ifdef _WIN64 + patchBytes = (DWORD)(ref->targetPointer - ref->addressVA - 6); +#else + patchBytes = ref->targetPointer; +#endif + ProcessAccessHelp::writeMemoryToProcess(ref->addressVA + 2, sizeof(DWORD), &patchBytes); + } +} + +DWORD_PTR IATReferenceScan::lookUpIatForPointer(DWORD_PTR addr) +{ + if(!iatBackup) + { + iatBackup = (DWORD_PTR*)calloc(IatSize + sizeof(DWORD_PTR), 1); + if(!iatBackup) + { + return 0; + } + if(!ProcessAccessHelp::readMemoryFromProcess(IatAddressVA, IatSize, iatBackup)) + { + free(iatBackup); + iatBackup = 0; + return 0; + } + } + + for(int i = 0; i < ((int)IatSize / (int)sizeof(DWORD_PTR)); i++) + { + if(iatBackup[i] == addr) + { + return (DWORD_PTR)&iatBackup[i] - (DWORD_PTR)iatBackup + IatAddressVA; + } + } + + return 0; +} + +void IATReferenceScan::patchNewIat(DWORD_PTR stdImagebase, DWORD_PTR newIatBaseAddress, PeParser* peParser) +{ + NewIatAddressRVA = newIatBaseAddress; + DWORD patchBytes = 0; + + for(std::vector::iterator iter = iatReferenceList.begin(); iter != iatReferenceList.end(); iter++) + { + IATReference* ref = &(*iter); + + DWORD_PTR newIatAddressPointer = (ref->targetPointer - IatAddressVA) + NewIatAddressRVA + stdImagebase; + +#ifdef _WIN64 + patchBytes = (DWORD)(newIatAddressPointer - (ref->addressVA - ImageBase + stdImagebase) - 6); +#else + patchBytes = newIatAddressPointer; +#endif + DWORD_PTR patchOffset = peParser->convertRVAToOffsetRelative(ref->addressVA - ImageBase); + int index = peParser->convertRVAToOffsetVectorIndex(ref->addressVA - ImageBase); + BYTE* memory = peParser->getSectionMemoryByIndex(index); + DWORD memorySize = peParser->getSectionMemorySizeByIndex(index); + + + if(memorySize < (DWORD)(patchOffset + 6)) + { + // Scylla::debugLog.log(L"Error - Cannot fix IAT reference RVA: " PRINTF_DWORD_PTR_FULL, ref->addressVA - ImageBase); + } + else + { + memory += patchOffset + 2; + + *((DWORD*)memory) = patchBytes; + } + //Scylla::debugLog.log(L"address %X old %X new %X",ref->addressVA, ref->targetPointer, newIatAddressPointer); + + } +} + +void IATReferenceScan::printDirectImportLog() +{ + // IATReferenceScan::directImportLog.log(L"------------------------------------------------------------"); + // IATReferenceScan::directImportLog.log(L"ImageBase " PRINTF_DWORD_PTR_FULL L" ImageSize %08X IATAddress " PRINTF_DWORD_PTR_FULL L" IATSize 0x%X", ImageBase, ImageSize, IatAddressVA, IatSize); + int count = 0; + bool isSuspect = false; + + for(std::vector::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++) + { + IATReference* ref = &(*iter); + + ApiInfo* apiInfo = apiReader->getApiByVirtualAddress(ref->targetAddressInIat, &isSuspect); + + count++; + WCHAR* type = L"U"; + + if(ref->type == IAT_REFERENCE_DIRECT_CALL) + { + type = L"CALL"; + } + else if(ref->type == IAT_REFERENCE_DIRECT_JMP) + { + type = L"JMP"; + } + else if(ref->type == IAT_REFERENCE_DIRECT_MOV) + { + type = L"MOV"; + } + else if(ref->type == IAT_REFERENCE_DIRECT_PUSH) + { + type = L"PUSH"; + } + else if(ref->type == IAT_REFERENCE_DIRECT_LEA) + { + type = L"LEA"; + } + + //IATReferenceScan::directImportLog.log(L"%04d AddrVA " PRINTF_DWORD_PTR_FULL L" Type %s Value " PRINTF_DWORD_PTR_FULL L" IatRefPointer " PRINTF_DWORD_PTR_FULL L" Api %s %S", count, ref->addressVA, type, ref->targetAddressInIat, ref->targetPointer,apiInfo->module->getFilename(), apiInfo->name); + + } + + //IATReferenceScan::directImportLog.log(L"------------------------------------------------------------"); +} + +void IATReferenceScan::findDirectIatReferenceCallJmp(_DInst* instruction) +{ + IATReference ref; + + if(META_GET_FC(instruction->meta) == FC_CALL || META_GET_FC(instruction->meta) == FC_UNC_BRANCH) + { + if((instruction->size >= 5) && (instruction->ops[0].type == O_PC)) //CALL/JMP 0x00000000 + { + if(META_GET_FC(instruction->meta) == FC_CALL) + { + ref.type = IAT_REFERENCE_DIRECT_CALL; + } + else + { + ref.type = IAT_REFERENCE_DIRECT_JMP; + } + + ref.targetAddressInIat = (DWORD_PTR)INSTRUCTION_GET_TARGET(instruction); + + checkMemoryRangeAndAddToList(&ref, instruction); + } + } +} + +void IATReferenceScan::findDirectIatReferenceMov(_DInst* instruction) +{ + IATReference ref; + ref.type = IAT_REFERENCE_DIRECT_MOV; + + if(instruction->opcode == I_MOV) + { +#ifdef _WIN64 + if(instruction->size >= 7) //MOV REGISTER, 0xFFFFFFFFFFFFFFFF +#else + if(instruction->size >= 5) //MOV REGISTER, 0xFFFFFFFF +#endif + { + if(instruction->ops[0].type == O_REG && instruction->ops[1].type == O_IMM) + { + ref.targetAddressInIat = (DWORD_PTR)instruction->imm.qword; + + checkMemoryRangeAndAddToList(&ref, instruction); + } + } + } +} + +void IATReferenceScan::findDirectIatReferencePush(_DInst* instruction) +{ + IATReference ref; + ref.type = IAT_REFERENCE_DIRECT_PUSH; + + if(instruction->size >= 5 && instruction->opcode == I_PUSH) + { + ref.targetAddressInIat = (DWORD_PTR)instruction->imm.qword; + + checkMemoryRangeAndAddToList(&ref, instruction); + } +} + +void IATReferenceScan::findDirectIatReferenceLea(_DInst* instruction) +{ + IATReference ref; + ref.type = IAT_REFERENCE_DIRECT_LEA; + + if(instruction->size >= 5 && instruction->opcode == I_LEA) + { + if(instruction->ops[0].type == O_REG && instruction->ops[1].type == O_DISP) //LEA EDX, [0xb58bb8] + { + ref.targetAddressInIat = (DWORD_PTR)instruction->disp; + + checkMemoryRangeAndAddToList(&ref, instruction); + } + } +} + +void IATReferenceScan::checkMemoryRangeAndAddToList(IATReference* ref, _DInst* instruction) +{ +#ifdef DEBUG_COMMENTS + _DecodedInst inst; +#endif + + if(ref->targetAddressInIat > 0x000FFFFF && ref->targetAddressInIat != (DWORD_PTR) - 1) + { + if((ref->targetAddressInIat < ImageBase) || (ref->targetAddressInIat > (ImageBase + ImageSize))) //outside pe image + { + //if (isAddressValidImageMemory(ref->targetAddressInIat)) + { + bool isSuspect = false; + if(apiReader->getApiByVirtualAddress(ref->targetAddressInIat, &isSuspect) != 0) + { + ref->addressVA = (DWORD_PTR)instruction->addr; + ref->instructionSize = instruction->size; + ref->targetPointer = lookUpIatForPointer(ref->targetAddressInIat); + +#ifdef DEBUG_COMMENTS + distorm_format(&ProcessAccessHelp::decomposerCi, instruction, &inst); + Scylla::debugLog.log(PRINTF_DWORD_PTR_FULL L" " PRINTF_DWORD_PTR_FULL L" %S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, (DWORD_PTR)instruction->addr, ImageBase, inst.mnemonic.p, inst.operands.p, instruction->ops[0].type, instruction->size, ref->targetAddressInIat); +#endif + iatDirectImportList.push_back(*ref); + } + } + } + } +} + +void IATReferenceScan::patchDirectJumpTableEntry(DWORD_PTR targetIatPointer, DWORD_PTR stdImagebase, DWORD directImportsJumpTableRVA, PeParser* peParser, BYTE* jmpTableMemory, DWORD newIatBase) +{ + DWORD patchBytes = 0; + for(std::vector::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++) + { + IATReference* ref = &(*iter); + + //only one jmp in table for different direct imports with same iat address + if(ref->targetPointer == targetIatPointer) + { + //patch dump + DWORD patchOffset = (DWORD)peParser->convertRVAToOffsetRelative(ref->addressVA - ImageBase); + int index = peParser->convertRVAToOffsetVectorIndex(ref->addressVA - ImageBase); + BYTE* memory = peParser->getSectionMemoryByIndex(index); + DWORD memorySize = peParser->getSectionMemorySizeByIndex(index); + DWORD sectionRVA = peParser->getSectionAddressRVAByIndex(index); + + if(ref->type == IAT_REFERENCE_DIRECT_CALL || ref->type == IAT_REFERENCE_DIRECT_JMP) + { +#ifndef _WIN64 + if(ref->instructionSize == 5) + { + patchBytes = directImportsJumpTableRVA - (ref->addressVA - ImageBase) - 5; + patchDirectImportInDump32(1, 5, patchBytes, memory, memorySize, false, patchOffset, sectionRVA); + } +#endif + } + else if(ref->type == IAT_REFERENCE_DIRECT_PUSH || ref->type == IAT_REFERENCE_DIRECT_MOV) + { +#ifndef _WIN64 + if(ref->instructionSize == 5) //for x86 + { + patchBytes = directImportsJumpTableRVA + stdImagebase; + patchDirectImportInDump32(1, 5, patchBytes, memory, memorySize, true, patchOffset, sectionRVA); + } +#else + if(ref->instructionSize == 10) //for x64 + { + DWORD_PTR patchBytes64 = directImportsJumpTableRVA + stdImagebase; + patchDirectImportInDump64(2, 10, patchBytes64, memory, memorySize, true, patchOffset, sectionRVA); + } +#endif + } + else if(ref->type == IAT_REFERENCE_DIRECT_LEA) + { +#ifndef _WIN64 + if(ref->instructionSize == 6) + { + patchBytes = directImportsJumpTableRVA + stdImagebase; + patchDirectImportInDump32(2, 6, patchBytes, memory, memorySize, true, patchOffset, sectionRVA); + } +#endif + } + } + } +} + +void IATReferenceScan::patchDirectJumpTable(DWORD_PTR stdImagebase, DWORD directImportsJumpTableRVA, PeParser* peParser, BYTE* jmpTableMemory, DWORD newIatBase) +{ + + std::set apiPointers; + for(std::vector::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++) + { + IATReference* ref = &(*iter); + apiPointers.insert(ref->targetPointer); + } + + DWORD patchBytes; + + for(std::set::iterator apiIter = apiPointers.begin(); apiIter != apiPointers.end(); apiIter++) + { + DWORD_PTR refTargetPointer = *apiIter; + if(newIatBase) //create new iat in section + { + refTargetPointer = (*apiIter - IatAddressVA) + newIatBase + ImageBase; + } + //create jump table in section + DWORD_PTR newIatAddressPointer = refTargetPointer - ImageBase + stdImagebase; + +#ifdef _WIN64 + patchBytes = (DWORD)(newIatAddressPointer - (directImportsJumpTableRVA + stdImagebase) - 6); +#else + patchBytes = newIatAddressPointer; + DWORD relocOffset = (directImportsJumpTableRVA + 2); + //directImportLog.log(L"Relocation direct imports fix: Base RVA %08X Type HIGHLOW Offset %04X RelocTableEntry %04X", relocOffset & 0xFFFFF000, relocOffset & 0x00000FFF, (IMAGE_REL_BASED_HIGHLOW << 12) + (relocOffset & 0x00000FFF)); +#endif + jmpTableMemory[0] = 0xFF; + jmpTableMemory[1] = 0x25; + *((DWORD*)&jmpTableMemory[2]) = patchBytes; + + patchDirectJumpTableEntry(*apiIter, stdImagebase, directImportsJumpTableRVA, peParser, jmpTableMemory, newIatBase); + + jmpTableMemory += 6; + directImportsJumpTableRVA += 6; + } +} + +void IATReferenceScan::patchDirectImportInDump32(int patchPreFixBytes, int instructionSize, DWORD patchBytes, BYTE* memory, DWORD memorySize, bool generateReloc, DWORD patchOffset, DWORD sectionRVA) +{ + if(memorySize < (DWORD)(patchOffset + instructionSize)) + { + //Scylla::debugLog.log(L"Error - Cannot fix direct import reference RVA: %X", sectionRVA + patchOffset); + } + else + { + memory += patchOffset + patchPreFixBytes; + if(generateReloc) + { + DWORD relocOffset = sectionRVA + patchOffset + patchPreFixBytes; + // directImportLog.log(L"Relocation direct imports fix: Base RVA %08X Type HIGHLOW Offset %04X RelocTableEntry %04X", relocOffset & 0xFFFFF000, relocOffset & 0x00000FFF, (IMAGE_REL_BASED_HIGHLOW << 12) + (relocOffset & 0x00000FFF)); + } + + *((DWORD*)memory) = patchBytes; + } +} + +void IATReferenceScan::patchDirectImportInDump64(int patchPreFixBytes, int instructionSize, DWORD_PTR patchBytes, BYTE* memory, DWORD memorySize, bool generateReloc, DWORD patchOffset, DWORD sectionRVA) +{ + if(memorySize < (DWORD)(patchOffset + instructionSize)) + { + // Scylla::debugLog.log(L"Error - Cannot fix direct import reference RVA: %X", sectionRVA + patchOffset); + } + else + { + memory += patchOffset + patchPreFixBytes; + if(generateReloc) + { + DWORD relocOffset = sectionRVA + patchOffset + patchPreFixBytes; + // directImportLog.log(L"Relocation direct imports fix: Base RVA %08X Type DIR64 Offset %04X RelocTableEntry %04X", relocOffset & 0xFFFFF000, relocOffset & 0x00000FFF, (IMAGE_REL_BASED_DIR64 << 12) + (relocOffset & 0x00000FFF)); + } + + *((DWORD_PTR*)memory) = patchBytes; + } +} + +DWORD IATReferenceScan::addAdditionalApisToList() +{ + std::set apiPointers; + + for(std::vector::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++) + { + IATReference* ref = &(*iter); + + if(ref->targetPointer == 0) + { + apiPointers.insert(ref->targetAddressInIat); + } + } + + DWORD_PTR iatAddy = IatAddressVA + IatSize; + DWORD newIatSize = IatSize; + + bool isSuspect = false; + for(std::set::iterator apiIter = apiPointers.begin(); apiIter != apiPointers.end(); apiIter++) + { + for(std::vector::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++) + { + IATReference* ref = &(*iter); + + if(ref->targetPointer == 0 && ref->targetAddressInIat == *apiIter) + { + ref->targetPointer = iatAddy; + ApiInfo* apiInfo = apiReader->getApiByVirtualAddress(ref->targetAddressInIat, &isSuspect); + apiReader->addFoundApiToModuleList(iatAddy, apiInfo, true, isSuspect); + } + } + + iatAddy += sizeof(DWORD_PTR); + newIatSize += sizeof(DWORD_PTR); + } + + return newIatSize; +} + + diff --git a/scylla_wrapper/IATReferenceScan.h b/scylla_wrapper/IATReferenceScan.h new file mode 100644 index 0000000..7f1b0b1 --- /dev/null +++ b/scylla_wrapper/IATReferenceScan.h @@ -0,0 +1,126 @@ +#pragma once +#include +#include "ProcessAccessHelp.h" +#include "PeParser.h" +#include "ApiReader.h" + +enum IATReferenceType +{ + IAT_REFERENCE_PTR_JMP, + IAT_REFERENCE_PTR_CALL, + IAT_REFERENCE_DIRECT_JMP, + IAT_REFERENCE_DIRECT_CALL, + IAT_REFERENCE_DIRECT_MOV, + IAT_REFERENCE_DIRECT_PUSH, + IAT_REFERENCE_DIRECT_LEA +}; + +class IATReference +{ +public: + DWORD_PTR addressVA; //Address of reference + DWORD_PTR targetPointer; //Place inside IAT + DWORD_PTR targetAddressInIat; //WIN API? + BYTE instructionSize; + IATReferenceType type; +}; + + +class IATReferenceScan +{ +public: + + IATReferenceScan() + { + apiReader = 0; + IatAddressVA = 0; + IatSize = 0; + ImageBase = 0; + ImageSize = 0; + iatBackup = 0; + ScanForDirectImports = false; + ScanForNormalImports = true; + } + + ~IATReferenceScan() + { + iatReferenceList.clear(); + iatDirectImportList.clear(); + + if(iatBackup) + { + free(iatBackup); + } + } + + bool ScanForDirectImports; + bool ScanForNormalImports; + bool JunkByteAfterInstruction; + ApiReader* apiReader; + + void startScan(DWORD_PTR imageBase, DWORD imageSize, DWORD_PTR iatAddress, DWORD iatSize); + //void patchNewIatBaseMemory(DWORD_PTR newIatBaseAddress); + //void patchNewIatBaseFile(DWORD_PTR newIatBaseAddress); + + void patchNewIat(DWORD_PTR stdImagebase, DWORD_PTR newIatBaseAddress, PeParser* peParser); + void patchDirectJumpTable(DWORD_PTR imageBase, DWORD directImportsJumpTableRVA, PeParser* peParser, BYTE* jmpTableMemory, DWORD newIatBase); + void patchDirectImportsMemory(bool junkByteAfterInstruction); + int numberOfFoundDirectImports(); + int numberOfFoundUniqueDirectImports(); + int numberOfDirectImportApisNotInIat(); + int getSizeInBytesOfJumpTableInSection(); + //static FileLog directImportLog; + void printDirectImportLog(); + void changeIatBaseOfDirectImports(DWORD newIatBaseAddressRVA); + DWORD addAdditionalApisToList(); +private: + DWORD_PTR NewIatAddressRVA; + + DWORD_PTR IatAddressVA; + DWORD IatSize; + DWORD_PTR ImageBase; + DWORD ImageSize; + + + DWORD_PTR* iatBackup; + + std::vector iatReferenceList; + std::vector iatDirectImportList; + + void scanMemoryPage(PVOID BaseAddress, SIZE_T RegionSize); + void analyzeInstruction(_DInst* instruction); + void findNormalIatReference(_DInst* instruction); + void getIatEntryAddress(IATReference* ref); + void findDirectIatReferenceCallJmp(_DInst* instruction); + bool isAddressValidImageMemory(DWORD_PTR address); + void patchReferenceInMemory(IATReference* ref); + void patchReferenceInFile(IATReference* ref); + void patchDirectImportInMemory(IATReference* iter); + DWORD_PTR lookUpIatForPointer(DWORD_PTR addr); + void findDirectIatReferenceMov(_DInst* instruction); + void findDirectIatReferencePush(_DInst* instruction); + void checkMemoryRangeAndAddToList(IATReference* ref, _DInst* instruction); + void findDirectIatReferenceLea(_DInst* instruction); + void patchDirectImportInDump32(int patchPreFixBytes, int instructionSize, DWORD patchBytes, BYTE* memory, DWORD memorySize, bool generateReloc, DWORD patchOffset, DWORD sectionRVA); + void patchDirectImportInDump64(int patchPreFixBytes, int instructionSize, DWORD_PTR patchBytes, BYTE* memory, DWORD memorySize, bool generateReloc, DWORD patchOffset, DWORD sectionRVA); + void patchDirectJumpTableEntry(DWORD_PTR targetIatPointer, DWORD_PTR stdImagebase, DWORD directImportsJumpTableRVA, PeParser* peParser, BYTE* jmpTableMemory, DWORD newIatBase); + + +}; + +/* +PE64 +---------- +000000013FF82D87 FF15 137C0A00 CALL QWORD [RIP+0xA7C13] +Result: 000000014002A9A0 + +000000013F65C952 FF25 F8EA0B00 JMP QWORD [RIP+0xBEAF8] +Result: 000000013F71B450 + +PE32 +---------- +0120FFA5 FF15 8C6D2601 CALL DWORD [0x01266D8C] + +0120FF52 FF25 D4722601 JMP DWORD [0x012672D4] +*/ + diff --git a/scylla_wrapper/IATSearch.cpp b/scylla_wrapper/IATSearch.cpp new file mode 100644 index 0000000..091674f --- /dev/null +++ b/scylla_wrapper/IATSearch.cpp @@ -0,0 +1,547 @@ +#include "stdafx.h" +#include "IATSearch.h" +#include "Architecture.h" + +//#define DEBUG_COMMENTS + +bool IATSearch::searchImportAddressTableInProcess(DWORD_PTR startAddress, DWORD_PTR* addressIAT, DWORD* sizeIAT, bool advanced) +{ + DWORD_PTR addressInIAT = 0; + + *addressIAT = 0; + *sizeIAT = 0; + + if(advanced) + { + return findIATAdvanced(startAddress, addressIAT, sizeIAT); + } + + addressInIAT = findAPIAddressInIAT(startAddress); + + + if(!addressInIAT) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"searchImportAddressTableInProcess :: addressInIAT not found, startAddress " PRINTF_DWORD_PTR_FULL, startAddress); +#endif + return false; + } + else + { + return findIATStartAndSize(addressInIAT, addressIAT, sizeIAT); + } +} + +bool IATSearch::findIATAdvanced(DWORD_PTR startAddress, DWORD_PTR* addressIAT, DWORD* sizeIAT) +{ + BYTE* dataBuffer; + DWORD_PTR baseAddress; + SIZE_T memorySize; + + findExecutableMemoryPagesByStartAddress(startAddress, &baseAddress, &memorySize); + + if(memorySize == 0) + return false; + + dataBuffer = new BYTE[memorySize]; + + if(!readMemoryFromProcess((DWORD_PTR)baseAddress, memorySize, dataBuffer)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"findAPIAddressInIAT2 :: error reading memory"); +#endif + return false; + } + + std::set iatPointers; + DWORD_PTR next; + BYTE* tempBuf = dataBuffer; + while(decomposeMemory(tempBuf, memorySize, (DWORD_PTR)baseAddress) && decomposerInstructionsCount != 0) + { + findIATPointers(iatPointers); + + next = (DWORD_PTR)(decomposerResult[decomposerInstructionsCount - 1].addr - baseAddress); + next += decomposerResult[decomposerInstructionsCount - 1].size; + // Advance ptr and recalc offset. + tempBuf += next; + + if(memorySize <= next) + { + break; + } + memorySize -= next; + baseAddress += next; + } + + if(iatPointers.size() == 0) + return false; + + filterIATPointersList(iatPointers); + + *addressIAT = *(iatPointers.begin()); + *sizeIAT = (DWORD)(*(--iatPointers.end()) - * (iatPointers.begin()) + sizeof(DWORD_PTR)); + + //Scylla::windowLog.log(L"IAT Search Advanced: Found %d (0x%X) possible IAT entries.", iatPointers.size(), iatPointers.size()); + //Scylla::windowLog.log(L"IAT Search Advanced: Possible IAT first " PRINTF_DWORD_PTR_FULL L" last " PRINTF_DWORD_PTR_FULL L" entry.", *(iatPointers.begin()), *(--iatPointers.end())); + + delete [] dataBuffer; + + return true; +} + +DWORD_PTR IATSearch::findAPIAddressInIAT(DWORD_PTR startAddress) +{ + const size_t MEMORY_READ_SIZE = 200; + BYTE dataBuffer[MEMORY_READ_SIZE]; + + DWORD_PTR iatPointer = 0; + int counter = 0; + + // to detect stolen api + memoryAddress = 0; + memorySize = 0; + + do + { + counter++; + + if(!readMemoryFromProcess(startAddress, sizeof(dataBuffer), dataBuffer)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"findAPIAddressInIAT :: error reading memory " PRINTF_DWORD_PTR_FULL, startAddress); +#endif + return 0; + } + + if(decomposeMemory(dataBuffer, sizeof(dataBuffer), startAddress)) + { + iatPointer = findIATPointer(); + if(iatPointer) + { + if(isIATPointerValid(iatPointer, true)) + { + return iatPointer; + } + } + } + + startAddress = findNextFunctionAddress(); + //printf("startAddress %08X\n",startAddress); + } + while(startAddress != 0 && counter != 8); + + return 0; +} + +DWORD_PTR IATSearch::findNextFunctionAddress() +{ +#ifdef DEBUG_COMMENTS + _DecodedInst inst; +#endif + + for(unsigned int i = 0; i < decomposerInstructionsCount; i++) + { + + if(decomposerResult[i].flags != FLAG_NOT_DECODABLE) + { + if(META_GET_FC(decomposerResult[i].meta) == FC_CALL || META_GET_FC(decomposerResult[i].meta) == FC_UNC_BRANCH) + { + if(decomposerResult[i].size >= 5) + { + if(decomposerResult[i].ops[0].type == O_PC) + { +#ifdef DEBUG_COMMENTS + distorm_format(&decomposerCi, &decomposerResult[i], &inst); + Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, INSTRUCTION_GET_TARGET(&decomposerResult[i])); +#endif + return (DWORD_PTR)INSTRUCTION_GET_TARGET(&decomposerResult[i]); + } + } + } + } + } + + return 0; +} + +DWORD_PTR IATSearch::findIATPointer() +{ +#ifdef DEBUG_COMMENTS + _DecodedInst inst; +#endif + + for(unsigned int i = 0; i < decomposerInstructionsCount; i++) + { + if(decomposerResult[i].flags != FLAG_NOT_DECODABLE) + { + if(META_GET_FC(decomposerResult[i].meta) == FC_CALL || META_GET_FC(decomposerResult[i].meta) == FC_UNC_BRANCH) + { + if(decomposerResult[i].size >= 5) + { +#ifdef _WIN64 + if(decomposerResult[i].flags & FLAG_RIP_RELATIVE) + { +#ifdef DEBUG_COMMENTS + distorm_format(&decomposerCi, &decomposerResult[i], &inst); + Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, INSTRUCTION_GET_RIP_TARGET(&decomposerResult[i])); +#endif + return INSTRUCTION_GET_RIP_TARGET(&decomposerResult[i]); + } +#else + if(decomposerResult[i].ops[0].type == O_DISP) + { + //jmp dword ptr || call dword ptr +#ifdef DEBUG_COMMENTS + distorm_format(&decomposerCi, &decomposerResult[i], &inst); + Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, decomposerResult[i].disp); +#endif + return (DWORD_PTR)decomposerResult[i].disp; + } +#endif + } + } + } + } + + return 0; +} + +bool IATSearch::isIATPointerValid(DWORD_PTR iatPointer, bool checkRedirects) +{ + DWORD_PTR apiAddress = 0; + + if(!readMemoryFromProcess(iatPointer, sizeof(DWORD_PTR), &apiAddress)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"isIATPointerValid :: error reading memory"); +#endif + return false; + } + + //printf("Win api ? %08X\n",apiAddress); + + if(isApiAddressValid(apiAddress) != 0) + { + return true; + } + else + { + + if(checkRedirects) + { + //maybe redirected import? + //if the address is 2 times inside a memory region it is possible a redirected api + if(apiAddress > memoryAddress && apiAddress < (memoryAddress + memorySize)) + { + return true; + } + else + { + getMemoryRegionFromAddress(apiAddress, &memoryAddress, &memorySize); + } + } + } + + return false; +} + +bool IATSearch::findIATStartAndSize(DWORD_PTR address, DWORD_PTR* addressIAT, DWORD* sizeIAT) +{ + BYTE* dataBuffer = 0; + DWORD_PTR baseAddress = 0; + DWORD baseSize = 0; + + getMemoryBaseAndSizeForIat(address, &baseAddress, &baseSize); + + if(!baseAddress) + return false; + + dataBuffer = new BYTE[baseSize * (sizeof(DWORD_PTR) * 3)]; + + if(!dataBuffer) + return false; + + ZeroMemory(dataBuffer, baseSize * (sizeof(DWORD_PTR) * 3)); + + if(!readMemoryFromProcess(baseAddress, baseSize, dataBuffer)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"findIATStartAddress :: error reading memory"); +#endif + return false; + } + + //printf("address %X memBasic.BaseAddress %X memBasic.RegionSize %X\n",address,memBasic.BaseAddress,memBasic.RegionSize); + + *addressIAT = findIATStartAddress(baseAddress, address, dataBuffer); + + *sizeIAT = findIATSize(baseAddress, *addressIAT, dataBuffer, baseSize); + + delete [] dataBuffer; + + return true; +} + +DWORD_PTR IATSearch::findIATStartAddress(DWORD_PTR baseAddress, DWORD_PTR startAddress, BYTE* dataBuffer) +{ + DWORD_PTR* pIATAddress = 0; + + pIATAddress = (DWORD_PTR*)((startAddress - baseAddress) + (DWORD_PTR)dataBuffer); + + while((DWORD_PTR)pIATAddress != (DWORD_PTR)dataBuffer) + { + if(isInvalidMemoryForIat(*pIATAddress)) + { + if((DWORD_PTR)(pIATAddress - 1) >= (DWORD_PTR)dataBuffer) + { + if(isInvalidMemoryForIat(*(pIATAddress - 1))) + { + if((DWORD_PTR)(pIATAddress - 2) >= (DWORD_PTR)dataBuffer) + { + if(!isApiAddressValid(*(pIATAddress - 2))) + { + return (((DWORD_PTR)pIATAddress - (DWORD_PTR)dataBuffer) + baseAddress); + } + } + } + } + } + + pIATAddress--; + } + + return baseAddress; +} + +DWORD IATSearch::findIATSize(DWORD_PTR baseAddress, DWORD_PTR iatAddress, BYTE* dataBuffer, DWORD bufferSize) +{ + DWORD_PTR* pIATAddress = 0; + + pIATAddress = (DWORD_PTR*)((iatAddress - baseAddress) + (DWORD_PTR)dataBuffer); + +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"findIATSize :: baseAddress %X iatAddress %X dataBuffer %X pIATAddress %X", baseAddress, iatAddress, dataBuffer, pIATAddress); +#endif + + while((DWORD_PTR)pIATAddress < ((DWORD_PTR)dataBuffer + bufferSize - 1)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"findIATSize :: %X %X %X", pIATAddress, *pIATAddress, *(pIATAddress + 1)); +#endif + if(isInvalidMemoryForIat(*pIATAddress)) //normal is 0 + { + if(isInvalidMemoryForIat(*(pIATAddress + 1))) + { + //IAT end + if(!isApiAddressValid(*(pIATAddress + 2))) + { + return (DWORD)((DWORD_PTR)pIATAddress - (DWORD_PTR)dataBuffer - (iatAddress - baseAddress)); + } + } + } + + pIATAddress++; + } + + return bufferSize; +} + +void IATSearch::findIATPointers(std::set & iatPointers) +{ +#ifdef DEBUG_COMMENTS + _DecodedInst inst; +#endif + + for(unsigned int i = 0; i < decomposerInstructionsCount; i++) + { + if(decomposerResult[i].flags != FLAG_NOT_DECODABLE) + { + if(META_GET_FC(decomposerResult[i].meta) == FC_CALL || META_GET_FC(decomposerResult[i].meta) == FC_UNC_BRANCH) + { + if(decomposerResult[i].size >= 5) + { +#ifdef _WIN64 + if(decomposerResult[i].flags & FLAG_RIP_RELATIVE) + { +#ifdef DEBUG_COMMENTS + distorm_format(&decomposerCi, &decomposerResult[i], &inst); + Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, INSTRUCTION_GET_RIP_TARGET(&decomposerResult[i])); +#endif + iatPointers.insert(INSTRUCTION_GET_RIP_TARGET(&decomposerResult[i])); + } +#else + if(decomposerResult[i].ops[0].type == O_DISP) + { + //jmp dword ptr || call dword ptr +#ifdef DEBUG_COMMENTS + distorm_format(&decomposerCi, &decomposerResult[i], &inst); + Scylla::debugLog.log(L"%S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, inst.mnemonic.p, inst.operands.p, decomposerResult[i].ops[0].type, decomposerResult[i].size, decomposerResult[i].disp); +#endif + iatPointers.insert((DWORD_PTR)decomposerResult[i].disp); + } +#endif + } + } + } + } + + +} + +void IATSearch::findExecutableMemoryPagesByStartAddress(DWORD_PTR startAddress, DWORD_PTR* baseAddress, SIZE_T* memorySize) +{ + MEMORY_BASIC_INFORMATION memBasic = {0}; + DWORD_PTR tempAddress; + + *memorySize = 0; + *baseAddress = 0; + + if(VirtualQueryEx(hProcess, (LPCVOID)startAddress, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"findIATStartAddress :: VirtualQueryEx error %u", GetLastError()); +#endif + return; + } + + //search down + do + { + *memorySize = memBasic.RegionSize; + *baseAddress = (DWORD_PTR)memBasic.BaseAddress; + tempAddress = (DWORD_PTR)memBasic.BaseAddress - 1; + + if(VirtualQueryEx(hProcess, (LPCVOID)tempAddress, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) + { + break; + } + } + while(isPageExecutable(memBasic.Protect)); + + tempAddress = *baseAddress; + memBasic.RegionSize = *memorySize; + *memorySize = 0; + //search up + do + { + tempAddress += memBasic.RegionSize; + *memorySize += memBasic.RegionSize; + + if(VirtualQueryEx(hProcess, (LPCVOID)tempAddress, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) + { + break; + } + } + while(isPageExecutable(memBasic.Protect)); +} + +void IATSearch::filterIATPointersList(std::set & iatPointers) +{ + std::set::iterator iter; + + if(iatPointers.size() <= 2) + { + return; + } + + iter = iatPointers.begin(); + std::advance(iter, iatPointers.size() / 2); //start in the middle, important! + + DWORD_PTR lastPointer = *iter; + iter++; + + for(; iter != iatPointers.end(); iter++) + { + if((*iter - lastPointer) > 0x100) //check difference + { + if(isIATPointerValid(lastPointer, false) == false || isIATPointerValid(*iter, false) == false) + { + iatPointers.erase(iter, iatPointers.end()); + break; + } + else + { + lastPointer = *iter; + } + } + else + { + lastPointer = *iter; + } + } + + + bool erased = true; + + while(erased) + { + iter = iatPointers.begin(); + lastPointer = *iter; + iter++; + + for(; iter != iatPointers.end(); iter++) + { + if((*iter - lastPointer) > 0x100) //check difference + { + if(isIATPointerValid(lastPointer, false) == false || isIATPointerValid(*iter, false) == false) + { + iter--; + iatPointers.erase(iter); + erased = true; + break; + } + else + { + erased = false; + lastPointer = *iter; + } + } + else + { + erased = false; + lastPointer = *iter; + } + } + } + +} + +void IATSearch::getMemoryBaseAndSizeForIat(DWORD_PTR address, DWORD_PTR* baseAddress, DWORD* baseSize) +{ + MEMORY_BASIC_INFORMATION memBasic1 = {0}; + MEMORY_BASIC_INFORMATION memBasic2 = {0}; + MEMORY_BASIC_INFORMATION memBasic3 = {0}; + + DWORD_PTR start = 0, end = 0; + *baseAddress = 0; + *baseSize = 0; + + if(!VirtualQueryEx(hProcess, (LPCVOID)address, &memBasic2, sizeof(MEMORY_BASIC_INFORMATION))) + { + return; + } + + *baseAddress = (DWORD_PTR)memBasic2.BaseAddress; + *baseSize = (DWORD)memBasic2.RegionSize; + + //Get the neighbours + if(!VirtualQueryEx(hProcess, (LPCVOID)((DWORD_PTR)memBasic2.BaseAddress - 1), &memBasic1, sizeof(MEMORY_BASIC_INFORMATION))) + { + return; + } + if(!VirtualQueryEx(hProcess, (LPCVOID)((DWORD_PTR)memBasic2.BaseAddress + (DWORD_PTR)memBasic2.RegionSize), &memBasic3, sizeof(MEMORY_BASIC_INFORMATION))) + { + return; + } + + if(memBasic3.State != MEM_COMMIT || memBasic1.State != MEM_COMMIT) + { + return; + } + + start = (DWORD_PTR)memBasic1.BaseAddress; + end = (DWORD_PTR)memBasic3.BaseAddress + (DWORD_PTR)memBasic3.RegionSize; + + *baseAddress = start; + *baseSize = (DWORD)(end - start); +} diff --git a/scylla_wrapper/IATSearch.h b/scylla_wrapper/IATSearch.h new file mode 100644 index 0000000..46e80b6 --- /dev/null +++ b/scylla_wrapper/IATSearch.h @@ -0,0 +1,34 @@ +#pragma once + +#include "ApiReader.h" +#include + +class IATSearch : protected ApiReader +{ +public: + + DWORD_PTR memoryAddress; + SIZE_T memorySize; + + bool searchImportAddressTableInProcess(DWORD_PTR startAddress, DWORD_PTR* addressIAT, DWORD* sizeIAT, bool advanced); + +private: + + DWORD_PTR findAPIAddressInIAT(DWORD_PTR startAddress); + bool findIATAdvanced(DWORD_PTR startAddress, DWORD_PTR* addressIAT, DWORD* sizeIAT); + DWORD_PTR findNextFunctionAddress(); + DWORD_PTR findIATPointer(); + //DWORD_PTR findAddressFromWORDString(char * stringBuffer); + //DWORD_PTR findAddressFromNormalCALLString(char * stringBuffer); + bool isIATPointerValid(DWORD_PTR iatPointer, bool checkRedirects); + + bool findIATStartAndSize(DWORD_PTR address, DWORD_PTR* addressIAT, DWORD* sizeIAT); + + DWORD_PTR findIATStartAddress(DWORD_PTR baseAddress, DWORD_PTR startAddress, BYTE* dataBuffer); + DWORD findIATSize(DWORD_PTR baseAddress, DWORD_PTR iatAddress, BYTE* dataBuffer, DWORD bufferSize); + + void findIATPointers(std::set & iatPointers); + void findExecutableMemoryPagesByStartAddress(DWORD_PTR startAddress, DWORD_PTR* baseAddress, SIZE_T* memorySize); + void filterIATPointersList(std::set & iatPointers); + void getMemoryBaseAndSizeForIat(DWORD_PTR address, DWORD_PTR* baseAddress, DWORD* baseSize); +}; diff --git a/scylla_wrapper/ImportRebuilder.cpp b/scylla_wrapper/ImportRebuilder.cpp new file mode 100644 index 0000000..d7f22e4 --- /dev/null +++ b/scylla_wrapper/ImportRebuilder.cpp @@ -0,0 +1,550 @@ +#include "stdafx.h" +#include "ImportRebuilder.h" +#include "StringConversion.h" + +//#define DEBUG_COMMENTS + +/* +New Scylla section contains: + +1. (optional) direct imports jump table +2. (optional) new iat +3. (optional) OFT +4. Normal IAT entries + +*/ + +bool ImportRebuilder::rebuildImportTable(const WCHAR* newFilePath, std::map & moduleList) +{ + bool retValue = false; + + std::map copyModule; + copyModule.insert(moduleList.begin(), moduleList.end()); + + if(isValidPeFile()) + { + if(readPeSectionsFromFile()) + { + setDefaultFileAlignment(); + + retValue = buildNewImportTable(copyModule); + + if(retValue) + { + alignAllSectionHeaders(); + fixPeHeader(); + + if(newIatInSection) + { + patchFileForNewIatLocation(); + } + + if(BuildDirectImportsJumpTable) + { + patchFileForDirectImportJumpTable(); + } + + retValue = savePeFileToDisk(newFilePath); + } + } + } + + return retValue; +} + +bool ImportRebuilder::rebuildMappedImportTable(DWORD_PTR iatVA, std::map & moduleList) +{ + bool retValue = false; + + if(isValidPeFile()) + { + if(readPeSectionsFromMappedFile()) + { + retValue = buildNewMappedImportTable(moduleList); + + //destructor of PEParser deletes .data so we need to remove our pointer to FileMapping + for(WORD i = 0; i < getNumberOfSections(); i++) + { + listPeSection[i].data = NULL; + } + } + } + + return retValue; +} + +bool ImportRebuilder::buildNewImportTable(std::map & moduleList) +{ + createNewImportSection(moduleList); + + importSectionIndex = listPeSection.size() - 1; + + if(BuildDirectImportsJumpTable) + { + directImportsJumpTableRVA = listPeSection[importSectionIndex].sectionHeader.VirtualAddress; + JMPTableMemory = listPeSection[importSectionIndex].data; + } + + if(newIatInSection) + { + newIatBaseAddressRVA = listPeSection[importSectionIndex].sectionHeader.VirtualAddress; + + if(BuildDirectImportsJumpTable) + { + newIatBaseAddressRVA += iatReferenceScan->getSizeInBytesOfJumpTableInSection(); + } + + changeIatBaseAddress(moduleList); + } + + DWORD dwSize = fillImportSection(moduleList); + + if(!dwSize) + { + return false; + } + + setFlagToIATSection((*moduleList.begin()).second.firstThunk); + + DWORD vaImportAddress = listPeSection[importSectionIndex].sectionHeader.VirtualAddress; + + if(useOFT) + { + //OFT array is at the beginning of the import section + vaImportAddress += (DWORD)sizeOfOFTArray; + } + if(newIatInSection) + { + vaImportAddress += (DWORD)IatSize; + } + + if(BuildDirectImportsJumpTable) + { + vaImportAddress += (DWORD)iatReferenceScan->getSizeInBytesOfJumpTableInSection(); + } + + if(isPE32()) + { + pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = vaImportAddress; + pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR)); + } + else + { + pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = vaImportAddress; + pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR)); + } + + + return true; +} + +bool ImportRebuilder::buildNewMappedImportTable(std::map & moduleList) +{ + calculateImportSizes(moduleList); + + importSectionIndex = listPeSection.size() - 1; + + DWORD dwSize = fillImportSection(moduleList); + + if(!dwSize) + { + return false; + } + + DWORD vaImportAddress = listPeSection[importSectionIndex].sectionHeader.VirtualAddress; + + if(useOFT) + { + //OFT array is at the beginning of the import section + vaImportAddress += (DWORD)sizeOfOFTArray; + } + + DWORD headerOffset = sizeof(IMAGE_DOS_HEADER); + if(dosStubSize && pDosStub) + { + headerOffset += dosStubSize; + } + + if(isPE32()) + { + PIMAGE_NT_HEADERS32 pMappedNTHeader32 = (PIMAGE_NT_HEADERS32)(fileMapVA + headerOffset); + + pMappedNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = vaImportAddress; + pMappedNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR)); + + headerOffset += sizeof(IMAGE_NT_HEADERS32); + } + else + { + PIMAGE_NT_HEADERS64 pMappedNTHeader64 = (PIMAGE_NT_HEADERS64)(fileMapVA + headerOffset); + + pMappedNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = vaImportAddress; + pMappedNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR)); + + headerOffset += sizeof(IMAGE_NT_HEADERS64); + } + + //setFlagToIATSection + headerOffset += sizeof(IMAGE_SECTION_HEADER) * importSectionIndex; + + PIMAGE_SECTION_HEADER pImportSection = (PIMAGE_SECTION_HEADER)(fileMapVA + headerOffset); + pImportSection->Characteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; + + return true; +} + +bool ImportRebuilder::createNewImportSection(std::map & moduleList) +{ + char sectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {0}; + StringConversion::ToASCII(this->sectionName, sectionName, IMAGE_SIZEOF_SHORT_NAME + 1); + + calculateImportSizes(moduleList); + + if(newIatInSection) + { + sizeOfImportSection += IatSize; + } + if(BuildDirectImportsJumpTable) + { + sizeOfImportSection += iatReferenceScan->getSizeInBytesOfJumpTableInSection(); + } + + return addNewLastSection(sectionName, (DWORD)sizeOfImportSection, 0); +} + +void ImportRebuilder::setFlagToIATSection(DWORD_PTR iatAddress) +{ + for(size_t i = 0; i < listPeSection.size(); i++) + { + if((listPeSection[i].sectionHeader.VirtualAddress <= iatAddress) && ((listPeSection[i].sectionHeader.VirtualAddress + listPeSection[i].sectionHeader.Misc.VirtualSize) > iatAddress)) + { + //section must be read and writeable + listPeSection[i].sectionHeader.Characteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; + } + } +} + +DWORD ImportRebuilder::fillImportSection(std::map & moduleList) +{ + std::map::iterator mapIt; + std::map::iterator mapIt2; + PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 0; + PIMAGE_IMPORT_BY_NAME pImportByName = 0; + PIMAGE_THUNK_DATA pThunk = 0; + ImportModuleThunk* importModuleThunk = 0; + ImportThunk* importThunk = 0; + + size_t stringLength = 0; + DWORD_PTR lastRVA = 0; + + BYTE* sectionData = listPeSection[importSectionIndex].data; + DWORD offset = 0; + DWORD offsetOFTArray = 0; + + /* + New Scylla section contains: + + 1. (optional) direct imports jump table + 2. (optional) new iat + 3. (optional) OFT + 4. Normal IAT entries + + */ + if(BuildDirectImportsJumpTable) + { + offset += iatReferenceScan->getSizeInBytesOfJumpTableInSection(); + offsetOFTArray += iatReferenceScan->getSizeInBytesOfJumpTableInSection(); + } + if(newIatInSection) + { + offset += IatSize; //new iat at the beginning + offsetOFTArray += IatSize; + memset(sectionData, 0xFF, offset); + } + if(useOFT) + { + offset += (DWORD)sizeOfOFTArray; //size includes null termination + } + + pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)sectionData + offset); + + //skip the IMAGE_IMPORT_DESCRIPTOR + offset += (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR)); + + for(mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++) + { + importModuleThunk = &((*mapIt).second); + + stringLength = addImportDescriptor(importModuleThunk, offset, offsetOFTArray); + +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"fillImportSection :: importDesc.Name %X", pImportDescriptor->Name); +#endif + + offset += (DWORD)stringLength; //stringLength has null termination char + + pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)sectionData + offset); + + //pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA(importModuleThunk->firstThunk)); + + lastRVA = importModuleThunk->firstThunk - sizeof(DWORD_PTR); + + for(mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++) + { + importThunk = &((*mapIt2).second); + + if(useOFT) + { + pThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)sectionData + offsetOFTArray); + offsetOFTArray += sizeof(DWORD_PTR); //increase OFT array index + } + else + { + pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA(importThunk->rva)); + } + + //check wrong iat pointer + if(!pThunk) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"fillImportSection :: Failed to get pThunk RVA: %X", importThunk->rva); +#endif + return 0; + } + + if((lastRVA + sizeof(DWORD_PTR)) != importThunk->rva) + { + //add additional import desc + addSpecialImportDescriptor(importThunk->rva, offsetOFTArray); + if(useOFT) + { + pThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)sectionData + offsetOFTArray); + offsetOFTArray += sizeof(DWORD_PTR); //increase OFT array index, next module + } + } + lastRVA = importThunk->rva; + +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"fillImportSection :: importThunk %X pThunk %X pImportByName %X offset %X", importThunk, pThunk, pImportByName, offset); +#endif + stringLength = addImportToImportTable(importThunk, pThunk, pImportByName, offset); + + offset += (DWORD)stringLength; //is 0 bei import by ordinal + pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)pImportByName + stringLength); + } + + offsetOFTArray += sizeof(DWORD_PTR); //increase OFT array index, next module + pImportDescriptor++; + } + + return offset; +} + +size_t ImportRebuilder::addImportDescriptor(ImportModuleThunk* pImportModule, DWORD sectionOffset, DWORD sectionOffsetOFTArray) +{ + char dllName[MAX_PATH]; + + StringConversion::ToASCII(pImportModule->moduleName, dllName, _countof(dllName)); + size_t stringLength = strlen(dllName) + 1; + + /* + Warning: stringLength MUST include null termination char + */ + + memcpy((listPeSection[importSectionIndex].data + sectionOffset), dllName, stringLength); //copy module name to section + + pImportDescriptor->FirstThunk = (DWORD)pImportModule->firstThunk; + pImportDescriptor->Name = (DWORD)convertOffsetToRVAVector(listPeSection[importSectionIndex].sectionHeader.PointerToRawData + sectionOffset); + + if(useOFT) + { + pImportDescriptor->OriginalFirstThunk = (DWORD)convertOffsetToRVAVector(listPeSection[importSectionIndex].sectionHeader.PointerToRawData + sectionOffsetOFTArray); + } + + return stringLength; +} + +void ImportRebuilder::addSpecialImportDescriptor(DWORD_PTR rvaFirstThunk, DWORD sectionOffsetOFTArray) +{ + PIMAGE_IMPORT_DESCRIPTOR oldID = pImportDescriptor; + pImportDescriptor++; + + pImportDescriptor->FirstThunk = (DWORD)rvaFirstThunk; + pImportDescriptor->Name = oldID->Name; + + if(useOFT) + { + pImportDescriptor->OriginalFirstThunk = (DWORD)convertOffsetToRVAVector(listPeSection[importSectionIndex].sectionHeader.PointerToRawData + sectionOffsetOFTArray); + } +} + +void ImportRebuilder::calculateImportSizes(std::map & moduleList) +{ + std::map::iterator mapIt; + std::map::iterator mapIt2; + DWORD_PTR lastRVA = 0; + + + sizeOfImportSection = 0; + sizeOfApiAndModuleNames = 0; + sizeOfOFTArray = 0; + + numberOfImportDescriptors = moduleList.size() + 1; //last is zero'd + + for(mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++) + { + lastRVA = (*mapIt).second.firstThunk - sizeof(DWORD_PTR); + + sizeOfApiAndModuleNames += (DWORD)(wcslen((*mapIt).second.moduleName) + 1); + + for(mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++) + { + if((lastRVA + sizeof(DWORD_PTR)) != (*mapIt2).second.rva) + { + numberOfImportDescriptors++; //add additional import desc + sizeOfOFTArray += sizeof(DWORD_PTR) + sizeof(DWORD_PTR); + } + + if((*mapIt2).second.name[0] != '\0') + { + sizeOfApiAndModuleNames += sizeof(WORD); //Hint from IMAGE_IMPORT_BY_NAME + sizeOfApiAndModuleNames += (DWORD)(strlen((*mapIt2).second.name) + 1); + } + + //OriginalFirstThunk Array in Import Section: value + sizeOfOFTArray += sizeof(DWORD_PTR); + + lastRVA = (*mapIt2).second.rva; + } + + //OriginalFirstThunk Array in Import Section: NULL termination + sizeOfOFTArray += sizeof(DWORD_PTR); + } + + sizeOfImportSection = sizeOfOFTArray + sizeOfApiAndModuleNames + (numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR)); +} + +size_t ImportRebuilder::addImportToImportTable(ImportThunk* pImport, PIMAGE_THUNK_DATA pThunk, PIMAGE_IMPORT_BY_NAME pImportByName, DWORD sectionOffset) +{ + size_t stringLength = 0; + + if(pImport->name[0] == '\0') + { + pThunk->u1.AddressOfData = (IMAGE_ORDINAL(pImport->ordinal) | IMAGE_ORDINAL_FLAG); + } + else + { + pImportByName->Hint = pImport->hint; + + stringLength = strlen(pImport->name) + 1; + memcpy(pImportByName->Name, pImport->name, stringLength); + + pThunk->u1.AddressOfData = convertOffsetToRVAVector(listPeSection[importSectionIndex].sectionHeader.PointerToRawData + sectionOffset); + + if(!pThunk->u1.AddressOfData) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"addImportToImportTable :: failed to get AddressOfData %X %X", listPeSection[importSectionIndex].sectionHeader.PointerToRawData, sectionOffset); +#endif + } + + //next import should be nulled + pThunk++; + pThunk->u1.AddressOfData = 0; + +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"addImportToImportTable :: pThunk->u1.AddressOfData %X %X %X", pThunk->u1.AddressOfData, pThunk, listPeSection[importSectionIndex].sectionHeader.PointerToRawData + sectionOffset); +#endif + stringLength += sizeof(WORD); + } + + return stringLength; +} + +BYTE* ImportRebuilder::getMemoryPointerFromRVA(DWORD_PTR dwRVA) +{ + int peSectionIndex = convertRVAToOffsetVectorIndex(dwRVA); + + if(peSectionIndex == -1) + { + return 0; + } + + DWORD rvaPointer = ((DWORD)dwRVA - listPeSection[peSectionIndex].sectionHeader.VirtualAddress); + DWORD minSectionSize = rvaPointer + (sizeof(DWORD_PTR) * 2); //add space for 1 IAT address + + if(listPeSection[peSectionIndex].data == 0 || listPeSection[peSectionIndex].dataSize == 0) + { + listPeSection[peSectionIndex].dataSize = minSectionSize; + listPeSection[peSectionIndex].normalSize = minSectionSize; + listPeSection[peSectionIndex].data = new BYTE[listPeSection[peSectionIndex].dataSize]; + + listPeSection[peSectionIndex].sectionHeader.SizeOfRawData = listPeSection[peSectionIndex].dataSize; + } + else if(listPeSection[peSectionIndex].dataSize < minSectionSize) + { + BYTE* temp = new BYTE[minSectionSize]; + memcpy(temp, listPeSection[peSectionIndex].data, listPeSection[peSectionIndex].dataSize); + delete [] listPeSection[peSectionIndex].data; + + listPeSection[peSectionIndex].data = temp; + listPeSection[peSectionIndex].dataSize = minSectionSize; + listPeSection[peSectionIndex].normalSize = minSectionSize; + + listPeSection[peSectionIndex].sectionHeader.SizeOfRawData = listPeSection[peSectionIndex].dataSize; + } + + return (BYTE*)((DWORD_PTR)listPeSection[peSectionIndex].data + rvaPointer); +} + +void ImportRebuilder::enableOFTSupport() +{ + useOFT = true; +} + +void ImportRebuilder::enableNewIatInSection(DWORD_PTR iatAddress, DWORD iatSize) +{ + newIatInSection = true; + IatAddress = iatAddress; + IatSize = iatSize; + + iatReferenceScan->ScanForDirectImports = false; + iatReferenceScan->ScanForNormalImports = true; + + iatReferenceScan->startScan(ProcessAccessHelp::targetImageBase, (DWORD)ProcessAccessHelp::targetSizeOfImage, IatAddress, IatSize); +} + +void ImportRebuilder::patchFileForNewIatLocation() +{ + iatReferenceScan->patchNewIat(getStandardImagebase(), newIatBaseAddressRVA, (PeParser*)this); +} + +void ImportRebuilder::changeIatBaseAddress(std::map & moduleList) +{ + std::map::iterator mapIt; + std::map::iterator mapIt2; + + DWORD_PTR oldIatRva = IatAddress - ProcessAccessHelp::targetImageBase; + + for(mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++) + { + (*mapIt).second.firstThunk = (*mapIt).second.firstThunk - oldIatRva + newIatBaseAddressRVA; + + for(mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++) + { + (*mapIt2).second.rva = (*mapIt2).second.rva - oldIatRva + newIatBaseAddressRVA; + } + } +} + +void ImportRebuilder::patchFileForDirectImportJumpTable() +{ + if(newIatInSection) + { + iatReferenceScan->patchDirectJumpTable(getStandardImagebase(), directImportsJumpTableRVA, (PeParser*)this, JMPTableMemory, newIatBaseAddressRVA); + } + else + { + iatReferenceScan->patchDirectJumpTable(getStandardImagebase(), directImportsJumpTableRVA, (PeParser*)this, JMPTableMemory, 0); + } +} \ No newline at end of file diff --git a/scylla_wrapper/ImportRebuilder.h b/scylla_wrapper/ImportRebuilder.h new file mode 100644 index 0000000..022bb0c --- /dev/null +++ b/scylla_wrapper/ImportRebuilder.h @@ -0,0 +1,101 @@ +#pragma once + +#include +#include "PeParser.h" +#include "Thunks.h" +#include "IATReferenceScan.h" + + +class ImportRebuilder : public PeParser +{ +public: + ImportRebuilder(const WCHAR* file, const WCHAR* sectionName) : PeParser(file, true) + { + pImportDescriptor = 0; + pThunkData = 0; + pImportByName = 0; + + numberOfImportDescriptors = 0; + sizeOfImportSection = 0; + sizeOfApiAndModuleNames = 0; + importSectionIndex = 0; + useOFT = false; + sizeOfOFTArray = 0; + newIatInSection = false; + BuildDirectImportsJumpTable = false; + sizeOfJumpTable = 0; + this->sectionName = (WCHAR*)sectionName; + } + + ImportRebuilder(const DWORD_PTR iatVA, const DWORD_PTR FileMapVA, const HANDLE hFileMap, const WCHAR* sectionName) : PeParser(iatVA, FileMapVA, hFileMap, true) + { + pImportDescriptor = 0; + pThunkData = 0; + pImportByName = 0; + + numberOfImportDescriptors = 0; + sizeOfImportSection = 0; + sizeOfApiAndModuleNames = 0; + importSectionIndex = 0; + useOFT = false; + sizeOfOFTArray = 0; + newIatInSection = false; + BuildDirectImportsJumpTable = false; + sizeOfJumpTable = 0; + this->sectionName = (WCHAR*)sectionName; + } + + bool rebuildImportTable(const WCHAR* newFilePath, std::map & moduleList); + bool rebuildMappedImportTable(DWORD_PTR iatVA, std::map & moduleList); + void enableOFTSupport(); + void enableNewIatInSection(DWORD_PTR iatAddress, DWORD iatSize); + int getIATSectionSize(std::map & moduleList) + { + this->calculateImportSizes(moduleList); + return this->sizeOfImportSection; + } ; + + IATReferenceScan* iatReferenceScan; + bool BuildDirectImportsJumpTable; +private: + PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor; + PIMAGE_THUNK_DATA pThunkData; + PIMAGE_IMPORT_BY_NAME pImportByName; + + size_t numberOfImportDescriptors; + size_t sizeOfImportSection; + size_t sizeOfApiAndModuleNames; + size_t importSectionIndex; + WCHAR* sectionName; + + //OriginalFirstThunk Array in Import Section + size_t sizeOfOFTArray; + bool useOFT; + bool newIatInSection; + DWORD_PTR IatAddress; + + DWORD IatSize; + + DWORD sizeOfJumpTable; + + DWORD directImportsJumpTableRVA; + BYTE* JMPTableMemory; + DWORD newIatBaseAddressRVA; + + DWORD fillImportSection(std::map & moduleList); + BYTE* getMemoryPointerFromRVA(DWORD_PTR dwRVA); + + bool createNewImportSection(std::map & moduleList); + bool buildNewImportTable(std::map & moduleList); + bool buildNewMappedImportTable(std::map & moduleList); + void setFlagToIATSection(DWORD_PTR iatAddress); + size_t addImportToImportTable(ImportThunk* pImport, PIMAGE_THUNK_DATA pThunk, PIMAGE_IMPORT_BY_NAME pImportByName, DWORD sectionOffset); + size_t addImportDescriptor(ImportModuleThunk* pImportModule, DWORD sectionOffset, DWORD sectionOffsetOFTArray); + + void calculateImportSizes(std::map & moduleList); + + void addSpecialImportDescriptor(DWORD_PTR rvaFirstThunk, DWORD sectionOffsetOFTArray); + void patchFileForNewIatLocation(); + void changeIatBaseAddress(std::map & moduleList); + void patchFileForDirectImportJumpTable(); +}; \ No newline at end of file diff --git a/scylla_wrapper/NativeWinApi.cpp b/scylla_wrapper/NativeWinApi.cpp new file mode 100644 index 0000000..1128d08 --- /dev/null +++ b/scylla_wrapper/NativeWinApi.cpp @@ -0,0 +1,84 @@ +#include "stdafx.h" +#include "NativeWinApi.h" + +def_NtCreateThreadEx NativeWinApi::NtCreateThreadEx = 0; +def_NtDuplicateObject NativeWinApi::NtDuplicateObject = 0; +def_NtOpenProcess NativeWinApi::NtOpenProcess = 0; +def_NtOpenThread NativeWinApi::NtOpenThread = 0; +def_NtQueryObject NativeWinApi::NtQueryObject = 0; +def_NtQueryInformationFile NativeWinApi::NtQueryInformationFile = 0; +def_NtQueryInformationProcess NativeWinApi::NtQueryInformationProcess = 0; +def_NtQueryInformationThread NativeWinApi::NtQueryInformationThread = 0; +def_NtQuerySystemInformation NativeWinApi::NtQuerySystemInformation = 0; +def_NtQueryVirtualMemory NativeWinApi::NtQueryVirtualMemory = 0; +def_NtResumeProcess NativeWinApi::NtResumeProcess = 0; +def_NtResumeThread NativeWinApi::NtResumeThread = 0; +def_NtSetInformationThread NativeWinApi::NtSetInformationThread = 0; +def_NtSuspendProcess NativeWinApi::NtSuspendProcess = 0; +def_NtTerminateProcess NativeWinApi::NtTerminateProcess = 0; + +def_NtOpenSymbolicLinkObject NativeWinApi::NtOpenSymbolicLinkObject = 0; +def_NtQuerySymbolicLinkObject NativeWinApi::NtQuerySymbolicLinkObject = 0; + +def_RtlNtStatusToDosError NativeWinApi::RtlNtStatusToDosError = 0; +def_NtClose NativeWinApi::NtClose = 0; + +void NativeWinApi::initialize() +{ + if(RtlNtStatusToDosError) + { + return; + } + + HMODULE hModuleNtdll = GetModuleHandle(L"ntdll.dll"); + + if(!hModuleNtdll) + { + return; + } + + NtCreateThreadEx = (def_NtCreateThreadEx)GetProcAddress(hModuleNtdll, "NtCreateThreadEx"); + NtDuplicateObject = (def_NtDuplicateObject)GetProcAddress(hModuleNtdll, "NtDuplicateObject"); + NtOpenProcess = (def_NtOpenProcess)GetProcAddress(hModuleNtdll, "NtOpenProcess"); + NtOpenThread = (def_NtOpenThread)GetProcAddress(hModuleNtdll, "NtOpenThread"); + NtQueryObject = (def_NtQueryObject)GetProcAddress(hModuleNtdll, "NtQueryObject"); + NtQueryInformationFile = (def_NtQueryInformationFile)GetProcAddress(hModuleNtdll, "NtQueryInformationFile"); + NtQueryInformationProcess = (def_NtQueryInformationProcess)GetProcAddress(hModuleNtdll, "NtQueryInformationProcess"); + NtQueryInformationThread = (def_NtQueryInformationThread)GetProcAddress(hModuleNtdll, "NtQueryInformationThread"); + NtQuerySystemInformation = (def_NtQuerySystemInformation)GetProcAddress(hModuleNtdll, "NtQuerySystemInformation"); + NtQueryVirtualMemory = (def_NtQueryVirtualMemory)GetProcAddress(hModuleNtdll, "NtQueryVirtualMemory"); + NtResumeProcess = (def_NtResumeProcess)GetProcAddress(hModuleNtdll, "NtResumeProcess"); + NtResumeThread = (def_NtResumeThread)GetProcAddress(hModuleNtdll, "NtResumeThread"); + NtSetInformationThread = (def_NtSetInformationThread)GetProcAddress(hModuleNtdll, "NtSetInformationThread"); + NtSuspendProcess = (def_NtSuspendProcess)GetProcAddress(hModuleNtdll, "NtSuspendProcess"); + NtTerminateProcess = (def_NtTerminateProcess)GetProcAddress(hModuleNtdll, "NtTerminateProcess"); + NtOpenSymbolicLinkObject = (def_NtOpenSymbolicLinkObject)GetProcAddress(hModuleNtdll, "NtOpenSymbolicLinkObject"); + NtQuerySymbolicLinkObject = (def_NtQuerySymbolicLinkObject)GetProcAddress(hModuleNtdll, "NtQuerySymbolicLinkObject"); + + RtlNtStatusToDosError = (def_RtlNtStatusToDosError)GetProcAddress(hModuleNtdll, "RtlNtStatusToDosError"); + NtClose = (def_NtClose)GetProcAddress(hModuleNtdll, "NtClose"); +} + + +PPEB NativeWinApi::getCurrentProcessEnvironmentBlock() +{ + return getProcessEnvironmentBlockAddress(GetCurrentProcess()); +} + +PPEB NativeWinApi::getProcessEnvironmentBlockAddress(HANDLE processHandle) +{ + ULONG lReturnLength = 0; + PROCESS_BASIC_INFORMATION processBasicInformation; + + if((NtQueryInformationProcess(processHandle, ProcessBasicInformation, &processBasicInformation, sizeof(PROCESS_BASIC_INFORMATION), &lReturnLength) >= 0) && (lReturnLength == sizeof(PROCESS_BASIC_INFORMATION))) + { + //printf("NtQueryInformationProcess success %d\n",sizeof(PROCESS_BASIC_INFORMATION)); + + return processBasicInformation.PebBaseAddress; + } + else + { + //printf("NtQueryInformationProcess failed %d vs %d\n",lReturnLength,sizeof(PROCESS_BASIC_INFORMATION)); + return 0; + } +} \ No newline at end of file diff --git a/scylla_wrapper/NativeWinApi.h b/scylla_wrapper/NativeWinApi.h new file mode 100644 index 0000000..62c3373 --- /dev/null +++ b/scylla_wrapper/NativeWinApi.h @@ -0,0 +1,502 @@ +#pragma once + +#include + +#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +#define DUPLICATE_SAME_ATTRIBUTES 0x00000004 +#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) + +typedef LONG KPRIORITY; +typedef LONG NTSTATUS; + +typedef enum _SYSTEM_INFORMATION_CLASS +{ + + SystemBasicInformation, + SystemProcessorInformation, + SystemPerformanceInformation, + SystemTimeOfDayInformation, + SystemPathInformation, + SystemProcessInformation, + SystemCallCountInformation, + SystemDeviceInformation, + SystemProcessorPerformanceInformation, + SystemFlagsInformation, + SystemCallTimeInformation, + SystemModuleInformation, + SystemLocksInformation, + SystemStackTraceInformation, + SystemPagedPoolInformation, + SystemNonPagedPoolInformation, + SystemHandleInformation, + SystemObjectInformation, + SystemPageFileInformation, + SystemVdmInstemulInformation, + SystemVdmBopInformation, + SystemFileCacheInformation, + SystemPoolTagInformation, + SystemInterruptInformation, + SystemDpcBehaviorInformation, + SystemFullMemoryInformation, + SystemLoadGdiDriverInformation, + SystemUnloadGdiDriverInformation, + SystemTimeAdjustmentInformation, + SystemSummaryMemoryInformation, + SystemNextEventIdInformation, + SystemEventIdsInformation, + SystemCrashDumpInformation, + SystemExceptionInformation, + SystemCrashDumpStateInformation, + SystemKernelDebuggerInformation, + SystemContextSwitchInformation, + SystemRegistryQuotaInformation, + SystemExtendServiceTableInformation, + SystemPrioritySeperation, + SystemPlugPlayBusInformation, + SystemDockInformation, + SystemPowerInformation2, + SystemProcessorSpeedInformation, + SystemCurrentTimeZoneInformation, + SystemLookasideInformation + +} SYSTEM_INFORMATION_CLASS; + +typedef struct _IO_STATUS_BLOCK +{ + union + { + NTSTATUS Status; + PVOID Pointer; + }; + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + +typedef struct _FILE_NAME_INFORMATION // Information Classes 9 and 21 +{ + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_NAME_INFORMATION; + +typedef enum _FILE_INFORMATION_CLASS +{ + FileNameInformation = 9, +} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; + +typedef struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +typedef struct _CLIENT_ID +{ + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID, *PCLIENT_ID; + +#define InitializeObjectAttributes(p,n,a,r,s) \ +{ \ + (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ + (p)->ObjectName = n; \ + (p)->Attributes = a; \ + (p)->RootDirectory = r; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ +} + +typedef struct _OBJECT_ATTRIBUTES +{ + ULONG Length; + PVOID RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; + +typedef struct _MEMORY_REGION_INFORMATION +{ + PVOID AllocationBase; //Imagebase + ULONG AllocationProtect; + ULONG RegionType; + SIZE_T RegionSize; //Size of image +} MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION; + +typedef enum _OBJECT_INFORMATION_CLASS +{ + ObjectBasicInformation, + ObjectNameInformation, + ObjectTypeInformation, + ObjectAllInformation, + ObjectDataInformation +} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS; + +typedef enum _THREADINFOCLASS +{ + ThreadBasicInformation, + ThreadTimes, + ThreadPriority, + ThreadBasePriority, + ThreadAffinityMask, + ThreadImpersonationToken, + ThreadDescriptorTableEntry, + ThreadEnableAlignmentFaultFixup, + ThreadEventPair_Reusable, + ThreadQuerySetWin32StartAddress, + ThreadZeroTlsCell, + ThreadPerformanceCount, + ThreadAmILastThread, + ThreadIdealProcessor, + ThreadPriorityBoost, + ThreadSetTlsArrayAddress, + ThreadIsIoPending, + ThreadHideFromDebugger, + ThreadBreakOnTermination, + MaxThreadInfoClass +} THREADINFOCLASS; + +// +// Memory Information Classes for NtQueryVirtualMemory +// +typedef enum _MEMORY_INFORMATION_CLASS +{ + MemoryBasicInformation, + MemoryWorkingSetInformation, + MemoryMappedFilenameInformation, //MemorySectionName, UNICODE_STRING, Wrapper: GetMappedFileNameW + MemoryRegionInformation, //MemoryBasicVlmInformation, MEMORY_REGION_INFORMATION + MemoryWorkingSetExInformation +} MEMORY_INFORMATION_CLASS; + +typedef enum _PROCESSINFOCLASS +{ + ProcessBasicInformation, + ProcessQuotaLimits, + ProcessIoCounters, + ProcessVmCounters, + ProcessTimes, + ProcessBasePriority, + ProcessRaisePriority, + ProcessDebugPort, + ProcessExceptionPort, + ProcessAccessToken, + ProcessLdtInformation, + ProcessLdtSize, + ProcessDefaultHardErrorMode, + ProcessIoPortHandlers, + ProcessPooledUsageAndLimits, + ProcessWorkingSetWatch, + ProcessUserModeIOPL, + ProcessEnableAlignmentFaultFixup, + ProcessPriorityClass, + ProcessWx86Information, + ProcessHandleCount, + ProcessAffinityMask, + ProcessPriorityBoost, + ProcessDeviceMap, + ProcessSessionInformation, + ProcessForegroundInformation, + ProcessWow64Information, + ProcessImageFileName, + ProcessLUIDDeviceMapsEnabled, + ProcessBreakOnTermination, + ProcessDebugObjectHandle, + ProcessDebugFlags, + ProcessHandleTracing, + ProcessIoPriority, + ProcessExecuteFlags, + ProcessResourceManagement, + ProcessCookie, + ProcessImageInformation, + MaxProcessInfoClass +} PROCESSINFOCLASS; + +typedef struct _PEB_LDR_DATA +{ + BYTE Reserved1[8]; + PVOID Reserved2[3]; + LIST_ENTRY InMemoryOrderModuleList; +} PEB_LDR_DATA, *PPEB_LDR_DATA; + +typedef struct _RTL_USER_PROCESS_PARAMETERS +{ + BYTE Reserved1[16]; + PVOID Reserved2[10]; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; +} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; + +typedef struct _PEB +{ + BYTE Reserved1[2]; + BYTE BeingDebugged; + BYTE Reserved2[1]; + PVOID Reserved3[2]; + PPEB_LDR_DATA Ldr; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + BYTE Reserved4[104]; + PVOID Reserved5[52]; + PVOID PostProcessInitRoutine; + BYTE Reserved6[128]; + PVOID Reserved7[1]; + ULONG SessionId; +} PEB, *PPEB; + +typedef struct _PROCESS_BASIC_INFORMATION +{ + PVOID Reserved1; + PPEB PebBaseAddress; + PVOID Reserved2[2]; + ULONG_PTR UniqueProcessId; + PVOID Reserved3; +} PROCESS_BASIC_INFORMATION; + + +typedef struct _MEMORY_WORKING_SET_LIST +{ + ULONG NumberOfPages; + ULONG WorkingSetList[1]; +} MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST; + +typedef struct _MEMORY_SECTION_NAME +{ + UNICODE_STRING SectionFileName; +} MEMORY_SECTION_NAME, *PMEMORY_SECTION_NAME; + +typedef struct _SYSTEM_SESSION_PROCESS_INFORMATION +{ + ULONG SessionId; + ULONG SizeOfBuf; + PVOID Buffer; +} SYSTEM_SESSION_PROCESS_INFORMATION, *PSYSTEM_SESSION_PROCESS_INFORMATION; + +typedef struct _SYSTEM_THREAD_INFORMATION +{ + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + ULONG WaitTime; + PVOID StartAddress; + CLIENT_ID ClientId; + KPRIORITY Priority; + LONG BasePriority; + ULONG ContextSwitches; + ULONG ThreadState; + ULONG WaitReason; +} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; + +typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION +{ + SYSTEM_THREAD_INFORMATION ThreadInfo; + PVOID StackBase; + PVOID StackLimit; + PVOID Win32StartAddress; + PVOID TebAddress; /* This is only filled in on Vista and above */ + ULONG_PTR Reserved2; + ULONG_PTR Reserved3; + ULONG_PTR Reserved4; +} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION; + +typedef struct _SYSTEM_PROCESS_INFORMATION +{ + ULONG NextEntryOffset; + ULONG NumberOfThreads; + LARGE_INTEGER SpareLi1; + LARGE_INTEGER SpareLi2; + LARGE_INTEGER SpareLi3; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ImageName; + KPRIORITY BasePriority; + HANDLE UniqueProcessId; + HANDLE InheritedFromUniqueProcessId; + ULONG HandleCount; + ULONG SessionId; + ULONG_PTR PageDirectoryBase; + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivatePageCount; + LARGE_INTEGER ReadOperationCount; + LARGE_INTEGER WriteOperationCount; + LARGE_INTEGER OtherOperationCount; + LARGE_INTEGER ReadTransferCount; + LARGE_INTEGER WriteTransferCount; + LARGE_INTEGER OtherTransferCount; + SYSTEM_THREAD_INFORMATION Threads[1]; +} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; + + +/////////////////////////////////////////////////////////////////////////////////////// +//Evolution of Process Environment Block (PEB) http://blog.rewolf.pl/blog/?p=573 +//March 2, 2013 / ReWolf posted in programming, reverse engineering, source code, x64 / + +#pragma pack(push) +#pragma pack(1) + +template +struct LIST_ENTRY_T +{ + T Flink; + T Blink; +}; + +template +struct UNICODE_STRING_T +{ + union + { + struct + { + WORD Length; + WORD MaximumLength; + }; + T dummy; + }; + T _Buffer; +}; + +template +struct _PEB_T +{ + union + { + struct + { + BYTE InheritedAddressSpace; + BYTE ReadImageFileExecOptions; + BYTE BeingDebugged; + BYTE _SYSTEM_DEPENDENT_01; + }; + T dummy01; + }; + T Mutant; + T ImageBaseAddress; + T Ldr; + T ProcessParameters; + T SubSystemData; + T ProcessHeap; + T FastPebLock; + T _SYSTEM_DEPENDENT_02; + T _SYSTEM_DEPENDENT_03; + T _SYSTEM_DEPENDENT_04; + union + { + T KernelCallbackTable; + T UserSharedInfoPtr; + }; + DWORD SystemReserved; + DWORD _SYSTEM_DEPENDENT_05; + T _SYSTEM_DEPENDENT_06; + T TlsExpansionCounter; + T TlsBitmap; + DWORD TlsBitmapBits[2]; + T ReadOnlySharedMemoryBase; + T _SYSTEM_DEPENDENT_07; + T ReadOnlyStaticServerData; + T AnsiCodePageData; + T OemCodePageData; + T UnicodeCaseTableData; + DWORD NumberOfProcessors; + union + { + DWORD NtGlobalFlag; + NGF dummy02; + }; + LARGE_INTEGER CriticalSectionTimeout; + T HeapSegmentReserve; + T HeapSegmentCommit; + T HeapDeCommitTotalFreeThreshold; + T HeapDeCommitFreeBlockThreshold; + DWORD NumberOfHeaps; + DWORD MaximumNumberOfHeaps; + T ProcessHeaps; +}; + +typedef _PEB_T PEB32; +typedef _PEB_T PEB64; + +#ifdef _WIN64 +typedef PEB64 PEB_CURRENT; +#else +typedef PEB32 PEB_CURRENT; +#endif + +#pragma pack(pop) + + +typedef NTSTATUS(WINAPI* def_NtTerminateProcess)(HANDLE ProcessHandle, NTSTATUS ExitStatus); +typedef NTSTATUS(WINAPI* def_NtQueryObject)(HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength); +typedef NTSTATUS(WINAPI* def_NtDuplicateObject)(HANDLE SourceProcessHandle, HANDLE SourceHandle, HANDLE TargetProcessHandle, PHANDLE TargetHandle, ACCESS_MASK DesiredAccess, BOOLEAN InheritHandle, ULONG Options); +typedef NTSTATUS(WINAPI* def_NtQueryInformationFile)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); +typedef NTSTATUS(WINAPI* def_NtQueryInformationThread)(HANDLE ThreadHandle, THREADINFOCLASS ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength, PULONG ReturnLength); +typedef NTSTATUS(WINAPI* def_NtQueryInformationProcess)(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength); +typedef NTSTATUS(WINAPI* def_NtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); +typedef NTSTATUS(WINAPI* def_NtQueryVirtualMemory)(HANDLE ProcessHandle, PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID Buffer, SIZE_T MemoryInformationLength, PSIZE_T ReturnLength); +typedef NTSTATUS(WINAPI* def_NtOpenProcess)(PHANDLE ProcessHandle, ACCESS_MASK AccessMask, PVOID ObjectAttributes, PCLIENT_ID ClientId); +typedef NTSTATUS(WINAPI* def_NtOpenThread)(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId); +typedef NTSTATUS(WINAPI* def_NtResumeThread)(HANDLE ThreadHandle, PULONG SuspendCount); +typedef NTSTATUS(WINAPI* def_NtSetInformationThread)(HANDLE ThreadHandle, THREADINFOCLASS ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength); +typedef NTSTATUS(WINAPI* def_NtCreateThreadEx)(PHANDLE hThread, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, int CreateFlags, ULONG StackZeroBits, LPVOID SizeOfStackCommit, LPVOID SizeOfStackReserve, LPVOID lpBytesBuffer); +typedef NTSTATUS(WINAPI* def_NtSuspendProcess)(HANDLE ProcessHandle); +typedef NTSTATUS(WINAPI* def_NtResumeProcess)(HANDLE ProcessHandle); + +typedef NTSTATUS(WINAPI* def_NtOpenSymbolicLinkObject)(PHANDLE LinkHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes); +typedef NTSTATUS(WINAPI* def_NtQuerySymbolicLinkObject)(HANDLE LinkHandle, PUNICODE_STRING LinkTarget, PULONG ReturnedLength); + +typedef ULONG(WINAPI* def_RtlNtStatusToDosError)(NTSTATUS Status); +typedef NTSTATUS(WINAPI* def_NtClose)(HANDLE Handle); + +//Flags from waliedassar +#define NtCreateThreadExFlagCreateSuspended 0x1 +#define NtCreateThreadExFlagSuppressDllMains 0x2 +#define NtCreateThreadExFlagHideFromDebugger 0x4 + +#define SYMBOLIC_LINK_QUERY (0x0001) + +class NativeWinApi +{ +public: + + static def_NtCreateThreadEx NtCreateThreadEx; + static def_NtDuplicateObject NtDuplicateObject; + static def_NtOpenProcess NtOpenProcess; + static def_NtOpenThread NtOpenThread; + static def_NtQueryObject NtQueryObject; + static def_NtQueryInformationFile NtQueryInformationFile; + static def_NtQueryInformationProcess NtQueryInformationProcess; + static def_NtQueryInformationThread NtQueryInformationThread; + static def_NtQuerySystemInformation NtQuerySystemInformation; + static def_NtQueryVirtualMemory NtQueryVirtualMemory; + static def_NtResumeProcess NtResumeProcess; + static def_NtResumeThread NtResumeThread; + static def_NtSetInformationThread NtSetInformationThread; + static def_NtSuspendProcess NtSuspendProcess; + static def_NtTerminateProcess NtTerminateProcess; + static def_NtOpenSymbolicLinkObject NtOpenSymbolicLinkObject; + static def_NtQuerySymbolicLinkObject NtQuerySymbolicLinkObject; + + static def_NtClose NtClose; + static def_RtlNtStatusToDosError RtlNtStatusToDosError; + + static void RtlInitUnicodeString(PUNICODE_STRING DestinationString, PWSTR SourceString) + { + DestinationString->Buffer = SourceString; + DestinationString->MaximumLength = DestinationString->Length = (USHORT)wcslen(SourceString) * sizeof(WCHAR); + } + + static void initialize(); + + static PPEB getCurrentProcessEnvironmentBlock(); + static PPEB getProcessEnvironmentBlockAddress(HANDLE processHandle); +}; diff --git a/scylla_wrapper/PeParser.cpp b/scylla_wrapper/PeParser.cpp new file mode 100644 index 0000000..211d4d1 --- /dev/null +++ b/scylla_wrapper/PeParser.cpp @@ -0,0 +1,1378 @@ +#include "stdafx.h" +#include "PeParser.h" +#include "ProcessAccessHelp.h" +#include +#include + +#pragma comment(lib, "Imagehlp.lib") + + +PeParser::PeParser() +{ + initClass(); +} + +PeParser::PeParser(const WCHAR* file, bool readSectionHeaders) +{ + initClass(); + + filename = file; + + if(filename) + { + readPeHeaderFromFile(readSectionHeaders); + + if(readSectionHeaders) + { + if(isValidPeFile()) + { + getSectionHeaders(); + } + } + } +} + +PeParser::PeParser(const DWORD_PTR moduleBase, bool readSectionHeaders) +{ + initClass(); + + moduleBaseAddress = moduleBase; + + if(moduleBaseAddress) + { + readPeHeaderFromProcess(readSectionHeaders); + + if(readSectionHeaders) + { + if(isValidPeFile()) + { + getSectionHeaders(); + } + } + } + +} + +PeParser::PeParser(const DWORD_PTR iatVA, const DWORD_PTR FileMapVA, const HANDLE hFileMap, bool readSectionHeaders) +{ + initClass(); + + hFile = hFileMap; + fileMapVA = FileMapVA; + + if(hFile) + { + readPeHeaderFromFileMapping(readSectionHeaders); + + if(readSectionHeaders) + { + if(isValidPeFile()) + { + getSectionHeaders(); + } + } + } +} + +PeParser::~PeParser() +{ + if(headerMemory) + { + delete [] headerMemory; + } + if(fileMemory) + { + delete [] fileMemory; + } + + for(size_t i = 0; i < listPeSection.size(); i++) + { + if(listPeSection[i].data) + { + delete [] listPeSection[i].data; + } + } + + listPeSection.clear(); +} + +void PeParser::initClass() +{ + fileMemory = 0; + headerMemory = 0; + + pDosHeader = 0; + pDosStub = 0; + dosStubSize = 0; + pNTHeader32 = 0; + pNTHeader64 = 0; + overlayData = 0; + overlaySize = 0; + + filename = 0; + fileSize = 0; + moduleBaseAddress = 0; + fileMapVA = 0; + hFile = INVALID_HANDLE_VALUE; +} + +bool PeParser::isPE64() +{ + if(isValidPeFile()) + { + return (pNTHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC); + } + else + { + return false; + } +} + +bool PeParser::isPE32() +{ + if(isValidPeFile()) + { + return (pNTHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC); + } + else + { + return false; + } +} + +bool PeParser::isTargetFileSamePeFormat() +{ +#ifdef _WIN64 + return isPE64(); +#else + return isPE32(); +#endif +} + +bool PeParser::isValidPeFile() +{ + bool retValue = false; + + if(pDosHeader) + { + if(pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) + { + if(pNTHeader32) + { + if(pNTHeader32->Signature == IMAGE_NT_SIGNATURE) + { + retValue = true; + } + } + } + } + + return retValue; +} + +bool PeParser::hasDirectory(const int directoryIndex) +{ + if(isPE32()) + { + return (pNTHeader32->OptionalHeader.DataDirectory[directoryIndex].VirtualAddress != 0); + } + else if(isPE64()) + { + return (pNTHeader64->OptionalHeader.DataDirectory[directoryIndex].VirtualAddress != 0); + } + else + { + return false; + } +} + +bool PeParser::hasExportDirectory() +{ + return hasDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT); +} + +bool PeParser::hasTLSDirectory() +{ + return hasDirectory(IMAGE_DIRECTORY_ENTRY_TLS); +} + +bool PeParser::hasRelocationDirectory() +{ + return hasDirectory(IMAGE_DIRECTORY_ENTRY_BASERELOC); +} + +DWORD PeParser::getEntryPoint() +{ + if(isPE32()) + { + return pNTHeader32->OptionalHeader.AddressOfEntryPoint; + } + else if(isPE64()) + { + return pNTHeader64->OptionalHeader.AddressOfEntryPoint; + } + else + { + return 0; + } +} + +bool PeParser::readPeHeaderFromProcess(bool readSectionHeaders) +{ + bool retValue = false; + DWORD correctSize = 0; + + DWORD readSize = getInitialHeaderReadSize(readSectionHeaders); + + headerMemory = new BYTE[readSize]; + + if(ProcessAccessHelp::readMemoryPartlyFromProcess(moduleBaseAddress, readSize, headerMemory)) + { + retValue = true; + + getDosAndNtHeader(headerMemory, (LONG)readSize); + + if(isValidPeFile()) + { + correctSize = calcCorrectPeHeaderSize(readSectionHeaders); + + if(readSize < correctSize) + { + readSize = correctSize; + delete [] headerMemory; + headerMemory = new BYTE[readSize]; + + if(ProcessAccessHelp::readMemoryPartlyFromProcess(moduleBaseAddress, readSize, headerMemory)) + { + getDosAndNtHeader(headerMemory, (LONG)readSize); + } + } + } + } + + return retValue; +} + +bool PeParser::readPeHeaderFromFile(bool readSectionHeaders) +{ + bool retValue = false; + DWORD correctSize = 0; + DWORD numberOfBytesRead = 0; + + DWORD readSize = getInitialHeaderReadSize(readSectionHeaders); + + headerMemory = new BYTE[readSize]; + + if(openFileHandle()) + { + fileSize = (DWORD)ProcessAccessHelp::getFileSize(hFile); + + if(ReadFile(hFile, headerMemory, readSize, &numberOfBytesRead, 0)) + { + retValue = true; + + getDosAndNtHeader(headerMemory, (LONG)readSize); + + if(isValidPeFile()) + { + correctSize = calcCorrectPeHeaderSize(readSectionHeaders); + + if(readSize < correctSize) + { + readSize = correctSize; + + if(fileSize > 0) + { + if(fileSize < correctSize) + { + readSize = fileSize; + } + } + + + delete [] headerMemory; + headerMemory = new BYTE[readSize]; + + SetFilePointer(hFile, 0, 0, FILE_BEGIN); + + if(ReadFile(hFile, headerMemory, readSize, &numberOfBytesRead, 0)) + { + getDosAndNtHeader(headerMemory, (LONG)readSize); + } + } + } + } + + closeFileHandle(); + } + + return retValue; +} + +bool PeParser::readPeHeaderFromFileMapping(bool readSectionHeaders) +{ + bool retValue = false; + DWORD correctSize = 0; + DWORD numberOfBytesRead = 0; + + DWORD readSize = getInitialHeaderReadSize(readSectionHeaders); + + headerMemory = new BYTE[readSize]; + + //not working for fileMapping, hopefully we dont need it + //fileSize = (DWORD)ProcessAccessHelp::getFileSize(hFile); + + memcpy((void*)headerMemory, (void*)fileMapVA, readSize); + + getDosAndNtHeader(headerMemory, (LONG)readSize); + + if(isValidPeFile()) + { + retValue = true; + correctSize = calcCorrectPeHeaderSize(readSectionHeaders); + + if(readSize < correctSize) + { + readSize = correctSize; + + if(fileSize > 0) + { + if(fileSize < correctSize) + { + readSize = fileSize; + } + } + + + delete [] headerMemory; + headerMemory = new BYTE[readSize]; + + memcpy((void*)headerMemory, (void*)fileMapVA, readSize); + + getDosAndNtHeader(headerMemory, (LONG)readSize); + } + } + + return retValue; +} + +bool PeParser::readPeSectionsFromProcess() +{ + bool retValue = true; + DWORD_PTR readOffset = 0; + + listPeSection.reserve(getNumberOfSections()); + + for(WORD i = 0; i < getNumberOfSections(); i++) + { + readOffset = listPeSection[i].sectionHeader.VirtualAddress + moduleBaseAddress; + + listPeSection[i].normalSize = listPeSection[i].sectionHeader.Misc.VirtualSize; + + if(!readSectionFromProcess(readOffset, listPeSection[i])) + { + retValue = false; + } + } + + return retValue; +} + +bool PeParser::readPeSectionsFromFile() +{ + bool retValue = true; + DWORD readOffset = 0; + + listPeSection.reserve(getNumberOfSections()); + + + if(openFileHandle()) + { + for(WORD i = 0; i < getNumberOfSections(); i++) + { + readOffset = listPeSection[i].sectionHeader.PointerToRawData; + + listPeSection[i].normalSize = listPeSection[i].sectionHeader.SizeOfRawData; + + if(!readSectionFromFile(readOffset, listPeSection[i])) + { + retValue = false; + } + + } + + closeFileHandle(); + } + else + { + retValue = false; + } + + return retValue; +} + +bool PeParser::readPeSectionsFromMappedFile() +{ + bool retValue = true; + DWORD_PTR readOffset = 0; + + listPeSection.reserve(getNumberOfSections()); + + for(WORD i = 0; i < getNumberOfSections(); i++) + { + readOffset = listPeSection[i].sectionHeader.VirtualAddress + moduleBaseAddress; + + listPeSection[i].normalSize = listPeSection[i].sectionHeader.Misc.VirtualSize; + + readPeSectionFromFileMapping(readOffset, listPeSection[i]); + } + + return retValue; +} + +bool PeParser::getSectionHeaders() +{ + PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNTHeader32); + + PeFileSection peFileSection; + + listPeSection.clear(); + listPeSection.reserve(getNumberOfSections()); + + for(WORD i = 0; i < getNumberOfSections(); i++) + { + memcpy_s(&peFileSection.sectionHeader, sizeof(IMAGE_SECTION_HEADER), pSection, sizeof(IMAGE_SECTION_HEADER)); + + listPeSection.push_back(peFileSection); + pSection++; + } + + return true; +} + +bool PeParser::getSectionNameUnicode(const int sectionIndex, WCHAR* output, const int outputLen) +{ + CHAR sectionNameA[IMAGE_SIZEOF_SHORT_NAME + 1] = {0}; + + output[0] = 0; + + memcpy(sectionNameA, listPeSection[sectionIndex].sectionHeader.Name, IMAGE_SIZEOF_SHORT_NAME); //not null terminated + + return (swprintf_s(output, outputLen, L"%S", sectionNameA) != -1); +} + +WORD PeParser::getNumberOfSections() +{ + return pNTHeader32->FileHeader.NumberOfSections; +} + +void PeParser::setNumberOfSections(WORD numberOfSections) +{ + pNTHeader32->FileHeader.NumberOfSections = numberOfSections; +} + +std::vector & PeParser::getSectionHeaderList() +{ + return listPeSection; +} + +void PeParser::getDosAndNtHeader(BYTE* memory, LONG size) +{ + pDosHeader = (PIMAGE_DOS_HEADER)memory; + + pNTHeader32 = 0; + pNTHeader64 = 0; + dosStubSize = 0; + pDosStub = 0; + + if(pDosHeader->e_lfanew > 0 && pDosHeader->e_lfanew < size) //malformed PE + { + pNTHeader32 = (PIMAGE_NT_HEADERS32)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew); + pNTHeader64 = (PIMAGE_NT_HEADERS64)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew); + + if(pDosHeader->e_lfanew > sizeof(IMAGE_DOS_HEADER)) + { + dosStubSize = pDosHeader->e_lfanew - sizeof(IMAGE_DOS_HEADER); + pDosStub = (BYTE*)((DWORD_PTR)pDosHeader + sizeof(IMAGE_DOS_HEADER)); + } + else if(pDosHeader->e_lfanew < sizeof(IMAGE_DOS_HEADER)) + { + //Overlapped Headers, e.g. Spack (by Bagie) + pDosHeader->e_lfanew = sizeof(IMAGE_DOS_HEADER); + } + } +} + +DWORD PeParser::calcCorrectPeHeaderSize(bool readSectionHeaders) +{ + DWORD correctSize = pDosHeader->e_lfanew + 50; //extra buffer + + if(readSectionHeaders) + { + correctSize += getNumberOfSections() * sizeof(IMAGE_SECTION_HEADER); + } + + if(isPE32()) + { + correctSize += sizeof(IMAGE_NT_HEADERS32); + } + else if(isPE64()) + { + correctSize += sizeof(IMAGE_NT_HEADERS64); + } + else + { + correctSize = 0; //not a valid PE + } + + return correctSize; +} + +DWORD PeParser::getInitialHeaderReadSize(bool readSectionHeaders) +{ + DWORD readSize = sizeof(IMAGE_DOS_HEADER) + 0x300 + sizeof(IMAGE_NT_HEADERS64); + + //if (readSectionHeaders) + //{ + // readSize += (10 * sizeof(IMAGE_SECTION_HEADER)); + //} + + return readSize; +} + +DWORD PeParser::getSectionHeaderBasedFileSize() +{ + DWORD lastRawOffset = 0, lastRawSize = 0; + + //this is needed if the sections aren't sorted by their RawOffset (e.g. Petite) + for(WORD i = 0; i < getNumberOfSections(); i++) + { + if((listPeSection[i].sectionHeader.PointerToRawData + listPeSection[i].sectionHeader.SizeOfRawData) > (lastRawOffset + lastRawSize)) + { + lastRawOffset = listPeSection[i].sectionHeader.PointerToRawData; + lastRawSize = listPeSection[i].sectionHeader.SizeOfRawData; + } + } + + return (lastRawSize + lastRawOffset); +} + +DWORD PeParser::getSectionHeaderBasedSizeOfImage() +{ + DWORD lastVirtualOffset = 0, lastVirtualSize = 0; + + //this is needed if the sections aren't sorted by their RawOffset (e.g. Petite) + for(WORD i = 0; i < getNumberOfSections(); i++) + { + if((listPeSection[i].sectionHeader.VirtualAddress + listPeSection[i].sectionHeader.Misc.VirtualSize) > (lastVirtualOffset + lastVirtualSize)) + { + lastVirtualOffset = listPeSection[i].sectionHeader.VirtualAddress; + lastVirtualSize = listPeSection[i].sectionHeader.Misc.VirtualSize; + } + } + + return (lastVirtualSize + lastVirtualOffset); +} + +bool PeParser::openFileHandle() +{ + if(hFile == INVALID_HANDLE_VALUE) + { + if(filename) + { + hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + } + else + { + hFile = INVALID_HANDLE_VALUE; + } + } + + return (hFile != INVALID_HANDLE_VALUE); +} + +bool PeParser::openWriteFileHandle(const WCHAR* newFile) +{ + if(newFile) + { + hFile = CreateFile(newFile, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + } + else + { + hFile = INVALID_HANDLE_VALUE; + } + + return (hFile != INVALID_HANDLE_VALUE); +} + + +void PeParser::closeFileHandle() +{ + if(hFile != INVALID_HANDLE_VALUE) + { + CloseHandle(hFile); + hFile = INVALID_HANDLE_VALUE; + } +} + +bool PeParser::readSectionFromProcess(const DWORD_PTR readOffset, PeFileSection & peFileSection) +{ + return readSectionFrom(readOffset, peFileSection, true); //process +} + +bool PeParser::readSectionFromFile(const DWORD readOffset, PeFileSection & peFileSection) +{ + return readSectionFrom(readOffset, peFileSection, false); //file +} + +bool PeParser::readSectionFrom(const DWORD_PTR readOffset, PeFileSection & peFileSection, const bool isProcess) +{ + const DWORD maxReadSize = 100; + DWORD currentReadSize; + BYTE data[maxReadSize]; + bool retValue = true; + DWORD valuesFound = 0; + DWORD readSize = 0; + DWORD_PTR currentOffset = 0; + + peFileSection.data = 0; + peFileSection.dataSize = 0; + readSize = peFileSection.normalSize; + + if(!readOffset || !readSize) + { + return true; //section without data is valid + } + + if(readSize <= maxReadSize) + { + peFileSection.dataSize = readSize; + peFileSection.normalSize = readSize; + + if(isProcess) + { + return readPeSectionFromProcess(readOffset, peFileSection); + } + else + { + return readPeSectionFromFile((DWORD)readOffset, peFileSection); + } + } + + currentReadSize = readSize % maxReadSize; //alignment % + + if(!currentReadSize) + { + currentReadSize = maxReadSize; + } + currentOffset = readOffset + readSize - currentReadSize; + + + while(currentOffset >= readOffset) //start from the end + { + ZeroMemory(data, currentReadSize); + + if(isProcess) + { + retValue = ProcessAccessHelp::readMemoryPartlyFromProcess(currentOffset, currentReadSize, data); + } + else + { + retValue = ProcessAccessHelp::readMemoryFromFile(hFile, (LONG)currentOffset, currentReadSize, data); + } + + if(!retValue) + { + break; + } + + valuesFound = isMemoryNotNull(data, currentReadSize); + if(valuesFound) + { + //found some real code + + currentOffset += valuesFound; + + if(readOffset < currentOffset) + { + //real size + peFileSection.dataSize = (DWORD)(currentOffset - readOffset); + + //some safety space because of something like this at the end of a section: + //FF25 C0604000 JMP DWORD PTR DS:[<&KERNEL32.RtlUnwind>] + peFileSection.dataSize += sizeof(DWORD); + + if(peFileSection.normalSize < peFileSection.dataSize) + { + peFileSection.dataSize = peFileSection.normalSize; + } + } + + break; + } + + currentReadSize = maxReadSize; + currentOffset -= currentReadSize; + } + + if(peFileSection.dataSize) + { + if(isProcess) + { + retValue = readPeSectionFromProcess(readOffset, peFileSection); + } + else + { + retValue = readPeSectionFromFile((DWORD)readOffset, peFileSection); + } + } + + return retValue; +} + + +DWORD PeParser::isMemoryNotNull(BYTE* data, int dataSize) +{ + for(int i = (dataSize - 1); i >= 0; i--) + { + if(data[i] != 0) + { + return i + 1; + } + } + + return 0; +} + +bool PeParser::savePeFileToDisk(const WCHAR* newFile) +{ + bool retValue = true; + DWORD dwFileOffset = 0, dwWriteSize = 0; + + if(getNumberOfSections() != listPeSection.size()) + { + return false; + } + + if(openWriteFileHandle(newFile)) + { + //Dos header + dwWriteSize = sizeof(IMAGE_DOS_HEADER); + if(!ProcessAccessHelp::writeMemoryToFile(hFile, dwFileOffset, dwWriteSize, pDosHeader)) + { + retValue = false; + } + dwFileOffset += dwWriteSize; + + + if(dosStubSize && pDosStub) + { + //Dos Stub + dwWriteSize = dosStubSize; + if(!ProcessAccessHelp::writeMemoryToFile(hFile, dwFileOffset, dwWriteSize, pDosStub)) + { + retValue = false; + } + dwFileOffset += dwWriteSize; + } + + + //Pe Header + if(isPE32()) + { + dwWriteSize = sizeof(IMAGE_NT_HEADERS32); + } + else + { + dwWriteSize = sizeof(IMAGE_NT_HEADERS64); + } + + if(!ProcessAccessHelp::writeMemoryToFile(hFile, dwFileOffset, dwWriteSize, pNTHeader32)) + { + retValue = false; + } + dwFileOffset += dwWriteSize; + + //section headers + dwWriteSize = sizeof(IMAGE_SECTION_HEADER); + + for(WORD i = 0; i < getNumberOfSections(); i++) + { + if(!ProcessAccessHelp::writeMemoryToFile(hFile, dwFileOffset, dwWriteSize, &listPeSection[i].sectionHeader)) + { + retValue = false; + break; + } + dwFileOffset += dwWriteSize; + } + + for(WORD i = 0; i < getNumberOfSections(); i++) + { + if(!listPeSection[i].sectionHeader.PointerToRawData) + continue; + + + if(listPeSection[i].sectionHeader.PointerToRawData > dwFileOffset) + { + dwWriteSize = listPeSection[i].sectionHeader.PointerToRawData - dwFileOffset; //padding + + if(!writeZeroMemoryToFile(hFile, dwFileOffset, dwWriteSize)) + { + retValue = false; + break; + } + dwFileOffset += dwWriteSize; + } + + dwWriteSize = listPeSection[i].dataSize; + + if(dwWriteSize) + { + if(!ProcessAccessHelp::writeMemoryToFile(hFile, listPeSection[i].sectionHeader.PointerToRawData, dwWriteSize, listPeSection[i].data)) + { + retValue = false; + break; + } + dwFileOffset += dwWriteSize; + + if(listPeSection[i].dataSize < listPeSection[i].sectionHeader.SizeOfRawData) //padding + { + dwWriteSize = listPeSection[i].sectionHeader.SizeOfRawData - listPeSection[i].dataSize; + + if(!writeZeroMemoryToFile(hFile, dwFileOffset, dwWriteSize)) + { + retValue = false; + break; + } + dwFileOffset += dwWriteSize; + } + } + + } + + //add overlay? + if(overlaySize && overlayData) + { + dwWriteSize = overlaySize; + if(!ProcessAccessHelp::writeMemoryToFile(hFile, dwFileOffset, dwWriteSize, overlayData)) + { + retValue = false; + } + dwFileOffset += dwWriteSize; + } + + SetEndOfFile(hFile); + + closeFileHandle(); + } + + return retValue; +} + +bool PeParser::writeZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size) +{ + bool retValue = false; + PVOID zeromemory = calloc(size, 1); + + if(zeromemory) + { + retValue = ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, size, zeromemory); + free(zeromemory); + } + + return retValue; +} + +void PeParser::removeDosStub() +{ + if(pDosHeader) + { + dosStubSize = 0; + pDosStub = 0; //must not delete [] + pDosHeader->e_lfanew = sizeof(IMAGE_DOS_HEADER); + } +} + +bool PeParser::readPeSectionFromFile(DWORD readOffset, PeFileSection & peFileSection) +{ + DWORD bytesRead = 0; + + peFileSection.data = new BYTE[peFileSection.dataSize]; + + SetFilePointer(hFile, readOffset, 0, FILE_BEGIN); + + return (ReadFile(hFile, peFileSection.data, peFileSection.dataSize, &bytesRead, 0) != FALSE); +} + +bool PeParser::readPeSectionFromFileMapping(DWORD readOffset, PeFileSection & peFileSection) +{ + DWORD bytesRead = 0; + + peFileSection.data = (BYTE*)fileMapVA + readOffset; + + return true; +} + +bool PeParser::readPeSectionFromProcess(DWORD_PTR readOffset, PeFileSection & peFileSection) +{ + peFileSection.data = new BYTE[peFileSection.dataSize]; + + return ProcessAccessHelp::readMemoryPartlyFromProcess(readOffset, peFileSection.dataSize, peFileSection.data); +} + +DWORD PeParser::alignValue(DWORD badValue, DWORD alignTo) +{ + return (((badValue + alignTo - 1) / alignTo) * alignTo); +} + +bool PeParser::addNewLastSection(const CHAR* sectionName, DWORD sectionSize, BYTE* sectionData) +{ + size_t nameLength = strlen(sectionName); + DWORD fileAlignment = 0, sectionAlignment = 0; + PeFileSection peFileSection; + + if(nameLength > IMAGE_SIZEOF_SHORT_NAME) + { + return false; + } + + if(isPE32()) + { + fileAlignment = pNTHeader32->OptionalHeader.FileAlignment; + sectionAlignment = pNTHeader32->OptionalHeader.SectionAlignment; + } + else + { + fileAlignment = pNTHeader64->OptionalHeader.FileAlignment; + sectionAlignment = pNTHeader64->OptionalHeader.SectionAlignment; + } + + memcpy_s(peFileSection.sectionHeader.Name, IMAGE_SIZEOF_SHORT_NAME, sectionName, nameLength); + + //last section doesn't need SizeOfRawData alignment + peFileSection.sectionHeader.SizeOfRawData = sectionSize; //alignValue(sectionSize, fileAlignment); + peFileSection.sectionHeader.Misc.VirtualSize = alignValue(sectionSize, sectionAlignment); + + peFileSection.sectionHeader.PointerToRawData = alignValue(getSectionHeaderBasedFileSize(), fileAlignment); + peFileSection.sectionHeader.VirtualAddress = alignValue(getSectionHeaderBasedSizeOfImage(), sectionAlignment); + + peFileSection.sectionHeader.Characteristics = IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA; + + peFileSection.normalSize = peFileSection.sectionHeader.SizeOfRawData; + peFileSection.dataSize = peFileSection.sectionHeader.SizeOfRawData; + + if(sectionData == 0) + { + peFileSection.data = new BYTE[peFileSection.sectionHeader.SizeOfRawData]; + ZeroMemory(peFileSection.data, peFileSection.sectionHeader.SizeOfRawData); + } + else + { + peFileSection.data = sectionData; + } + + listPeSection.push_back(peFileSection); + + setNumberOfSections(getNumberOfSections() + 1); + + return true; +} + +DWORD_PTR PeParser::getStandardImagebase() +{ + if(isPE32()) + { + return pNTHeader32->OptionalHeader.ImageBase; + } + else + { + return pNTHeader64->OptionalHeader.ImageBase; + } +} + +int PeParser::convertRVAToOffsetVectorIndex(DWORD_PTR dwRVA) +{ + for(WORD i = 0; i < getNumberOfSections(); i++) + { + if((listPeSection[i].sectionHeader.VirtualAddress <= dwRVA) && ((listPeSection[i].sectionHeader.VirtualAddress + listPeSection[i].sectionHeader.Misc.VirtualSize) > dwRVA)) + { + return i; + } + } + + return -1; +} + +DWORD_PTR PeParser::convertRVAToOffsetVector(DWORD_PTR dwRVA) +{ + for(WORD i = 0; i < getNumberOfSections(); i++) + { + if((listPeSection[i].sectionHeader.VirtualAddress <= dwRVA) && ((listPeSection[i].sectionHeader.VirtualAddress + listPeSection[i].sectionHeader.Misc.VirtualSize) > dwRVA)) + { + return ((dwRVA - listPeSection[i].sectionHeader.VirtualAddress) + listPeSection[i].sectionHeader.PointerToRawData); + } + } + + return 0; +} + +DWORD_PTR PeParser::convertRVAToOffsetRelative(DWORD_PTR dwRVA) +{ + for(WORD i = 0; i < getNumberOfSections(); i++) + { + if((listPeSection[i].sectionHeader.VirtualAddress <= dwRVA) && ((listPeSection[i].sectionHeader.VirtualAddress + listPeSection[i].sectionHeader.Misc.VirtualSize) > dwRVA)) + { + return (dwRVA - listPeSection[i].sectionHeader.VirtualAddress); + } + } + + return 0; +} + +DWORD_PTR PeParser::convertOffsetToRVAVector(DWORD_PTR dwOffset) +{ + for(WORD i = 0; i < getNumberOfSections(); i++) + { + if((listPeSection[i].sectionHeader.PointerToRawData <= dwOffset) && ((listPeSection[i].sectionHeader.PointerToRawData + listPeSection[i].sectionHeader.SizeOfRawData) > dwOffset)) + { + return ((dwOffset - listPeSection[i].sectionHeader.PointerToRawData) + listPeSection[i].sectionHeader.VirtualAddress); + } + } + + return 0; +} + +void PeParser::fixPeHeader() +{ + DWORD dwSize = pDosHeader->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER); + + if(isPE32()) + { + //delete bound import directories + pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0; + pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; + + //max 16, zeroing possible garbage values + for(DWORD i = pNTHeader32->OptionalHeader.NumberOfRvaAndSizes; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) + { + pNTHeader32->OptionalHeader.DataDirectory[i].Size = 0; + pNTHeader32->OptionalHeader.DataDirectory[i].VirtualAddress = 0; + } + + pNTHeader32->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; + pNTHeader32->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER32); + + pNTHeader32->OptionalHeader.SizeOfImage = getSectionHeaderBasedSizeOfImage(); + + if(moduleBaseAddress) + { + pNTHeader32->OptionalHeader.ImageBase = (DWORD)moduleBaseAddress; + } + + pNTHeader32->OptionalHeader.SizeOfHeaders = alignValue(dwSize + pNTHeader32->FileHeader.SizeOfOptionalHeader + (getNumberOfSections() * sizeof(IMAGE_SECTION_HEADER)), pNTHeader32->OptionalHeader.FileAlignment); + } + else + { + //delete bound import directories + pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0; + pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; + + //max 16, zeroing possible garbage values + for(DWORD i = pNTHeader64->OptionalHeader.NumberOfRvaAndSizes; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) + { + pNTHeader64->OptionalHeader.DataDirectory[i].Size = 0; + pNTHeader64->OptionalHeader.DataDirectory[i].VirtualAddress = 0; + } + + pNTHeader64->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; + pNTHeader64->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64); + + pNTHeader64->OptionalHeader.SizeOfImage = getSectionHeaderBasedSizeOfImage(); + + if(moduleBaseAddress) + { + pNTHeader64->OptionalHeader.ImageBase = moduleBaseAddress; + } + + pNTHeader64->OptionalHeader.SizeOfHeaders = alignValue(dwSize + pNTHeader64->FileHeader.SizeOfOptionalHeader + (getNumberOfSections() * sizeof(IMAGE_SECTION_HEADER)), pNTHeader64->OptionalHeader.FileAlignment); + } + + removeIatDirectory(); +} + +void PeParser::removeIatDirectory() +{ + DWORD searchAddress = 0; + + if(isPE32()) + { + searchAddress = pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress; + + pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0; + pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0; + } + else + { + searchAddress = pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress; + + pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0; + pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0; + } + + if(searchAddress) + { + for(WORD i = 0; i < getNumberOfSections(); i++) + { + if((listPeSection[i].sectionHeader.VirtualAddress <= searchAddress) && ((listPeSection[i].sectionHeader.VirtualAddress + listPeSection[i].sectionHeader.Misc.VirtualSize) > searchAddress)) + { + //section must be read and writable + listPeSection[i].sectionHeader.Characteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; + } + } + } +} + +void PeParser::setDefaultFileAlignment() +{ + if(isPE32()) + { + pNTHeader32->OptionalHeader.FileAlignment = FileAlignmentConstant; + } + else + { + pNTHeader64->OptionalHeader.FileAlignment = FileAlignmentConstant; + } +} + +bool PeFileSectionSortByPointerToRawData(const PeFileSection & d1, const PeFileSection & d2) +{ + return d1.sectionHeader.PointerToRawData < d2.sectionHeader.PointerToRawData; +} + +bool PeFileSectionSortByVirtualAddress(const PeFileSection & d1, const PeFileSection & d2) +{ + return d1.sectionHeader.VirtualAddress < d2.sectionHeader.VirtualAddress; +} + +void PeParser::alignAllSectionHeaders() +{ + DWORD sectionAlignment = 0; + DWORD fileAlignment = 0; + DWORD newFileSize = 0; + + if(isPE32()) + { + sectionAlignment = pNTHeader32->OptionalHeader.SectionAlignment; + fileAlignment = pNTHeader32->OptionalHeader.FileAlignment; + } + else + { + sectionAlignment = pNTHeader64->OptionalHeader.SectionAlignment; + fileAlignment = pNTHeader64->OptionalHeader.FileAlignment; + } + + std::sort(listPeSection.begin(), listPeSection.end(), PeFileSectionSortByPointerToRawData); //sort by PointerToRawData ascending + + newFileSize = pDosHeader->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + pNTHeader32->FileHeader.SizeOfOptionalHeader + (getNumberOfSections() * sizeof(IMAGE_SECTION_HEADER)); + + + for(WORD i = 0; i < getNumberOfSections(); i++) + { + listPeSection[i].sectionHeader.VirtualAddress = alignValue(listPeSection[i].sectionHeader.VirtualAddress, sectionAlignment); + listPeSection[i].sectionHeader.Misc.VirtualSize = alignValue(listPeSection[i].sectionHeader.Misc.VirtualSize, sectionAlignment); + + listPeSection[i].sectionHeader.PointerToRawData = alignValue(newFileSize, fileAlignment); + listPeSection[i].sectionHeader.SizeOfRawData = alignValue(listPeSection[i].dataSize, fileAlignment); + + newFileSize = listPeSection[i].sectionHeader.PointerToRawData + listPeSection[i].sectionHeader.SizeOfRawData; + } + + std::sort(listPeSection.begin(), listPeSection.end(), PeFileSectionSortByVirtualAddress); //sort by VirtualAddress ascending +} + +bool PeParser::dumpProcess(DWORD_PTR modBase, DWORD_PTR entryPoint, const WCHAR* dumpFilePath) +{ + moduleBaseAddress = modBase; + + if(readPeSectionsFromProcess()) + { + setDefaultFileAlignment(); + + setEntryPointVa(entryPoint); + + alignAllSectionHeaders(); + fixPeHeader(); + + getFileOverlay(); + + return savePeFileToDisk(dumpFilePath); + } + + return false; +} + +bool PeParser::dumpProcess(DWORD_PTR modBase, DWORD_PTR entryPoint, const WCHAR* dumpFilePath, std::vector & sectionList) +{ + if(listPeSection.size() == sectionList.size()) + { + for(int i = (getNumberOfSections() - 1); i >= 0; i--) + { + if(!sectionList[i].isDumped) + { + listPeSection.erase(listPeSection.begin() + i); + setNumberOfSections(getNumberOfSections() - 1); + } + else + { + listPeSection[i].sectionHeader.Misc.VirtualSize = sectionList[i].virtualSize; + listPeSection[i].sectionHeader.SizeOfRawData = sectionList[i].rawSize; + listPeSection[i].sectionHeader.Characteristics = sectionList[i].characteristics; + } + } + } + + return dumpProcess(modBase, entryPoint, dumpFilePath); +} + +void PeParser::setEntryPointVa(DWORD_PTR entryPoint) +{ + DWORD entryPointRva = (DWORD)(entryPoint - moduleBaseAddress); + + setEntryPointRva(entryPointRva); +} + +void PeParser::setEntryPointRva(DWORD entryPoint) +{ + if(isPE32()) + { + pNTHeader32->OptionalHeader.AddressOfEntryPoint = entryPoint; + } + else if(isPE64()) + { + pNTHeader64->OptionalHeader.AddressOfEntryPoint = entryPoint; + } +} + +bool PeParser::getFileOverlay() +{ + DWORD numberOfBytesRead; + bool retValue = false; + + if(!hasOverlayData()) + { + return false; + } + + if(openFileHandle()) + { + DWORD overlayOffset = getSectionHeaderBasedFileSize(); + DWORD fileSize = (DWORD)ProcessAccessHelp::getFileSize(hFile); + overlaySize = fileSize - overlayOffset; + + overlayData = new BYTE[overlaySize]; + + SetFilePointer(hFile, overlayOffset, 0, FILE_BEGIN); + + if(ReadFile(hFile, overlayData, overlaySize, &numberOfBytesRead, 0)) + { + retValue = true; + } + + closeFileHandle(); + } + + return retValue; +} + +bool PeParser::hasOverlayData() +{ + if(!filename) + return false; + + if(isValidPeFile()) + { + DWORD fileSize = (DWORD)ProcessAccessHelp::getFileSize(filename); + + return (fileSize > getSectionHeaderBasedFileSize()); + } + else + { + return false; + } +} + +bool PeParser::updatePeHeaderChecksum(const WCHAR* targetFile, DWORD fileSize) +{ + PIMAGE_NT_HEADERS32 pNTHeader32 = 0; + PIMAGE_NT_HEADERS64 pNTHeader64 = 0; + DWORD headerSum = 0; + DWORD checkSum = 0; + bool retValue = false; + + if(!fileSize) + return retValue; + + HANDLE hFileToMap = CreateFile(targetFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + + if(hFileToMap != INVALID_HANDLE_VALUE) + { + HANDLE hMappedFile = CreateFileMapping(hFileToMap, 0, PAGE_READWRITE, 0, 0, 0); + if(hMappedFile) + { + if(GetLastError() != ERROR_ALREADY_EXISTS) + { + LPVOID addrMappedDll = MapViewOfFile(hMappedFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); + + if(addrMappedDll) + { + pNTHeader32 = (PIMAGE_NT_HEADERS32)CheckSumMappedFile(addrMappedDll, fileSize, &headerSum, &checkSum); + + if(pNTHeader32) + { + if(pNTHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + pNTHeader64 = (PIMAGE_NT_HEADERS64)pNTHeader32; + pNTHeader64->OptionalHeader.CheckSum = checkSum; + } + else + { + pNTHeader32->OptionalHeader.CheckSum = checkSum; + } + + retValue = true; + } + + UnmapViewOfFile(addrMappedDll); + } + } + CloseHandle(hMappedFile); + } + CloseHandle(hFileToMap); + } + + return retValue; +} + +BYTE* PeParser::getSectionMemoryByIndex(int index) +{ + return listPeSection[index].data; +} + +DWORD PeParser::getSectionMemorySizeByIndex(int index) +{ + return listPeSection[index].dataSize; +} + +DWORD PeParser::getSectionAddressRVAByIndex(int index) +{ + return listPeSection[index].sectionHeader.VirtualAddress; +} + +PIMAGE_NT_HEADERS PeParser::getCurrentNtHeader() +{ +#ifdef _WIN64 + return pNTHeader64; +#else + return pNTHeader32; +#endif +} \ No newline at end of file diff --git a/scylla_wrapper/PeParser.h b/scylla_wrapper/PeParser.h new file mode 100644 index 0000000..75c7332 --- /dev/null +++ b/scylla_wrapper/PeParser.h @@ -0,0 +1,167 @@ +#pragma once + +#include +#include + +class PeSection +{ +public: + WCHAR name[IMAGE_SIZEOF_SHORT_NAME + 1]; + DWORD_PTR virtualAddress; + DWORD virtualSize; + DWORD rawAddress; + DWORD rawSize; + DWORD characteristics; + + bool isDumped; + + //highlight big virtual sizes -> anti-dump protection + bool highlightVirtualSize() + { + return (virtualSize > 0x2000000); + }; +}; + +class PeFileSection +{ +public: + IMAGE_SECTION_HEADER sectionHeader; + BYTE* data; + DWORD dataSize; + DWORD normalSize; + + PeFileSection() + { + ZeroMemory(§ionHeader, sizeof(IMAGE_SECTION_HEADER)); + data = 0; + dataSize = 0; + normalSize = 0; + } +}; + +class PeParser +{ +public: + PeParser(const WCHAR* file, bool readSectionHeaders = true); + PeParser(const DWORD_PTR moduleBase, bool readSectionHeaders = true); + PeParser(const DWORD_PTR iatVA, const DWORD_PTR FileMapVA, const HANDLE hFileMap, bool readSectionHeaders = true); + + ~PeParser(); + + bool isValidPeFile(); + bool isPE64(); + bool isPE32(); + + bool isTargetFileSamePeFormat(); + + WORD getNumberOfSections(); + std::vector & getSectionHeaderList(); + + bool hasExportDirectory(); + bool hasTLSDirectory(); + bool hasRelocationDirectory(); + bool hasOverlayData(); + + DWORD getEntryPoint(); + + bool getSectionNameUnicode(const int sectionIndex, WCHAR* output, const int outputLen); + + DWORD getSectionHeaderBasedFileSize(); + DWORD getSectionHeaderBasedSizeOfImage(); + + bool readPeSectionsFromProcess(); + bool readPeSectionsFromFile(); + bool readPeSectionsFromMappedFile(); + bool savePeFileToDisk(const WCHAR* newFile); + void removeDosStub(); + void alignAllSectionHeaders(); + void fixPeHeader(); + void setDefaultFileAlignment(); + bool dumpProcess(DWORD_PTR modBase, DWORD_PTR entryPoint, const WCHAR* dumpFilePath); + bool dumpProcess(DWORD_PTR modBase, DWORD_PTR entryPoint, const WCHAR* dumpFilePath, std::vector & sectionList); + + void setEntryPointVa(DWORD_PTR entryPoint); + void setEntryPointRva(DWORD entryPoint); + + static bool updatePeHeaderChecksum(const WCHAR* targetFile, DWORD fileSize); + BYTE* getSectionMemoryByIndex(int index); + DWORD getSectionMemorySizeByIndex(int index); + int convertRVAToOffsetVectorIndex(DWORD_PTR dwRVA); + DWORD_PTR convertOffsetToRVAVector(DWORD_PTR dwOffset); + DWORD_PTR convertRVAToOffsetVector(DWORD_PTR dwRVA); + DWORD_PTR convertRVAToOffsetRelative(DWORD_PTR dwRVA); + DWORD getSectionAddressRVAByIndex(int index); + + PIMAGE_NT_HEADERS getCurrentNtHeader(); +protected: + PeParser(); + + + static const DWORD FileAlignmentConstant = 0x200; + + const WCHAR* filename; + DWORD_PTR moduleBaseAddress; + DWORD_PTR fileMapVA; + + /************************************************************************/ + /* PE FILE */ + /* */ + /* IMAGE_DOS_HEADER 64 0x40 */ + /* IMAGE_NT_HEADERS32 248 0xF8 */ + /* IMAGE_NT_HEADERS64 264 0x108 */ + /* IMAGE_SECTION_HEADER 40 0x28 */ + /************************************************************************/ + + PIMAGE_DOS_HEADER pDosHeader; + BYTE* pDosStub; //between dos header and section header + DWORD dosStubSize; + PIMAGE_NT_HEADERS32 pNTHeader32; + PIMAGE_NT_HEADERS64 pNTHeader64; + std::vector listPeSection; + BYTE* overlayData; + DWORD overlaySize; + /************************************************************************/ + + BYTE* fileMemory; + BYTE* headerMemory; + + HANDLE hFile; + DWORD fileSize; + + bool readPeHeaderFromFile(bool readSectionHeaders); + bool readPeHeaderFromFileMapping(bool readSectionHeaders); + bool readPeHeaderFromProcess(bool readSectionHeaders); + + bool hasDirectory(const int directoryIndex); + bool getSectionHeaders(); + void getDosAndNtHeader(BYTE* memory, LONG size); + DWORD calcCorrectPeHeaderSize(bool readSectionHeaders); + DWORD getInitialHeaderReadSize(bool readSectionHeaders); + bool openFileHandle(); + void closeFileHandle(); + void initClass(); + + DWORD isMemoryNotNull(BYTE* data, int dataSize); + bool openWriteFileHandle(const WCHAR* newFile); + bool writeZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size); + + bool readPeSectionFromFile(DWORD readOffset, PeFileSection & peFileSection); + bool readPeSectionFromProcess(DWORD_PTR readOffset, PeFileSection & peFileSection); + bool readPeSectionFromFileMapping(DWORD readOffset, PeFileSection & peFileSection); + + bool readSectionFromProcess(const DWORD_PTR readOffset, PeFileSection & peFileSection); + bool readSectionFromFile(const DWORD readOffset, PeFileSection & peFileSection); + bool readSectionFrom(const DWORD_PTR readOffset, PeFileSection & peFileSection, const bool isProcess); + + + DWORD_PTR getStandardImagebase(); + + bool addNewLastSection(const CHAR* sectionName, DWORD sectionSize, BYTE* sectionData); + DWORD alignValue(DWORD badValue, DWORD alignTo); + + void setNumberOfSections(WORD numberOfSections); + + void removeIatDirectory(); + bool getFileOverlay(); +}; + diff --git a/scylla_wrapper/ProcessAccessHelp.cpp b/scylla_wrapper/ProcessAccessHelp.cpp new file mode 100644 index 0000000..eea9a0d --- /dev/null +++ b/scylla_wrapper/ProcessAccessHelp.cpp @@ -0,0 +1,963 @@ +#include "stdafx.h" +#include "ProcessAccessHelp.h" +#include "DeviceNameResolver.h" +#include +#include "PeParser.h" +#include "NativeWinApi.h" + +HANDLE ProcessAccessHelp::hProcess = 0; + +ModuleInfo* ProcessAccessHelp::selectedModule; +DWORD_PTR ProcessAccessHelp::targetImageBase = 0; +DWORD_PTR ProcessAccessHelp::targetSizeOfImage = 0; +DWORD_PTR ProcessAccessHelp::maxValidAddress = 0; + +std::vector ProcessAccessHelp::moduleList; //target process module list +std::vector ProcessAccessHelp::ownModuleList; //own module list + +_DInst ProcessAccessHelp::decomposerResult[MAX_INSTRUCTIONS]; +unsigned int ProcessAccessHelp::decomposerInstructionsCount = 0; +_CodeInfo ProcessAccessHelp::decomposerCi = {0}; + +_DecodedInst ProcessAccessHelp::decodedInstructions[MAX_INSTRUCTIONS]; +unsigned int ProcessAccessHelp::decodedInstructionsCount = 0; + +BYTE ProcessAccessHelp::fileHeaderFromDisk[PE_HEADER_BYTES_COUNT]; + +//#define DEBUG_COMMENTS + +bool ProcessAccessHelp::openProcessHandle(DWORD dwPID) +{ + if(dwPID > 0) + { + if(hProcess) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"openProcessHandle :: There is already a process handle, HANDLE %X", hProcess); +#endif + return false; + } + else + { + //hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, 0, dwPID); + //if (!NT_SUCCESS(NativeWinApi::NtOpenProcess(&hProcess,PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE,&ObjectAttributes, &cid))) + + hProcess = NativeOpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_SUSPEND_RESUME | PROCESS_TERMINATE, dwPID); + + if(hProcess) + { + return true; + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"openProcessHandle :: Failed to open handle, PID %X", dwPID); +#endif + return false; + } + } + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"openProcessHandle :: Wrong PID, PID %X", dwPID); +#endif + return false; + } + +} + +HANDLE ProcessAccessHelp::NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId) +{ + HANDLE hProcess = 0; + CLIENT_ID cid = {0}; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS ntStatus = 0; + + InitializeObjectAttributes(&ObjectAttributes, 0, 0, 0, 0); + cid.UniqueProcess = (HANDLE)dwProcessId; + + ntStatus = NativeWinApi::NtOpenProcess(&hProcess, dwDesiredAccess, &ObjectAttributes, &cid); + + if(NT_SUCCESS(ntStatus)) + { + return hProcess; + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"NativeOpenProcess :: Failed to open handle, PID %X Error 0x%X", dwProcessId, NativeWinApi::RtlNtStatusToDosError(ntStatus)); +#endif + return 0; + } +} + +void ProcessAccessHelp::closeProcessHandle() +{ + if(hProcess) + { + CloseHandle(hProcess); + hProcess = 0; + } + + moduleList.clear(); + targetImageBase = 0; + selectedModule = 0; +} + +bool ProcessAccessHelp::readMemoryPartlyFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer) +{ + DWORD_PTR addressPart = 0; + DWORD_PTR readBytes = 0; + DWORD_PTR bytesToRead = 0; + MEMORY_BASIC_INFORMATION memBasic = {0}; + bool returnValue = false; + + if(!hProcess) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: hProcess == NULL"); +#endif + return returnValue; + } + + if(!readMemoryFromProcess(address, size, dataBuffer)) + { + addressPart = address; + + do + { + if(!VirtualQueryEx(ProcessAccessHelp::hProcess, (LPCVOID)addressPart, &memBasic, sizeof(memBasic))) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: Error VirtualQueryEx %X %X err: %u", addressPart, size, GetLastError()); +#endif + break; + } + + bytesToRead = memBasic.RegionSize; + + if((readBytes + bytesToRead) > size) + { + bytesToRead = size - readBytes; + } + + if(memBasic.State == MEM_COMMIT) + { + if(!readMemoryFromProcess(addressPart, bytesToRead, (LPVOID)((DWORD_PTR)dataBuffer + readBytes))) + { + break; + } + } + else + { + ZeroMemory((LPVOID)((DWORD_PTR)dataBuffer + readBytes), bytesToRead); + } + + + readBytes += bytesToRead; + + addressPart += memBasic.RegionSize; + + } + while(readBytes < size); + + if(readBytes == size) + { + returnValue = true; + } + + } + else + { + returnValue = true; + } + + return returnValue; +} + +bool ProcessAccessHelp::writeMemoryToProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer) +{ + SIZE_T lpNumberOfBytesWritten = 0; + if(!hProcess) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryFromProcess :: hProcess == NULL"); +#endif + return false; + } + + + return (WriteProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesWritten) != FALSE); +} + +bool ProcessAccessHelp::readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer) +{ + SIZE_T lpNumberOfBytesRead = 0; + DWORD dwProtect = 0; + bool returnValue = false; + + if(!hProcess) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryFromProcess :: hProcess == NULL"); +#endif + return returnValue; + } + + if(!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u", address, size, GetLastError()); +#endif + if(!VirtualProtectEx(hProcess, (LPVOID)address, size, PAGE_READWRITE, &dwProtect)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryFromProcess :: Error VirtualProtectEx %X %X err: %u", address, size, GetLastError()); +#endif + returnValue = false; + } + else + { + if(!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u", address, size, GetLastError()); +#endif + returnValue = false; + } + else + { + returnValue = true; + } + VirtualProtectEx(hProcess, (LPVOID)address, size, dwProtect, &dwProtect); + } + } + else + { + returnValue = true; + } + + if(returnValue) + { + if(size != lpNumberOfBytesRead) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory read %d bytes requested %d bytes", lpNumberOfBytesRead, size); +#endif + returnValue = false; + } + else + { + returnValue = true; + } + } + + return returnValue; +} + +bool ProcessAccessHelp::decomposeMemory(BYTE* dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress) +{ + + ZeroMemory(&decomposerCi, sizeof(_CodeInfo)); + decomposerCi.code = dataBuffer; + decomposerCi.codeLen = (int)bufferSize; + decomposerCi.dt = dt; + decomposerCi.codeOffset = startAddress; + + decomposerInstructionsCount = 0; + + if(distorm_decompose(&decomposerCi, decomposerResult, sizeof(decomposerResult) / sizeof(decomposerResult[0]), &decomposerInstructionsCount) == DECRES_INPUTERR) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"decomposeMemory :: distorm_decompose == DECRES_INPUTERR"); +#endif + return false; + } + else + { + return true; + } +} + +bool ProcessAccessHelp::disassembleMemory(BYTE* dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset) +{ + // Holds the result of the decoding. + _DecodeResult res; + + // next is used for instruction's offset synchronization. + // decodedInstructionsCount holds the count of filled instructions' array by the decoder. + + decodedInstructionsCount = 0; + + _OffsetType offset = startOffset; + + res = distorm_decode(offset, dataBuffer, (int)bufferSize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); + + /* for (unsigned int i = 0; i < decodedInstructionsCount; i++) { + #ifdef SUPPORT_64BIT_OFFSET + printf("%0*I64x (%02d) %-24s %s%s%s\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); + #else + printf("%08x (%02d) %-24s %s%s%s\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); + #endif + + }*/ + + if(res == DECRES_INPUTERR) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"disassembleMemory :: res == DECRES_INPUTERR"); +#endif + return false; + } + else if(res == DECRES_SUCCESS) + { + //printf("disassembleMemory :: res == DECRES_SUCCESS\n"); + return true; + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"disassembleMemory :: res == %d", res); +#endif + return true; //not all instructions fit in buffer + } +} + +DWORD_PTR ProcessAccessHelp::findPattern(DWORD_PTR startOffset, DWORD size, BYTE* pattern, const char* mask) +{ + DWORD pos = 0; + size_t searchLen = strlen(mask) - 1; + + for(DWORD_PTR retAddress = startOffset; retAddress < startOffset + size; retAddress++) + { + if(*(BYTE*)retAddress == pattern[pos] || mask[pos] == '?') + { + if(mask[pos + 1] == 0x00) + { + return (retAddress - searchLen); + } + pos++; + } + else + { + pos = 0; + } + } + return 0; +} + +bool ProcessAccessHelp::readHeaderFromCurrentFile(const WCHAR* filePath) +{ + return readHeaderFromFile(fileHeaderFromDisk, sizeof(fileHeaderFromDisk), filePath); +} + +LONGLONG ProcessAccessHelp::getFileSize(const WCHAR* filePath) +{ + LONGLONG fileSize = 0; + + HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + + if(hFile != INVALID_HANDLE_VALUE) + { + fileSize = getFileSize(hFile); + CloseHandle(hFile); + } + + return fileSize; +} + +LONGLONG ProcessAccessHelp::getFileSize(HANDLE hFile) +{ + LARGE_INTEGER lpFileSize = {0}; + + if((hFile != INVALID_HANDLE_VALUE) && (hFile != 0)) + { + if(!GetFileSizeEx(hFile, &lpFileSize)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize :: GetFileSizeEx failed %u", GetLastError()); +#endif + return 0; + } + else + { + return lpFileSize.QuadPart; + } + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize hFile invalid"); +#endif + return 0; + } +} + + +bool ProcessAccessHelp::readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer) +{ + DWORD lpNumberOfBytesRead = 0; + DWORD retValue = 0; + DWORD dwError = 0; + + if(hFile != INVALID_HANDLE_VALUE) + { + retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN); + dwError = GetLastError(); + + if((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryFromFile :: SetFilePointer failed error %u", dwError); +#endif + return false; + } + else + { + if(ReadFile(hFile, dataBuffer, size, &lpNumberOfBytesRead, 0)) + { + return true; + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryFromFile :: ReadFile failed - size %d - error %u", size, GetLastError()); +#endif + return false; + } + } + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readMemoryFromFile :: hFile invalid"); +#endif + return false; + } +} + +bool ProcessAccessHelp::writeMemoryToNewFile(const WCHAR* file, DWORD size, LPCVOID dataBuffer) +{ + HANDLE hFile = CreateFile(file, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); + + if(hFile != INVALID_HANDLE_VALUE) + { + bool resultValue = writeMemoryToFile(hFile, 0, size, dataBuffer); + CloseHandle(hFile); + return resultValue; + } + else + { + return false; + } +} + +bool ProcessAccessHelp::writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPCVOID dataBuffer) +{ + DWORD lpNumberOfBytesWritten = 0; + DWORD retValue = 0; + DWORD dwError = 0; + + if((hFile != INVALID_HANDLE_VALUE) && dataBuffer) + { + retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN); + dwError = GetLastError(); + + if((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"writeMemoryToFile :: SetFilePointer failed error %u", dwError); +#endif + return false; + } + else + { + if(WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0)) + { + return true; + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"writeMemoryToFile :: WriteFile failed - size %d - error %u", size, GetLastError()); +#endif + return false; + } + } + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"writeMemoryToFile :: hFile invalid"); +#endif + return false; + } +} + +bool ProcessAccessHelp::writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPCVOID dataBuffer) +{ + DWORD lpNumberOfBytesWritten = 0; + DWORD retValue = 0; + + if((hFile != INVALID_HANDLE_VALUE) && (hFile != 0)) + { + SetFilePointer(hFile, 0, 0, FILE_END); + + if(WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0)) + { + return true; + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"writeMemoryToFileEnd :: WriteFile failed - size %d - error %u", size, GetLastError()); +#endif + return false; + } + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"writeMemoryToFileEnd :: hFile invalid"); +#endif + return false; + } +} + +bool ProcessAccessHelp::readHeaderFromFile(BYTE* buffer, DWORD bufferSize, const WCHAR* filePath) +{ + DWORD lpNumberOfBytesRead = 0; + LONGLONG fileSize = 0; + DWORD dwSize = 0; + bool returnValue = 0; + + HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + + if(hFile == INVALID_HANDLE_VALUE) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"readHeaderFromFile :: INVALID_HANDLE_VALUE %u", GetLastError()); +#endif + returnValue = false; + } + else + { + fileSize = getFileSize(hFile); + + if(fileSize > 0) + { + if(fileSize > bufferSize) + { + dwSize = bufferSize; + } + else + { + dwSize = (DWORD)(fileSize - 1); + } + + returnValue = readMemoryFromFile(hFile, 0, dwSize, buffer); + } + + CloseHandle(hFile); + } + + return returnValue; +} + +LPVOID ProcessAccessHelp::createFileMappingViewRead(const WCHAR* filePath) +{ + return createFileMappingView(filePath, GENERIC_READ, PAGE_READONLY | SEC_IMAGE, FILE_MAP_READ); +} + +LPVOID ProcessAccessHelp::createFileMappingViewFull(const WCHAR* filePath) +{ + return createFileMappingView(filePath, GENERIC_ALL, PAGE_EXECUTE_READWRITE, FILE_MAP_ALL_ACCESS); +} + +LPVOID ProcessAccessHelp::createFileMappingView(const WCHAR* filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap) +{ + HANDLE hFile = CreateFile(filePath, accessFile, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + + if(hFile == INVALID_HANDLE_VALUE) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"createFileMappingView :: INVALID_HANDLE_VALUE %u", GetLastError()); +#endif + return NULL; + } + + HANDLE hMappedFile = CreateFileMapping(hFile, NULL, flProtect, 0, 0, NULL); + CloseHandle(hFile); + + if(hMappedFile == NULL) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"createFileMappingView :: hMappedFile == NULL"); +#endif + return NULL; + } + + if(GetLastError() == ERROR_ALREADY_EXISTS) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS"); +#endif + return NULL; + } + + LPVOID addrMappedDll = MapViewOfFile(hMappedFile, accessMap, 0, 0, 0); + + if(addrMappedDll == NULL) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"createFileMappingView :: addrMappedDll == NULL"); +#endif + CloseHandle(hMappedFile); + return NULL; + } + + CloseHandle(hMappedFile); + + return addrMappedDll; +} + +DWORD ProcessAccessHelp::getProcessByName(const WCHAR* processName) +{ + DWORD dwPID = 0; + HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + PROCESSENTRY32W pe32; + pe32.dwSize = sizeof(PROCESSENTRY32W); + + if(!Process32FirstW(hProcessSnap, &pe32)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"getProcessByName :: Error getting first Process"); +#endif + CloseHandle(hProcessSnap); + return 0; + } + + do + { + if(!_wcsicmp(pe32.szExeFile, processName)) + { + dwPID = pe32.th32ProcessID; + break; + } + } + while(Process32NextW(hProcessSnap, &pe32)); + + CloseHandle(hProcessSnap); + + return dwPID; +} + +bool ProcessAccessHelp::getProcessModules(HANDLE hProcess, std::vector & moduleList) +{ + ModuleInfo module; + WCHAR filename[MAX_PATH * 2] = {0}; + DWORD cbNeeded = 0; + bool retVal = false; + DeviceNameResolver deviceNameResolver; + + moduleList.reserve(20); + + EnumProcessModules(hProcess, 0, 0, &cbNeeded); + + HMODULE* hMods = (HMODULE*)malloc(cbNeeded * sizeof(HMODULE)); + + if(hMods) + { + if(EnumProcessModules(hProcess, hMods, cbNeeded, &cbNeeded)) + { + for(unsigned int i = 1; i < (cbNeeded / sizeof(HMODULE)); i++) //skip first module! + { + module.modBaseAddr = (DWORD_PTR)hMods[i]; + module.modBaseSize = (DWORD)getSizeOfImageProcess(hProcess, module.modBaseAddr); + module.isAlreadyParsed = false; + module.parsing = false; + + filename[0] = 0; + module.fullPath[0] = 0; + + if(GetMappedFileNameW(hProcess, (LPVOID)module.modBaseAddr, filename, _countof(filename)) > 0) + { + if(!deviceNameResolver.resolveDeviceLongNameToShort(filename, module.fullPath)) + { + if(!GetModuleFileNameExW(hProcess, (HMODULE)module.modBaseAddr, module.fullPath, _countof(module.fullPath))) + { + wcscpy_s(module.fullPath, filename); + } + } + } + else + { + GetModuleFileNameExW(hProcess, (HMODULE)module.modBaseAddr, module.fullPath, _countof(module.fullPath)); + } + + moduleList.push_back(module); + } + + retVal = true; + } + + free(hMods); + } + + return retVal; +} + +bool ProcessAccessHelp::getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR* memoryRegionBase, SIZE_T* memoryRegionSize) +{ + MEMORY_BASIC_INFORMATION memBasic; + + if(VirtualQueryEx(hProcess, (LPCVOID)address, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"getMemoryRegionFromAddress :: VirtualQueryEx error %u", GetLastError()); +#endif + return false; + } + else + { + *memoryRegionBase = (DWORD_PTR)memBasic.BaseAddress; + *memoryRegionSize = memBasic.RegionSize; + return true; + } +} + +bool ProcessAccessHelp::getSizeOfImageCurrentProcess() +{ + DWORD_PTR newSizeOfImage = getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase); + + if(newSizeOfImage != 0) + { + ProcessAccessHelp::targetSizeOfImage = newSizeOfImage; + return true; + } + else + { + return false; + } +} + +SIZE_T ProcessAccessHelp::getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase) +{ + SIZE_T sizeOfImage = 0, sizeOfImageNative = 0; + MEMORY_BASIC_INFORMATION lpBuffer = {0}; + + sizeOfImageNative = getSizeOfImageProcessNative(processHandle, moduleBase); + + if(sizeOfImageNative) + { + return sizeOfImageNative; + } + + WCHAR filenameOriginal[MAX_PATH * 2] = {0}; + WCHAR filenameTest[MAX_PATH * 2] = {0}; + + GetMappedFileNameW(processHandle, (LPVOID)moduleBase, filenameOriginal, _countof(filenameOriginal)); + + do + { + moduleBase = (DWORD_PTR)((SIZE_T)moduleBase + lpBuffer.RegionSize); + sizeOfImage += lpBuffer.RegionSize; + + + if(!VirtualQueryEx(processHandle, (LPCVOID)moduleBase, &lpBuffer, sizeof(MEMORY_BASIC_INFORMATION))) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"getSizeOfImageProcess :: VirtualQuery failed %X", GetLastError()); +#endif + lpBuffer.Type = 0; + sizeOfImage = 0; + } + + GetMappedFileNameW(processHandle, (LPVOID)moduleBase, filenameTest, _countof(filenameTest)); + + if(_wcsicmp(filenameOriginal, filenameTest) != 0)//problem: 2 modules without free space + { + break; + } + + } + while(lpBuffer.Type == MEM_IMAGE); + + + //if (sizeOfImage != sizeOfImageNative) + //{ + // WCHAR temp[1000] = {0}; + // wsprintfW(temp, L"0x%X sizeofimage\n0x%X sizeOfImageNative", sizeOfImage, sizeOfImageNative); + // MessageBoxW(0, temp, L"Test", 0); + //} + + return sizeOfImage; +} + +DWORD ProcessAccessHelp::getEntryPointFromFile(const WCHAR* filePath) +{ + PeParser peFile(filePath, false); + + return peFile.getEntryPoint(); +} + +bool ProcessAccessHelp::createBackupFile(const WCHAR* filePath) +{ + size_t fileNameLength = wcslen(filePath) + 5; //.bak + null + BOOL retValue = 0; + + WCHAR* backupFile = new WCHAR[fileNameLength]; + + wcscpy_s(backupFile, fileNameLength, filePath); + wcscat_s(backupFile, fileNameLength, L".bak"); + retValue = CopyFile(filePath, backupFile, FALSE); + + if(!retValue) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"createBackupFile :: CopyFile failed with error 0x%X", GetLastError()); +#endif + } + + delete [] backupFile; + + return retValue != 0; +} + +DWORD ProcessAccessHelp::getModuleHandlesFromProcess(const HANDLE hProcess, HMODULE** hMods) +{ + DWORD count = 30; + DWORD cbNeeded = 0; + bool notEnough = true; + + *hMods = new HMODULE[count]; + + do + { + if(!EnumProcessModules(hProcess, *hMods, count * sizeof(HMODULE), &cbNeeded)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"getModuleHandlesFromProcess :: EnumProcessModules failed count %d", count); +#endif + delete [] *hMods; + return 0; + } + + if((count * sizeof(HMODULE)) < cbNeeded) + { + delete [] *hMods; + count = cbNeeded / sizeof(HMODULE); + *hMods = new HMODULE[count]; + } + else + { + notEnough = false; + } + } + while(notEnough); + + return cbNeeded / sizeof(HMODULE); +} + +void ProcessAccessHelp::setCurrentProcessAsTarget() +{ + ProcessAccessHelp::hProcess = GetCurrentProcess(); +} + +bool ProcessAccessHelp::suspendProcess() +{ + if(NativeWinApi::NtSuspendProcess) + { + if(NT_SUCCESS(NativeWinApi::NtSuspendProcess(ProcessAccessHelp::hProcess))) + { + return true; + } + } + + return false; +} + +bool ProcessAccessHelp::resumeProcess() +{ + if(NativeWinApi::NtResumeProcess) + { + if(NT_SUCCESS(NativeWinApi::NtResumeProcess(ProcessAccessHelp::hProcess))) + { + return true; + } + } + + return false; +} + +bool ProcessAccessHelp::terminateProcess() +{ + if(NativeWinApi::NtTerminateProcess) + { + if(NT_SUCCESS(NativeWinApi::NtTerminateProcess(ProcessAccessHelp::hProcess, 0))) + { + return true; + } + } + + return false; +} + +bool ProcessAccessHelp::isPageAccessable(DWORD Protect) +{ + if(Protect & PAGE_NOCACHE) Protect ^= PAGE_NOCACHE; + if(Protect & PAGE_GUARD) Protect ^= PAGE_GUARD; + if(Protect & PAGE_WRITECOMBINE) Protect ^= PAGE_WRITECOMBINE; + + if(Protect != PAGE_NOACCESS) + { + return true; + } + else + { + return false; + } +} + +bool ProcessAccessHelp::isPageExecutable(DWORD Protect) +{ + if(Protect & PAGE_NOCACHE) Protect ^= PAGE_NOCACHE; + if(Protect & PAGE_GUARD) Protect ^= PAGE_GUARD; + if(Protect & PAGE_WRITECOMBINE) Protect ^= PAGE_WRITECOMBINE; + + switch(Protect) + { + case PAGE_EXECUTE: + { + return true; + } + case PAGE_EXECUTE_READ: + { + return true; + } + case PAGE_EXECUTE_READWRITE: + { + return true; + } + case PAGE_EXECUTE_WRITECOPY: + { + return true; + } + default: + return false; + } + +} + +SIZE_T ProcessAccessHelp::getSizeOfImageProcessNative(HANDLE processHandle, DWORD_PTR moduleBase) +{ + MEMORY_REGION_INFORMATION memRegion = {0}; + SIZE_T retLen = 0; + if(NativeWinApi::NtQueryVirtualMemory(processHandle, (PVOID)moduleBase, MemoryRegionInformation, &memRegion, sizeof(MEMORY_REGION_INFORMATION), &retLen) == STATUS_SUCCESS) + { + return memRegion.RegionSize; + } + + return 0; +} diff --git a/scylla_wrapper/ProcessAccessHelp.h b/scylla_wrapper/ProcessAccessHelp.h new file mode 100644 index 0000000..9bbd8a1 --- /dev/null +++ b/scylla_wrapper/ProcessAccessHelp.h @@ -0,0 +1,230 @@ +#pragma once + +#include +#include +#include + +/************************************************************************/ +/* distorm */ +/************************************************************************/ +#include "distorm.h" +#include "mnemonics.h" + +// The number of the array of instructions the decoder function will use to return the disassembled instructions. +// Play with this value for performance... +#define MAX_INSTRUCTIONS (200) + +/************************************************************************/ + +class ApiInfo; + +class ModuleInfo +{ +public: + + WCHAR fullPath[MAX_PATH]; + DWORD_PTR modBaseAddr; + DWORD modBaseSize; + + bool isAlreadyParsed; + bool parsing; + + /* + for iat rebuilding with duplicate entries: + + ntdll = low priority + kernelbase = low priority + SHLWAPI = low priority + + kernel32 = high priority + + priority = 1 -> normal/high priority + priority = 0 -> low priority + */ + int priority; + + std::vector apiList; + + ModuleInfo() + { + modBaseAddr = 0; + modBaseSize = 0; + priority = 1; + isAlreadyParsed = false; + parsing = false; + } + + const WCHAR* getFilename() const + { + const WCHAR* slash = wcsrchr(fullPath, L'\\'); + if(slash) + { + return slash + 1; + } + return fullPath; + } +}; + +class ApiInfo +{ +public: + + char name[MAX_PATH]; + WORD hint; + DWORD_PTR va; + DWORD_PTR rva; + WORD ordinal; + bool isForwarded; + ModuleInfo* module; +}; + +class ProcessAccessHelp +{ +public: + + static HANDLE hProcess; //OpenProcess handle to target process + + static DWORD_PTR targetImageBase; + static DWORD_PTR targetSizeOfImage; + static DWORD_PTR maxValidAddress; + + static ModuleInfo* selectedModule; + + static std::vector moduleList; //target process module list + static std::vector ownModuleList; //own module list + + static const size_t PE_HEADER_BYTES_COUNT = 2000; + + static BYTE fileHeaderFromDisk[PE_HEADER_BYTES_COUNT]; + + + //for decomposer + static _DInst decomposerResult[MAX_INSTRUCTIONS]; + static unsigned int decomposerInstructionsCount; + static _CodeInfo decomposerCi; + + //distorm :: Decoded instruction information. + static _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; + static unsigned int decodedInstructionsCount; +#ifdef _WIN64 + static const _DecodeType dt = Decode64Bits; +#else + static const _DecodeType dt = Decode32Bits; +#endif + + /* + * Open a new process handle + */ + static bool openProcessHandle(DWORD dwPID); + + static HANDLE NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId); + + static void closeProcessHandle(); + + /* + * Get all modules from a process + */ + static bool getProcessModules(HANDLE hProcess, std::vector & moduleList); + + + /* + * file mapping view with different access level + */ + static LPVOID createFileMappingViewRead(const WCHAR* filePath); + static LPVOID createFileMappingViewFull(const WCHAR* filePath); + + /* + * Create a file mapping view of a file + */ + static LPVOID createFileMappingView(const WCHAR* filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap); + + /* + * Read memory from target process + */ + static bool readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer); + static bool writeMemoryToProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer); + + /* + * Read memory from target process and ignore no data pages + */ + static bool readMemoryPartlyFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer); + + /* + * Read memory from file + */ + static bool readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer); + + /* + * Write memory to file + */ + static bool writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPCVOID dataBuffer); + + + /* + * Write memory to new file + */ + static bool writeMemoryToNewFile(const WCHAR* file, DWORD size, LPCVOID dataBuffer); + + /* + * Write memory to file end + */ + static bool writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPCVOID dataBuffer); + + /* + * Disassemble Memory + */ + static bool disassembleMemory(BYTE* dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset); + + static bool decomposeMemory(BYTE* dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress); + + /* + * Search for pattern + */ + static DWORD_PTR findPattern(DWORD_PTR startOffset, DWORD size, BYTE* pattern, const char* mask); + + /* + * Get process ID by process name + */ + static DWORD getProcessByName(const WCHAR* processName); + + /* + * Get memory region from address + */ + static bool getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR* memoryRegionBase, SIZE_T* memoryRegionSize); + + + /* + * Read PE Header from file + */ + static bool readHeaderFromFile(BYTE* buffer, DWORD bufferSize, const WCHAR* filePath); + + static bool readHeaderFromCurrentFile(const WCHAR* filePath); + + /* + * Get real sizeOfImage value + */ + static SIZE_T getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase); + + /* + * Get real sizeOfImage value current process + */ + static bool getSizeOfImageCurrentProcess(); + + static LONGLONG getFileSize(HANDLE hFile); + static LONGLONG getFileSize(const WCHAR* filePath); + + static DWORD getEntryPointFromFile(const WCHAR* filePath); + + static bool createBackupFile(const WCHAR* filePath); + + static DWORD getModuleHandlesFromProcess(const HANDLE hProcess, HMODULE** hMods); + + static void setCurrentProcessAsTarget(); + + static bool suspendProcess(); + static bool resumeProcess(); + static bool terminateProcess(); + static bool isPageExecutable(DWORD Protect); + static bool isPageAccessable(DWORD Protect); + static SIZE_T getSizeOfImageProcessNative(HANDLE processHandle, DWORD_PTR moduleBase); +}; diff --git a/scylla_wrapper/ProcessLister.cpp b/scylla_wrapper/ProcessLister.cpp new file mode 100644 index 0000000..9501bb2 --- /dev/null +++ b/scylla_wrapper/ProcessLister.cpp @@ -0,0 +1,291 @@ +#include "stdafx.h" +#include "ProcessLister.h" +#include "SystemInformation.h" +#include "ProcessAccessHelp.h" + +#include + +//#define DEBUG_COMMENTS + +def_IsWow64Process ProcessLister::_IsWow64Process = 0; + +std::vector & ProcessLister::getProcessList() +{ + return processList; +} + +bool ProcessLister::isWindows64() +{ +#ifdef _WIN64 + //compiled 64bit application + return true; +#else + //32bit exe, check wow64 + BOOL bIsWow64 = FALSE; + + //not available in all windows operating systems + //Minimum supported client: Windows Vista, Windows XP with SP2 + //Minimum supported server: Windows Server 2008, Windows Server 2003 with SP1 + + if(_IsWow64Process) + { + _IsWow64Process(GetCurrentProcess(), &bIsWow64); + if(bIsWow64 != FALSE) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } +#endif +} + +//only needed in windows xp +DWORD ProcessLister::setDebugPrivileges() +{ + DWORD err = 0; + HANDLE hToken = 0; + TOKEN_PRIVILEGES Debug_Privileges = {0}; + + if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Debug_Privileges.Privileges[0].Luid)) + { + return GetLastError(); + } + + if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) + { + err = GetLastError(); + if(hToken) CloseHandle(hToken); + return err; + } + + Debug_Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + Debug_Privileges.PrivilegeCount = 1; + + AdjustTokenPrivileges(hToken, false, &Debug_Privileges, 0, NULL, NULL); + + CloseHandle(hToken); + return GetLastError(); +} + + +/************************************************************************/ +/* Check if a process is 32 or 64bit */ +/************************************************************************/ +ProcessType ProcessLister::checkIsProcess64(HANDLE hProcess) +{ + BOOL bIsWow64 = FALSE; + + if(!hProcess) + { + return PROCESS_MISSING_RIGHTS; + } + + if(!isWindows64()) + { + //32bit win can only run 32bit process + return PROCESS_32; + } + + _IsWow64Process(hProcess, &bIsWow64); + + if(bIsWow64 == FALSE) + { + //process not running under wow + return PROCESS_64; + } + else + { + //process running under wow -> 32bit + return PROCESS_32; + } +} + +bool ProcessLister::getAbsoluteFilePath(HANDLE hProcess, Process* process) +{ + WCHAR processPath[MAX_PATH]; + bool retVal = false; + + wcscpy_s(process->fullPath, L"Unknown path"); + + if(!hProcess) + { + //missing rights + return false; + } + + if(GetProcessImageFileNameW(hProcess, processPath, _countof(processPath)) > 0) + { + if(!deviceNameResolver->resolveDeviceLongNameToShort(processPath, process->fullPath)) + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"getAbsoluteFilePath :: resolveDeviceLongNameToShort failed with path %s", processPath); +#endif + //some virtual volumes + if(GetModuleFileNameExW(hProcess, 0, process->fullPath, _countof(process->fullPath)) != 0) + { + retVal = true; + } + } + else + { + retVal = true; + } + } + else + { +#ifdef DEBUG_COMMENTS + Scylla::debugLog.log(L"getAbsoluteFilePath :: GetProcessImageFileName failed %u", GetLastError()); +#endif + if(GetModuleFileNameExW(hProcess, 0, process->fullPath, _countof(process->fullPath)) != 0) + { + retVal = true; + } + } + + return retVal; +} + +std::vector & ProcessLister::getProcessListSnapshotNative() +{ + ULONG retLength = 0; + ULONG bufferLength = 1; + PSYSTEM_PROCESS_INFORMATION pBuffer = (PSYSTEM_PROCESS_INFORMATION)malloc(bufferLength); + PSYSTEM_PROCESS_INFORMATION pIter; + if(!processList.empty()) + { + //clear elements, but keep reversed memory + processList.clear(); + } + else + { + //first time, reserve memory + processList.reserve(34); + } + + if(NativeWinApi::NtQuerySystemInformation(SystemProcessInformation, pBuffer, bufferLength, &retLength) == STATUS_INFO_LENGTH_MISMATCH) + { + free(pBuffer); + bufferLength = retLength + sizeof(SYSTEM_PROCESS_INFORMATION); + pBuffer = (PSYSTEM_PROCESS_INFORMATION)malloc(bufferLength); + if(!pBuffer) + return processList; + + if(NativeWinApi::NtQuerySystemInformation(SystemProcessInformation, pBuffer, bufferLength, &retLength) != STATUS_SUCCESS) + { + return processList; + } + } + else + { + return processList; + } + + pIter = pBuffer; + + while(TRUE) + { + if(pIter->UniqueProcessId > (HANDLE)4) //small filter + { + handleProcessInformationAndAddToList(pIter); + } + + if(pIter->NextEntryOffset == 0) + { + break; + } + else + { + pIter = (PSYSTEM_PROCESS_INFORMATION)((DWORD_PTR)pIter + (DWORD_PTR)pIter->NextEntryOffset); + } + } + + std::reverse(processList.begin(), processList.end()); //reverse process list + + free(pBuffer); + return processList; +} + +void ProcessLister::handleProcessInformationAndAddToList(PSYSTEM_PROCESS_INFORMATION pProcess) +{ + Process process; + WCHAR tempProcessName[MAX_PATH * 2] = {0}; + + process.PID = (DWORD)pProcess->UniqueProcessId; + + HANDLE hProcess = ProcessAccessHelp::NativeOpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, process.PID); + + if(hProcess) + { + ProcessType processType = checkIsProcess64(hProcess); + +#ifdef _WIN64 + if(processType == PROCESS_64) +#else + if(processType == PROCESS_32) +#endif + { + process.sessionId = pProcess->SessionId; + + memcpy(tempProcessName, pProcess->ImageName.Buffer, pProcess->ImageName.Length); + wcscpy_s(process.filename, tempProcessName); + + getAbsoluteFilePath(hProcess, &process); + process.pebAddress = getPebAddressFromProcess(hProcess); + getProcessImageInformation(hProcess, &process); + + processList.push_back(process); + } + CloseHandle(hProcess); + } +} + +void ProcessLister::getProcessImageInformation(HANDLE hProcess, Process* process) +{ + DWORD_PTR readImagebase = 0; + process->imageBase = 0; + process->imageSize = 0; + + if(hProcess && process->pebAddress) + { + PEB_CURRENT* peb = (PEB_CURRENT*)process->pebAddress; + + if(ReadProcessMemory(hProcess, &peb->ImageBaseAddress, &readImagebase, sizeof(DWORD_PTR), 0)) + { + process->imageBase = readImagebase; + process->imageSize = (DWORD)ProcessAccessHelp::getSizeOfImageProcess(hProcess, process->imageBase); + } + } +} + +DWORD_PTR ProcessLister::getPebAddressFromProcess(HANDLE hProcess) +{ + if(hProcess) + { + ULONG RequiredLen = 0; + void* PebAddress = 0; + PROCESS_BASIC_INFORMATION myProcessBasicInformation[5] = {0}; + + if(NativeWinApi::NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, sizeof(PROCESS_BASIC_INFORMATION), &RequiredLen) == STATUS_SUCCESS) + { + PebAddress = (void*)myProcessBasicInformation->PebBaseAddress; + } + else + { + if(NativeWinApi::NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, RequiredLen, &RequiredLen) == STATUS_SUCCESS) + { + PebAddress = (void*)myProcessBasicInformation->PebBaseAddress; + } + } + + return (DWORD_PTR)PebAddress; + } + + return 0; +} diff --git a/scylla_wrapper/ProcessLister.h b/scylla_wrapper/ProcessLister.h new file mode 100644 index 0000000..0da76d5 --- /dev/null +++ b/scylla_wrapper/ProcessLister.h @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include +#include + +#include "NativeWinApi.h" +#include "DeviceNameResolver.h" + +typedef BOOL (WINAPI* def_IsWow64Process)(HANDLE hProcess, PBOOL Wow64Process); + +class Process +{ +public: + DWORD PID; + DWORD sessionId; + DWORD_PTR imageBase; + DWORD_PTR pebAddress; + DWORD entryPoint; //RVA without imagebase + DWORD imageSize; + WCHAR filename[MAX_PATH]; + WCHAR fullPath[MAX_PATH]; + + Process() + { + PID = 0; + } +}; + +enum ProcessType +{ + PROCESS_UNKNOWN, + PROCESS_MISSING_RIGHTS, + PROCESS_32, + PROCESS_64 +}; + +class ProcessLister +{ +public: + + static def_IsWow64Process _IsWow64Process; + + ProcessLister() + { + deviceNameResolver = new DeviceNameResolver(); + _IsWow64Process = (def_IsWow64Process)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process"); + } + ~ProcessLister() + { + delete deviceNameResolver; + } + + std::vector & getProcessList(); + static bool isWindows64(); + static DWORD setDebugPrivileges(); + std::vector & getProcessListSnapshotNative(); +private: + std::vector processList; + + DeviceNameResolver* deviceNameResolver; + + ProcessType checkIsProcess64(HANDLE hProcess); + + bool getAbsoluteFilePath(HANDLE hProcess, Process* process); + + + void handleProcessInformationAndAddToList(PSYSTEM_PROCESS_INFORMATION pProcess); + void getProcessImageInformation(HANDLE hProcess, Process* process); + DWORD_PTR getPebAddressFromProcess(HANDLE hProcess); +}; \ No newline at end of file diff --git a/scylla_wrapper/README.md b/scylla_wrapper/README.md new file mode 100644 index 0000000..b42eac8 --- /dev/null +++ b/scylla_wrapper/README.md @@ -0,0 +1,122 @@ +Source: https://bitbucket.org/cypherpunk/scylla_wrapper_dll + +``` +This is a wrapper around Scylla. +It exports functions for IAT fixing, dumping and PE rebuilding. + +based on http://github.com/NtQuery/Scylla commit 0f6b7198be (v0.9.6b) + +What has been changed: +- stripped all WTL/ATL dependencies +- stripped GUI (obviously) +``` + +## Exports ## + :::c++ + //searches IAT, writes to iatStart, iatSize + int scylla_searchIAT(DWORD pid, DWORD_PTR &iatStart, DWORD &iatSize, DWORD_PTR searchStart, bool advancedSearch); + //reads the imports, iatAddr is VA + int scylla_getImports(DWORD_PTR iatAddr, DWORD iatSize, DWORD pid, LPVOID invalidImportCallback = NULL); + //add a module manually, in case auto-search didnt get it, e.g scattered IAT + bool scylla_addModule(const WCHAR* moduleName, DWORD_PTR firstThunkRVA); + //add API manually, in case auto-search didnt get it, e.g scattered IAT + bool scylla_addImport(const WCHAR* importName, DWORD_PTR thunkVA); + //are all imports valid? + bool scylla_importsValid(); + //cut an Import, because its invalid or whatever reason. Calling this from within the invalidImportCallback will crash! + //Call it after scylla_getImports call returned ! + bool scylla_cutImport(DWORD_PTR apiAddr); + //fix the dump + int scylla_fixDump(WCHAR* dumpFile, WCHAR* iatFixFile, WCHAR* sectionName = L".scy"); + //fix a mapped dump + int scylla_fixMappedDump(DWORD_PTR iatVA, DWORD_PTR FileMapVA, HANDLE hFileMap); + //get imported DLL count + int scylla_getModuleCount(); + //get total API Imports count + int scylla_getImportCount(); + //enumerate imports tree + void scylla_enumImportTree(LPVOID enumCallBack); + //size which the new IAT will consume + long scylla_estimatedIATSize(); + //get thunkVA by API name + DWORD_PTR scylla_findImportWriteLocation(char* importName); + //get thunkVA by ordinal + DWORD_PTR scylla_findOrdinalImportWriteLocation(DWORD_PTR ordinalNumber); + //get API name by thunkVA, cast return to char* + DWORD_PTR scylla_findImportNameByWriteLocation(DWORD_PTR thunkVA); + //get DLL name by thunkVA, cast return to char* + DWORD_PTR scylla_findModuleNameByWriteLocation(DWORD_PTR thunkVA); + + //dumps a process + bool scylla_dumpProcessW(DWORD_PTR pid, const WCHAR * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR * fileResult); + bool scylla_dumpProcessA(DWORD_PTR pid, const char * fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char * fileResult); + + //rebuilds a files PE header + bool scylla_rebuildFileW(const WCHAR * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); + bool scylla_rebuildFileA(const char * fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); + +## Return Codes ## + :::c++ + const BYTE SCY_ERROR_SUCCESS = 0; + const BYTE SCY_ERROR_PROCOPEN = -1; + const BYTE SCY_ERROR_IATWRITE = -2; + const BYTE SCY_ERROR_IATSEARCH = -3; + const BYTE SCY_ERROR_IATNOTFOUND = -4; + +## Usage ## + :::c++ + typedef int (*SEARCHIAT) (DWORD, DWORD_PTR &, DWORD &, DWORD_PTR, bool); + typedef int (*GETIMPORTS) (DWORD_PTR, DWORD, DWORD, LPVOID); + typedef bool (*IMPORTSVALID) (); + typedef int (*FIXDUMP) (WCHAR*, WCHAR*); + + HMODULE lib = LoadLibrary(_T("scylla_wrapper")); + SEARCHIAT searchIAT = (SEARCHIAT) GetProcAddress(lib, "scylla_searchIAT"); + GETIMPORTS getImports = (GETIMPORTS) GetProcAddress(lib, "scylla_getImports"); + IMPORTSVALID importsValid = (IMPORTSVALID) GetProcAddress(lib, "scylla_importsValid"); + FIXDUMP fixDump = (FIXDUMP) GetProcAddress(lib, "scylla_fixDump"); + + DWORD iatStart = 0xDEADBEEF; + DWORD iatSize = 0xDEADBEEF; + + int search = searchIAT(fdProcessInfo->dwProcessId, iatStart, iatSize, eip, false); + + if(search==0) int imports = getImports(iatStart, iatSize, pid); + bool valid = importsValid(); + if(valid) int fix = fixDump(dumpFileName, IatFixFileName); + +## Definitions ## + :::c++ + typedef void*(*fCallback)(LPVOID invalidImport); + + //e.g. + void* cbInvalidImport(void* apiAddr) + + typedef void(*fCallback)(LPVOID importDetail); + + typedef struct + { + bool NewDll; + int NumberOfImports; + ULONG_PTR ImageBase; + ULONG_PTR BaseImportThunk; + ULONG_PTR ImportThunk; + char* APIName; + char* DLLName; + } ImportEnumData + + //e.g. pointer on this struct used in scylla_enumImportTree as argument + void cbEnumImports(void* importDetail) + { + ImportEnumData* data = (ImportEnumData*)importDetail; + } + +## Notes ## +``` +The pre-compiled binaries and project standard uses _cdecl calling convention. +For assembly users, this means you have to push arguments from right-to-left onto the stack +and clean the stack yourself after calling. + +#pragma pack(push,1) or compiler flag /Zp1 is needed for the struct members to be aligned correctly + +``` diff --git a/scylla_wrapper/StringConversion.cpp b/scylla_wrapper/StringConversion.cpp new file mode 100644 index 0000000..b7ea2ae --- /dev/null +++ b/scylla_wrapper/StringConversion.cpp @@ -0,0 +1,27 @@ +#include "stdafx.h" +#include "StringConversion.h" +#include +//#include +//#include + +const char* StringConversion::ToASCII(const wchar_t* str, char* buf, size_t bufsize) +{ + wcstombs(buf, str, bufsize); + /* + ATL::CW2A str_a = str; + strncpy_s(buf, bufsize, str_a, bufsize); + buf[bufsize - 1] = '\0'; + */ + return buf; +} + +const wchar_t* StringConversion::ToUTF16(const char* str, wchar_t* buf, size_t bufsize) +{ + mbstowcs(buf, str, bufsize); + /* + ATL::CA2W str_w = str; + wcsncpy_s(buf, bufsize, str_w, bufsize); + buf[bufsize - 1] = L'\0'; + */ + return buf; +} diff --git a/scylla_wrapper/StringConversion.h b/scylla_wrapper/StringConversion.h new file mode 100644 index 0000000..07deb12 --- /dev/null +++ b/scylla_wrapper/StringConversion.h @@ -0,0 +1,9 @@ +#pragma once + +class StringConversion +{ +public: + + static const char* ToASCII(const wchar_t* str, char* buf, size_t bufsize); + static const wchar_t* ToUTF16(const char* str, wchar_t* buf, size_t bufsize); +}; diff --git a/scylla_wrapper/SystemInformation.cpp b/scylla_wrapper/SystemInformation.cpp new file mode 100644 index 0000000..4792ea5 --- /dev/null +++ b/scylla_wrapper/SystemInformation.cpp @@ -0,0 +1,77 @@ +#include "stdafx.h" +#include "SystemInformation.h" + +OPERATING_SYSTEM SystemInformation::currenOS = UNKNOWN_OS; + +bool SystemInformation::getSystemInformation() +{ + OSVERSIONINFOEX osvi = {0}; + SYSTEM_INFO si = {0}; + def_GetNativeSystemInfo _GetNativeSystemInfo = 0; + + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if(!GetVersionEx((OSVERSIONINFO*) &osvi)) + { + return false; + } + + if((osvi.dwMajorVersion < 5) || ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0))) + { + return false; + } + + _GetNativeSystemInfo = (def_GetNativeSystemInfo)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetNativeSystemInfo"); + if(_GetNativeSystemInfo) + { + _GetNativeSystemInfo(&si); + } + else + { + GetSystemInfo(&si); + } + + bool isX64 = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; + bool isX86 = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL; + + DWORD major = osvi.dwMajorVersion; + DWORD minor = osvi.dwMinorVersion; + + if(isX64 && major == 5 && minor == 2) + { + currenOS = WIN_XP_64; + } + else if(isX86 && major == 5 && minor == 1) + { + currenOS = WIN_XP_32; + } + else if(isX64 && major == 6 && minor == 0) + { + currenOS = WIN_VISTA_64; + } + else if(isX86 && major == 6 && minor == 0) + { + currenOS = WIN_VISTA_32; + } + else if(isX64 && major == 6 && minor == 1) + { + currenOS = WIN_7_64; + } + else if(isX86 && major == 6 && minor == 1) + { + currenOS = WIN_7_32; + } + else if(isX64 && major == 6 && minor == 2) + { + currenOS = WIN_8_64; + } + else if(isX86 && major == 6 && minor == 2) + { + currenOS = WIN_8_32; + } + else + { + currenOS = UNKNOWN_OS; + } + + return (currenOS != UNKNOWN_OS); +} diff --git a/scylla_wrapper/SystemInformation.h b/scylla_wrapper/SystemInformation.h new file mode 100644 index 0000000..dc114c3 --- /dev/null +++ b/scylla_wrapper/SystemInformation.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +enum OPERATING_SYSTEM +{ + UNKNOWN_OS, + WIN_XP_32, + WIN_XP_64, + WIN_VISTA_32, + WIN_VISTA_64, + WIN_7_32, + WIN_7_64, + WIN_8_32, + WIN_8_64 +}; + +typedef void (WINAPI* def_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo); + +class SystemInformation +{ +public: + + static OPERATING_SYSTEM currenOS; + static bool getSystemInformation(); +}; diff --git a/scylla_wrapper/Thunks.cpp b/scylla_wrapper/Thunks.cpp new file mode 100644 index 0000000..eca1b8a --- /dev/null +++ b/scylla_wrapper/Thunks.cpp @@ -0,0 +1,40 @@ +#include "stdafx.h" +#include "Thunks.h" + +void ImportThunk::invalidate() +{ + ordinal = 0; + hint = 0; + valid = false; + suspect = false; + moduleName[0] = 0; + name[0] = 0; +} + +bool ImportModuleThunk::isValid() const +{ + std::map::const_iterator iterator = thunkList.begin(); + while(iterator != thunkList.end()) + { + if(iterator->second.valid == false) + { + return false; + } + iterator++; + } + + return true; +} + +DWORD_PTR ImportModuleThunk::getFirstThunk() const +{ + if(thunkList.size() > 0) + { + const std::map::const_iterator iterator = thunkList.begin(); + return iterator->first; + } + else + { + return 0; + } +} \ No newline at end of file diff --git a/scylla_wrapper/Thunks.h b/scylla_wrapper/Thunks.h new file mode 100644 index 0000000..71a77fe --- /dev/null +++ b/scylla_wrapper/Thunks.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +class ImportThunk +{ +public: + WCHAR moduleName[MAX_PATH]; + char name[MAX_PATH]; + DWORD_PTR va; + DWORD_PTR rva; + WORD ordinal; + DWORD_PTR apiAddressVA; + WORD hint; + bool valid; + bool suspect; + + DWORD_PTR key; + + void invalidate(); +}; + +class ImportModuleThunk +{ +public: + WCHAR moduleName[MAX_PATH]; + std::map thunkList; + + DWORD_PTR firstThunk; + + DWORD_PTR key; + + DWORD_PTR getFirstThunk() const; + bool isValid() const; +}; diff --git a/TitanEngine/distorm_x64.lib b/scylla_wrapper/distorm_x64.lib similarity index 100% rename from TitanEngine/distorm_x64.lib rename to scylla_wrapper/distorm_x64.lib diff --git a/TitanEngine/distorm_x86.lib b/scylla_wrapper/distorm_x86.lib similarity index 100% rename from TitanEngine/distorm_x86.lib rename to scylla_wrapper/distorm_x86.lib diff --git a/scylla_wrapper/dllmain.cpp b/scylla_wrapper/dllmain.cpp new file mode 100644 index 0000000..0a177a5 --- /dev/null +++ b/scylla_wrapper/dllmain.cpp @@ -0,0 +1,18 @@ +#include "stdafx.h" + +BOOL APIENTRY DllMain(HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch(ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/scylla_wrapper/mnemonics.h b/scylla_wrapper/mnemonics.h new file mode 100644 index 0000000..6e63aab --- /dev/null +++ b/scylla_wrapper/mnemonics.h @@ -0,0 +1,316 @@ +/* +mnemonics.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +(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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + + +#ifndef MNEMONICS_H +#define MNEMONICS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DISTORM_LIGHT + +typedef struct WMnemonic +{ + unsigned char length; + unsigned char p[1]; /* p is a null terminated string, which contains 'length' characters. */ +} _WMnemonic; + +typedef struct WRegister +{ + unsigned int length; + unsigned char p[6]; /* p is a null terminated string. */ +} _WRegister; + +extern const unsigned char _MNEMONICS[]; +extern const _WRegister _REGISTERS[]; + +#endif /* DISTORM_LIGHT */ + +#ifdef __cplusplus +} /* End Of Extern */ +#endif + +#define GET_REGISTER_NAME(r) (unsigned char*)_REGISTERS[(r)].p +#define GET_MNEMONIC_NAME(m) ((_WMnemonic*)&_MNEMONICS[(m)])->p + +typedef enum +{ + I_UNDEFINED = 0, I_AAA = 66, I_AAD = 389, I_AAM = 384, I_AAS = 76, I_ADC = 31, I_ADD = 11, I_ADDPD = 3110, + I_ADDPS = 3103, I_ADDSD = 3124, I_ADDSS = 3117, I_ADDSUBPD = 6394, I_ADDSUBPS = 6404, + I_AESDEC = 9209, I_AESDECLAST = 9226, I_AESENC = 9167, I_AESENCLAST = 9184, + I_AESIMC = 9150, I_AESKEYGENASSIST = 9795, I_AND = 41, I_ANDNPD = 3021, I_ANDNPS = 3013, + I_ANDPD = 2990, I_ANDPS = 2983, I_ARPL = 111, I_BLENDPD = 9372, I_BLENDPS = 9353, + I_BLENDVPD = 7619, I_BLENDVPS = 7609, I_BOUND = 104, I_BSF = 4346, I_BSR = 4358, + I_BSWAP = 960, I_BT = 872, I_BTC = 934, I_BTR = 912, I_BTS = 887, I_CALL = 456, + I_CALL_FAR = 260, I_CBW = 228, I_CDQ = 250, I_CDQE = 239, I_CLC = 492, I_CLD = 512, + I_CLFLUSH = 4329, I_CLGI = 1833, I_CLI = 502, I_CLTS = 541, I_CMC = 487, I_CMOVA = 694, + I_CMOVAE = 663, I_CMOVB = 656, I_CMOVBE = 686, I_CMOVG = 754, I_CMOVGE = 738, + I_CMOVL = 731, I_CMOVLE = 746, I_CMOVNO = 648, I_CMOVNP = 723, I_CMOVNS = 708, + I_CMOVNZ = 678, I_CMOVO = 641, I_CMOVP = 716, I_CMOVS = 701, I_CMOVZ = 671, + I_CMP = 71, I_CMPEQPD = 4449, I_CMPEQPS = 4370, I_CMPEQSD = 4607, I_CMPEQSS = 4528, + I_CMPLEPD = 4467, I_CMPLEPS = 4388, I_CMPLESD = 4625, I_CMPLESS = 4546, I_CMPLTPD = 4458, + I_CMPLTPS = 4379, I_CMPLTSD = 4616, I_CMPLTSS = 4537, I_CMPNEQPD = 4488, I_CMPNEQPS = 4409, + I_CMPNEQSD = 4646, I_CMPNEQSS = 4567, I_CMPNLEPD = 4508, I_CMPNLEPS = 4429, + I_CMPNLESD = 4666, I_CMPNLESS = 4587, I_CMPNLTPD = 4498, I_CMPNLTPS = 4419, + I_CMPNLTSD = 4656, I_CMPNLTSS = 4577, I_CMPORDPD = 4518, I_CMPORDPS = 4439, + I_CMPORDSD = 4676, I_CMPORDSS = 4597, I_CMPS = 301, I_CMPUNORDPD = 4476, I_CMPUNORDPS = 4397, + I_CMPUNORDSD = 4634, I_CMPUNORDSS = 4555, I_CMPXCHG = 898, I_CMPXCHG16B = 6373, + I_CMPXCHG8B = 6362, I_COMISD = 2779, I_COMISS = 2771, I_CPUID = 865, I_CQO = 255, + I_CRC32 = 9258, I_CVTDQ2PD = 6787, I_CVTDQ2PS = 3307, I_CVTPD2DQ = 6797, I_CVTPD2PI = 2681, + I_CVTPD2PS = 3233, I_CVTPH2PS = 4161, I_CVTPI2PD = 2495, I_CVTPI2PS = 2485, + I_CVTPS2DQ = 3317, I_CVTPS2PD = 3223, I_CVTPS2PH = 4171, I_CVTPS2PI = 2671, + I_CVTSD2SI = 2701, I_CVTSD2SS = 3253, I_CVTSI2SD = 2515, I_CVTSI2SS = 2505, + I_CVTSS2SD = 3243, I_CVTSS2SI = 2691, I_CVTTPD2DQ = 6776, I_CVTTPD2PI = 2614, + I_CVTTPS2DQ = 3327, I_CVTTPS2PI = 2603, I_CVTTSD2SI = 2636, I_CVTTSS2SI = 2625, + I_CWD = 245, I_CWDE = 233, I_DAA = 46, I_DAS = 56, I_DEC = 86, I_DIV = 1630, + I_DIVPD = 3499, I_DIVPS = 3492, I_DIVSD = 3513, I_DIVSS = 3506, I_DPPD = 9615, + I_DPPS = 9602, I_EMMS = 4100, I_ENTER = 340, I_EXTRACTPS = 9480, I_EXTRQ = 4136, + I_F2XM1 = 1176, I_FABS = 1107, I_FADD = 1007, I_FADDP = 1533, I_FBLD = 1585, + I_FBSTP = 1591, I_FCHS = 1101, I_FCLEX = 7289, I_FCMOVB = 1360, I_FCMOVBE = 1376, + I_FCMOVE = 1368, I_FCMOVNB = 1429, I_FCMOVNBE = 1447, I_FCMOVNE = 1438, I_FCMOVNU = 1457, + I_FCMOVU = 1385, I_FCOM = 1019, I_FCOMI = 1496, I_FCOMIP = 1607, I_FCOMP = 1025, + I_FCOMPP = 1547, I_FCOS = 1295, I_FDECSTP = 1222, I_FDIV = 1045, I_FDIVP = 1578, + I_FDIVR = 1051, I_FDIVRP = 1570, I_FEDISI = 1472, I_FEMMS = 574, I_FENI = 1466, + I_FFREE = 1511, I_FIADD = 1301, I_FICOM = 1315, I_FICOMP = 1322, I_FIDIV = 1345, + I_FIDIVR = 1352, I_FILD = 1402, I_FIMUL = 1308, I_FINCSTP = 1231, I_FINIT = 7304, + I_FIST = 1416, I_FISTP = 1422, I_FISTTP = 1408, I_FISUB = 1330, I_FISUBR = 1337, + I_FLD = 1058, I_FLD1 = 1125, I_FLDCW = 1082, I_FLDENV = 1074, I_FLDL2E = 1139, + I_FLDL2T = 1131, I_FLDLG2 = 1154, I_FLDLN2 = 1162, I_FLDPI = 1147, I_FLDZ = 1170, + I_FMUL = 1013, I_FMULP = 1540, I_FNCLEX = 7281, I_FNINIT = 7296, I_FNOP = 1095, + I_FNSAVE = 7311, I_FNSTCW = 7266, I_FNSTENV = 7249, I_FNSTSW = 7326, I_FPATAN = 1197, + I_FPREM = 1240, I_FPREM1 = 1214, I_FPTAN = 1190, I_FRNDINT = 1272, I_FRSTOR = 1503, + I_FSAVE = 7319, I_FSCALE = 1281, I_FSETPM = 1480, I_FSIN = 1289, I_FSINCOS = 1263, + I_FSQRT = 1256, I_FST = 1063, I_FSTCW = 7274, I_FSTENV = 7258, I_FSTP = 1068, + I_FSTSW = 7334, I_FSUB = 1032, I_FSUBP = 1563, I_FSUBR = 1038, I_FSUBRP = 1555, + I_FTST = 1113, I_FUCOM = 1518, I_FUCOMI = 1488, I_FUCOMIP = 1598, I_FUCOMP = 1525, + I_FUCOMPP = 1393, I_FXAM = 1119, I_FXCH = 1089, I_FXRSTOR = 9892, I_FXRSTOR64 = 9901, + I_FXSAVE = 9864, I_FXSAVE64 = 9872, I_FXTRACT = 1205, I_FYL2X = 1183, I_FYL2XP1 = 1247, + I_GETSEC = 633, I_HADDPD = 4181, I_HADDPS = 4189, I_HLT = 482, I_HSUBPD = 4215, + I_HSUBPS = 4223, I_IDIV = 1635, I_IMUL = 117, I_IN = 447, I_INC = 81, I_INS = 123, + I_INSERTPS = 9547, I_INSERTQ = 4143, I_INT = 367, I_INT_3 = 360, I_INT1 = 476, + I_INTO = 372, I_INVD = 555, I_INVEPT = 8284, I_INVLPG = 1711, I_INVLPGA = 1847, + I_INVPCID = 8301, I_INVVPID = 8292, I_IRET = 378, I_JA = 166, I_JAE = 147, + I_JB = 143, I_JBE = 161, I_JCXZ = 427, I_JECXZ = 433, I_JG = 202, I_JGE = 192, + I_JL = 188, I_JLE = 197, I_JMP = 462, I_JMP_FAR = 467, I_JNO = 138, I_JNP = 183, + I_JNS = 174, I_JNZ = 156, I_JO = 134, I_JP = 179, I_JRCXZ = 440, I_JS = 170, + I_JZ = 152, I_LAHF = 289, I_LAR = 522, I_LDDQU = 6994, I_LDMXCSR = 9922, I_LDS = 335, + I_LEA = 223, I_LEAVE = 347, I_LES = 330, I_LFENCE = 4265, I_LFS = 917, I_LGDT = 1687, + I_LGS = 922, I_LIDT = 1693, I_LLDT = 1652, I_LMSW = 1705, I_LODS = 313, I_LOOP = 421, + I_LOOPNZ = 406, I_LOOPZ = 414, I_LSL = 527, I_LSS = 907, I_LTR = 1658, I_LZCNT = 4363, + I_MASKMOVDQU = 7119, I_MASKMOVQ = 7109, I_MAXPD = 3559, I_MAXPS = 3552, I_MAXSD = 3573, + I_MAXSS = 3566, I_MFENCE = 4291, I_MINPD = 3439, I_MINPS = 3432, I_MINSD = 3453, + I_MINSS = 3446, I_MONITOR = 1755, I_MOV = 218, I_MOVAPD = 2459, I_MOVAPS = 2451, + I_MOVBE = 9251, I_MOVD = 3920, I_MOVDDUP = 2186, I_MOVDQ2Q = 6522, I_MOVDQA = 3946, + I_MOVDQU = 3954, I_MOVHLPS = 2151, I_MOVHPD = 2345, I_MOVHPS = 2337, I_MOVLHPS = 2328, + I_MOVLPD = 2168, I_MOVLPS = 2160, I_MOVMSKPD = 2815, I_MOVMSKPS = 2805, I_MOVNTDQ = 6849, + I_MOVNTDQA = 7895, I_MOVNTI = 952, I_MOVNTPD = 2556, I_MOVNTPS = 2547, I_MOVNTQ = 6841, + I_MOVNTSD = 2574, I_MOVNTSS = 2565, I_MOVQ = 3926, I_MOVQ2DQ = 6513, I_MOVS = 295, + I_MOVSD = 2110, I_MOVSHDUP = 2353, I_MOVSLDUP = 2176, I_MOVSS = 2103, I_MOVSX = 939, + I_MOVSXD = 10013, I_MOVUPD = 2095, I_MOVUPS = 2087, I_MOVZX = 927, I_MPSADBW = 9628, + I_MUL = 1625, I_MULPD = 3170, I_MULPS = 3163, I_MULSD = 3184, I_MULSS = 3177, + I_MWAIT = 1764, I_NEG = 1620, I_NOP = 581, I_NOT = 1615, I_OR = 27, I_ORPD = 3053, + I_ORPS = 3047, I_OUT = 451, I_OUTS = 128, I_PABSB = 7688, I_PABSD = 7718, I_PABSW = 7703, + I_PACKSSDW = 3849, I_PACKSSWB = 3681, I_PACKUSDW = 7916, I_PACKUSWB = 3759, + I_PADDB = 7204, I_PADDD = 7234, I_PADDQ = 6481, I_PADDSB = 6930, I_PADDSW = 6947, + I_PADDUSB = 6620, I_PADDUSW = 6639, I_PADDW = 7219, I_PALIGNR = 9410, I_PAND = 6607, + I_PANDN = 6665, I_PAUSE = 10021, I_PAVGB = 6680, I_PAVGUSB = 2078, I_PAVGW = 6725, + I_PBLENDVB = 7599, I_PBLENDW = 9391, I_PCLMULQDQ = 9647, I_PCMPEQB = 4043, + I_PCMPEQD = 4081, I_PCMPEQQ = 7876, I_PCMPEQW = 4062, I_PCMPESTRI = 9726, + I_PCMPESTRM = 9703, I_PCMPGTB = 3702, I_PCMPGTD = 3740, I_PCMPGTQ = 8087, + I_PCMPGTW = 3721, I_PCMPISTRI = 9772, I_PCMPISTRM = 9749, I_PEXTRB = 9429, + I_PEXTRD = 9446, I_PEXTRQ = 9454, I_PEXTRW = 6311, I_PF2ID = 1914, I_PF2IW = 1907, + I_PFACC = 2028, I_PFADD = 1977, I_PFCMPEQ = 2035, I_PFCMPGE = 1938, I_PFCMPGT = 1984, + I_PFMAX = 1993, I_PFMIN = 1947, I_PFMUL = 2044, I_PFNACC = 1921, I_PFPNACC = 1929, + I_PFRCP = 1954, I_PFRCPIT1 = 2000, I_PFRCPIT2 = 2051, I_PFRSQIT1 = 2010, I_PFRSQRT = 1961, + I_PFSUB = 1970, I_PFSUBR = 2020, I_PHADDD = 7375, I_PHADDSW = 7392, I_PHADDW = 7358, + I_PHMINPOSUW = 8259, I_PHSUBD = 7451, I_PHSUBSW = 7468, I_PHSUBW = 7434, I_PI2FD = 1900, + I_PI2FW = 1893, I_PINSRB = 9530, I_PINSRD = 9568, I_PINSRQ = 9576, I_PINSRW = 6294, + I_PMADDUBSW = 7411, I_PMADDWD = 7073, I_PMAXSB = 8174, I_PMAXSD = 8191, I_PMAXSW = 6964, + I_PMAXUB = 6648, I_PMAXUD = 8225, I_PMAXUW = 8208, I_PMINSB = 8106, I_PMINSD = 8123, + I_PMINSW = 6902, I_PMINUB = 6590, I_PMINUD = 8157, I_PMINUW = 8140, I_PMOVMSKB = 6531, + I_PMOVSXBD = 7754, I_PMOVSXBQ = 7775, I_PMOVSXBW = 7733, I_PMOVSXDQ = 7838, + I_PMOVSXWD = 7796, I_PMOVSXWQ = 7817, I_PMOVZXBD = 7982, I_PMOVZXBQ = 8003, + I_PMOVZXBW = 7961, I_PMOVZXDQ = 8066, I_PMOVZXWD = 8024, I_PMOVZXWQ = 8045, + I_PMULDQ = 7859, I_PMULHRSW = 7538, I_PMULHRW = 2061, I_PMULHUW = 6740, I_PMULHW = 6759, + I_PMULLD = 8242, I_PMULLW = 6496, I_PMULUDQ = 7054, I_POP = 22, I_POPA = 98, + I_POPCNT = 4338, I_POPF = 277, I_POR = 6919, I_PREFETCH = 1872, I_PREFETCHNTA = 2402, + I_PREFETCHT0 = 2415, I_PREFETCHT1 = 2427, I_PREFETCHT2 = 2439, I_PREFETCHW = 1882, + I_PSADBW = 7092, I_PSHUFB = 7341, I_PSHUFD = 3988, I_PSHUFHW = 3996, I_PSHUFLW = 4005, + I_PSHUFW = 3980, I_PSIGNB = 7487, I_PSIGND = 7521, I_PSIGNW = 7504, I_PSLLD = 7024, + I_PSLLDQ = 9847, I_PSLLQ = 7039, I_PSLLW = 7009, I_PSRAD = 6710, I_PSRAW = 6695, + I_PSRLD = 6451, I_PSRLDQ = 9830, I_PSRLQ = 6466, I_PSRLW = 6436, I_PSUBB = 7144, + I_PSUBD = 7174, I_PSUBQ = 7189, I_PSUBSB = 6868, I_PSUBSW = 6885, I_PSUBUSB = 6552, + I_PSUBUSW = 6571, I_PSUBW = 7159, I_PSWAPD = 2070, I_PTEST = 7629, I_PUNPCKHBW = 3780, + I_PUNPCKHDQ = 3826, I_PUNPCKHQDQ = 3895, I_PUNPCKHWD = 3803, I_PUNPCKLBW = 3612, + I_PUNPCKLDQ = 3658, I_PUNPCKLQDQ = 3870, I_PUNPCKLWD = 3635, I_PUSH = 16, + I_PUSHA = 91, I_PUSHF = 270, I_PXOR = 6981, I_RCL = 977, I_RCPPS = 2953, I_RCPSS = 2960, + I_RCR = 982, I_RDFSBASE = 9882, I_RDGSBASE = 9912, I_RDMSR = 600, I_RDPMC = 607, + I_RDRAND = 9980, I_RDTSC = 593, I_RDTSCP = 1864, I_RET = 325, I_RETF = 354, + I_ROL = 967, I_ROR = 972, I_ROUNDPD = 9296, I_ROUNDPS = 9277, I_ROUNDSD = 9334, + I_ROUNDSS = 9315, I_RSM = 882, I_RSQRTPS = 2915, I_RSQRTSS = 2924, I_SAHF = 283, + I_SAL = 997, I_SALC = 394, I_SAR = 1002, I_SBB = 36, I_SCAS = 319, I_SETA = 807, + I_SETAE = 780, I_SETB = 774, I_SETBE = 800, I_SETG = 859, I_SETGE = 845, I_SETL = 839, + I_SETLE = 852, I_SETNO = 767, I_SETNP = 832, I_SETNS = 819, I_SETNZ = 793, + I_SETO = 761, I_SETP = 826, I_SETS = 813, I_SETZ = 787, I_SFENCE = 4321, I_SGDT = 1675, + I_SHL = 987, I_SHLD = 876, I_SHR = 992, I_SHRD = 892, I_SHUFPD = 6336, I_SHUFPS = 6328, + I_SIDT = 1681, I_SKINIT = 1839, I_SLDT = 1641, I_SMSW = 1699, I_SQRTPD = 2855, + I_SQRTPS = 2847, I_SQRTSD = 2871, I_SQRTSS = 2863, I_STC = 497, I_STD = 517, + I_STGI = 1827, I_STI = 507, I_STMXCSR = 9951, I_STOS = 307, I_STR = 1647, I_SUB = 51, + I_SUBPD = 3379, I_SUBPS = 3372, I_SUBSD = 3393, I_SUBSS = 3386, I_SWAPGS = 1856, + I_SYSCALL = 532, I_SYSENTER = 614, I_SYSEXIT = 624, I_SYSRET = 547, I_TEST = 206, + I_TZCNT = 4351, I_UCOMISD = 2742, I_UCOMISS = 2733, I_UD2 = 569, I_UNPCKHPD = 2296, + I_UNPCKHPS = 2286, I_UNPCKLPD = 2254, I_UNPCKLPS = 2244, I_VADDPD = 3139, + I_VADDPS = 3131, I_VADDSD = 3155, I_VADDSS = 3147, I_VADDSUBPD = 6414, I_VADDSUBPS = 6425, + I_VAESDEC = 9217, I_VAESDECLAST = 9238, I_VAESENC = 9175, I_VAESENCLAST = 9196, + I_VAESIMC = 9158, I_VAESKEYGENASSIST = 9812, I_VANDNPD = 3038, I_VANDNPS = 3029, + I_VANDPD = 3005, I_VANDPS = 2997, I_VBLENDPD = 9381, I_VBLENDPS = 9362, I_VBLENDVPD = 9681, + I_VBLENDVPS = 9670, I_VBROADCASTF128 = 7672, I_VBROADCASTSD = 7658, I_VBROADCASTSS = 7644, + I_VCMPEQPD = 5088, I_VCMPEQPS = 4686, I_VCMPEQSD = 5892, I_VCMPEQSS = 5490, + I_VCMPEQ_OSPD = 5269, I_VCMPEQ_OSPS = 4867, I_VCMPEQ_OSSD = 6073, I_VCMPEQ_OSSS = 5671, + I_VCMPEQ_UQPD = 5175, I_VCMPEQ_UQPS = 4773, I_VCMPEQ_UQSD = 5979, I_VCMPEQ_UQSS = 5577, + I_VCMPEQ_USPD = 5378, I_VCMPEQ_USPS = 4976, I_VCMPEQ_USSD = 6182, I_VCMPEQ_USSS = 5780, + I_VCMPFALSEPD = 5210, I_VCMPFALSEPS = 4808, I_VCMPFALSESD = 6014, I_VCMPFALSESS = 5612, + I_VCMPFALSE_OSPD = 5419, I_VCMPFALSE_OSPS = 5017, I_VCMPFALSE_OSSD = 6223, + I_VCMPFALSE_OSSS = 5821, I_VCMPGEPD = 5237, I_VCMPGEPS = 4835, I_VCMPGESD = 6041, + I_VCMPGESS = 5639, I_VCMPGE_OQPD = 5449, I_VCMPGE_OQPS = 5047, I_VCMPGE_OQSD = 6253, + I_VCMPGE_OQSS = 5851, I_VCMPGTPD = 5247, I_VCMPGTPS = 4845, I_VCMPGTSD = 6051, + I_VCMPGTSS = 5649, I_VCMPGT_OQPD = 5462, I_VCMPGT_OQPS = 5060, I_VCMPGT_OQSD = 6266, + I_VCMPGT_OQSS = 5864, I_VCMPLEPD = 5108, I_VCMPLEPS = 4706, I_VCMPLESD = 5912, + I_VCMPLESS = 5510, I_VCMPLE_OQPD = 5295, I_VCMPLE_OQPS = 4893, I_VCMPLE_OQSD = 6099, + I_VCMPLE_OQSS = 5697, I_VCMPLTPD = 5098, I_VCMPLTPS = 4696, I_VCMPLTSD = 5902, + I_VCMPLTSS = 5500, I_VCMPLT_OQPD = 5282, I_VCMPLT_OQPS = 4880, I_VCMPLT_OQSD = 6086, + I_VCMPLT_OQSS = 5684, I_VCMPNEQPD = 5131, I_VCMPNEQPS = 4729, I_VCMPNEQSD = 5935, + I_VCMPNEQSS = 5533, I_VCMPNEQ_OQPD = 5223, I_VCMPNEQ_OQPS = 4821, I_VCMPNEQ_OQSD = 6027, + I_VCMPNEQ_OQSS = 5625, I_VCMPNEQ_OSPD = 5435, I_VCMPNEQ_OSPS = 5033, I_VCMPNEQ_OSSD = 6239, + I_VCMPNEQ_OSSS = 5837, I_VCMPNEQ_USPD = 5323, I_VCMPNEQ_USPS = 4921, I_VCMPNEQ_USSD = 6127, + I_VCMPNEQ_USSS = 5725, I_VCMPNGEPD = 5188, I_VCMPNGEPS = 4786, I_VCMPNGESD = 5992, + I_VCMPNGESS = 5590, I_VCMPNGE_UQPD = 5391, I_VCMPNGE_UQPS = 4989, I_VCMPNGE_UQSD = 6195, + I_VCMPNGE_UQSS = 5793, I_VCMPNGTPD = 5199, I_VCMPNGTPS = 4797, I_VCMPNGTSD = 6003, + I_VCMPNGTSS = 5601, I_VCMPNGT_UQPD = 5405, I_VCMPNGT_UQPS = 5003, I_VCMPNGT_UQSD = 6209, + I_VCMPNGT_UQSS = 5807, I_VCMPNLEPD = 5153, I_VCMPNLEPS = 4751, I_VCMPNLESD = 5957, + I_VCMPNLESS = 5555, I_VCMPNLE_UQPD = 5351, I_VCMPNLE_UQPS = 4949, I_VCMPNLE_UQSD = 6155, + I_VCMPNLE_UQSS = 5753, I_VCMPNLTPD = 5142, I_VCMPNLTPS = 4740, I_VCMPNLTSD = 5946, + I_VCMPNLTSS = 5544, I_VCMPNLT_UQPD = 5337, I_VCMPNLT_UQPS = 4935, I_VCMPNLT_UQSD = 6141, + I_VCMPNLT_UQSS = 5739, I_VCMPORDPD = 5164, I_VCMPORDPS = 4762, I_VCMPORDSD = 5968, + I_VCMPORDSS = 5566, I_VCMPORD_SPD = 5365, I_VCMPORD_SPS = 4963, I_VCMPORD_SSD = 6169, + I_VCMPORD_SSS = 5767, I_VCMPTRUEPD = 5257, I_VCMPTRUEPS = 4855, I_VCMPTRUESD = 6061, + I_VCMPTRUESS = 5659, I_VCMPTRUE_USPD = 5475, I_VCMPTRUE_USPS = 5073, I_VCMPTRUE_USSD = 6279, + I_VCMPTRUE_USSS = 5877, I_VCMPUNORDPD = 5118, I_VCMPUNORDPS = 4716, I_VCMPUNORDSD = 5922, + I_VCMPUNORDSS = 5520, I_VCMPUNORD_SPD = 5308, I_VCMPUNORD_SPS = 4906, I_VCMPUNORD_SSD = 6112, + I_VCMPUNORD_SSS = 5710, I_VCOMISD = 2796, I_VCOMISS = 2787, I_VCVTDQ2PD = 6819, + I_VCVTDQ2PS = 3338, I_VCVTPD2DQ = 6830, I_VCVTPD2PS = 3274, I_VCVTPS2DQ = 3349, + I_VCVTPS2PD = 3263, I_VCVTSD2SI = 2722, I_VCVTSD2SS = 3296, I_VCVTSI2SD = 2536, + I_VCVTSI2SS = 2525, I_VCVTSS2SD = 3285, I_VCVTSS2SI = 2711, I_VCVTTPD2DQ = 6807, + I_VCVTTPS2DQ = 3360, I_VCVTTSD2SI = 2659, I_VCVTTSS2SI = 2647, I_VDIVPD = 3528, + I_VDIVPS = 3520, I_VDIVSD = 3544, I_VDIVSS = 3536, I_VDPPD = 9621, I_VDPPS = 9608, + I_VERR = 1663, I_VERW = 1669, I_VEXTRACTF128 = 9516, I_VEXTRACTPS = 9491, + I_VFMADD132PD = 8387, I_VFMADD132PS = 8374, I_VFMADD132SD = 8413, I_VFMADD132SS = 8400, + I_VFMADD213PD = 8667, I_VFMADD213PS = 8654, I_VFMADD213SD = 8693, I_VFMADD213SS = 8680, + I_VFMADD231PD = 8947, I_VFMADD231PS = 8934, I_VFMADD231SD = 8973, I_VFMADD231SS = 8960, + I_VFMADDSUB132PD = 8326, I_VFMADDSUB132PS = 8310, I_VFMADDSUB213PD = 8606, + I_VFMADDSUB213PS = 8590, I_VFMADDSUB231PD = 8886, I_VFMADDSUB231PS = 8870, + I_VFMSUB132PD = 8439, I_VFMSUB132PS = 8426, I_VFMSUB132SD = 8465, I_VFMSUB132SS = 8452, + I_VFMSUB213PD = 8719, I_VFMSUB213PS = 8706, I_VFMSUB213SD = 8745, I_VFMSUB213SS = 8732, + I_VFMSUB231PD = 8999, I_VFMSUB231PS = 8986, I_VFMSUB231SD = 9025, I_VFMSUB231SS = 9012, + I_VFMSUBADD132PD = 8358, I_VFMSUBADD132PS = 8342, I_VFMSUBADD213PD = 8638, + I_VFMSUBADD213PS = 8622, I_VFMSUBADD231PD = 8918, I_VFMSUBADD231PS = 8902, + I_VFNMADD132PD = 8492, I_VFNMADD132PS = 8478, I_VFNMADD132SD = 8520, I_VFNMADD132SS = 8506, + I_VFNMADD213PD = 8772, I_VFNMADD213PS = 8758, I_VFNMADD213SD = 8800, I_VFNMADD213SS = 8786, + I_VFNMADD231PD = 9052, I_VFNMADD231PS = 9038, I_VFNMADD231SD = 9080, I_VFNMADD231SS = 9066, + I_VFNMSUB132PD = 8548, I_VFNMSUB132PS = 8534, I_VFNMSUB132SD = 8576, I_VFNMSUB132SS = 8562, + I_VFNMSUB213PD = 8828, I_VFNMSUB213PS = 8814, I_VFNMSUB213SD = 8856, I_VFNMSUB213SS = 8842, + I_VFNMSUB231PD = 9108, I_VFNMSUB231PS = 9094, I_VFNMSUB231SD = 9136, I_VFNMSUB231SS = 9122, + I_VHADDPD = 4197, I_VHADDPS = 4206, I_VHSUBPD = 4231, I_VHSUBPS = 4240, I_VINSERTF128 = 9503, + I_VINSERTPS = 9557, I_VLDDQU = 7001, I_VLDMXCSR = 9941, I_VMASKMOVDQU = 7131, + I_VMASKMOVPD = 7949, I_VMASKMOVPS = 7937, I_VMAXPD = 3588, I_VMAXPS = 3580, + I_VMAXSD = 3604, I_VMAXSS = 3596, I_VMCALL = 1719, I_VMCLEAR = 9997, I_VMFUNC = 1787, + I_VMINPD = 3468, I_VMINPS = 3460, I_VMINSD = 3484, I_VMINSS = 3476, I_VMLAUNCH = 1727, + I_VMLOAD = 1811, I_VMMCALL = 1802, I_VMOVAPD = 2476, I_VMOVAPS = 2467, I_VMOVD = 3932, + I_VMOVDDUP = 2234, I_VMOVDQA = 3962, I_VMOVDQU = 3971, I_VMOVHLPS = 2195, + I_VMOVHPD = 2382, I_VMOVHPS = 2373, I_VMOVLHPS = 2363, I_VMOVLPD = 2214, I_VMOVLPS = 2205, + I_VMOVMSKPD = 2836, I_VMOVMSKPS = 2825, I_VMOVNTDQ = 6858, I_VMOVNTDQA = 7905, + I_VMOVNTPD = 2593, I_VMOVNTPS = 2583, I_VMOVQ = 3939, I_VMOVSD = 2143, I_VMOVSHDUP = 2391, + I_VMOVSLDUP = 2223, I_VMOVSS = 2135, I_VMOVUPD = 2126, I_VMOVUPS = 2117, I_VMPSADBW = 9637, + I_VMPTRLD = 9988, I_VMPTRST = 6385, I_VMREAD = 4128, I_VMRESUME = 1737, I_VMRUN = 1795, + I_VMSAVE = 1819, I_VMULPD = 3199, I_VMULPS = 3191, I_VMULSD = 3215, I_VMULSS = 3207, + I_VMWRITE = 4152, I_VMXOFF = 1747, I_VMXON = 10006, I_VORPD = 3066, I_VORPS = 3059, + I_VPABSB = 7695, I_VPABSD = 7725, I_VPABSW = 7710, I_VPACKSSDW = 3859, I_VPACKSSWB = 3691, + I_VPACKUSDW = 7926, I_VPACKUSWB = 3769, I_VPADDB = 7211, I_VPADDD = 7241, + I_VPADDQ = 6488, I_VPADDSB = 6938, I_VPADDSW = 6955, I_VPADDUSW = 6629, I_VPADDW = 7226, + I_VPALIGNR = 9419, I_VPAND = 6613, I_VPANDN = 6672, I_VPAVGB = 6687, I_VPAVGW = 6732, + I_VPBLENDVB = 9692, I_VPBLENDW = 9400, I_VPCLMULQDQ = 9658, I_VPCMPEQB = 4052, + I_VPCMPEQD = 4090, I_VPCMPEQQ = 7885, I_VPCMPEQW = 4071, I_VPCMPESTRI = 9737, + I_VPCMPESTRM = 9714, I_VPCMPGTB = 3711, I_VPCMPGTD = 3749, I_VPCMPGTQ = 8096, + I_VPCMPGTW = 3730, I_VPCMPISTRI = 9783, I_VPCMPISTRM = 9760, I_VPERM2F128 = 9265, + I_VPERMILPD = 7570, I_VPERMILPS = 7559, I_VPEXTRB = 9437, I_VPEXTRD = 9462, + I_VPEXTRQ = 9471, I_VPEXTRW = 6319, I_VPHADDD = 7383, I_VPHADDSW = 7401, I_VPHADDW = 7366, + I_VPHMINPOSUW = 8271, I_VPHSUBD = 7459, I_VPHSUBSW = 7477, I_VPHSUBW = 7442, + I_VPINSRB = 9538, I_VPINSRD = 9584, I_VPINSRQ = 9593, I_VPINSRW = 6302, I_VPMADDUBSW = 7422, + I_VPMADDWD = 7082, I_VPMAXSB = 8182, I_VPMAXSD = 8199, I_VPMAXSW = 6972, I_VPMAXUB = 6656, + I_VPMAXUD = 8233, I_VPMAXUW = 8216, I_VPMINSB = 8114, I_VPMINSD = 8131, I_VPMINSW = 6910, + I_VPMINUB = 6598, I_VPMINUD = 8165, I_VPMINUW = 8148, I_VPMOVMSKB = 6541, + I_VPMOVSXBD = 7764, I_VPMOVSXBQ = 7785, I_VPMOVSXBW = 7743, I_VPMOVSXDQ = 7848, + I_VPMOVSXWD = 7806, I_VPMOVSXWQ = 7827, I_VPMOVZXBD = 7992, I_VPMOVZXBQ = 8013, + I_VPMOVZXBW = 7971, I_VPMOVZXDQ = 8076, I_VPMOVZXWD = 8034, I_VPMOVZXWQ = 8055, + I_VPMULDQ = 7867, I_VPMULHRSW = 7548, I_VPMULHUW = 6749, I_VPMULHW = 6767, + I_VPMULLD = 8250, I_VPMULLW = 6504, I_VPMULUDQ = 7063, I_VPOR = 6924, I_VPSADBW = 7100, + I_VPSHUFB = 7349, I_VPSHUFD = 4014, I_VPSHUFHW = 4023, I_VPSHUFLW = 4033, + I_VPSIGNB = 7495, I_VPSIGND = 7529, I_VPSIGNW = 7512, I_VPSLLD = 7031, I_VPSLLDQ = 9855, + I_VPSLLQ = 7046, I_VPSLLW = 7016, I_VPSRAD = 6717, I_VPSRAW = 6702, I_VPSRLD = 6458, + I_VPSRLDQ = 9838, I_VPSRLQ = 6473, I_VPSRLW = 6443, I_VPSUBB = 7151, I_VPSUBD = 7181, + I_VPSUBQ = 7196, I_VPSUBSB = 6876, I_VPSUBSW = 6893, I_VPSUBUSB = 6561, I_VPSUBUSW = 6580, + I_VPSUBW = 7166, I_VPTEST = 7636, I_VPUNPCKHBW = 3791, I_VPUNPCKHDQ = 3837, + I_VPUNPCKHQDQ = 3907, I_VPUNPCKHWD = 3814, I_VPUNPCKLBW = 3623, I_VPUNPCKLDQ = 3669, + I_VPUNPCKLQDQ = 3882, I_VPUNPCKLWD = 3646, I_VPXOR = 6987, I_VRCPPS = 2967, + I_VRCPSS = 2975, I_VROUNDPD = 9305, I_VROUNDPS = 9286, I_VROUNDSD = 9343, + I_VROUNDSS = 9324, I_VRSQRTPS = 2933, I_VRSQRTSS = 2943, I_VSHUFPD = 6353, + I_VSHUFPS = 6344, I_VSQRTPD = 2888, I_VSQRTPS = 2879, I_VSQRTSD = 2906, I_VSQRTSS = 2897, + I_VSTMXCSR = 9970, I_VSUBPD = 3408, I_VSUBPS = 3400, I_VSUBSD = 3424, I_VSUBSS = 3416, + I_VTESTPD = 7590, I_VTESTPS = 7581, I_VUCOMISD = 2761, I_VUCOMISS = 2751, + I_VUNPCKHPD = 2317, I_VUNPCKHPS = 2306, I_VUNPCKLPD = 2275, I_VUNPCKLPS = 2264, + I_VXORPD = 3095, I_VXORPS = 3087, I_VZEROALL = 4118, I_VZEROUPPER = 4106, + I_WAIT = 10028, I_WBINVD = 561, I_WRFSBASE = 9931, I_WRGSBASE = 9960, I_WRMSR = 586, + I_XADD = 946, I_XCHG = 212, I_XGETBV = 1771, I_XLAT = 400, I_XOR = 61, I_XORPD = 3080, + I_XORPS = 3073, I_XRSTOR = 4273, I_XRSTOR64 = 4281, I_XSAVE = 4249, I_XSAVE64 = 4256, + I_XSAVEOPT = 4299, I_XSAVEOPT64 = 4309, I_XSETBV = 1779, I__3DNOW = 10034 +} _InstructionType; + +typedef enum +{ + R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15, + R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI, R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D, + R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI, R_R8W, R_R9W, R_R10W, R_R11W, R_R12W, R_R13W, R_R14W, R_R15W, + R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH, R_R8B, R_R9B, R_R10B, R_R11B, R_R12B, R_R13B, R_R14B, R_R15B, + R_SPL, R_BPL, R_SIL, R_DIL, + R_ES, R_CS, R_SS, R_DS, R_FS, R_GS, + R_RIP, + R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7, + R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7, + R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15, + R_YMM0, R_YMM1, R_YMM2, R_YMM3, R_YMM4, R_YMM5, R_YMM6, R_YMM7, R_YMM8, R_YMM9, R_YMM10, R_YMM11, R_YMM12, R_YMM13, R_YMM14, R_YMM15, + R_CR0, R_UNUSED0, R_CR2, R_CR3, R_CR4, R_UNUSED1, R_UNUSED2, R_UNUSED3, R_CR8, + R_DR0, R_DR1, R_DR2, R_DR3, R_UNUSED4, R_UNUSED5, R_DR6, R_DR7 +} _RegisterType; + +#endif /* MNEMONICS_H */ diff --git a/scylla_wrapper/scylla_wrapper.cpp b/scylla_wrapper/scylla_wrapper.cpp new file mode 100644 index 0000000..4703fc8 --- /dev/null +++ b/scylla_wrapper/scylla_wrapper.cpp @@ -0,0 +1,660 @@ +/* +* +* Copyright (c) 2014 +* +* cypher + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License version 3 as +published by the Free Software Foundation. + +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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include "stdafx.h" +#include "scylla_wrapper.h" +#include "ApiReader.h" +#include "ProcessLister.h" +#include "ImportRebuilder.h" +#include "IATSearch.h" +#include "StringConversion.h" +#include "SystemInformation.h" + +static std::map moduleList; +static int moduleCount = 0; +static int importCount = 0; + +void updateCounts() +{ + std::map::iterator it_module; + std::map::iterator it_import; + + moduleCount = 0; + importCount = 0; + + it_module = moduleList.begin(); + while(it_module != moduleList.end()) + { + ImportModuleThunk & moduleThunk = it_module->second; + + it_import = moduleThunk.thunkList.begin(); + while(it_import != moduleThunk.thunkList.end()) + { + ImportThunk & importThunk = it_import->second; + + importCount++; + it_import++; + } + + moduleCount++; + it_module++; + } +} + +int scylla_searchIAT(DWORD pid, DWORD_PTR & iatStart, DWORD & iatSize, DWORD_PTR searchStart = 0xDEADBEEF, bool advancedSearch = false) +{ + ApiReader apiReader; + DWORD_PTR searchAddress = 0; + DWORD_PTR addressIAT = 0, addressIATAdv = 0; + DWORD sizeIAT = 0, sizeIATAdv = 0; + IATSearch iatSearch; + ProcessLister processLister; + + NativeWinApi::initialize(); + SystemInformation::getSystemInformation(); + + //need to find correct process by PID + Process* processPtr = 0; + std::vector & processList = processLister.getProcessListSnapshotNative(); + for(std::vector::iterator it = processList.begin(); it != processList.end(); ++it) + { + if(it->PID == pid) + { + processPtr = &(*it); + break; + } + } + + if(!processPtr) return SCY_ERROR_PROCOPEN; + + //init process access + ProcessAccessHelp::closeProcessHandle(); + apiReader.clearAll(); + + if(!ProcessAccessHelp::openProcessHandle(processPtr->PID)) + { + return SCY_ERROR_PROCOPEN; + } + + ProcessAccessHelp::getProcessModules(ProcessAccessHelp::hProcess, ProcessAccessHelp::moduleList); + + ProcessAccessHelp::selectedModule = 0; + ProcessAccessHelp::targetSizeOfImage = ProcessAccessHelp::getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase); + ProcessAccessHelp::targetImageBase = processPtr->imageBase; + + apiReader.readApisFromModuleList(); + + int retVal = SCY_ERROR_IATNOTFOUND; + + //now actually do some searching + if(searchStart != 0xDEADBEEF) + { + searchAddress = searchStart; + if(searchAddress) + { + + if(advancedSearch) + { + if(iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIATAdv, &sizeIATAdv, true)) + { + //Scylla::windowLog.log(L"IAT Search Advanced: IAT VA " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" Size 0x%04X (%d)", addressIATAdv, addressIATAdv - ProcessAccessHelp::targetImageBase, sizeIATAdv, sizeIATAdv); + + iatStart = addressIATAdv; + iatSize = sizeIATAdv; + + retVal = SCY_ERROR_SUCCESS; + } + } + + + if(iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIAT, &sizeIAT, false)) + { + //Scylla::windowLog.log(L"IAT Search Normal: IAT VA " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" Size 0x%04X (%d)", addressIAT, addressIAT - ProcessAccessHelp::targetImageBase, sizeIAT, sizeIAT); + + iatStart = addressIAT; + iatSize = sizeIAT; + + retVal = SCY_ERROR_SUCCESS; + } + + } + } + else + { + return SCY_ERROR_IATSEARCH; + } + + processList.clear(); + ProcessAccessHelp::closeProcessHandle(); + apiReader.clearAll(); + + return retVal; +} + +int scylla_getImports(DWORD_PTR iatAddr, DWORD iatSize, DWORD pid, LPVOID invalidImportCallback) +{ + //some things we need + ApiReader apiReader; + ProcessLister processLister; + typedef void* (*fCallback)(LPVOID invalidImport); + fCallback myCallback = (fCallback)invalidImportCallback; + + NativeWinApi::initialize(); + SystemInformation::getSystemInformation(); + + //need to find correct process by PID + Process* processPtr = 0; + std::vector & processList = processLister.getProcessListSnapshotNative(); + for(std::vector::iterator it = processList.begin(); it != processList.end(); ++it) + { + if(it->PID == pid) + { + processPtr = &(*it); + break; + } + } + + if(!processPtr) return SCY_ERROR_PROCOPEN; + + //init process access + ProcessAccessHelp::closeProcessHandle(); + apiReader.clearAll(); + + if(!ProcessAccessHelp::openProcessHandle(processPtr->PID)) + { + return SCY_ERROR_PROCOPEN; + } + + ProcessAccessHelp::getProcessModules(ProcessAccessHelp::hProcess, ProcessAccessHelp::moduleList); + + ProcessAccessHelp::selectedModule = 0; + ProcessAccessHelp::targetSizeOfImage = ProcessAccessHelp::getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase); + ProcessAccessHelp::targetImageBase = processPtr->imageBase; + + apiReader.readApisFromModuleList(); + + //parse IAT + apiReader.readAndParseIAT(iatAddr, iatSize, moduleList); + + //callback for invalid imports + if(invalidImportCallback != NULL) + { + std::map::iterator it_module; + std::map::iterator it_import; + + it_module = moduleList.begin(); + while(it_module != moduleList.end()) + { + ImportModuleThunk & moduleThunk = it_module->second; + + it_import = moduleThunk.thunkList.begin(); + while(it_import != moduleThunk.thunkList.end()) + { + ImportThunk & importThunk = it_import->second; + + if(!importThunk.valid) + { + DWORD_PTR apiAddr = (DWORD_PTR)myCallback((LPVOID)importThunk.apiAddressVA); + + //we trust the users return value + if(apiAddr != NULL) + { + importThunk.apiAddressVA = apiAddr; + importThunk.valid = true; + } + } + it_import++; + } + + it_module++; + } + } + + updateCounts(); + + return SCY_ERROR_SUCCESS; +} + +bool scylla_addModule(const WCHAR* moduleName, DWORD_PTR firstThunk) +{ + ApiReader apiReader; + + return apiReader.addModuleToModuleList(moduleName, firstThunk); +} + +bool scylla_addImport(const WCHAR* importName, DWORD_PTR thunkVA) +{ + ApiReader apiReader; + ApiInfo* apiFound = 0; + DWORD apiVA = 0; + bool suspect = false; + + if(ProcessAccessHelp::readMemoryFromProcess(thunkVA, sizeof(DWORD_PTR), (LPVOID)&apiVA)) + { + apiFound = apiReader.getApiByVirtualAddress(apiVA, &suspect); + apiReader.addFoundApiToModuleList(thunkVA, apiFound, false, suspect); + + return true; + } + + return false; +} + +bool scylla_importsValid() +{ + std::map::iterator it_module; + std::map::iterator it_import; + bool valid = true; + + it_module = moduleList.begin(); + while(it_module != moduleList.end()) + { + ImportModuleThunk & moduleThunk = it_module->second; + + it_import = moduleThunk.thunkList.begin(); + while(it_import != moduleThunk.thunkList.end()) + { + ImportThunk & importThunk = it_import->second; + + if(!importThunk.valid) + { + valid = false; + break;; + } + it_import++; + } + + it_module++; + } + + return valid; +} + +bool scylla_cutImport(DWORD_PTR apiAddr) +{ + std::map::iterator it_module; + std::map::iterator it_import; + + it_module = moduleList.begin(); + while(it_module != moduleList.end()) + { + ImportModuleThunk & moduleThunk = it_module->second; + + it_import = moduleThunk.thunkList.begin(); + while(it_import != moduleThunk.thunkList.end()) + { + ImportThunk & importThunk = it_import->second; + + //we found the API Addr to be cut + if(importThunk.apiAddressVA == apiAddr) + { + moduleThunk.thunkList.erase(it_import); + + //whole module empty now? + if(moduleThunk.thunkList.empty()) + { + moduleList.erase(it_module); + } + else //maybe the module is valid now? + { + if(moduleThunk.isValid() && moduleThunk.moduleName[0] == L'?') + { + //update module name + wcscpy_s(moduleThunk.moduleName, moduleThunk.thunkList.begin()->second.moduleName); + } + + moduleThunk.firstThunk = moduleThunk.thunkList.begin()->second.rva; + } + + updateCounts(); + + return true; + } + it_import++; + } + + it_module++; + } + + return false; +} + +int scylla_fixDump(WCHAR* dumpFile, WCHAR* iatFixFile, WCHAR* sectionName) +{ + WCHAR dumpedFilePath[MAX_PATH]; + WCHAR fixedFilePath[MAX_PATH]; + + wcscpy_s(fixedFilePath, iatFixFile); + wcscpy_s(dumpedFilePath, dumpFile); + + //add IAT section to dump + ImportRebuilder importRebuild(dumpedFilePath, sectionName); + importRebuild.enableOFTSupport(); + + if(importRebuild.rebuildImportTable(fixedFilePath, moduleList)) + { + return SCY_ERROR_SUCCESS; + } + else + { + return SCY_ERROR_IATWRITE; + } +} + +int scylla_fixMappedDump(DWORD_PTR iatVA, DWORD_PTR FileMapVA, HANDLE hFileMap) +{ + ImportRebuilder importRebuild(iatVA, FileMapVA, hFileMap, L".test"); + importRebuild.enableOFTSupport(); + + if(importRebuild.rebuildMappedImportTable(iatVA, moduleList)) + { + return SCY_ERROR_SUCCESS; + } + else + { + return SCY_ERROR_IATWRITE; + } + + return SCY_ERROR_SUCCESS; +} + +int scylla_getModuleCount() +{ + return moduleCount; +} + +int scylla_getImportCount() +{ + return importCount; +} + +void scylla_enumImportTree(LPVOID enumCallback) +{ + std::map::iterator it_module; + std::map::iterator it_import; + typedef void(*fCallback)(LPVOID importDetail); + fCallback myCallback = (fCallback)enumCallback; + ImportEnumData myImportEnumData; + myImportEnumData.DLLName = (char*)malloc(sizeof(char) * MAX_PATH); + myImportEnumData.APIName = (char*)malloc(sizeof(char) * MAX_PATH); + + if(enumCallback == NULL || moduleList.empty()) + { + return; + } + + it_module = moduleList.begin(); + while(it_module != moduleList.end()) + { + ImportModuleThunk & moduleThunk = it_module->second; + + //module + myImportEnumData.NewDll = true; + myImportEnumData.NumberOfImports = moduleThunk.thunkList.size(); + StringConversion::ToASCII(moduleThunk.moduleName, myImportEnumData.DLLName, sizeof(char)*MAX_PATH); + myImportEnumData.BaseImportThunk = moduleThunk.firstThunk; + + it_import = moduleThunk.thunkList.begin(); + while(it_import != moduleThunk.thunkList.end()) + { + ImportThunk & importThunk = it_import->second; + + //import + myImportEnumData.ImageBase = 0; + myImportEnumData.ImportThunk = importThunk.apiAddressVA; + strcpy_s(myImportEnumData.APIName, sizeof(char)*MAX_PATH, importThunk.name); + + myCallback(&myImportEnumData); + + myImportEnumData.NewDll = false; + + it_import++; + } + + it_module++; + } +} + +long scylla_estimatedIATSize() +{ + //faking a file to be rebuild + ImportRebuilder importRebuild(L"", L""); + + return importRebuild.getIATSectionSize(moduleList); +} + +DWORD_PTR scylla_findImportWriteLocation(char* importName) +{ + std::map::iterator it_module; + std::map::iterator it_import; + + it_module = moduleList.begin(); + while(it_module != moduleList.end()) + { + ImportModuleThunk & moduleThunk = it_module->second; + + it_import = moduleThunk.thunkList.begin(); + while(it_import != moduleThunk.thunkList.end()) + { + ImportThunk & importThunk = it_import->second; + + if(_stricmp(importName, importThunk.name)) + { + //returns VA + return importThunk.va; + } + } + it_import++; + } + + it_module++; + + return NULL; +} + +DWORD_PTR scylla_findOrdinalImportWriteLocation(DWORD_PTR ordinalNumber) +{ + std::map::iterator it_module; + std::map::iterator it_import; + + it_module = moduleList.begin(); + while(it_module != moduleList.end()) + { + ImportModuleThunk & moduleThunk = it_module->second; + + it_import = moduleThunk.thunkList.begin(); + while(it_import != moduleThunk.thunkList.end()) + { + ImportThunk & importThunk = it_import->second; + + if(importThunk.ordinal == ordinalNumber) + { + return importThunk.va; + } + } + it_import++; + } + + it_module++; + + return NULL; +} + +DWORD_PTR scylla_findImportNameByWriteLocation(DWORD_PTR thunkVA) +{ + std::map::iterator it_module; + std::map::iterator it_import; + + it_module = moduleList.begin(); + while(it_module != moduleList.end()) + { + ImportModuleThunk & moduleThunk = it_module->second; + + it_import = moduleThunk.thunkList.begin(); + while(it_import != moduleThunk.thunkList.end()) + { + ImportThunk & importThunk = it_import->second; + + if(importThunk.va == thunkVA) + { + return (DWORD_PTR)importThunk.name; + } + } + it_import++; + } + + it_module++; + + return NULL; +} + +DWORD_PTR scylla_findModuleNameByWriteLocation(DWORD_PTR thunkVA) +{ + std::map::iterator it_module; + std::map::iterator it_import; + + it_module = moduleList.begin(); + while(it_module != moduleList.end()) + { + ImportModuleThunk & moduleThunk = it_module->second; + + it_import = moduleThunk.thunkList.begin(); + while(it_import != moduleThunk.thunkList.end()) + { + ImportThunk & importThunk = it_import->second; + + if(importThunk.va == thunkVA) + { + return (DWORD_PTR)importThunk.moduleName; + } + } + it_import++; + } + + it_module++; + + return NULL; +} + +BOOL DumpProcessW(const WCHAR* fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR* fileResult) +{ + PeParser* peFile = 0; + + if(fileToDump) + { + peFile = new PeParser(fileToDump, true); + } + else + { + peFile = new PeParser(imagebase, true); + } + + return peFile->dumpProcess(imagebase, entrypoint, fileResult); +} + +bool scylla_dumpProcessW(DWORD_PTR pid, const WCHAR* fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR* fileResult) +{ + //BUGFiX: You need to initialize native WinAPIs before you can actually call them. + //Without this line of code you need to call some other dummy function in order to dump. + + NativeWinApi::initialize(); + if(ProcessAccessHelp::openProcessHandle((DWORD)pid)) + { + return DumpProcessW(fileToDump, imagebase, entrypoint, fileResult); + } + else + { + return FALSE; + } +} + +bool scylla_dumpProcessA(DWORD_PTR pid, const char* fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char* fileResult) +{ + WCHAR fileToDumpW[MAX_PATH]; + WCHAR fileResultW[MAX_PATH]; + + if(fileResult == 0) + { + return FALSE; + } + + if(MultiByteToWideChar(CP_ACP, 0, fileResult, -1, fileResultW, _countof(fileResultW)) == 0) + { + return FALSE; + } + + if(fileToDump != 0) + { + if(MultiByteToWideChar(CP_ACP, 0, fileToDump, -1, fileToDumpW, _countof(fileToDumpW)) == 0) + { + return FALSE; + } + + return scylla_dumpProcessW(pid, fileToDumpW, imagebase, entrypoint, fileResultW); + } + else + { + return scylla_dumpProcessW(pid, 0, imagebase, entrypoint, fileResultW); + } +} + +bool scylla_rebuildFileW(const WCHAR* fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup) +{ + + if(createBackup) + { + if(!ProcessAccessHelp::createBackupFile(fileToRebuild)) + { + return FALSE; + } + } + + PeParser peFile(fileToRebuild, true); + if(peFile.readPeSectionsFromFile()) + { + peFile.setDefaultFileAlignment(); + if(removeDosStub) + { + peFile.removeDosStub(); + } + peFile.alignAllSectionHeaders(); + peFile.fixPeHeader(); + + if(peFile.savePeFileToDisk(fileToRebuild)) + { + if(updatePeHeaderChecksum) + { + PeParser::updatePeHeaderChecksum(fileToRebuild, (DWORD)ProcessAccessHelp::getFileSize(fileToRebuild)); + } + return TRUE; + } + } + + return FALSE; +} + +bool scylla_rebuildFileA(const char* fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup) +{ + WCHAR fileToRebuildW[MAX_PATH]; + if(MultiByteToWideChar(CP_ACP, 0, fileToRebuild, -1, fileToRebuildW, _countof(fileToRebuildW)) == 0) + { + return FALSE; + } + + return scylla_rebuildFileW(fileToRebuildW, removeDosStub, updatePeHeaderChecksum, createBackup); +} \ No newline at end of file diff --git a/scylla_wrapper/scylla_wrapper.h b/scylla_wrapper/scylla_wrapper.h new file mode 100644 index 0000000..774047d --- /dev/null +++ b/scylla_wrapper/scylla_wrapper.h @@ -0,0 +1,66 @@ +/* +* +* Copyright (c) 2014 +* +* cypher + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License version 3 as +published by the Free Software Foundation. + +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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +//packing set to 1 needed because TitanEngine uses same +#pragma pack(push, 1) + +const BYTE SCY_ERROR_SUCCESS = 0; +const BYTE SCY_ERROR_PROCOPEN = -1; +const BYTE SCY_ERROR_IATWRITE = -2; +const BYTE SCY_ERROR_IATSEARCH = -3; +const BYTE SCY_ERROR_IATNOTFOUND = -4; + +typedef struct +{ + bool NewDll; + int NumberOfImports; + ULONG_PTR ImageBase; + ULONG_PTR BaseImportThunk; + ULONG_PTR ImportThunk; + char* APIName; + char* DLLName; +} ImportEnumData, *PImportEnumData; + +//IAT exports +int scylla_searchIAT(DWORD pid, DWORD_PTR & iatStart, DWORD & iatSize, DWORD_PTR searchStart, bool advancedSearch); +int scylla_getImports(DWORD_PTR iatAddr, DWORD iatSize, DWORD pid, LPVOID invalidImportCallback = NULL); +bool scylla_addModule(const WCHAR* moduleName, DWORD_PTR firstThunkRVA); +bool scylla_addImport(const WCHAR* importName, DWORD_PTR thunkVA); +bool scylla_importsValid(); +bool scylla_cutImport(DWORD_PTR apiAddr); +int scylla_fixDump(WCHAR* dumpFile, WCHAR* iatFixFile, WCHAR* sectionName = L".scy"); +int scylla_fixMappedDump(DWORD_PTR iatVA, DWORD_PTR FileMapVA, HANDLE hFileMap); +int scylla_getModuleCount(); +int scylla_getImportCount(); +void scylla_enumImportTree(LPVOID enumCallBack); +long scylla_estimatedIATSize(); +DWORD_PTR scylla_findImportWriteLocation(char* importName); +DWORD_PTR scylla_findOrdinalImportWriteLocation(DWORD_PTR ordinalNumber); +DWORD_PTR scylla_findImportNameByWriteLocation(DWORD_PTR thunkVA); +DWORD_PTR scylla_findModuleNameByWriteLocation(DWORD_PTR thunkVA); + +//dumper exports +bool scylla_dumpProcessW(DWORD_PTR pid, const WCHAR* fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const WCHAR* fileResult); +bool scylla_dumpProcessA(DWORD_PTR pid, const char* fileToDump, DWORD_PTR imagebase, DWORD_PTR entrypoint, const char* fileResult); + +//rebuilder exports +bool scylla_rebuildFileW(const WCHAR* fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); +bool scylla_rebuildFileA(const char* fileToRebuild, BOOL removeDosStub, BOOL updatePeHeaderChecksum, BOOL createBackup); + +#pragma pack(pop) \ No newline at end of file diff --git a/scylla_wrapper/scylla_wrapper.vcxproj b/scylla_wrapper/scylla_wrapper.vcxproj new file mode 100644 index 0000000..6c7b5b3 --- /dev/null +++ b/scylla_wrapper/scylla_wrapper.vcxproj @@ -0,0 +1,229 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {F874B1B3-8EF7-4DF1-9889-57098E08A51C} + Win32Proj + scylla_iatfix + scylla_wrapper + 7.0 + + + + StaticLibrary + true + Unicode + v141_xp + + + StaticLibrary + true + Unicode + v141_xp + + + StaticLibrary + false + true + Unicode + v141_xp + + + StaticLibrary + false + true + Unicode + v141_xp + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ + $(SolutionDir)distorm\include;$(IncludePath) + + + true + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ + $(SolutionDir)distorm\include;$(IncludePath) + + + false + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ + $(SolutionDir)distorm\include;$(IncludePath) + + + false + $(SolutionDir)bin\$(Configuration)\$(Platform)\ + $(SolutionDir)obj\$(MSBuildProjectName)\$(Configuration)\$(Platform)\ + $(SolutionDir)distorm\include;$(IncludePath) + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + false + MultiThreadedDebug + ProgramDatabase + + + Windows + true + distorm.lib;PSAPI.LIB;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + false + MultiThreadedDebug + ProgramDatabase + + + Windows + true + distorm.lib;PSAPI.LIB;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + MultiThreaded + + + Windows + true + true + true + distorm.lib;PSAPI.LIB;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + MultiThreaded + + + Windows + true + true + true + distorm.lib;PSAPI.LIB;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + + + + + false + false + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + {25ff4a19-7088-4687-aa32-76e61bd62e51} + + + + + + \ No newline at end of file diff --git a/scylla_wrapper/scylla_wrapper.vcxproj.filters b/scylla_wrapper/scylla_wrapper.vcxproj.filters new file mode 100644 index 0000000..bcb8e88 --- /dev/null +++ b/scylla_wrapper/scylla_wrapper.vcxproj.filters @@ -0,0 +1,123 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;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 + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/scylla_wrapper/stdafx.cpp b/scylla_wrapper/stdafx.cpp new file mode 100644 index 0000000..cae1d6b --- /dev/null +++ b/scylla_wrapper/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : Quelldatei, die nur die Standard-Includes einbindet. +// scylla_iatfix.pch ist der vorkompilierte Header. +// stdafx.obj enth�lt die vorkompilierten Typinformationen. + +#include "stdafx.h" + +// TODO: Auf zus�tzliche Header verweisen, die in STDAFX.H +// und nicht in dieser Datei erforderlich sind. diff --git a/scylla_wrapper/stdafx.h b/scylla_wrapper/stdafx.h new file mode 100644 index 0000000..65f0c42 --- /dev/null +++ b/scylla_wrapper/stdafx.h @@ -0,0 +1,8 @@ +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN +#include + + diff --git a/scylla_wrapper/targetver.h b/scylla_wrapper/targetver.h new file mode 100644 index 0000000..9c39707 --- /dev/null +++ b/scylla_wrapper/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Durch Einbeziehen von"SDKDDKVer.h" wird die h�chste verf�gbare Windows-Plattform definiert. + +// Wenn Sie die Anwendung f�r eine fr�here Windows-Plattform erstellen m�chten, schlie�en Sie "WinSDKVer.h" ein, und +// legen Sie das _WIN32_WINNT-Makro auf die zu unterst�tzende Plattform fest, bevor Sie "SDKDDKVer.h" einschlie�en. + +#include diff --git a/scylla_wrapper_dll b/scylla_wrapper_dll deleted file mode 160000 index 4f7892b..0000000 --- a/scylla_wrapper_dll +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4f7892b43dfcf4fda041b03b992541cac1367c2c