├── .gitattributes ├── .gitignore ├── README.md ├── libScanHook.sln └── libScanHook ├── ModuleLister.cpp ├── ModuleLister.h ├── PeLoader.cpp ├── PeLoader.h ├── ReadMe.txt ├── apisetschema.cpp ├── apisetschema.h ├── libPe.cpp ├── libPe.h ├── libScanHook.cpp ├── libScanHook.h ├── libScanHook.vcxproj ├── libScanHook.vcxproj.filters ├── libdasm.c ├── libdasm.h ├── ntdll.h ├── ntdll.lib ├── opcode_tables.h ├── stdafx.cpp ├── stdafx.h ├── targetver.h └── test.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 扫描IAT、EAT、inline Hook 2 | -------------------------------------------------------------------------------- /libScanHook.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30501.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libScanHook", "libScanHook\libScanHook.vcxproj", "{87C2005B-6523-4E4A-B3CF-F790880D12CD}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Debug-StaticLib|Win32 = Debug-StaticLib|Win32 13 | Debug-StaticLib|x64 = Debug-StaticLib|x64 14 | Release|Win32 = Release|Win32 15 | Release|x64 = Release|x64 16 | Release-StaticLib|Win32 = Release-StaticLib|Win32 17 | Release-StaticLib|x64 = Release-StaticLib|x64 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Debug|Win32.ActiveCfg = Debug|Win32 21 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Debug|Win32.Build.0 = Debug|Win32 22 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Debug|x64.ActiveCfg = Debug|x64 23 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Debug|x64.Build.0 = Debug|x64 24 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Debug-StaticLib|Win32.ActiveCfg = Debug-StaticLib|Win32 25 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Debug-StaticLib|Win32.Build.0 = Debug-StaticLib|Win32 26 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Debug-StaticLib|x64.ActiveCfg = Debug-StaticLib|x64 27 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Debug-StaticLib|x64.Build.0 = Debug-StaticLib|x64 28 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Release|Win32.ActiveCfg = Release|Win32 29 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Release|Win32.Build.0 = Release|Win32 30 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Release|x64.ActiveCfg = Release|x64 31 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Release|x64.Build.0 = Release|x64 32 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Release-StaticLib|Win32.ActiveCfg = Release-StaticLib|Win32 33 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Release-StaticLib|Win32.Build.0 = Release-StaticLib|Win32 34 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Release-StaticLib|x64.ActiveCfg = Release-StaticLib|x64 35 | {87C2005B-6523-4E4A-B3CF-F790880D12CD}.Release-StaticLib|x64.Build.0 = Release-StaticLib|x64 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /libScanHook/ModuleLister.cpp: -------------------------------------------------------------------------------- 1 | #include "ModuleLister.h" 2 | 3 | -------------------------------------------------------------------------------- /libScanHook/ModuleLister.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | -------------------------------------------------------------------------------- /libScanHook/PeLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "PeLoader.h" 2 | 3 | namespace peloader 4 | { 5 | bool PELOADER::Loader(WCHAR *FilePath, DWORD DllBase, void *Buffer, DWORD BufferSize) 6 | { 7 | bool ret = 0; 8 | void *FileBuffer; 9 | DWORD SectionNum, HeaderSize, DateSize, FileAlignment, SectionAlignment, i; 10 | HANDLE hFile; 11 | LIBPE Pe; 12 | PE_INFO PeInfo; 13 | PIMAGE_SECTION_HEADER SectionHead; 14 | if (Buffer) 15 | { 16 | hFile = CreateFile(FilePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); 17 | if (hFile != INVALID_HANDLE_VALUE) 18 | { 19 | FileBuffer = new BYTE[BufferSize]; 20 | if (FileBuffer) 21 | { 22 | if (ReadFile(hFile, FileBuffer, BufferSize, 0, 0)) 23 | { 24 | Pe.Parse((DWORD)FileBuffer, &PeInfo); 25 | SectionHead = IMAGE_FIRST_SECTION(PeInfo.PeHead); 26 | SectionNum = PeInfo.PeHead->FileHeader.NumberOfSections; 27 | HeaderSize = PeInfo.PeHead->OptionalHeader.SizeOfHeaders; 28 | FileAlignment = PeInfo.PeHead->OptionalHeader.FileAlignment; 29 | SectionAlignment = PeInfo.PeHead->OptionalHeader.SectionAlignment; 30 | memset(Buffer, 0, BufferSize); 31 | memcpy(Buffer, FileBuffer, HeaderSize); 32 | for (i = 0; i < SectionNum; ++i) 33 | { 34 | SectionHead[i].SizeOfRawData = AlignSize(SectionHead[i].SizeOfRawData, FileAlignment); 35 | SectionHead[i].Misc.VirtualSize = AlignSize(SectionHead[i].Misc.VirtualSize, SectionAlignment); 36 | } 37 | if (SectionHead[SectionNum - 1].VirtualAddress + SectionHead[SectionNum - 1].SizeOfRawData > BufferSize) 38 | SectionHead[SectionNum - 1].SizeOfRawData = BufferSize - SectionHead[SectionNum - 1].VirtualAddress; 39 | for (i = 0; i < SectionNum; ++i) 40 | { 41 | DateSize = SectionHead[i].SizeOfRawData; 42 | memcpy((void *)((DWORD)Buffer + SectionHead[i].VirtualAddress), 43 | (void *)((DWORD)FileBuffer + SectionHead[i].PointerToRawData), DateSize); 44 | } 45 | FixBaseRelocTable((DWORD)Buffer, DllBase); 46 | ret = 1; 47 | } 48 | delete[] FileBuffer; 49 | } 50 | CloseHandle(hFile); 51 | } 52 | } 53 | return ret; 54 | } 55 | 56 | UINT PELOADER::AlignSize(UINT Size, UINT Align) 57 | { 58 | return ((Size + Align - 1) / Align * Align); 59 | } 60 | 61 | bool PELOADER::FixBaseRelocTable(DWORD NewImageBase, DWORD ExistImageBase) 62 | { 63 | LONGLONG Diff; 64 | ULONG TotalCountBytes, SizeOfBlock; 65 | ULONG_PTR VA; 66 | ULONGLONG OriginalImageBase; 67 | PUSHORT NextOffset = 0; 68 | LIBPE Pe; 69 | PE_INFO PeInfo; 70 | PIMAGE_BASE_RELOCATION NextBlock; 71 | Pe.Parse(NewImageBase, &PeInfo); 72 | if (PeInfo.PeHead == 0) 73 | return 0; 74 | switch (PeInfo.PeHead->OptionalHeader.Magic) 75 | { 76 | case IMAGE_NT_OPTIONAL_HDR32_MAGIC: 77 | { 78 | OriginalImageBase = ((PIMAGE_NT_HEADERS32)PeInfo.PeHead)->OptionalHeader.ImageBase; 79 | break; 80 | } 81 | case IMAGE_NT_OPTIONAL_HDR64_MAGIC: 82 | { 83 | OriginalImageBase = ((PIMAGE_NT_HEADERS64)PeInfo.PeHead)->OptionalHeader.ImageBase; 84 | break; 85 | } 86 | default: 87 | return 0; 88 | } 89 | NextBlock = (PIMAGE_BASE_RELOCATION)(NewImageBase + 90 | PeInfo.PeHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); 91 | TotalCountBytes = PeInfo.PeHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; 92 | if (!NextBlock || !TotalCountBytes) 93 | { 94 | if (PeInfo.PeHead->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) 95 | return 0; 96 | else 97 | return 1; 98 | } 99 | Diff = ExistImageBase - OriginalImageBase; 100 | while (TotalCountBytes) 101 | { 102 | SizeOfBlock = NextBlock->SizeOfBlock; 103 | TotalCountBytes -= SizeOfBlock; 104 | SizeOfBlock -= sizeof(IMAGE_BASE_RELOCATION); 105 | SizeOfBlock /= sizeof(USHORT); 106 | NextOffset = (PUSHORT)((PCHAR)NextBlock + sizeof(IMAGE_BASE_RELOCATION)); 107 | VA = NewImageBase + NextBlock->VirtualAddress; 108 | NextBlock = ProcessRelocationBlock(VA, SizeOfBlock, NextOffset, Diff); 109 | if (!NextBlock) 110 | return 0; 111 | } 112 | return 1; 113 | } 114 | 115 | PIMAGE_BASE_RELOCATION PELOADER::ProcessRelocationBlock(ULONG_PTR VA, ULONG SizeOfBlock, PUSHORT NextOffset, LONGLONG Diff) 116 | { 117 | PUCHAR FixupVA; 118 | USHORT Offset; 119 | LONG Temp; 120 | ULONGLONG Value64; 121 | while (SizeOfBlock--) 122 | { 123 | Offset = *NextOffset & (USHORT)0xfff; 124 | FixupVA = (PUCHAR)(VA + Offset); 125 | switch ((*NextOffset) >> 12) 126 | { 127 | case IMAGE_REL_BASED_HIGHLOW: 128 | { 129 | *(LONG UNALIGNED *)FixupVA += (ULONG)Diff; 130 | break; 131 | } 132 | case IMAGE_REL_BASED_HIGH: 133 | { 134 | Temp = *(PUSHORT)FixupVA & 16; 135 | Temp += (ULONG)Diff; 136 | *(PUSHORT)FixupVA = (USHORT)(Temp >> 16); 137 | break; 138 | } 139 | case IMAGE_REL_BASED_HIGHADJ: 140 | { 141 | if (Offset & LDRP_RELOCATION_FINAL) 142 | { 143 | ++NextOffset; 144 | --SizeOfBlock; 145 | break; 146 | } 147 | Temp = *(PUSHORT)FixupVA & 16; 148 | ++NextOffset; 149 | --SizeOfBlock; 150 | Temp += (LONG)(*(PSHORT)NextOffset); 151 | Temp += (ULONG)Diff; 152 | Temp += 0x8000; 153 | *(PUSHORT)FixupVA = (USHORT)(Temp >> 16); 154 | break; 155 | } 156 | case IMAGE_REL_BASED_LOW: 157 | { 158 | Temp = *(PSHORT)FixupVA; 159 | Temp += (ULONG)Diff; 160 | *(PUSHORT)FixupVA = (USHORT)Temp; 161 | break; 162 | } 163 | case IMAGE_REL_BASED_IA64_IMM64: 164 | { 165 | FixupVA = (PUCHAR)((ULONG_PTR)FixupVA & ~(15)); 166 | Value64 = (ULONGLONG)0; 167 | EXT_IMM64(Value64, 168 | (PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X, 169 | EMARCH_ENC_I17_IMM7B_SIZE_X, 170 | EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X, 171 | EMARCH_ENC_I17_IMM7B_VAL_POS_X); 172 | EXT_IMM64(Value64, 173 | (PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X, 174 | EMARCH_ENC_I17_IMM9D_SIZE_X, 175 | EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X, 176 | EMARCH_ENC_I17_IMM9D_VAL_POS_X); 177 | EXT_IMM64(Value64, 178 | (PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X, 179 | EMARCH_ENC_I17_IMM5C_SIZE_X, 180 | EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X, 181 | EMARCH_ENC_I17_IMM5C_VAL_POS_X); 182 | EXT_IMM64(Value64, 183 | (PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X, 184 | EMARCH_ENC_I17_IC_SIZE_X, 185 | EMARCH_ENC_I17_IC_INST_WORD_POS_X, 186 | EMARCH_ENC_I17_IC_VAL_POS_X); 187 | EXT_IMM64(Value64, 188 | (PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X, 189 | EMARCH_ENC_I17_IMM41a_SIZE_X, 190 | EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X, 191 | EMARCH_ENC_I17_IMM41a_VAL_POS_X); 192 | EXT_IMM64(Value64, 193 | ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X), 194 | EMARCH_ENC_I17_IMM41b_SIZE_X, 195 | EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X, 196 | EMARCH_ENC_I17_IMM41b_VAL_POS_X); 197 | EXT_IMM64(Value64, 198 | ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X), 199 | EMARCH_ENC_I17_IMM41c_SIZE_X, 200 | EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X, 201 | EMARCH_ENC_I17_IMM41c_VAL_POS_X); 202 | EXT_IMM64(Value64, 203 | ((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X), 204 | EMARCH_ENC_I17_SIGN_SIZE_X, 205 | EMARCH_ENC_I17_SIGN_INST_WORD_POS_X, 206 | EMARCH_ENC_I17_SIGN_VAL_POS_X); 207 | Value64 += Diff; 208 | INS_IMM64(Value64, 209 | ((PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X), 210 | EMARCH_ENC_I17_IMM7B_SIZE_X, 211 | EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X, 212 | EMARCH_ENC_I17_IMM7B_VAL_POS_X); 213 | INS_IMM64(Value64, 214 | ((PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X), 215 | EMARCH_ENC_I17_IMM9D_SIZE_X, 216 | EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X, 217 | EMARCH_ENC_I17_IMM9D_VAL_POS_X); 218 | INS_IMM64(Value64, 219 | ((PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X), 220 | EMARCH_ENC_I17_IMM5C_SIZE_X, 221 | EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X, 222 | EMARCH_ENC_I17_IMM5C_VAL_POS_X); 223 | INS_IMM64(Value64, 224 | ((PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X), 225 | EMARCH_ENC_I17_IC_SIZE_X, 226 | EMARCH_ENC_I17_IC_INST_WORD_POS_X, 227 | EMARCH_ENC_I17_IC_VAL_POS_X); 228 | INS_IMM64(Value64, 229 | ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X), 230 | EMARCH_ENC_I17_IMM41a_SIZE_X, 231 | EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X, 232 | EMARCH_ENC_I17_IMM41a_VAL_POS_X); 233 | INS_IMM64(Value64, 234 | ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X), 235 | EMARCH_ENC_I17_IMM41b_SIZE_X, 236 | EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X, 237 | EMARCH_ENC_I17_IMM41b_VAL_POS_X); 238 | INS_IMM64(Value64, 239 | ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X), 240 | EMARCH_ENC_I17_IMM41c_SIZE_X, 241 | EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X, 242 | EMARCH_ENC_I17_IMM41c_VAL_POS_X); 243 | INS_IMM64(Value64, 244 | ((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X), 245 | EMARCH_ENC_I17_SIGN_SIZE_X, 246 | EMARCH_ENC_I17_SIGN_INST_WORD_POS_X, 247 | EMARCH_ENC_I17_SIGN_VAL_POS_X); 248 | break; 249 | } 250 | case IMAGE_REL_BASED_DIR64: 251 | { 252 | *(ULONGLONG UNALIGNED *)FixupVA += Diff; 253 | break; 254 | } 255 | case IMAGE_REL_BASED_MIPS_JMPADDR: 256 | { 257 | Temp = (*(PULONG)FixupVA & 0x3ffffff) & 2; 258 | Temp += (ULONG)Diff; 259 | *(PULONG)FixupVA = (*(PULONG)FixupVA & ~0x3ffffff) | ((Temp >> 2) & 0x3ffffff); 260 | break; 261 | } 262 | case IMAGE_REL_BASED_ABSOLUTE: 263 | break; 264 | default: 265 | return (PIMAGE_BASE_RELOCATION)NULL; 266 | } 267 | ++NextOffset; 268 | } 269 | return (PIMAGE_BASE_RELOCATION)NextOffset; 270 | } 271 | } -------------------------------------------------------------------------------- /libScanHook/PeLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "ntdll.h" 5 | #include "libPe.h" 6 | using namespace libpe; 7 | 8 | namespace peloader 9 | { 10 | class PELOADER 11 | { 12 | public: 13 | bool Loader(WCHAR *FilePath, DWORD DllBase, void *Buffer, DWORD BufferSize); 14 | 15 | private: 16 | UINT AlignSize(UINT Size, UINT Align); 17 | bool FixBaseRelocTable(DWORD NewImageBase, DWORD ExistImageBase); 18 | PIMAGE_BASE_RELOCATION ProcessRelocationBlock(ULONG_PTR VA, ULONG SizeOfBlock, PUSHORT NextOffset, LONGLONG Diff); 19 | }; 20 | } -------------------------------------------------------------------------------- /libScanHook/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : libScanHook Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this libScanHook application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your libScanHook application. 9 | 10 | 11 | libScanHook.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | libScanHook.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | libScanHook.cpp 25 | This is the main application source file. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other standard files: 29 | 30 | StdAfx.h, StdAfx.cpp 31 | These files are used to build a precompiled header (PCH) file 32 | named libScanHook.pch and a precompiled types file named StdAfx.obj. 33 | 34 | ///////////////////////////////////////////////////////////////////////////// 35 | Other notes: 36 | 37 | AppWizard uses "TODO:" comments to indicate parts of the source code you 38 | should add to or customize. 39 | 40 | ///////////////////////////////////////////////////////////////////////////// 41 | -------------------------------------------------------------------------------- /libScanHook/apisetschema.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frenda/libScanHook/bffa77ac4c9428fcc633d664c44fb868d5c29623/libScanHook/apisetschema.cpp -------------------------------------------------------------------------------- /libScanHook/apisetschema.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frenda/libScanHook/bffa77ac4c9428fcc633d664c44fb868d5c29623/libScanHook/apisetschema.h -------------------------------------------------------------------------------- /libScanHook/libPe.cpp: -------------------------------------------------------------------------------- 1 | #include "libPe.h" 2 | 3 | namespace libpe 4 | { 5 | bool LIBPE::Parse(DWORD ImageBase, PPE_INFO Pe) 6 | { 7 | bool ret = 0; 8 | PIMAGE_DOS_HEADER DosHead; 9 | PIMAGE_OPTIONAL_HEADER OpitionHead; 10 | if (ImageBase) 11 | { 12 | DosHead = (PIMAGE_DOS_HEADER)ImageBase; 13 | if (DosHead->e_magic == IMAGE_DOS_SIGNATURE) 14 | { 15 | Pe->PeHead = (PIMAGE_NT_HEADERS)(ImageBase + DosHead->e_lfanew); 16 | if (Pe->PeHead->Signature == IMAGE_NT_SIGNATURE) 17 | { 18 | OpitionHead = &(Pe->PeHead->OptionalHeader); 19 | Pe->ExportTableRva = OpitionHead->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 20 | Pe->ExportSize = OpitionHead->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; 21 | Pe->ImportTableRva = OpitionHead->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 22 | Pe->ImportSize = OpitionHead->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; 23 | ret = 1; 24 | } 25 | } 26 | } 27 | return ret; 28 | } 29 | 30 | bool LIBPE::IsGlobalVar(PIMAGE_NT_HEADERS PeHead, DWORD Rva) 31 | { 32 | WORD SectionNum; 33 | PIMAGE_SECTION_HEADER Section; 34 | SectionNum = PeHead->FileHeader.NumberOfSections; 35 | Section = IMAGE_FIRST_SECTION(PeHead); 36 | for (int i = 0; i < SectionNum; ++i) 37 | { 38 | if ((Section->VirtualAddress <= Rva) && (Rva < (Section->SizeOfRawData + Section->VirtualAddress))) 39 | return 0; 40 | ++Section; 41 | } 42 | return 1; 43 | } 44 | } -------------------------------------------------------------------------------- /libScanHook/libPe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace libpe 6 | { 7 | 8 | typedef struct _PE_INFO 9 | { 10 | PIMAGE_NT_HEADERS PeHead; 11 | DWORD ExportTableRva; 12 | DWORD ExportSize; 13 | DWORD ImportTableRva; 14 | DWORD ImportSize; 15 | } PE_INFO, *PPE_INFO; 16 | 17 | class LIBPE 18 | { 19 | public: 20 | bool Parse(DWORD ImageBase, PPE_INFO Pe); 21 | bool IsGlobalVar(PIMAGE_NT_HEADERS PeHead, DWORD Rva); 22 | }; 23 | } -------------------------------------------------------------------------------- /libScanHook/libScanHook.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frenda/libScanHook/bffa77ac4c9428fcc633d664c44fb868d5c29623/libScanHook/libScanHook.cpp -------------------------------------------------------------------------------- /libScanHook/libScanHook.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frenda/libScanHook/bffa77ac4c9428fcc633d664c44fb868d5c29623/libScanHook/libScanHook.h -------------------------------------------------------------------------------- /libScanHook/libScanHook.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug-StaticLib 6 | Win32 7 | 8 | 9 | Debug-StaticLib 10 | x64 11 | 12 | 13 | Debug 14 | Win32 15 | 16 | 17 | Debug 18 | x64 19 | 20 | 21 | Release-StaticLib 22 | Win32 23 | 24 | 25 | Release-StaticLib 26 | x64 27 | 28 | 29 | Release 30 | Win32 31 | 32 | 33 | Release 34 | x64 35 | 36 | 37 | 38 | {87C2005B-6523-4E4A-B3CF-F790880D12CD} 39 | Win32Proj 40 | libScanHook 41 | 42 | 43 | 44 | Application 45 | true 46 | v120 47 | Unicode 48 | 49 | 50 | Application 51 | true 52 | v120 53 | Unicode 54 | 55 | 56 | Application 57 | true 58 | v120 59 | Unicode 60 | 61 | 62 | Application 63 | true 64 | v120 65 | Unicode 66 | 67 | 68 | Application 69 | false 70 | v120 71 | true 72 | Unicode 73 | 74 | 75 | Application 76 | false 77 | v120 78 | true 79 | Unicode 80 | 81 | 82 | Application 83 | false 84 | v120 85 | true 86 | Unicode 87 | 88 | 89 | Application 90 | false 91 | v120 92 | true 93 | Unicode 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | true 125 | 126 | 127 | true 128 | 129 | 130 | true 131 | 132 | 133 | true 134 | 135 | 136 | false 137 | 138 | 139 | false 140 | 141 | 142 | false 143 | 144 | 145 | false 146 | 147 | 148 | 149 | NotUsing 150 | Level3 151 | Disabled 152 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 153 | true 154 | 155 | 156 | Console 157 | true 158 | 159 | 160 | 161 | 162 | NotUsing 163 | Level3 164 | Disabled 165 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 166 | true 167 | 168 | 169 | Console 170 | true 171 | 172 | 173 | 174 | 175 | NotUsing 176 | Level3 177 | Disabled 178 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 179 | true 180 | MultiThreadedDebug 181 | 182 | 183 | Console 184 | true 185 | 186 | 187 | 188 | 189 | NotUsing 190 | Level3 191 | Disabled 192 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 193 | true 194 | MultiThreadedDebug 195 | 196 | 197 | Console 198 | true 199 | 200 | 201 | 202 | 203 | Level3 204 | NotUsing 205 | MaxSpeed 206 | true 207 | true 208 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 209 | true 210 | MultiThreadedDLL 211 | 212 | 213 | Console 214 | true 215 | true 216 | true 217 | 218 | 219 | 220 | 221 | Level3 222 | NotUsing 223 | MaxSpeed 224 | true 225 | true 226 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 227 | true 228 | MultiThreaded 229 | 230 | 231 | Console 232 | true 233 | true 234 | true 235 | 236 | 237 | 238 | 239 | Level3 240 | NotUsing 241 | MaxSpeed 242 | true 243 | true 244 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 245 | true 246 | MultiThreaded 247 | 248 | 249 | Console 250 | true 251 | true 252 | true 253 | 254 | 255 | 256 | 257 | Level3 258 | NotUsing 259 | MaxSpeed 260 | true 261 | true 262 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 263 | true 264 | MultiThreaded 265 | 266 | 267 | Console 268 | true 269 | true 270 | true 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | NotUsing 289 | NotUsing 290 | NotUsing 291 | NotUsing 292 | NotUsing 293 | NotUsing 294 | NotUsing 295 | NotUsing 296 | 297 | 298 | 299 | NotUsing 300 | NotUsing 301 | NotUsing 302 | NotUsing 303 | NotUsing 304 | NotUsing 305 | NotUsing 306 | NotUsing 307 | 308 | 309 | 310 | Create 311 | Create 312 | Create 313 | Create 314 | Create 315 | Create 316 | Create 317 | Create 318 | 319 | 320 | NotUsing 321 | NotUsing 322 | NotUsing 323 | NotUsing 324 | 325 | 326 | 327 | 328 | 329 | -------------------------------------------------------------------------------- /libScanHook/libScanHook.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | Source Files 61 | 62 | 63 | Source Files 64 | 65 | 66 | -------------------------------------------------------------------------------- /libScanHook/libdasm.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * libdasm -- simple x86 disassembly library 4 | * (c) 2004 - 2006 jt / nologin.org 5 | * 6 | * libdasm.c: 7 | * This file contains most code of libdasm. Check out 8 | * libdasm.h for function definitions. 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | #include "libdasm.h" 15 | #include "opcode_tables.h" 16 | 17 | #pragma warning(disable:4996) 18 | 19 | // Endianess conversion routines (thanks Ero) 20 | 21 | __inline__ BYTE FETCH8(BYTE *addr) { 22 | // So far byte cast seems to work on all tested platforms 23 | return *(BYTE *)addr; 24 | } 25 | 26 | __inline__ WORD FETCH16(BYTE *addr) { 27 | #if defined __X86__ 28 | // Direct cast only for x86 29 | return *(WORD *)addr; 30 | #else 31 | // Revert to memcpy 32 | WORD val; 33 | memcpy(&val, addr, 2); 34 | #if defined __LITTLE_ENDIAN__ 35 | return val; 36 | #else 37 | return ((val & 0xff00) >> 8) | 38 | ((val & 0x00ff) << 8); 39 | 40 | #endif // __LITTLE_ENDIAN__ 41 | #endif // __X86__ 42 | } 43 | 44 | __inline__ DWORD FETCH32(BYTE *addr) { 45 | #if defined __X86__ 46 | return *(DWORD *)addr; 47 | #else 48 | DWORD val; 49 | memcpy(&val, addr, 4); 50 | #if defined __LITTLE_ENDIAN__ 51 | return val; 52 | #else 53 | return ((val & (0xff000000)) >> 24) | 54 | ((val & (0x00ff0000)) >> 8) | 55 | ((val & (0x0000ff00)) << 8) | 56 | ((val & (0x000000ff)) << 24); 57 | 58 | #endif // __LITTLE_ENDIAN__ 59 | #endif // __X86__ 60 | } 61 | 62 | // Check for address/operand size override 63 | 64 | __inline__ enum Mode MODE_CHECK_ADDR(enum Mode mode, int flags) { 65 | if (((mode == MODE_32) && (MASK_PREFIX_ADDR(flags) == 0)) || 66 | ((mode == MODE_16) && (MASK_PREFIX_ADDR(flags) == 1))) 67 | return MODE_32; 68 | else 69 | return MODE_16; 70 | } 71 | __inline__ enum Mode MODE_CHECK_OPERAND(enum Mode mode, int flags) { 72 | if (((mode == MODE_32) && (MASK_PREFIX_OPERAND(flags) == 0)) || 73 | ((mode == MODE_16) && (MASK_PREFIX_OPERAND(flags) == 1))) 74 | return MODE_32; 75 | else 76 | return MODE_16; 77 | } 78 | 79 | 80 | // Parse 2 and 3-byte opcodes 81 | 82 | int get_real_instruction2(BYTE *addr, int *flags) { 83 | switch (*addr) { 84 | 85 | // opcode extensions for 2-byte opcodes 86 | case 0x00: 87 | // Clear extension 88 | *flags &= 0xffffff00; 89 | *flags |= EXT_G6; 90 | break; 91 | case 0x01: 92 | *flags &= 0xffffff00; 93 | *flags |= EXT_G7; 94 | break; 95 | case 0x71: 96 | *flags &= 0xffffff00; 97 | *flags |= EXT_GC; 98 | break; 99 | case 0x72: 100 | *flags &= 0xffffff00; 101 | *flags |= EXT_GD; 102 | break; 103 | case 0x73: 104 | *flags &= 0xffffff00; 105 | *flags |= EXT_GE; 106 | break; 107 | case 0xae: 108 | *flags &= 0xffffff00; 109 | *flags |= EXT_GF; 110 | break; 111 | case 0xba: 112 | *flags &= 0xffffff00; 113 | *flags |= EXT_G8; 114 | break; 115 | case 0xc7: 116 | *flags &= 0xffffff00; 117 | *flags |= EXT_G9; 118 | break; 119 | default: 120 | break; 121 | } 122 | return 0; 123 | } 124 | 125 | // Parse instruction flags, get opcode index 126 | 127 | int get_real_instruction(BYTE *addr, int *index, int *flags) { 128 | switch (*addr) { 129 | 130 | // 2-byte opcode 131 | case 0x0f: 132 | *index += 1; 133 | *flags |= EXT_T2; 134 | break; 135 | 136 | // Prefix group 2 137 | case 0x2e: 138 | *index += 1; 139 | // Clear previous flags from same group (undefined effect) 140 | *flags &= 0xff00ffff; 141 | *flags |= PREFIX_CS_OVERRIDE; 142 | get_real_instruction(addr + 1, index, flags); 143 | break; 144 | case 0x36: 145 | *index += 1; 146 | *flags &= 0xff00ffff; 147 | *flags |= PREFIX_SS_OVERRIDE; 148 | get_real_instruction(addr + 1, index, flags); 149 | break; 150 | case 0x3e: 151 | *index += 1; 152 | *flags &= 0xff00ffff; 153 | *flags |= PREFIX_DS_OVERRIDE; 154 | get_real_instruction(addr + 1, index, flags); 155 | break; 156 | case 0x26: 157 | *index += 1; 158 | *flags &= 0xff00ffff; 159 | *flags |= PREFIX_ES_OVERRIDE; 160 | get_real_instruction(addr + 1, index, flags); 161 | break; 162 | case 0x64: 163 | *index += 1; 164 | *flags &= 0xff00ffff; 165 | *flags |= PREFIX_FS_OVERRIDE; 166 | get_real_instruction(addr + 1, index, flags); 167 | break; 168 | case 0x65: 169 | *index += 1; 170 | *flags &= 0xff00ffff; 171 | *flags |= PREFIX_GS_OVERRIDE; 172 | get_real_instruction(addr + 1, index, flags); 173 | break; 174 | // Prefix group 3 or 3-byte opcode 175 | case 0x66: 176 | // Do not clear flags from the same group!!!! 177 | *index += 1; 178 | *flags |= PREFIX_OPERAND_SIZE_OVERRIDE; 179 | get_real_instruction(addr + 1, index, flags); 180 | break; 181 | // Prefix group 4 182 | case 0x67: 183 | // Do not clear flags from the same group!!!! 184 | *index += 1; 185 | *flags |= PREFIX_ADDR_SIZE_OVERRIDE; 186 | get_real_instruction(addr + 1, index, flags); 187 | break; 188 | 189 | // Extension group 1 190 | case 0x80: 191 | *flags |= EXT_G1_1; 192 | break; 193 | case 0x81: 194 | *flags |= EXT_G1_2; 195 | break; 196 | case 0x82: 197 | *flags |= EXT_G1_1; 198 | break; 199 | case 0x83: 200 | *flags |= EXT_G1_3; 201 | break; 202 | 203 | // Extension group 2 204 | case 0xc0: 205 | *flags |= EXT_G2_1; 206 | break; 207 | case 0xc1: 208 | *flags |= EXT_G2_2; 209 | break; 210 | case 0xd0: 211 | *flags |= EXT_G2_3; 212 | break; 213 | case 0xd1: 214 | *flags |= EXT_G2_4; 215 | break; 216 | case 0xd2: 217 | *flags |= EXT_G2_5; 218 | break; 219 | case 0xd3: 220 | *flags |= EXT_G2_6; 221 | break; 222 | 223 | // Escape to co-processor 224 | case 0xd8: 225 | case 0xd9: 226 | case 0xda: 227 | case 0xdb: 228 | case 0xdc: 229 | case 0xdd: 230 | case 0xde: 231 | case 0xdf: 232 | *index += 1; 233 | *flags |= EXT_CP; 234 | break; 235 | 236 | // Prefix group 1 or 3-byte opcode 237 | case 0xf0: 238 | *index += 1; 239 | *flags &= 0x00ffffff; 240 | *flags |= PREFIX_LOCK; 241 | get_real_instruction(addr + 1, index, flags); 242 | break; 243 | case 0xf2: 244 | *index += 1; 245 | *flags &= 0x00ffffff; 246 | *flags |= PREFIX_REPNE; 247 | get_real_instruction(addr + 1, index, flags); 248 | break; 249 | case 0xf3: 250 | *index += 1; 251 | *flags &= 0x00ffffff; 252 | *flags |= PREFIX_REP; 253 | get_real_instruction(addr + 1, index, flags); 254 | break; 255 | 256 | // Extension group 3 257 | case 0xf6: 258 | *flags |= EXT_G3_1; 259 | break; 260 | case 0xf7: 261 | *flags |= EXT_G3_2; 262 | break; 263 | 264 | // Extension group 4 265 | case 0xfe: 266 | *flags |= EXT_G4; 267 | break; 268 | 269 | // Extension group 5 270 | case 0xff: 271 | *flags |= EXT_G5; 272 | break; 273 | default: 274 | break; 275 | } 276 | return 0; 277 | } 278 | 279 | // Parse operand and fill OPERAND structure 280 | 281 | /* 282 | * This function is quite complex.. I'm not perfectly happy 283 | * with the logic yet. Anyway, the idea is to 284 | * 285 | * - check out modrm and sib 286 | * - based on modrm/sib and addressing method (AM_X), 287 | * figure out the operand members and fill the struct 288 | * 289 | */ 290 | int get_operand(PINST inst, int oflags, PINSTRUCTION instruction, 291 | POPERAND op, BYTE *data, int offset, enum Mode mode, int iflags) { 292 | BYTE *addr = data + offset; 293 | int index = 0, sib = 0, scale = 0; 294 | int reg = REG_NOP; 295 | int basereg = REG_NOP; 296 | int indexreg = REG_NOP; 297 | int dispbytes = 0; 298 | enum Mode pmode; 299 | 300 | // Is this valid operand? 301 | if (oflags == FLAGS_NONE) { 302 | op->type = OPERAND_TYPE_NONE; 303 | return 1; 304 | } 305 | // Copy flags 306 | op->flags = oflags; 307 | 308 | // Set operand registers 309 | op->reg = REG_NOP; 310 | op->basereg = REG_NOP; 311 | op->indexreg = REG_NOP; 312 | 313 | // Offsets 314 | op->dispoffset = 0; 315 | op->immoffset = 0; 316 | 317 | // Parse modrm and sib 318 | if (inst->modrm) { 319 | pmode = MODE_CHECK_ADDR(mode, iflags); 320 | 321 | // Update length only once! 322 | if (!instruction->length) { 323 | instruction->modrm = *addr; 324 | instruction->length += 1; 325 | } 326 | // Register 327 | reg = MASK_MODRM_REG(*addr); 328 | 329 | // Displacement bytes 330 | // SIB can also specify additional displacement, see below 331 | if (MASK_MODRM_MOD(*addr) == 0) { 332 | if ((pmode == MODE_32) && (MASK_MODRM_RM(*addr) == REG_EBP)) 333 | dispbytes = 4; 334 | if ((pmode == MODE_16) && (MASK_MODRM_RM(*addr) == REG_ESI)) 335 | dispbytes = 2; 336 | } else if (MASK_MODRM_MOD(*addr) == 1) { 337 | dispbytes = 1; 338 | 339 | } else if (MASK_MODRM_MOD(*addr) == 2) { 340 | dispbytes = (pmode == MODE_32) ? 4 : 2; 341 | } 342 | // Base and index registers 343 | 344 | // 32-bit mode 345 | if (pmode == MODE_32) { 346 | if ((MASK_MODRM_RM(*addr) == REG_ESP) && 347 | (MASK_MODRM_MOD(*addr) != 3)) { 348 | sib = 1; 349 | instruction->sib = *(addr + 1); 350 | 351 | // Update length only once! 352 | if (instruction->length == 1) { 353 | instruction->sib = *(addr + 1); 354 | instruction->length += 1; 355 | } 356 | basereg = MASK_SIB_BASE( *(addr + 1)); 357 | indexreg = MASK_SIB_INDEX(*(addr + 1)); 358 | scale = MASK_SIB_SCALE(*(addr + 1)) * 2; 359 | // Fix scale *8 360 | if (scale == 6) 361 | scale += 2; 362 | 363 | // Special case where base=ebp and MOD = 0 364 | if ((basereg == REG_EBP) && !MASK_MODRM_MOD(*addr)) { 365 | basereg = REG_NOP; 366 | dispbytes = 4; 367 | } 368 | if (indexreg == REG_ESP) 369 | indexreg = REG_NOP; 370 | } else { 371 | if (!MASK_MODRM_MOD(*addr) && (MASK_MODRM_RM(*addr) == REG_EBP)) 372 | basereg = REG_NOP; 373 | else 374 | basereg = MASK_MODRM_RM(*addr); 375 | } 376 | // 16-bit 377 | } else { 378 | switch (MASK_MODRM_RM(*addr)) { 379 | case 0: 380 | basereg = REG_EBX; 381 | indexreg = REG_ESI; 382 | break; 383 | case 1: 384 | basereg = REG_EBX; 385 | indexreg = REG_EDI; 386 | break; 387 | case 2: 388 | basereg = REG_EBP; 389 | indexreg = REG_ESI; 390 | break; 391 | case 3: 392 | basereg = REG_EBP; 393 | indexreg = REG_EDI; 394 | break; 395 | case 4: 396 | basereg = REG_ESI; 397 | indexreg = REG_NOP; 398 | break; 399 | case 5: 400 | basereg = REG_EDI; 401 | indexreg = REG_NOP; 402 | break; 403 | case 6: 404 | if (!MASK_MODRM_MOD(*addr)) 405 | basereg = REG_NOP; 406 | else 407 | basereg = REG_EBP; 408 | indexreg = REG_NOP; 409 | break; 410 | case 7: 411 | basereg = REG_EBX; 412 | indexreg = REG_NOP; 413 | break; 414 | } 415 | if (MASK_MODRM_MOD(*addr) == 3) { 416 | basereg = MASK_MODRM_RM(*addr); 417 | indexreg = REG_NOP; 418 | } 419 | } 420 | } 421 | 422 | // Operand addressing method -specific parsing 423 | switch (MASK_AM(oflags)) { 424 | 425 | // Register encoded in instruction 426 | case AM_REG: 427 | op->type = OPERAND_TYPE_REGISTER; 428 | op->reg = MASK_REG(oflags); 429 | break; 430 | 431 | // Register indirect encoded in instruction 432 | case AM_IND: 433 | op->type = OPERAND_TYPE_MEMORY; 434 | op->basereg = MASK_REG(oflags); 435 | break; 436 | 437 | // Register/memory encoded in MODRM 438 | case AM_M: 439 | if (MASK_MODRM_MOD(*addr) == 3) 440 | return 0; 441 | goto skip_rest; 442 | case AM_R: 443 | if (MASK_MODRM_MOD(*addr) != 3) 444 | return 0; 445 | skip_rest: 446 | case AM_Q: 447 | case AM_W: 448 | case AM_E: 449 | op->type = OPERAND_TYPE_MEMORY; 450 | op->dispbytes = dispbytes; 451 | instruction->dispbytes = dispbytes; 452 | op->basereg = basereg; 453 | op->indexreg = indexreg; 454 | op->scale = scale; 455 | 456 | index = (sib) ? 1 : 0; 457 | if (dispbytes) 458 | op->dispoffset = index + 1 + offset; 459 | switch (dispbytes) { 460 | case 0: 461 | break; 462 | case 1: 463 | op->displacement = FETCH8(addr + 1 + index); 464 | // Always sign-extend 465 | if (op->displacement >= 0x80) 466 | op->displacement |= 0xffffff00; 467 | break; 468 | case 2: 469 | op->displacement = FETCH16(addr + 1 + index); 470 | break; 471 | case 4: 472 | op->displacement = FETCH32(addr + 1 + index); 473 | break; 474 | } 475 | 476 | // MODRM defines register 477 | if ((basereg != REG_NOP) && (MASK_MODRM_MOD(*addr) == 3)) { 478 | op->type = OPERAND_TYPE_REGISTER; 479 | op->reg = basereg; 480 | } 481 | break; 482 | 483 | // Immediate byte 1 encoded in instruction 484 | case AM_I1: 485 | op->type = OPERAND_TYPE_IMMEDIATE; 486 | op->immbytes = 1; 487 | op->immediate = 1; 488 | break; 489 | // Immediate value 490 | case AM_J: 491 | op->type = OPERAND_TYPE_IMMEDIATE; 492 | // Always sign-extend 493 | oflags |= F_s; 494 | case AM_I: 495 | op->type = OPERAND_TYPE_IMMEDIATE; 496 | index = (inst->modrm) ? 1 : 0; 497 | index += (sib) ? 1 : 0; 498 | index += instruction->immbytes; 499 | index += instruction->dispbytes; 500 | op->immoffset = index + offset; 501 | 502 | // check mode 503 | mode = MODE_CHECK_OPERAND(mode, iflags); 504 | 505 | switch (MASK_OT(oflags)) { 506 | case OT_b: 507 | op->immbytes = 1; 508 | op->immediate = FETCH8(addr + index); 509 | if ((op->immediate >= 0x80) && 510 | (MASK_FLAGS(oflags) == F_s)) 511 | op->immediate |= 0xffffff00; 512 | break; 513 | case OT_v: 514 | op->immbytes = (mode == MODE_32) ? 515 | 4 : 2; 516 | op->immediate = (mode == MODE_32) ? 517 | FETCH32(addr + index) : 518 | FETCH16(addr + index); 519 | break; 520 | case OT_w: 521 | op->immbytes = 2; 522 | op->immediate = FETCH16(addr + index); 523 | break; 524 | } 525 | instruction->immbytes += op->immbytes; 526 | break; 527 | 528 | // 32-bit or 48-bit address 529 | case AM_A: 530 | op->type = OPERAND_TYPE_IMMEDIATE; 531 | // check mode 532 | mode = MODE_CHECK_OPERAND(mode, iflags); 533 | 534 | op->dispbytes = (mode == MODE_32) ? 6 : 4; 535 | op->displacement = (mode == MODE_32) ? 536 | FETCH32(addr) : FETCH16(addr); 537 | op->section = FETCH16(addr + op->dispbytes - 2); 538 | 539 | instruction->dispbytes = op->dispbytes; 540 | instruction->sectionbytes = 2; 541 | break; 542 | 543 | // Plain displacement without MODRM/SIB 544 | case AM_O: 545 | op->type = OPERAND_TYPE_MEMORY; 546 | switch (MASK_OT(oflags)) { 547 | case OT_b: 548 | op->dispbytes = 1; 549 | op->displacement = FETCH8(addr); 550 | break; 551 | case OT_v: 552 | op->dispbytes = (mode == MODE_32) ? 4 : 2; 553 | op->displacement = (mode == MODE_32) ? 554 | FETCH32(addr) : FETCH16(addr); 555 | break; 556 | } 557 | instruction->dispbytes = op->dispbytes; 558 | op->dispoffset = offset; 559 | break; 560 | 561 | // General-purpose register encoded in MODRM 562 | case AM_G: 563 | op->type = OPERAND_TYPE_REGISTER; 564 | op->reg = reg; 565 | break; 566 | 567 | // control register encoded in MODRM 568 | case AM_C: 569 | // debug register encoded in MODRM 570 | case AM_D: 571 | // Segment register encoded in MODRM 572 | case AM_S: 573 | // TEST register encoded in MODRM 574 | case AM_T: 575 | // MMX register encoded in MODRM 576 | case AM_P: 577 | // XMM register encoded in MODRM 578 | case AM_V: 579 | op->type = OPERAND_TYPE_REGISTER; 580 | op->reg = MASK_MODRM_REG(instruction->modrm); 581 | break; 582 | } 583 | return 1; 584 | } 585 | 586 | 587 | // Print operand string 588 | 589 | #if !defined NOSTR 590 | int get_operand_string(INSTRUCTION *inst, OPERAND *op, 591 | enum Format format, DWORD offset, char *string, int length) { 592 | 593 | enum Mode mode; 594 | int regtype = 0; 595 | DWORD tmp = 0; 596 | 597 | memset(string, 0, length); 598 | 599 | if (op->type == OPERAND_TYPE_REGISTER) { 600 | // check mode 601 | mode = MODE_CHECK_OPERAND(inst->mode, inst->flags); 602 | 603 | if (format == FORMAT_ATT) 604 | snprintf(string + strlen(string), length - strlen(string), "%%"); 605 | 606 | // Determine register type 607 | switch (MASK_AM(op->flags)) { 608 | case AM_REG: 609 | if (MASK_FLAGS(op->flags) == F_r) 610 | regtype = REG_SEGMENT; 611 | else if (MASK_FLAGS(op->flags) == F_f) 612 | regtype = REG_FPU; 613 | else 614 | regtype = REG_GEN_DWORD; 615 | break; 616 | case AM_E: 617 | case AM_G: 618 | case AM_R: 619 | regtype = REG_GEN_DWORD; 620 | break; 621 | // control register encoded in MODRM 622 | case AM_C: 623 | regtype = REG_CONTROL; 624 | break; 625 | // debug register encoded in MODRM 626 | case AM_D: 627 | regtype = REG_DEBUG; 628 | break; 629 | // Segment register encoded in MODRM 630 | case AM_S: 631 | regtype = REG_SEGMENT; 632 | break; 633 | // TEST register encoded in MODRM 634 | case AM_T: 635 | regtype = REG_TEST; 636 | break; 637 | // MMX register encoded in MODRM 638 | case AM_P: 639 | case AM_Q: 640 | regtype = REG_MMX; 641 | break; 642 | // XMM register encoded in MODRM 643 | case AM_V: 644 | case AM_W: 645 | regtype = REG_XMM; 646 | break; 647 | } 648 | if (regtype == REG_GEN_DWORD) { 649 | switch (MASK_OT(op->flags)) { 650 | case OT_b: 651 | snprintf(string + strlen(string), length - strlen(string), 652 | "%s", reg_table[REG_GEN_BYTE][op->reg]); 653 | break; 654 | case OT_v: 655 | snprintf(string + strlen(string), length - strlen(string), 656 | "%s", (mode == MODE_32) ? 657 | reg_table[REG_GEN_DWORD][op->reg] : 658 | reg_table[REG_GEN_WORD][op->reg]); 659 | break; 660 | case OT_w: 661 | snprintf(string + strlen(string), length - strlen(string), 662 | "%s", reg_table[REG_GEN_WORD][op->reg]); 663 | break; 664 | case OT_d: 665 | snprintf(string + strlen(string), length - strlen(string), 666 | "%s", reg_table[REG_GEN_DWORD][op->reg]); 667 | break; 668 | } 669 | } else 670 | snprintf(string + strlen(string), length - strlen(string), 671 | "%s", reg_table[regtype][op->reg]); 672 | 673 | } else if (op->type == OPERAND_TYPE_MEMORY) { 674 | // check mode 675 | mode = MODE_CHECK_ADDR(inst->mode, inst->flags); 676 | 677 | // Operand-specific segment override 678 | if (MASK_PREFIX_G2(inst->flags)) 679 | snprintf(string + strlen(string), 680 | length - strlen(string), 681 | "%s%s:", (format == FORMAT_ATT) ? "%" : "", 682 | reg_table[REG_SEGMENT][(MASK_PREFIX_G2(inst->flags)) - 1]); 683 | // Some ATT stuff we need to check at this point 684 | if (format == FORMAT_ATT) { 685 | 686 | // "executable" operand 687 | if (MASK_PERMS(op->flags) == P_x) 688 | snprintf(string + strlen(string), 689 | length - strlen(string), "*"); 690 | 691 | // displacement in front of brackets 692 | if (op->dispbytes) 693 | snprintf(string + strlen(string), 694 | length - strlen(string), 695 | "0x%x", op->displacement); 696 | 697 | // no empty brackets - we're ready 698 | if ((op->basereg == REG_NOP) && 699 | (op->indexreg == REG_NOP)) 700 | return 1; 701 | } 702 | // Open memory addressing brackets 703 | snprintf(string + strlen(string), length - strlen(string), 704 | "%s", (format == FORMAT_ATT) ? "(" : "["); 705 | 706 | // Base register 707 | if (op->basereg != REG_NOP) { 708 | snprintf(string + strlen(string), length - strlen(string), 709 | "%s%s", (format == FORMAT_ATT) ? "%" : "", 710 | (mode == MODE_32) ? 711 | reg_table[REG_GEN_DWORD][op->basereg] : 712 | reg_table[REG_GEN_WORD][op->basereg]); 713 | } 714 | // Index register 715 | if (op->indexreg != REG_NOP) { 716 | if (op->basereg != REG_NOP) 717 | snprintf(string + strlen(string), length - strlen(string), 718 | "%s%s", (format == FORMAT_ATT) ? ",%" : "+", 719 | (mode == MODE_32) ? 720 | reg_table[REG_GEN_DWORD][op->indexreg] : 721 | reg_table[REG_GEN_WORD][op->indexreg]); 722 | else 723 | snprintf(string + strlen(string), length - strlen(string), 724 | "%s%s", (format == FORMAT_ATT) ? "%" : "", 725 | (mode == MODE_32) ? 726 | reg_table[REG_GEN_DWORD][op->indexreg] : 727 | reg_table[REG_GEN_WORD][op->indexreg]); 728 | switch (op->scale) { 729 | case 2: 730 | snprintf(string + strlen(string), length - strlen(string), 731 | "%s", (format == FORMAT_ATT) ? 732 | ",2" : "*2"); 733 | break; 734 | case 4: 735 | snprintf(string + strlen(string), length - strlen(string), 736 | "%s", (format == FORMAT_ATT) ? 737 | ",4" : "*4"); 738 | break; 739 | case 8: 740 | snprintf(string + strlen(string), length - strlen(string), 741 | "%s", (format == FORMAT_ATT) ? 742 | ",8" : "*8"); 743 | break; 744 | } 745 | } 746 | // INTEL displacement 747 | if (inst->dispbytes && (format != FORMAT_ATT)) { 748 | if ((op->basereg != REG_NOP) || (op->indexreg != REG_NOP)) { 749 | // Negative displacement 750 | if (op->displacement & (1<<(op->dispbytes*8-1))) { 751 | tmp = op->displacement; 752 | switch (op->dispbytes) { 753 | case 1: 754 | tmp = ~tmp & 0xff; 755 | break; 756 | case 2: 757 | tmp = ~tmp & 0xffff; 758 | break; 759 | case 4: 760 | tmp = ~tmp; 761 | break; 762 | } 763 | snprintf(string + strlen(string), 764 | length - strlen(string), 765 | "-0x%x", tmp + 1); 766 | // Positive displacement 767 | } else 768 | snprintf(string + strlen(string), 769 | length - strlen(string), 770 | "+0x%x", op->displacement); 771 | // Plain displacement 772 | } else { 773 | snprintf(string + strlen(string), 774 | length - strlen(string), 775 | "0x%x", op->displacement); 776 | } 777 | } 778 | // Close memory addressing brackets 779 | snprintf(string + strlen(string), length - strlen(string), 780 | "%s", (format == FORMAT_ATT) ? ")" : "]"); 781 | 782 | } else if (op->type == OPERAND_TYPE_IMMEDIATE) { 783 | 784 | switch (MASK_AM(op->flags)) { 785 | case AM_J: 786 | snprintf(string + strlen(string), length - strlen(string), 787 | "0x%x", op->immediate + inst->length + offset); 788 | break; 789 | case AM_I1: 790 | case AM_I: 791 | if (format == FORMAT_ATT) 792 | snprintf(string + strlen(string), length - strlen(string), "$"); 793 | snprintf(string + strlen(string), length - strlen(string), 794 | "0x%x", op->immediate); 795 | break; 796 | // 32-bit or 48-bit address 797 | case AM_A: 798 | snprintf(string + strlen(string), length - strlen(string), 799 | "%s0x%x:%s0x%x", 800 | (format == FORMAT_ATT) ? "$" : "", 801 | op->section, 802 | (format == FORMAT_ATT) ? "$" : "", 803 | op->displacement); 804 | break; 805 | } 806 | 807 | } else 808 | return 0; 809 | 810 | return 1; 811 | } 812 | 813 | #endif 814 | 815 | 816 | // Fetch instruction 817 | 818 | /* 819 | * The operation is quite straightforward: 820 | * 821 | * - determine actual opcode (skip prefixes etc.) 822 | * - figure out which instruction table to use 823 | * - index the table with opcode 824 | * - parse operands 825 | * - fill instruction structure 826 | * 827 | * Only point where this gets hairy is those *brilliant* 828 | * opcode extensions.... 829 | * 830 | */ 831 | int get_instruction(PINSTRUCTION inst, BYTE *addr, enum Mode mode) { 832 | PINST ptr = NULL; 833 | int index = 0; 834 | int flags = 0; 835 | 836 | memset(inst, 0, sizeof(INSTRUCTION)); 837 | 838 | // Parse flags, skip prefixes etc. 839 | get_real_instruction(addr, &index, &flags); 840 | 841 | // Select instruction table 842 | 843 | // No extensions - normal 1-byte opcode: 844 | if (MASK_EXT(flags) == 0) { 845 | inst->opcode = *(addr + index); 846 | ptr = &inst_table1[inst->opcode]; 847 | 848 | // FPU opcodes 849 | } else if (MASK_EXT(flags) == EXT_CP) { 850 | if (*(addr + index) < 0xc0) { 851 | // MODRM byte adds the additional byte 852 | index--; 853 | inst->fpuindex = *(addr + index) - 0xd8; 854 | inst->opcode = *(addr + index + 1); 855 | ptr = &inst_table4[inst->fpuindex] 856 | [MASK_MODRM_REG(inst->opcode)]; 857 | } else { 858 | inst->fpuindex = *(addr + index - 1) - 0xd8; 859 | inst->opcode = *(addr + index); 860 | ptr = &inst_table4[inst->fpuindex] 861 | [inst->opcode - 0xb8]; 862 | } 863 | // 2 or 3-byte opcodes 864 | } else if (MASK_EXT(flags) == EXT_T2) { 865 | inst->opcode = *(addr + index); 866 | 867 | // Parse flags, skip prefixes etc. (again) 868 | get_real_instruction2(addr + index, &flags); 869 | 870 | // 2-byte opcode table 871 | ptr = &inst_table2[inst->opcode]; 872 | 873 | // 3-byte opcode tables 874 | if (MASK_TYPE_FLAGS(ptr->type) == TYPE_3) { 875 | // prefix 0x66 876 | if (MASK_PREFIX_OPERAND(flags) == 1) { 877 | ptr = &inst_table3_66[inst->opcode]; 878 | 879 | // prefix 0xf2 880 | } else if (MASK_PREFIX_G1(flags) == 2) { 881 | ptr = &inst_table3_f2[inst->opcode]; 882 | 883 | // prefix 0xf3 884 | } else if (MASK_PREFIX_G1(flags) == 3) { 885 | ptr = &inst_table3_f3[inst->opcode]; 886 | 887 | } 888 | } 889 | } 890 | // Opcode extension tables 891 | if (MASK_EXT(flags) && (MASK_EXT(flags) < EXT_T2)) { 892 | inst->opcode = *(addr + index); 893 | inst->extindex = MASK_MODRM_REG(*(addr + index + 1)); 894 | 895 | switch (MASK_EXT(flags)) { 896 | case EXT_GC: 897 | // prefix 0x66 898 | if (MASK_PREFIX_OPERAND(flags) == 1) 899 | ptr = &inst_table_ext12_66[inst->extindex]; 900 | else 901 | ptr = &inst_table_ext12[inst->extindex]; 902 | break; 903 | case EXT_GD: 904 | // prefix 0x66 905 | if (MASK_PREFIX_OPERAND(flags) == 1) 906 | ptr = &inst_table_ext13_66[inst->extindex]; 907 | else 908 | ptr = &inst_table_ext13[inst->extindex]; 909 | break; 910 | case EXT_GE: 911 | // prefix 0x66 912 | if (MASK_PREFIX_OPERAND(flags) == 1) 913 | ptr = &inst_table_ext14_66[inst->extindex]; 914 | else 915 | ptr = &inst_table_ext14[inst->extindex]; 916 | break; 917 | // monitor/mwait 918 | // XXX: hack..... 919 | case EXT_G7: 920 | if (MASK_MODRM_MOD(*(addr + index + 1)) == 3) { 921 | if (inst->extindex != 1) 922 | return 0; 923 | if (MASK_MODRM_RM(*(addr + index + 1)) == 0) { 924 | ptr = &inst_monitor; 925 | // index is incremented to get 926 | // correct instruction len 927 | index++; 928 | } else if (MASK_MODRM_RM(*(addr + index + 1)) == 1) { 929 | ptr = &inst_mwait; 930 | index++; 931 | } else 932 | return 0; 933 | 934 | } else { 935 | ptr = &inst_table_ext7[inst->extindex]; 936 | } 937 | break; 938 | default: 939 | ptr = &inst_table_ext[(MASK_EXT(flags)) - 1] 940 | [inst->extindex]; 941 | break; 942 | } 943 | } 944 | // Index points now to first byte after prefixes/escapes 945 | index++; 946 | 947 | // MODRM byte offset 948 | if (ptr->modrm) 949 | inst->modrm_offset = index; 950 | 951 | // Illegal instruction 952 | if (!ptr) 953 | return 0; 954 | if (!ptr->mnemonic) 955 | return 0; 956 | 957 | // Copy instruction type 958 | inst->type = MASK_TYPE_VALUE(ptr->type); 959 | 960 | // Eflags affected by this instruction 961 | inst->eflags_affected = ptr->eflags_affected; 962 | inst->eflags_used = ptr->eflags_used; 963 | 964 | // Pointer to instruction table 965 | inst->ptr = ptr; 966 | 967 | 968 | // Parse operands 969 | if (!get_operand(ptr, ptr->flags1, inst, &inst->op1, addr, index, 970 | mode, flags)) 971 | return 0; 972 | if (!get_operand(ptr, ptr->flags2, inst, &inst->op2, addr, index, 973 | mode, flags)) 974 | return 0; 975 | if (!get_operand(ptr, ptr->flags3, inst, &inst->op3, addr, index, 976 | mode, flags)) 977 | return 0; 978 | 979 | // Implied operands 980 | inst->iop_read = ptr->iop_read; 981 | inst->iop_written = ptr->iop_written; 982 | 983 | // Add modrm/sib, displacement and immediate bytes in size 984 | inst->length += index + inst->immbytes + inst->dispbytes; 985 | 986 | // Copy addressing mode 987 | inst->mode = mode; 988 | 989 | // Copy instruction flags 990 | inst->flags = flags; 991 | 992 | return inst->length; 993 | } 994 | 995 | 996 | // Print instruction mnemonic 997 | 998 | #if !defined NOSTR 999 | int get_mnemonic_string(INSTRUCTION *inst, enum Format format, char *string, int length) { 1000 | int mode; 1001 | 1002 | memset(string, 0, length); 1003 | 1004 | // Segment override, branch hint 1005 | if (MASK_PREFIX_G2(inst->flags) && 1006 | (inst->op1.type != OPERAND_TYPE_MEMORY) && 1007 | (inst->op2.type != OPERAND_TYPE_MEMORY)) { 1008 | // Branch hint 1009 | if (inst->type == INSTRUCTION_TYPE_JMPC) 1010 | snprintf(string + strlen(string), length - strlen(string), 1011 | "%s ", reg_table[REG_BRANCH][(MASK_PREFIX_G2(inst->flags)) - 1]); 1012 | // Segment override for others 1013 | else 1014 | snprintf(string + strlen(string), length - strlen(string), 1015 | "%s ", reg_table[REG_SEGMENT][(MASK_PREFIX_G2(inst->flags)) - 1]); 1016 | } 1017 | 1018 | // Rep, lock etc. 1019 | if (MASK_PREFIX_G1(inst->flags) && 1020 | (MASK_EXT(inst->flags) != EXT_T2)) 1021 | snprintf(string + strlen(string), length - strlen(string), 1022 | "%s", rep_table[(MASK_PREFIX_G1(inst->flags)) - 1]); 1023 | 1024 | // Mnemonic 1025 | // XXX: quick hack for jcxz/jecxz.. check if there are more 1026 | // of these opcodes that have different mnemonic in same opcode 1027 | if (((inst->type == INSTRUCTION_TYPE_JMPC) && 1028 | (inst->opcode == 0xe3)) && 1029 | (MASK_PREFIX_ADDR(inst->flags) == 1)) 1030 | snprintf(string + strlen(string), length - strlen(string), 1031 | "jcxz"); 1032 | else 1033 | snprintf(string + strlen(string), length - strlen(string), 1034 | "%s", inst->ptr->mnemonic); 1035 | 1036 | 1037 | // memory operation size in push/pop: 1038 | if (inst->type == INSTRUCTION_TYPE_PUSH) { 1039 | if (inst->op1.type == OPERAND_TYPE_IMMEDIATE) { 1040 | switch (inst->op1.immbytes) { 1041 | case 1: 1042 | snprintf(string + strlen(string), 1043 | length - strlen(string), 1044 | "%s", (format == FORMAT_ATT) ? 1045 | "b" : " byte"); 1046 | break; 1047 | case 2: 1048 | snprintf(string + strlen(string), 1049 | length - strlen(string), 1050 | "%s", (format == FORMAT_ATT) ? 1051 | "w" : " word"); 1052 | break; 1053 | case 4: 1054 | snprintf(string + strlen(string), 1055 | length - strlen(string), 1056 | "%s", (format == FORMAT_ATT) ? 1057 | "l" : " dword"); 1058 | break; 1059 | } 1060 | 1061 | } else if (inst->op1.type == OPERAND_TYPE_MEMORY) { 1062 | mode = MODE_CHECK_OPERAND(inst->mode, inst->flags); 1063 | 1064 | if (mode == MODE_16) { 1065 | snprintf(string + strlen(string), 1066 | length - strlen(string), 1067 | "%s", (format == FORMAT_ATT) ? 1068 | "w" : " word"); 1069 | } else if (mode == MODE_32) { 1070 | snprintf(string + strlen(string), 1071 | length - strlen(string), 1072 | "%s", (format == FORMAT_ATT) ? 1073 | "l" : " dword"); 1074 | } 1075 | 1076 | } 1077 | return 1; 1078 | 1079 | } 1080 | if (inst->type == INSTRUCTION_TYPE_POP) { 1081 | if (inst->op1.type == OPERAND_TYPE_MEMORY) { 1082 | mode = MODE_CHECK_OPERAND(inst->mode, inst->flags); 1083 | 1084 | if (mode == MODE_16) { 1085 | snprintf(string + strlen(string), 1086 | length - strlen(string), 1087 | "%s", (format == FORMAT_ATT) ? 1088 | "w" : " word"); 1089 | } else if (mode == MODE_32) { 1090 | snprintf(string + strlen(string), 1091 | length - strlen(string), 1092 | "%s", (format == FORMAT_ATT) ? 1093 | "l" : " dword"); 1094 | } 1095 | } 1096 | return 1; 1097 | } 1098 | 1099 | // memory operation size in immediate to memory operations 1100 | if (inst->ptr->modrm && (MASK_MODRM_MOD(inst->modrm) != 3) && 1101 | (MASK_AM(inst->op2.flags) == AM_I)) { 1102 | 1103 | switch (MASK_OT(inst->op1.flags)) { 1104 | case OT_b: 1105 | snprintf(string + strlen(string), length - strlen(string), 1106 | "%s", (format == FORMAT_ATT) ? 1107 | "b" : " byte"); 1108 | break; 1109 | case OT_w: 1110 | snprintf(string + strlen(string), length - strlen(string), 1111 | "%s", (format == FORMAT_ATT) ? 1112 | "w" : " word"); 1113 | break; 1114 | case OT_d: 1115 | snprintf(string + strlen(string), length - strlen(string), 1116 | "%s", (format == FORMAT_ATT) ? 1117 | "l" : " dword"); 1118 | break; 1119 | case OT_v: 1120 | if (((inst->mode == MODE_32) && (MASK_PREFIX_OPERAND(inst->flags) == 0)) || 1121 | ((inst->mode == MODE_16) && (MASK_PREFIX_OPERAND(inst->flags) == 1))) 1122 | snprintf(string + strlen(string), length - strlen(string), 1123 | "%s", (format == FORMAT_ATT) ? 1124 | "l" : " dword"); 1125 | else 1126 | snprintf(string + strlen(string), length - strlen(string), 1127 | "%s", (format == FORMAT_ATT) ? 1128 | "w" : " word"); 1129 | break; 1130 | } 1131 | } 1132 | 1133 | // XXX: there might be some other cases where size is needed.. 1134 | 1135 | return 1; 1136 | } 1137 | 1138 | // Print operands 1139 | 1140 | int get_operands_string(INSTRUCTION *inst, enum Format format, DWORD offset, 1141 | char *string, int length) { 1142 | 1143 | if (format == FORMAT_ATT) { 1144 | if (inst->op3.type != OPERAND_TYPE_NONE) { 1145 | get_operand_string(inst, &inst->op3, format, offset, 1146 | string + strlen(string), length - strlen(string)); 1147 | snprintf(string + strlen(string), length - strlen(string), ","); 1148 | } 1149 | if (inst->op2.type != OPERAND_TYPE_NONE) { 1150 | get_operand_string(inst, &inst->op2, format, offset, 1151 | string + strlen(string), length - strlen(string)); 1152 | snprintf(string + strlen(string), length - strlen(string), ","); 1153 | } 1154 | if (inst->op1.type != OPERAND_TYPE_NONE) 1155 | get_operand_string(inst, &inst->op1, format, offset, 1156 | string + strlen(string), length - strlen(string)); 1157 | } else if (format == FORMAT_INTEL) { 1158 | if (inst->op1.type != OPERAND_TYPE_NONE) 1159 | get_operand_string(inst, &inst->op1, format, offset, 1160 | string + strlen(string), length - strlen(string)); 1161 | if (inst->op2.type != OPERAND_TYPE_NONE) { 1162 | snprintf(string + strlen(string), length - strlen(string), ","); 1163 | get_operand_string(inst, &inst->op2, format, offset, 1164 | string + strlen(string), length - strlen(string)); 1165 | } 1166 | if (inst->op3.type != OPERAND_TYPE_NONE) { 1167 | snprintf(string + strlen(string), length - strlen(string), ","); 1168 | get_operand_string(inst, &inst->op3, format, offset, 1169 | string + strlen(string), length - strlen(string)); 1170 | } 1171 | } else 1172 | return 0; 1173 | 1174 | return 1; 1175 | } 1176 | 1177 | // Print instruction mnemonic, prefixes and operands 1178 | 1179 | int get_instruction_string(INSTRUCTION *inst, enum Format format, DWORD offset, 1180 | char *string, int length) { 1181 | 1182 | // Print the actual instruction string with possible prefixes etc. 1183 | get_mnemonic_string(inst, format, string, length); 1184 | 1185 | snprintf(string + strlen(string), length - strlen(string), " "); 1186 | 1187 | // Print operands 1188 | if (!get_operands_string(inst, format, offset, 1189 | string + strlen(string), length - strlen(string))) 1190 | return 0; 1191 | 1192 | return 1; 1193 | } 1194 | 1195 | #endif 1196 | 1197 | // Helper functions 1198 | 1199 | int get_register_type(POPERAND op) { 1200 | 1201 | if (op->type != OPERAND_TYPE_REGISTER) 1202 | return 0; 1203 | switch (MASK_AM(op->flags)) { 1204 | case AM_REG: 1205 | if (MASK_FLAGS(op->flags) == F_r) 1206 | return REGISTER_TYPE_SEGMENT; 1207 | else if (MASK_FLAGS(op->flags) == F_f) 1208 | return REGISTER_TYPE_FPU; 1209 | else 1210 | return REGISTER_TYPE_GEN; 1211 | case AM_E: 1212 | case AM_G: 1213 | case AM_R: 1214 | return REGISTER_TYPE_GEN; 1215 | case AM_C: 1216 | return REGISTER_TYPE_CONTROL; 1217 | case AM_D: 1218 | return REGISTER_TYPE_DEBUG; 1219 | case AM_S: 1220 | return REGISTER_TYPE_SEGMENT; 1221 | case AM_T: 1222 | return REGISTER_TYPE_TEST; 1223 | case AM_P: 1224 | case AM_Q: 1225 | return REGISTER_TYPE_MMX; 1226 | case AM_V: 1227 | case AM_W: 1228 | return REGISTER_TYPE_XMM; 1229 | default: 1230 | break; 1231 | } 1232 | return 0; 1233 | } 1234 | 1235 | int get_operand_type(POPERAND op) { 1236 | return op->type; 1237 | } 1238 | 1239 | int get_operand_register(POPERAND op) { 1240 | return op->reg; 1241 | } 1242 | 1243 | int get_operand_basereg(POPERAND op) { 1244 | return op->basereg; 1245 | } 1246 | 1247 | int get_operand_indexreg(POPERAND op) { 1248 | return op->indexreg; 1249 | } 1250 | 1251 | int get_operand_scale(POPERAND op) { 1252 | return op->scale; 1253 | } 1254 | 1255 | int get_operand_immediate(POPERAND op, DWORD *imm) { 1256 | if (op->immbytes) { 1257 | *imm = op->immediate; 1258 | return 1; 1259 | } else 1260 | return 0; 1261 | } 1262 | 1263 | int get_operand_displacement(POPERAND op, DWORD *disp) { 1264 | if (op->dispbytes) { 1265 | *disp = op->displacement; 1266 | return 1; 1267 | } else 1268 | return 0; 1269 | } 1270 | 1271 | // XXX: note that source and destination are not always literal 1272 | 1273 | POPERAND get_source_operand(PINSTRUCTION inst) { 1274 | if (inst->op2.type != OPERAND_TYPE_NONE) 1275 | return &inst->op2; 1276 | else 1277 | return NULL; 1278 | } 1279 | POPERAND get_destination_operand(PINSTRUCTION inst) { 1280 | if (inst->op1.type != OPERAND_TYPE_NONE) 1281 | return &inst->op1; 1282 | else 1283 | return NULL; 1284 | } 1285 | 1286 | 1287 | -------------------------------------------------------------------------------- /libScanHook/libdasm.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * libdasm -- simple x86 disassembly library 4 | * (c) 2004 - 2006 jt / nologin.org 5 | * 6 | * libdasm.h: 7 | * Definitions for structures, functions and other weird stuff 8 | * 9 | */ 10 | 11 | 12 | #ifndef _LIBDASM_H 13 | #define _LIBDASM_H 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #define __LIBDASM_VERSION__ 0x01050000 20 | 21 | #define GET_VERSION_MAJOR \ 22 | (__LIBDASM_VERSION__ & 0xff000000) >> 24 23 | #define GET_VERSION_MINOR1 \ 24 | (__LIBDASM_VERSION__ & 0x00ff0000) >> 16 25 | #define GET_VERSION_MINOR2 \ 26 | (__LIBDASM_VERSION__ & 0x0000ff00) >> 8 27 | #define GET_VERSION_MINOR3 \ 28 | (__LIBDASM_VERSION__ & 0x000000ff) 29 | 30 | // Data types 31 | 32 | #if _WIN32 33 | #include 34 | #define __inline__ __inline 35 | #define snprintf _snprintf 36 | typedef unsigned __int64 QWORD; // for MSVC 37 | typedef signed __int8 SBYTE; 38 | typedef signed __int16 SWORD; 39 | typedef signed __int32 SDWORD; 40 | typedef signed __int64 SQWORD; 41 | #else 42 | #if defined __sun 43 | #define BYTE_ORDER 1234 44 | #define BIG_ENDIAN 1234 45 | #define LITTLE_ENDIAN 4321 46 | #define u_int8_t uint8_t 47 | #define u_int16_t uint16_t 48 | #define u_int32_t uint32_t 49 | #define u_int64_t uint64_t 50 | 51 | #endif // other *nix 52 | #include 53 | typedef u_int8_t BYTE; 54 | typedef u_int16_t WORD; 55 | typedef u_int32_t DWORD; 56 | typedef u_int64_t QWORD; 57 | typedef int8_t SBYTE; 58 | typedef int16_t SWORD; 59 | typedef int32_t SDWORD; 60 | typedef int64_t SQWORD; 61 | #endif 62 | 63 | // Define endianess 64 | 65 | #ifndef __X86__ 66 | // These should catch x86 with most compilers 67 | #if defined _X86_ || defined _i386_ || defined __i386__ 68 | #define __X86__ 69 | #endif 70 | #endif 71 | 72 | #ifndef __LITTLE_ENDIAN__ 73 | // These should catch little-endian with most compilers 74 | #if (BYTE_ORDER == LITTLE_ENDIAN) || defined __X86__ || defined _ALPHA_ 75 | #define __LITTLE_ENDIAN__ 76 | #endif 77 | #endif 78 | 79 | 80 | // Registers 81 | #define REGISTER_EAX 0 82 | #define REGISTER_ECX 1 83 | #define REGISTER_EDX 2 84 | #define REGISTER_EBX 3 85 | #define REGISTER_ESP 4 86 | #define REGISTER_EBP 5 87 | #define REGISTER_ESI 6 88 | #define REGISTER_EDI 7 89 | #define REGISTER_NOP 8 // no register defined 90 | 91 | // Registers 92 | #define REG_EAX REGISTER_EAX 93 | #define REG_AX REG_EAX 94 | #define REG_AL REG_EAX 95 | #define REG_ES REG_EAX // Just for reg_table consistence 96 | #define REG_ST0 REG_EAX // Just for reg_table consistence 97 | #define REG_ECX REGISTER_ECX 98 | #define REG_CX REG_ECX 99 | #define REG_CL REG_ECX 100 | #define REG_CS REG_ECX 101 | #define REG_ST1 REG_ECX 102 | #define REG_EDX REGISTER_EDX 103 | #define REG_DX REG_EDX 104 | #define REG_DL REG_EDX 105 | #define REG_SS REG_EDX 106 | #define REG_ST2 REG_EDX 107 | #define REG_EBX REGISTER_EBX 108 | #define REG_BX REG_EBX 109 | #define REG_BL REG_EBX 110 | #define REG_DS REG_EBX 111 | #define REG_ST3 REG_EBX 112 | #define REG_ESP REGISTER_ESP 113 | #define REG_SP REG_ESP 114 | #define REG_AH REG_ESP // Just for reg_table consistence 115 | #define REG_FS REG_ESP 116 | #define REG_ST4 REG_ESP 117 | #define REG_EBP REGISTER_EBP 118 | #define REG_BP REG_EBP 119 | #define REG_CH REG_EBP 120 | #define REG_GS REG_EBP 121 | #define REG_ST5 REG_EBP 122 | #define REG_ESI REGISTER_ESI 123 | #define REG_SI REG_ESI 124 | #define REG_DH REG_ESI 125 | #define REG_ST6 REG_ESI 126 | #define REG_EDI REGISTER_EDI 127 | #define REG_DI REG_EDI 128 | #define REG_BH REG_EDI 129 | #define REG_ST7 REG_EDI 130 | #define REG_NOP REGISTER_NOP 131 | 132 | // Implied operands 133 | #define IOP_EAX 1 134 | #define IOP_ECX (1 << REG_ECX) 135 | #define IOP_EDX (1 << REG_EDX) 136 | #define IOP_EBX (1 << REG_EBX) 137 | #define IOP_ESP (1 << REG_ESP) 138 | #define IOP_EBP (1 << REG_EBP) 139 | #define IOP_ESI (1 << REG_ESI) 140 | #define IOP_EDI (1 << REG_EDI) 141 | #define IOP_ALL IOP_EAX|IOP_ECX|IOP_EDX|IOP_ESP|IOP_EBP|IOP_ESI|IOP_EDI 142 | #define IS_IOP_REG(x,y) (x >> y) & 1 143 | #define IS_IOP_EAX(x) (x) & 1 144 | #define IS_IOP_ECX(x) (x >> REG_ECX) & 1 145 | #define IS_IOP_EDX(x) (x >> REG_EDX) & 1 146 | #define IS_IOP_EBX(x) (x >> REG_EBX) & 1 147 | #define IS_IOP_EBP(x) (x >> REG_EBP) & 1 148 | #define IS_IOP_ESI(x) (x >> REG_ESI) & 1 149 | #define IS_IOP_EDI(x) (x >> REG_EDI) & 1 150 | 151 | 152 | // Register types 153 | #define REGISTER_TYPE_GEN 1 154 | #define REGISTER_TYPE_SEGMENT 2 155 | #define REGISTER_TYPE_DEBUG 3 156 | #define REGISTER_TYPE_CONTROL 4 157 | #define REGISTER_TYPE_TEST 5 158 | #define REGISTER_TYPE_XMM 6 159 | #define REGISTER_TYPE_MMX 7 160 | #define REGISTER_TYPE_FPU 8 161 | 162 | // Disassembling mode 163 | enum Mode { 164 | MODE_32, // 32-bit 165 | MODE_16 // 16-bit 166 | }; 167 | 168 | // Disassembling format 169 | enum Format { 170 | FORMAT_ATT, 171 | FORMAT_INTEL, 172 | }; 173 | 174 | // Process eflags 175 | #define EFL_CF (1 << 0) 176 | #define EFL_PF (1 << 2) 177 | #define EFL_AF (1 << 4) 178 | #define EFL_ZF (1 << 6) 179 | #define EFL_SF (1 << 7) 180 | #define EFL_TF (1 << 8) 181 | #define EFL_IF (1 << 9) 182 | #define EFL_DF (1 << 10) 183 | #define EFL_OF (1 << 11) 184 | #define EFL_MATH EFL_OF|EFL_SF|EFL_ZF|EFL_AF|EFL_PF|EFL_CF 185 | #define EFL_BITWISE EFL_OF|EFL_CF|EFL_SF|EFL_ZF|EFL_PF 186 | #define EFL_ALL_COMMON EFL_CF|EFL_OF|EFL_SF|EFL_ZF|EFL_AF|EFL_PF 187 | 188 | // Instruction types (just the most common ones atm) 189 | enum Instruction { 190 | // Integer instructions 191 | INSTRUCTION_TYPE_ASC, // aaa, aam, etc. 192 | INSTRUCTION_TYPE_DCL, // daa, das 193 | INSTRUCTION_TYPE_MOV, 194 | INSTRUCTION_TYPE_MOVSR, // segment register 195 | INSTRUCTION_TYPE_ADD, 196 | INSTRUCTION_TYPE_XADD, 197 | INSTRUCTION_TYPE_ADC, 198 | INSTRUCTION_TYPE_SUB, 199 | INSTRUCTION_TYPE_SBB, 200 | INSTRUCTION_TYPE_INC, 201 | INSTRUCTION_TYPE_DEC, 202 | INSTRUCTION_TYPE_DIV, 203 | INSTRUCTION_TYPE_IDIV, 204 | INSTRUCTION_TYPE_NOT, 205 | INSTRUCTION_TYPE_NEG, 206 | INSTRUCTION_TYPE_STOS, 207 | INSTRUCTION_TYPE_LODS, 208 | INSTRUCTION_TYPE_SCAS, 209 | INSTRUCTION_TYPE_MOVS, 210 | INSTRUCTION_TYPE_MOVSX, 211 | INSTRUCTION_TYPE_MOVZX, 212 | INSTRUCTION_TYPE_CMPS, 213 | INSTRUCTION_TYPE_SHX, // signed/unsigned shift left/right 214 | INSTRUCTION_TYPE_ROX, // signed/unsigned rot left/right 215 | INSTRUCTION_TYPE_MUL, 216 | INSTRUCTION_TYPE_IMUL, 217 | INSTRUCTION_TYPE_EIMUL, // "extended" imul with 2-3 operands 218 | INSTRUCTION_TYPE_XOR, 219 | INSTRUCTION_TYPE_LEA, 220 | INSTRUCTION_TYPE_XCHG, 221 | INSTRUCTION_TYPE_CMP, 222 | INSTRUCTION_TYPE_TEST, 223 | INSTRUCTION_TYPE_PUSH, 224 | INSTRUCTION_TYPE_AND, 225 | INSTRUCTION_TYPE_OR, 226 | INSTRUCTION_TYPE_POP, 227 | INSTRUCTION_TYPE_JMP, 228 | INSTRUCTION_TYPE_JMPC, // conditional jump 229 | INSTRUCTION_TYPE_JECXZ, 230 | INSTRUCTION_TYPE_SETC, // conditional byte set 231 | INSTRUCTION_TYPE_MOVC, // conditional mov 232 | INSTRUCTION_TYPE_LOOP, 233 | INSTRUCTION_TYPE_CALL, 234 | INSTRUCTION_TYPE_RET, 235 | INSTRUCTION_TYPE_ENTER, 236 | INSTRUCTION_TYPE_INT, // interrupt 237 | INSTRUCTION_TYPE_BT, // bit tests 238 | INSTRUCTION_TYPE_BTS, 239 | INSTRUCTION_TYPE_BTR, 240 | INSTRUCTION_TYPE_BTC, 241 | INSTRUCTION_TYPE_BSF, 242 | INSTRUCTION_TYPE_BSR, 243 | INSTRUCTION_TYPE_BSWAP, 244 | INSTRUCTION_TYPE_SGDT, 245 | INSTRUCTION_TYPE_SIDT, 246 | INSTRUCTION_TYPE_SLDT, 247 | INSTRUCTION_TYPE_LFP, 248 | INSTRUCTION_TYPE_CLD, 249 | INSTRUCTION_TYPE_STD, 250 | INSTRUCTION_TYPE_XLAT, 251 | // FPU instructions 252 | INSTRUCTION_TYPE_FCMOVC, // float conditional mov 253 | INSTRUCTION_TYPE_FADD, 254 | INSTRUCTION_TYPE_FADDP, 255 | INSTRUCTION_TYPE_FIADD, 256 | INSTRUCTION_TYPE_FSUB, 257 | INSTRUCTION_TYPE_FSUBP, 258 | INSTRUCTION_TYPE_FISUB, 259 | INSTRUCTION_TYPE_FSUBR, 260 | INSTRUCTION_TYPE_FSUBRP, 261 | INSTRUCTION_TYPE_FISUBR, 262 | INSTRUCTION_TYPE_FMUL, 263 | INSTRUCTION_TYPE_FMULP, 264 | INSTRUCTION_TYPE_FIMUL, 265 | INSTRUCTION_TYPE_FDIV, 266 | INSTRUCTION_TYPE_FDIVP, 267 | INSTRUCTION_TYPE_FDIVR, 268 | INSTRUCTION_TYPE_FDIVRP, 269 | INSTRUCTION_TYPE_FIDIV, 270 | INSTRUCTION_TYPE_FIDIVR, 271 | INSTRUCTION_TYPE_FCOM, 272 | INSTRUCTION_TYPE_FCOMP, 273 | INSTRUCTION_TYPE_FCOMPP, 274 | INSTRUCTION_TYPE_FCOMI, 275 | INSTRUCTION_TYPE_FCOMIP, 276 | INSTRUCTION_TYPE_FUCOM, 277 | INSTRUCTION_TYPE_FUCOMP, 278 | INSTRUCTION_TYPE_FUCOMPP, 279 | INSTRUCTION_TYPE_FUCOMI, 280 | INSTRUCTION_TYPE_FUCOMIP, 281 | INSTRUCTION_TYPE_FST, 282 | INSTRUCTION_TYPE_FSTP, 283 | INSTRUCTION_TYPE_FIST, 284 | INSTRUCTION_TYPE_FISTP, 285 | INSTRUCTION_TYPE_FISTTP, 286 | INSTRUCTION_TYPE_FLD, 287 | INSTRUCTION_TYPE_FILD, 288 | INSTRUCTION_TYPE_FICOM, 289 | INSTRUCTION_TYPE_FICOMP, 290 | INSTRUCTION_TYPE_FFREE, 291 | INSTRUCTION_TYPE_FFREEP, 292 | INSTRUCTION_TYPE_FXCH, 293 | INSTRUCTION_TYPE_SYSENTER, 294 | INSTRUCTION_TYPE_FPU_CTRL, // FPU control instruction 295 | INSTRUCTION_TYPE_FPU, // Other FPU instructions 296 | 297 | INSTRUCTION_TYPE_MMX, // Other MMX instructions 298 | 299 | INSTRUCTION_TYPE_SSE, // Other SSE instructions 300 | 301 | INSTRUCTION_TYPE_OTHER, // Other instructions :-) 302 | INSTRUCTION_TYPE_PRIV // Privileged instruction 303 | }; 304 | 305 | // Operand types 306 | enum Operand { 307 | OPERAND_TYPE_NONE, // operand not present 308 | OPERAND_TYPE_MEMORY, // memory operand ([eax], [0], etc.) 309 | OPERAND_TYPE_REGISTER, // register operand (eax, mm0, etc.) 310 | OPERAND_TYPE_IMMEDIATE, // immediate operand (0x1234) 311 | }; 312 | 313 | // Structure definitions 314 | 315 | // struct INST is used internally by the library 316 | typedef struct _INST { 317 | DWORD type; // Instruction type and flags 318 | const char *mnemonic; // Instruction mnemonic 319 | int flags1; // First operand flags (if any) 320 | int flags2; // Second operand flags (if any) 321 | int flags3; // Additional operand flags (if any) 322 | int modrm; // Is MODRM byte present? 323 | short eflags_affected; // Processor eflags affected 324 | short eflags_used; // Processor eflags used by this instruction 325 | int iop_written; // mask of affected implied registers (written) 326 | int iop_read; // mask of affected implied registers (read) 327 | } INST, *PINST; 328 | 329 | // Operands for the instruction 330 | typedef struct _OPERAND { 331 | enum Operand type; // Operand type (register, memory, etc) 332 | int reg; // Register (if any) 333 | int basereg; // Base register (if any) 334 | int indexreg; // Index register (if any) 335 | int scale; // Scale (if any) 336 | int dispbytes; // Displacement bytes (0 = no displacement) 337 | int dispoffset; // Displacement value offset 338 | int immbytes; // Immediate bytes (0 = no immediate) 339 | int immoffset; // Immediate value offset 340 | int sectionbytes; // Section prefix bytes (0 = no section prefix) 341 | WORD section; // Section prefix value 342 | DWORD displacement; // Displacement value 343 | DWORD immediate; // Immediate value 344 | int flags; // Operand flags 345 | } OPERAND, *POPERAND; 346 | 347 | // struct INSTRUCTION is used to interface the library 348 | typedef struct _INSTRUCTION { 349 | int length; // Instruction length 350 | enum Instruction type; // Instruction type 351 | enum Mode mode; // Addressing mode 352 | BYTE opcode; // Actual opcode 353 | BYTE modrm; // MODRM byte 354 | BYTE sib; // SIB byte 355 | int modrm_offset; // MODRM byte offset 356 | int extindex; // Extension table index 357 | int fpuindex; // FPU table index 358 | int dispbytes; // Displacement bytes (0 = no displacement) 359 | int immbytes; // Immediate bytes (0 = no immediate) 360 | int sectionbytes; // Section prefix bytes (0 = no section prefix) 361 | OPERAND op1; // First operand (if any) 362 | OPERAND op2; // Second operand (if any) 363 | OPERAND op3; // Additional operand (if any) 364 | PINST ptr; // Pointer to instruction table 365 | int flags; // Instruction flags 366 | short eflags_affected; // Process eflags affected 367 | short eflags_used; // Processor eflags used by this instruction 368 | int iop_written; // mask of affected implied registers (written) 369 | int iop_read; // mask of affected implied registers (read) 370 | } INSTRUCTION, *PINSTRUCTION; 371 | 372 | 373 | // Function definitions 374 | 375 | int get_instruction( 376 | INSTRUCTION *inst, // pointer to INSTRUCTION structure 377 | BYTE *addr, // code buffer 378 | enum Mode mode // mode: MODE_32 or MODE_16 379 | ); 380 | 381 | // Get complete instruction string 382 | int get_instruction_string( 383 | INSTRUCTION *inst, // pointer to INSTRUCTION structure 384 | enum Format format, // instruction format: FORMAT_ATT or FORMAT_INTEL 385 | DWORD offset, // instruction absolute address 386 | char *string, // string buffer 387 | int length // string length 388 | ); 389 | 390 | // Get mnemonic string 391 | int get_mnemonic_string( 392 | INSTRUCTION *inst, // pointer to INSTRUCTION structure 393 | enum Format format, // instruction format: FORMAT_ATT or FORMAT_INTEL 394 | char *string, // string buffer 395 | int length // string length 396 | ); 397 | 398 | // Get individual operand string 399 | int get_operand_string( 400 | INSTRUCTION *inst, // pointer to INSTRUCTION structure 401 | POPERAND op, // pointer to OPERAND structure 402 | enum Format format, // instruction format: FORMAT_ATT or FORMAT_INTEL 403 | DWORD offset, // instruction absolute address 404 | char *string, // string buffer 405 | int length // string length 406 | ); 407 | 408 | // Helper functions 409 | 410 | int get_register_type( 411 | POPERAND op 412 | ); 413 | int get_operand_type( 414 | POPERAND op 415 | ); 416 | int get_operand_register( 417 | POPERAND op 418 | ); 419 | int get_operand_basereg( 420 | POPERAND op 421 | ); 422 | int get_operand_indexreg( 423 | POPERAND op 424 | ); 425 | int get_operand_scale( 426 | POPERAND op 427 | ); 428 | int get_operand_immediate( 429 | POPERAND op, 430 | DWORD *imm // returned immediate value 431 | ); 432 | int get_operand_displacement( 433 | POPERAND op, 434 | DWORD *disp // returned displacement value 435 | ); 436 | POPERAND get_source_operand( 437 | PINSTRUCTION inst 438 | ); 439 | POPERAND get_destination_operand( 440 | PINSTRUCTION inst 441 | ); 442 | 443 | 444 | // Instruction flags (prefixes) 445 | 446 | // Group 1 447 | #define MASK_PREFIX_G1(x) ((x) & 0xff000000) >> 24 448 | #define PREFIX_LOCK 0x01000000 // 0xf0 449 | #define PREFIX_REPNE 0x02000000 // 0xf2 450 | #define PREFIX_REP 0x03000000 // 0xf3 451 | #define PREFIX_REPE 0x03000000 // 0xf3 452 | // Group 2 453 | #define MASK_PREFIX_G2(x) ((x) & 0x00ff0000) >> 16 454 | #define PREFIX_ES_OVERRIDE 0x00010000 // 0x26 455 | #define PREFIX_CS_OVERRIDE 0x00020000 // 0x2e 456 | #define PREFIX_SS_OVERRIDE 0x00030000 // 0x36 457 | #define PREFIX_DS_OVERRIDE 0x00040000 // 0x3e 458 | #define PREFIX_FS_OVERRIDE 0x00050000 // 0x64 459 | #define PREFIX_GS_OVERRIDE 0x00060000 // 0x65 460 | // Group 3 & 4 461 | #define MASK_PREFIX_G3(x) ((x) & 0x0000ff00) >> 8 462 | #define MASK_PREFIX_OPERAND(x) ((x) & 0x00000f00) >> 8 463 | #define MASK_PREFIX_ADDR(x) ((x) & 0x0000f000) >> 12 464 | #define PREFIX_OPERAND_SIZE_OVERRIDE 0x00000100 // 0x66 465 | #define PREFIX_ADDR_SIZE_OVERRIDE 0x00001000 // 0x67 466 | 467 | // Extensions 468 | 469 | #define MASK_EXT(x) ((x) & 0x000000ff) 470 | #define EXT_G1_1 0x00000001 471 | #define EXT_G1_2 0x00000002 472 | #define EXT_G1_3 0x00000003 473 | #define EXT_G2_1 0x00000004 474 | #define EXT_G2_2 0x00000005 475 | #define EXT_G2_3 0x00000006 476 | #define EXT_G2_4 0x00000007 477 | #define EXT_G2_5 0x00000008 478 | #define EXT_G2_6 0x00000009 479 | #define EXT_G3_1 0x0000000a 480 | #define EXT_G3_2 0x0000000b 481 | #define EXT_G4 0x0000000c 482 | #define EXT_G5 0x0000000d 483 | #define EXT_G6 0x0000000e 484 | #define EXT_G7 0x0000000f 485 | #define EXT_G8 0x00000010 486 | #define EXT_G9 0x00000011 487 | #define EXT_GA 0x00000012 488 | #define EXT_GB 0x00000013 489 | #define EXT_GC 0x00000014 490 | #define EXT_GD 0x00000015 491 | #define EXT_GE 0x00000016 492 | #define EXT_GF 0x00000017 493 | #define EXT_G0 0x00000018 494 | 495 | // Extra groups for 2 and 3-byte opcodes, and FPU stuff 496 | #define EXT_T2 0x00000020 // opcode table 2 497 | #define EXT_CP 0x00000030 // co-processor 498 | 499 | // Instruction type flags 500 | 501 | #define TYPE_3 0x80000000 502 | #define MASK_TYPE_FLAGS(x) ((x) & 0xff000000) 503 | #define MASK_TYPE_VALUE(x) ((x) & 0x00ffffff) 504 | 505 | 506 | // Operand flags 507 | 508 | #define FLAGS_NONE 0 509 | 510 | // Operand Addressing Methods, from the Intel manual 511 | #define MASK_AM(x) ((x) & 0x00ff0000) 512 | #define AM_A 0x00010000 // Direct address with segment prefix 513 | #define AM_C 0x00020000 // MODRM reg field defines control register 514 | #define AM_D 0x00030000 // MODRM reg field defines debug register 515 | #define AM_E 0x00040000 // MODRM byte defines reg/memory address 516 | #define AM_G 0x00050000 // MODRM byte defines general-purpose reg 517 | #define AM_I 0x00060000 // Immediate data follows 518 | #define AM_J 0x00070000 // Immediate value is relative to EIP 519 | #define AM_M 0x00080000 // MODRM mod field can refer only to memory 520 | #define AM_O 0x00090000 // Displacement follows (without modrm/sib) 521 | #define AM_P 0x000a0000 // MODRM reg field defines MMX register 522 | #define AM_Q 0x000b0000 // MODRM defines MMX register or memory 523 | #define AM_R 0x000c0000 // MODRM mod field can only refer to register 524 | #define AM_S 0x000d0000 // MODRM reg field defines segment register 525 | #define AM_T 0x000e0000 // MODRM reg field defines test register 526 | #define AM_V 0x000f0000 // MODRM reg field defines XMM register 527 | #define AM_W 0x00100000 // MODRM defines XMM register or memory 528 | // Extra addressing modes used in this implementation 529 | #define AM_I1 0x00200000 // Immediate byte 1 encoded in instruction 530 | #define AM_REG 0x00210000 // Register encoded in instruction 531 | #define AM_IND 0x00220000 // Register indirect encoded in instruction 532 | 533 | // Operand Types, from the intel manual 534 | #define MASK_OT(x) ((x) & 0xff000000) 535 | #define OT_a 0x01000000 536 | #define OT_b 0x02000000 // always 1 byte 537 | #define OT_c 0x03000000 // byte or word, depending on operand 538 | #define OT_d 0x04000000 // double-word 539 | #define OT_q 0x05000000 // quad-word 540 | #define OT_dq 0x06000000 // double quad-word 541 | #define OT_v 0x07000000 // word or double-word, depending on operand 542 | #define OT_w 0x08000000 // always word 543 | #define OT_p 0x09000000 // 32-bit or 48-bit pointer 544 | #define OT_pi 0x0a000000 // quadword MMX register 545 | #define OT_pd 0x0b000000 // 128-bit double-precision float 546 | #define OT_ps 0x0c000000 // 128-bit single-precision float 547 | #define OT_s 0x0d000000 // 6-byte pseudo descriptor 548 | #define OT_sd 0x0e000000 // Scalar of 128-bit double-precision float 549 | #define OT_ss 0x0f000000 // Scalar of 128-bit single-precision float 550 | #define OT_si 0x10000000 // Doubleword integer register 551 | #define OT_t 0x11000000 // 80-bit packed FP data 552 | 553 | // Operand permissions 554 | #define MASK_PERMS(x) ((x) & 0x0000f000) 555 | #define P_r 0x00004000 // Read 556 | #define P_w 0x00002000 // Write 557 | #define P_x 0x00001000 // Execute 558 | 559 | // Additional operand flags 560 | #define MASK_FLAGS(x) ((x) & 0x00000f00) 561 | #define F_s 0x00000100 // sign-extend 1-byte immediate 562 | #define F_r 0x00000200 // use segment register 563 | #define F_f 0x00000400 // use FPU register 564 | 565 | // Mask 0x000000f0 unused atm 566 | 567 | // Operand register mask 568 | #define MASK_REG(x) ((x) & 0x0000000f) 569 | 570 | 571 | 572 | // MODRM byte 573 | #define MASK_MODRM_MOD(x) (((x) & 0xc0) >> 6) 574 | #define MASK_MODRM_REG(x) (((x) & 0x38) >> 3) 575 | #define MASK_MODRM_RM(x) ((x) & 0x7) 576 | 577 | // SIB byte 578 | #define MASK_SIB_SCALE(x) MASK_MODRM_MOD(x) 579 | #define MASK_SIB_INDEX(x) MASK_MODRM_REG(x) 580 | #define MASK_SIB_BASE(x) MASK_MODRM_RM(x) 581 | 582 | 583 | #ifdef __cplusplus 584 | } 585 | #endif 586 | 587 | #endif 588 | -------------------------------------------------------------------------------- /libScanHook/ntdll.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frenda/libScanHook/bffa77ac4c9428fcc633d664c44fb868d5c29623/libScanHook/ntdll.h -------------------------------------------------------------------------------- /libScanHook/ntdll.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frenda/libScanHook/bffa77ac4c9428fcc633d664c44fb868d5c29623/libScanHook/ntdll.lib -------------------------------------------------------------------------------- /libScanHook/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // libScanHook.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /libScanHook/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | 13 | 14 | 15 | // TODO: reference additional headers your program requires here 16 | -------------------------------------------------------------------------------- /libScanHook/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /libScanHook/test.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frenda/libScanHook/bffa77ac4c9428fcc633d664c44fb868d5c29623/libScanHook/test.cpp --------------------------------------------------------------------------------