├── CMakeLists.txt ├── Configure.bat ├── HookEngine ├── CMakeLists.txt ├── HookEngine.cpp ├── HookEngine.h └── HookEngine.inl ├── HookTest ├── CMakeLists.txt └── HookTest.cpp ├── README.md └── Udis86 ├── CMakeLists.txt ├── libudis86 ├── decode.c ├── decode.h ├── extern.h ├── itab.c ├── itab.h ├── syn-att.c ├── syn-intel.c ├── syn.c ├── syn.h ├── types.h ├── udint.h └── udis86.c └── udis86.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Nettitude 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without modification, 5 | # are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, 8 | # this list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # 3. Neither the name of the copyright holder nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 19 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 | # THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | cmake_minimum_required (VERSION 2.6) 30 | 31 | project(Hooking) 32 | 33 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 34 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 35 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 36 | 37 | add_subdirectory(HookTest) 38 | add_subdirectory(HookEngine) 39 | add_subdirectory(Udis86) 40 | -------------------------------------------------------------------------------- /Configure.bat: -------------------------------------------------------------------------------- 1 | @mkdir build-x86 >nul 2 | pushd build-x86 >nul 3 | cmake -G "Visual Studio 12" ..\ 4 | popd >nul 5 | 6 | @mkdir build-x64 >nul 7 | pushd build-x64 >nul 8 | cmake -G "Visual Studio 12 Win64" ..\ 9 | popd >nul -------------------------------------------------------------------------------- /HookEngine/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Nettitude 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without modification, 5 | # are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, 8 | # this list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # 3. Neither the name of the copyright holder nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 19 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 | # THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | cmake_minimum_required (VERSION 2.6) 30 | 31 | project( HookEngine ) 32 | 33 | include_directories( ${CMAKE_SOURCE_DIR}/Udis86/ ) 34 | 35 | add_library(${PROJECT_NAME} STATIC HookEngine.h HookEngine.cpp HookEngine.inl ) 36 | 37 | target_link_libraries( ${PROJECT_NAME} Udis86 ) 38 | -------------------------------------------------------------------------------- /HookEngine/HookEngine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Nettitude 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 | THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "HookEngine.h" 31 | #include "udis86.h" 32 | #include 33 | 34 | #include "HookEngine.inl" 35 | 36 | namespace nettitude 37 | { 38 | // 39 | // CriticalSection wrapper 40 | // 41 | class CriticalSection 42 | { 43 | public: 44 | CriticalSection(){ InitializeCriticalSection(&m_CS); } 45 | ~CriticalSection(){ DeleteCriticalSection(&m_CS); } 46 | 47 | void Lock() { EnterCriticalSection(&m_CS); } 48 | void Unlock() { LeaveCriticalSection(&m_CS); } 49 | private: 50 | CriticalSection(const CriticalSection&); 51 | CriticalSection& operator=(const CriticalSection&); 52 | private: 53 | CRITICAL_SECTION m_CS; 54 | }; 55 | 56 | // 57 | // Quick and dirty object to lock within scope 58 | // 59 | class ScopeLock 60 | { 61 | public: 62 | ScopeLock(CriticalSection& cs) : m_CS(cs){ m_CS.Lock(); } 63 | ~ScopeLock(){ m_CS.Unlock(); } 64 | private: 65 | ScopeLock(const ScopeLock&); 66 | ScopeLock& operator=(const ScopeLock&); 67 | private: 68 | CriticalSection& m_CS; 69 | }; 70 | 71 | 72 | typedef LPVOID(WINAPI *fpVirtualAlloc)(LPVOID, SIZE_T, DWORD, DWORD); 73 | typedef BOOL(WINAPI *fpVirtualFree)(LPVOID, SIZE_T, DWORD); 74 | typedef BOOL(WINAPI *fpVirtualProtect)(LPVOID, SIZE_T, DWORD, PDWORD); 75 | typedef SIZE_T(WINAPI *fpVirtualQuery)(LPCVOID, PMEMORY_BASIC_INFORMATION, SIZE_T); 76 | 77 | // 78 | // Number of trampolines we create during init to bounce into VirtualAlloc etc 79 | // 80 | const UINT64 InternalHookCount = 4; 81 | 82 | // 83 | // HookEngine critical section to prevent shutdown on one thread 84 | // while hooking on another 85 | // 86 | static CriticalSection g_CriticalSection; 87 | 88 | static volatile BOOL g_Initialised = FALSE; 89 | static volatile BOOL g_Initialising = FALSE; 90 | static UINT64 g_HookCount = 0; 91 | static HOOKCONTEXT* g_VirtualAllocTrampoline = NULL; 92 | static HOOKCONTEXT* g_VirtualQueryTrampoline = NULL; 93 | static HOOKCONTEXT* g_VirtualFreeTrampoline = NULL; 94 | static HOOKCONTEXT* g_VirtualProtectTrampoline = NULL; 95 | 96 | // 97 | // pointers to VirtualAlloc etc 98 | // Which are set to our trampolines on init 99 | // 100 | fpVirtualAlloc g_pVirtualAlloc = &VirtualAlloc; 101 | fpVirtualFree g_pVirtualFree = &VirtualFree; 102 | fpVirtualProtect g_pVirtualProtect = &VirtualProtect; 103 | fpVirtualQuery g_pVirtualQuery = &VirtualQuery; 104 | 105 | 106 | /** 107 | HookEngine_SetupTargetMemProtection 108 | 109 | Set the target function memory to PAGE_EXECUTE_READWRITE 110 | */ 111 | static BOOL HookEngine_SetupTargetMemProtection(LPVOID pTargetFunctionAddress, DWORD& oldProtection) 112 | { 113 | 114 | CONST SIZE_T Page = 4096; 115 | BOOL result = FALSE; 116 | 117 | if (g_pVirtualProtect(pTargetFunctionAddress, Page, PAGE_EXECUTE_READWRITE, &oldProtection)) 118 | { 119 | result = TRUE; 120 | } 121 | 122 | return result; 123 | } 124 | 125 | /** 126 | HookEngine_RestoreTargetMemProtection 127 | 128 | Restore the protection flags on the memory of the target function 129 | */ 130 | static BOOL HookEngine_RestoreTargetMemProtection(LPVOID pTargetFunctionAddress, DWORD oldProtection) 131 | { 132 | CONST SIZE_T Page = 4096; 133 | DWORD tmp = 0; 134 | BOOL result = FALSE; 135 | 136 | //adjust the protection to be RWE 137 | if (g_pVirtualProtect(pTargetFunctionAddress, Page, oldProtection, &tmp)) 138 | { 139 | result = TRUE; 140 | } 141 | 142 | return result; 143 | } 144 | 145 | 146 | /** 147 | HookEngine_Memcpy 148 | 149 | memcpy without calling memcpy 150 | */ 151 | __forceinline void HookEngine_Memcpy(LPVOID dst, LPCVOID src, SIZE_T length) 152 | { 153 | if (dst && src && length) 154 | { 155 | __movsb((unsigned char*)dst, (const unsigned char*)src, length); 156 | } 157 | } 158 | 159 | /** 160 | HookEngine_Memset 161 | 162 | memset without calling memset 163 | */ 164 | __forceinline void HookEngine_Memset(LPVOID dst, BYTE set, SIZE_T length) 165 | { 166 | if (dst && length) 167 | { 168 | __stosb((unsigned char*)dst, set, length); 169 | } 170 | } 171 | 172 | /** 173 | HookEngine_Disassemble 174 | 175 | Obtain the minimum number of instruction bytes that need to be copied 176 | from the target function, in order to accomodate our jump instruction 177 | */ 178 | static DWORD HookEngine_Disassemble(DWORD cbRequired, LPVOID pTargetFunctionAddress, DISASSEMBLY_DATA& DisassemblyData ) 179 | { 180 | CONST SIZE_T Page = 4096; 181 | 182 | ud_t ud_obj = { 0 }; 183 | ud_init(&ud_obj); 184 | #if defined(_M_IX86) 185 | ud_set_mode(&ud_obj, 32); 186 | #elif defined(_M_X64) 187 | ud_set_mode(&ud_obj, 64); 188 | #else 189 | #error Unsuported platform 190 | #endif 191 | ud_set_pc(&ud_obj, uint64_t(pTargetFunctionAddress)); 192 | ud_set_vendor(&ud_obj, UD_VENDOR_INTEL); 193 | ud_set_input_buffer(&ud_obj, (unsigned char*)pTargetFunctionAddress, Page); 194 | 195 | DWORD instrlen = 0; 196 | 197 | DisassemblyData.Count = 0; 198 | DisassemblyData.Length = 0; 199 | 200 | HookEngine_Memset(DisassemblyData.Instructions, 0, sizeof(DisassemblyData.Instructions)); 201 | HookEngine_Memset(DisassemblyData.InstuctionBuffer, 0, sizeof(DisassemblyData.InstuctionBuffer)); 202 | HookEngine_Memset(DisassemblyData.InstructionLengths, 0, sizeof(DisassemblyData.InstructionLengths)); 203 | 204 | do 205 | { 206 | instrlen = ud_disassemble(&ud_obj); 207 | 208 | if (instrlen) 209 | { 210 | if ((DisassemblyData.Length + instrlen) < MAX_INSTRUCTION_BUFFER) 211 | { 212 | DisassemblyData.Instructions[DisassemblyData.Count] = ud_obj; 213 | DisassemblyData.InstructionLengths[DisassemblyData.Count] = instrlen; 214 | DisassemblyData.Count++; 215 | HookEngine_Memcpy(&DisassemblyData.InstuctionBuffer[DisassemblyData.Length], ((BYTE*)pTargetFunctionAddress) + DisassemblyData.Length, instrlen); 216 | DisassemblyData.Length += instrlen; 217 | } 218 | } 219 | 220 | } while (DisassemblyData.Length < cbRequired && 221 | DisassemblyData.Count < MAX_INSTRUCTIONS && 222 | instrlen != 0); 223 | 224 | return DisassemblyData.Length; 225 | } 226 | 227 | /** 228 | HookEngine_IsJump(ud_mnemonic_code) 229 | */ 230 | BOOL HookEngine_IsJump(ud_mnemonic_code code) 231 | { 232 | switch (code) 233 | { 234 | case UD_Ija: 235 | case UD_Ijae: 236 | case UD_Ijb: 237 | case UD_Ijbe: 238 | case UD_Ijcxz: 239 | case UD_Ijecxz: 240 | case UD_Ijg: 241 | case UD_Ijge: 242 | case UD_Ijl: 243 | case UD_Ijle: 244 | case UD_Ijmp: 245 | case UD_Ijno: 246 | case UD_Ijnp: 247 | case UD_Ijns: 248 | case UD_Ijnz: 249 | case UD_Ijo: 250 | case UD_Ijp: 251 | case UD_Ijrcxz: 252 | case UD_Ijs: 253 | case UD_Ijz: 254 | return TRUE; 255 | } 256 | 257 | return FALSE; 258 | } 259 | 260 | /** 261 | HookEngine_IsRet(ud_mnemonic_code) 262 | */ 263 | BOOL HookEngine_IsRet(ud_mnemonic_code code) 264 | { 265 | switch (code) 266 | { 267 | case UD_Iret: 268 | case UD_Iretf: 269 | return TRUE; 270 | } 271 | 272 | return FALSE; 273 | } 274 | 275 | /** 276 | HookEngine_AllocateContextWithin2GB 277 | 278 | Try and allocate a context, within 2GB of the target function 279 | return NULL if the memory cannot be allocated. 280 | */ 281 | static HOOKCONTEXT_INTERNAL* HookEngine_AllocateContextWithin2GB(DWORD contextSize, UINT_PTR pTargetFunction) 282 | { 283 | CONST UINT_PTR twoGB = 0x7FFFFFFF; 284 | CONST SIZE_T Page = 4096; 285 | UINT_PTR currentAddress = pTargetFunction; 286 | UINT_PTR maxAddress = pTargetFunction + twoGB - Page; 287 | UINT_PTR minAddress = pTargetFunction - twoGB + Page; 288 | MEMORY_BASIC_INFORMATION memInfo = { 0 }; 289 | HOOKCONTEXT_INTERNAL* pResult = NULL; 290 | 291 | 292 | while (currentAddressminAddress) 323 | { 324 | if (g_pVirtualQuery((LPVOID)currentAddress, &memInfo, contextSize)) 325 | { 326 | //if this is unallocated, then try and allocate it... 327 | if (memInfo.State == MEM_FREE) 328 | { 329 | pResult = (HOOKCONTEXT_INTERNAL*)g_pVirtualAlloc((LPVOID)currentAddress, contextSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 330 | 331 | if (pResult) 332 | { 333 | //early out 334 | return pResult; 335 | } 336 | } 337 | 338 | currentAddress -= memInfo.RegionSize; 339 | 340 | } 341 | else 342 | { 343 | currentAddress -= Page; 344 | } 345 | 346 | } 347 | 348 | 349 | return pResult; 350 | } 351 | 352 | /** 353 | HookEngine_AllocateContext 354 | 355 | Allocates a context that can be anywhere in user space 356 | */ 357 | static HOOKCONTEXT_INTERNAL* HookEngine_AllocateContext(DWORD contextSize) 358 | { 359 | CONST SIZE_T Page = 4096; 360 | HOOKCONTEXT_INTERNAL* pResult = (HOOKCONTEXT_INTERNAL*)g_pVirtualAlloc(NULL, contextSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 361 | return pResult; 362 | } 363 | 364 | 365 | /** 366 | HookEngine_AllocateContext 367 | 368 | Allocates a context that can be anywhere in user space 369 | */ 370 | static VOID HookEngine_FreeContext(HOOKCONTEXT_INTERNAL* pContext) 371 | { 372 | HOOKCONTEXT_INTERNAL* pResult = (HOOKCONTEXT_INTERNAL*)g_pVirtualFree(pContext, pContext->cbSize, MEM_RELEASE); 373 | } 374 | 375 | /** 376 | HookEngine_RelativeJumpOffset32 377 | 378 | calculate the relative jump offset from src function to dst function 379 | */ 380 | __forceinline INT32 HookEngine_RelativeJumpOffset32(UINT_PTR src, UINT_PTR dst) 381 | { 382 | UINT_PTR ret = max(src, dst) - min(src, dst); 383 | 384 | if (src < dst) 385 | { 386 | return (INT32)ret - (INT32)sizeof(JMP_INSTR_86); 387 | } 388 | 389 | return -((INT32)ret + (INT32)sizeof(JMP_INSTR_86)); 390 | } 391 | 392 | BOOL IsInitialised() 393 | { 394 | return g_Initialised; 395 | } 396 | 397 | BOOL IsInitialising() 398 | { 399 | return g_Initialising; 400 | } 401 | } 402 | 403 | using namespace nettitude; 404 | 405 | /************************************************************************** 406 | * 407 | * HookEngine_Init 408 | * 409 | ***************************************************************************/ 410 | extern "C" HOOKRESULT HookEngine_Init() 411 | { 412 | ScopeLock lock(g_CriticalSection); 413 | 414 | if (g_Initialising) 415 | { 416 | return HOOK_ERROR; 417 | } 418 | 419 | if (g_Initialised) 420 | { 421 | return HOOK_SUCCESS; 422 | } 423 | 424 | g_Initialising = TRUE; 425 | 426 | if (HOOK_SUCCESS == HookEngine_InstallHook(&VirtualProtect, NULL, &g_VirtualProtectTrampoline)) 427 | { 428 | if (HOOK_SUCCESS == HookEngine_InstallHook(&VirtualAlloc, NULL, &g_VirtualAllocTrampoline)) 429 | { 430 | if (HOOK_SUCCESS == HookEngine_InstallHook(&VirtualQuery, NULL, &g_VirtualQueryTrampoline)) 431 | { 432 | if (HOOK_SUCCESS == HookEngine_InstallHook(&VirtualFree, NULL, &g_VirtualFreeTrampoline)) 433 | { 434 | g_pVirtualAlloc = (fpVirtualAlloc)g_VirtualAllocTrampoline->pTrampoline; 435 | g_pVirtualQuery = (fpVirtualQuery)g_VirtualQueryTrampoline->pTrampoline; 436 | g_pVirtualFree = (fpVirtualFree)g_VirtualFreeTrampoline->pTrampoline; 437 | g_pVirtualProtect = (fpVirtualProtect)g_VirtualProtectTrampoline->pTrampoline; 438 | 439 | g_Initialised = TRUE; 440 | g_Initialising = FALSE; 441 | return HOOK_SUCCESS; 442 | } 443 | } 444 | } 445 | } 446 | 447 | //set the function pointers back to the original 448 | g_pVirtualAlloc = &VirtualAlloc; 449 | g_pVirtualQuery = &VirtualQuery; 450 | g_pVirtualFree = &VirtualFree; 451 | g_pVirtualProtect = &VirtualProtect; 452 | 453 | if (g_VirtualAllocTrampoline) 454 | { 455 | HookEngine_RemoveHook(g_VirtualAllocTrampoline); 456 | } 457 | 458 | if (g_VirtualQueryTrampoline) 459 | { 460 | HookEngine_RemoveHook(g_VirtualQueryTrampoline); 461 | } 462 | 463 | if (g_VirtualFreeTrampoline) 464 | { 465 | HookEngine_RemoveHook(g_VirtualFreeTrampoline); 466 | } 467 | 468 | if (g_VirtualProtectTrampoline) 469 | { 470 | HookEngine_RemoveHook(g_VirtualFreeTrampoline); 471 | } 472 | 473 | g_Initialised = FALSE; 474 | g_Initialising = FALSE; 475 | 476 | return HOOK_ERROR; 477 | } 478 | 479 | 480 | /************************************************************************** 481 | * 482 | * HookEngine_Shutdown 483 | * 484 | ***************************************************************************/ 485 | extern "C" HOOKRESULT HookEngine_Shutdown() 486 | { 487 | ScopeLock lock(g_CriticalSection); 488 | 489 | if (g_Initialising) 490 | { 491 | return HOOK_ERROR; 492 | } 493 | 494 | if (FALSE == g_Initialised) 495 | { 496 | return HOOK_SUCCESS; 497 | } 498 | 499 | if (g_HookCount == InternalHookCount) 500 | { 501 | //set the function pointers back to the original 502 | g_pVirtualAlloc = &VirtualAlloc; 503 | g_pVirtualQuery = &VirtualQuery; 504 | g_pVirtualFree = &VirtualFree; 505 | g_pVirtualProtect = &VirtualProtect; 506 | 507 | if (g_VirtualAllocTrampoline) 508 | { 509 | HookEngine_RemoveHook(g_VirtualAllocTrampoline); 510 | } 511 | 512 | if (g_VirtualQueryTrampoline) 513 | { 514 | HookEngine_RemoveHook(g_VirtualQueryTrampoline); 515 | } 516 | 517 | if (g_VirtualFreeTrampoline) 518 | { 519 | HookEngine_RemoveHook(g_VirtualFreeTrampoline); 520 | } 521 | 522 | if (g_VirtualProtectTrampoline) 523 | { 524 | HookEngine_RemoveHook(g_VirtualFreeTrampoline); 525 | } 526 | 527 | g_Initialised = FALSE; 528 | g_Initialising = FALSE; 529 | 530 | return HOOK_SUCCESS; 531 | } 532 | 533 | return HOOK_ERROR_STILL_HOOKED; 534 | } 535 | 536 | /************************************************************************** 537 | * 538 | * HookEngine_InstallHook 539 | * 540 | ***************************************************************************/ 541 | extern "C" HOOKRESULT HookEngine_InstallHook 542 | ( 543 | IN LPVOID pTargetFunctionAddress, 544 | IN OPTIONAL LPVOID pUserFunctionAddress, 545 | OUT PHOOKCONTEXT* ppHookCtx 546 | ) 547 | { 548 | 549 | //Critical sections can be recursivley locked on the same thread 550 | ScopeLock lock(g_CriticalSection); 551 | 552 | #if defined(_M_IX86) 553 | JMP_INSTR_86 jmp = { JMP_INSTRUCTION, 0 }; 554 | JMP_TRAMPOLINE_INSTR_86 jmptramp = { 0 }; 555 | JMP_TRAMPOLINE_INSTR_86 jmpredir = { 0 }; 556 | #elif defined(_M_X64) 557 | 558 | JMP_INSTR_64 jmp = { JMP_INSTRUCTION, 0 }; 559 | JMP_TRAMPOLINE_INSTR_64 jmpredir = { 0 }; 560 | JMP_TRAMPOLINE_INSTR_64 jmptramp = { 0 }; 561 | #else 562 | #error Unsupported platform 563 | #endif 564 | 565 | if (FALSE == IsInitialised() && FALSE == IsInitialising() ) 566 | { 567 | return HOOK_ERROR_NOT_INITIALISED; 568 | } 569 | 570 | HOOKRESULT result = HOOK_ERROR_INVALID_PARAMETER; 571 | SIZE_T contextSize = 0; 572 | HOOKCONTEXT_INTERNAL* pCtx = NULL; 573 | 574 | if ( 575 | pTargetFunctionAddress && 576 | ppHookCtx 577 | ) 578 | { 579 | DWORD oldTargetMemProtection = 0; 580 | 581 | if (HookEngine_SetupTargetMemProtection(pTargetFunctionAddress, oldTargetMemProtection)) 582 | { 583 | DISASSEMBLY_DATA DisasmData = { 0 }; 584 | 585 | //disassemble some of the function to locate some space for a jump location 586 | CONST DWORD cbRequired = (DWORD)sizeof(jmp); 587 | DWORD cbLength = HookEngine_Disassemble((DWORD)sizeof(jmp), pTargetFunctionAddress, DisasmData); 588 | 589 | 590 | if (cbLength >= cbRequired) 591 | { 592 | //if it's a ret, abort 593 | if (HookEngine_IsRet(DisasmData.Instructions[0].mnemonic)) 594 | { 595 | result = HOOK_ERROR_DISASSEMBLE; 596 | } 597 | 598 | //this number of bytes will be copied into the trampoline... 599 | DWORD contextSize = sizeof(HOOKCONTEXT_INTERNAL)+ 600 | (DisasmData.Length * 2) + 601 | (STUB_PADDING_BYTES * 2) + 602 | sizeof(jmptramp)+ 603 | sizeof(jmpredir); 604 | 605 | //if a user callback function was specified, we need to make the redirector address 606 | //within a 2GB window of the target function, otherwise any memory will do 607 | if (pUserFunctionAddress) 608 | { 609 | pCtx = HookEngine_AllocateContextWithin2GB((DWORD)contextSize, (UINT_PTR)pTargetFunctionAddress); 610 | 611 | } 612 | else 613 | { 614 | pCtx = HookEngine_AllocateContext((DWORD)contextSize); 615 | } 616 | 617 | if (pCtx) 618 | { 619 | try 620 | { 621 | //clear struct with int3 622 | HookEngine_Memset(pCtx, INT3_INSTRUCTION, contextSize); 623 | 624 | //setup the context + trampoline 625 | pCtx->cbSavedInstructions = DisasmData.Length; 626 | pCtx->cbTrampoline = DisasmData.Length + sizeof(jmptramp); 627 | pCtx->cbRedirect = sizeof(jmpredir); 628 | pCtx->cbSize = (DWORD)contextSize; 629 | 630 | //setup pointers 631 | if (pUserFunctionAddress) 632 | { 633 | pCtx->pbSavedInstructions = (PBYTE)(pCtx + 1); 634 | pCtx->pbRedirect = (PBYTE)(pCtx + 1) + DisasmData.Length + STUB_PADDING_BYTES; 635 | 636 | //keep a full copy original bytes 637 | HookEngine_Memcpy(pCtx->pbSavedInstructions, DisasmData.InstuctionBuffer, DisasmData.Length); 638 | } 639 | else 640 | { 641 | pCtx->pbSavedInstructions = NULL; 642 | pCtx->pbRedirect = NULL; 643 | } 644 | 645 | pCtx->pbTrampoline = (PBYTE)(pCtx + 1) + 646 | pCtx->cbSavedInstructions + 647 | pCtx->cbRedirect + 648 | (STUB_PADDING_BYTES * 2); 649 | 650 | pCtx->Context.pTargetFunctionAddress = pTargetFunctionAddress; 651 | pCtx->Context.pUserFunctionAddress = pUserFunctionAddress; 652 | pCtx->Context.pTrampoline = pCtx->pbTrampoline; 653 | 654 | 655 | 656 | if (HookEngine_IsJump(DisasmData.Instructions[0].mnemonic) && 657 | DisasmData.InstructionLengths[0] >= cbRequired) 658 | { 659 | //get the relative offset of the jmp and create a trampoline that jumps to 660 | //that address 661 | const ud_operand& operand = DisasmData.Instructions[0].operand[0]; 662 | UINT_PTR address = 0; 663 | 664 | if (operand.type == UD_OP_JIMM) 665 | { 666 | switch (operand.size) 667 | { 668 | case 8: 669 | address = (UINT_PTR)pTargetFunctionAddress + (UINT_PTR)(DisasmData.Instructions[0].pc + operand.lval.sbyte) - DisasmData.InstructionLengths[0]; 670 | case 16: 671 | address = (UINT_PTR)pTargetFunctionAddress + (UINT_PTR)(DisasmData.Instructions[0].pc + operand.lval.sword) - DisasmData.InstructionLengths[0]; 672 | case 32: 673 | address = (UINT_PTR)pTargetFunctionAddress + (UINT_PTR)(DisasmData.Instructions[0].pc + operand.lval.sdword) - DisasmData.InstructionLengths[0]; 674 | } 675 | } 676 | else if (operand.type == UD_OP_MEM) 677 | { 678 | if (operand.base == UD_R_RIP && 679 | operand.index == UD_NONE && 680 | operand.scale == 0) 681 | { 682 | UINT_PTR* pAddr = (UINT_PTR*)((BYTE*)DisasmData.Instructions[0].pc + operand.lval.sdword); 683 | address = *pAddr; 684 | } 685 | else if (operand.base == UD_NONE && 686 | operand.index == UD_NONE && 687 | operand.scale == 0) 688 | { 689 | UINT_PTR* pAddr = (UINT_PTR*)(operand.lval.uqword); 690 | address = *pAddr; 691 | } 692 | } 693 | 694 | if (address != 0) 695 | { 696 | //make a trampoline that jumps to the address 697 | /************************************************************************** 698 | * 699 | * X86 700 | * 701 | ***************************************************************************/ 702 | #if defined(_M_IX86) 703 | // 704 | // Setup redirect and target function jump, only if a user function was specified 705 | // 706 | if (pUserFunctionAddress) 707 | { 708 | //setup the redirector which jumps to the user function 709 | HookEngine_Memcpy(&jmpredir, X86_TRAMPOLINE_INSTRUCTIONS, sizeof(X86_TRAMPOLINE_INSTRUCTIONS)); 710 | jmpredir.target = (UINT32)pUserFunctionAddress; 711 | 712 | //setup the jmp instruction that jumps to the redirector 713 | jmp.target = HookEngine_RelativeJumpOffset32((UINT_PTR)pTargetFunctionAddress, (UINT_PTR)pCtx->pbRedirect); 714 | } 715 | 716 | UINT_PTR pTarget = (UINT_PTR)pTargetFunctionAddress + (UINT_PTR)sizeof(jmp); 717 | 718 | //setup the trampoline 719 | HookEngine_Memcpy(&jmptramp, X86_TRAMPOLINE_INSTRUCTIONS, sizeof(X86_TRAMPOLINE_INSTRUCTIONS)); 720 | jmptramp.target = ((UINT32)address); 721 | 722 | #elif defined(_M_X64) 723 | /************************************************************************** 724 | * 725 | * X64 726 | * 727 | ***************************************************************************/ 728 | 729 | // Setup redirect and target function jump, only if a user function was specified 730 | // 731 | if (pUserFunctionAddress) 732 | { 733 | //setup the redirector which jumps to the user function 734 | HookEngine_Memcpy(&jmpredir, X64_TRAMPOLINE_INSTRUCTIONS, sizeof(X64_TRAMPOLINE_INSTRUCTIONS)); 735 | jmpredir.hiaddr = (UINT32)((UINT_PTR)pUserFunctionAddress >> 32); 736 | jmpredir.loaddr = (UINT32)((UINT_PTR)pUserFunctionAddress); 737 | 738 | //setup the jmp instruction that jumps to the redirector 739 | jmp.target = HookEngine_RelativeJumpOffset32((UINT_PTR)pTargetFunctionAddress, (UINT_PTR)pCtx->pbRedirect); 740 | } 741 | 742 | //setup the trampoline 743 | UINT_PTR pTarget = (UINT_PTR)pTargetFunctionAddress + (UINT_PTR)sizeof(jmp); 744 | HookEngine_Memcpy(&jmptramp, X64_TRAMPOLINE_INSTRUCTIONS, sizeof(X64_TRAMPOLINE_INSTRUCTIONS)); 745 | jmptramp.hiaddr = (UINT32)((UINT_PTR)address >> 32); 746 | jmptramp.loaddr = (UINT32)((UINT_PTR)address); 747 | #else 748 | /************************************************************************** 749 | * 750 | * Platform unsupported 751 | * 752 | ***************************************************************************/ 753 | 754 | #error Unsupported platform 755 | #endif 756 | //Copy the trampoline instructions into the trampoline area 757 | HookEngine_Memcpy(&pCtx->pbTrampoline[0], &jmptramp, sizeof(jmptramp)); 758 | 759 | // 760 | // If a user function was specified then install the jmp in the target 761 | // 762 | if (pUserFunctionAddress) 763 | { 764 | //copy redirect 765 | HookEngine_Memcpy(pCtx->pbRedirect, &jmpredir, sizeof(jmpredir)); 766 | 767 | //copy jump into the target function 768 | HookEngine_Memcpy(pTargetFunctionAddress, &jmp, sizeof(jmp)); 769 | 770 | //any remaining instructions of the target should be nop's 771 | DWORD remain = DisasmData.Length - sizeof(jmp); 772 | 773 | if (remain) 774 | { 775 | HookEngine_Memset((((PBYTE)pTargetFunctionAddress) + sizeof(jmp)), NOP_INSTRUCTION, remain); 776 | } 777 | } 778 | 779 | *ppHookCtx = &pCtx->Context; 780 | 781 | ++g_HookCount; 782 | 783 | result = HOOK_SUCCESS; 784 | } 785 | else 786 | { 787 | HookEngine_FreeContext(pCtx); 788 | result = HOOK_ERROR_DISASSEMBLE; 789 | } 790 | } 791 | else 792 | { 793 | //Copy instructions into the trampoline 794 | HookEngine_Memcpy(pCtx->pbTrampoline, DisasmData.InstuctionBuffer, DisasmData.Length); 795 | 796 | //setup the jump data 797 | 798 | /************************************************************************** 799 | * 800 | * X86 801 | * 802 | ***************************************************************************/ 803 | #if defined(_M_IX86) 804 | // 805 | // Setup redirect and target function jump, only if a user function was specified 806 | // 807 | if (pUserFunctionAddress) 808 | { 809 | //setup the redirector which jumps to the user function 810 | HookEngine_Memcpy(&jmpredir, X86_TRAMPOLINE_INSTRUCTIONS, sizeof(X86_TRAMPOLINE_INSTRUCTIONS)); 811 | jmpredir.target = (UINT32)pUserFunctionAddress; 812 | 813 | //setup the jmp instruction that jumps to the redirector 814 | jmp.target = HookEngine_RelativeJumpOffset32((UINT_PTR)pTargetFunctionAddress, (UINT_PTR)pCtx->pbRedirect); 815 | } 816 | 817 | UINT_PTR pTarget = (UINT_PTR)pTargetFunctionAddress + (UINT_PTR)sizeof(jmp); 818 | 819 | //setup the trampoline 820 | HookEngine_Memcpy(&jmptramp, X86_TRAMPOLINE_INSTRUCTIONS, sizeof(X86_TRAMPOLINE_INSTRUCTIONS)); 821 | jmptramp.target = ((UINT32)pTarget); 822 | 823 | #elif defined(_M_X64) 824 | /************************************************************************** 825 | * 826 | * X64 827 | * 828 | ***************************************************************************/ 829 | 830 | // Setup redirect and target function jump, only if a user function was specified 831 | // 832 | if (pUserFunctionAddress) 833 | { 834 | //setup the redirector which jumps to the user function 835 | HookEngine_Memcpy(&jmpredir, X64_TRAMPOLINE_INSTRUCTIONS, sizeof(X64_TRAMPOLINE_INSTRUCTIONS)); 836 | jmpredir.hiaddr = (UINT32)((UINT_PTR)pUserFunctionAddress >> 32); 837 | jmpredir.loaddr = (UINT32)((UINT_PTR)pUserFunctionAddress); 838 | 839 | //setup the jmp instruction that jumps to the redirector 840 | jmp.target = HookEngine_RelativeJumpOffset32((UINT_PTR)pTargetFunctionAddress, (UINT_PTR)pCtx->pbRedirect); 841 | } 842 | 843 | //setup the trampoline 844 | UINT_PTR pTarget = (UINT_PTR)pTargetFunctionAddress + (UINT_PTR)sizeof(jmp); 845 | HookEngine_Memcpy(&jmptramp, X64_TRAMPOLINE_INSTRUCTIONS, sizeof(X64_TRAMPOLINE_INSTRUCTIONS)); 846 | jmptramp.hiaddr = (UINT32)((UINT_PTR)pTarget >> 32); 847 | jmptramp.loaddr = (UINT32)((UINT_PTR)pTarget); 848 | #else 849 | /************************************************************************** 850 | * 851 | * Platform unsupported 852 | * 853 | ***************************************************************************/ 854 | 855 | #error Unsupported platform 856 | #endif 857 | 858 | //Copy the trampoline instructions into the trampoline area 859 | HookEngine_Memcpy(&pCtx->pbTrampoline[DisasmData.Length], &jmptramp, sizeof(jmptramp)); 860 | 861 | // 862 | // If a user function was specified then install the jmp in the target 863 | // 864 | if (pUserFunctionAddress) 865 | { 866 | //copy redirect 867 | HookEngine_Memcpy(pCtx->pbRedirect, &jmpredir, sizeof(jmpredir)); 868 | 869 | //copy jump into the target function 870 | HookEngine_Memcpy(pTargetFunctionAddress, &jmp, sizeof(jmp)); 871 | 872 | //any remaining instructions of the target should be nop's 873 | DWORD remain = DisasmData.Length - sizeof(jmp); 874 | 875 | if (remain) 876 | { 877 | HookEngine_Memset((((PBYTE)pTargetFunctionAddress) + sizeof(jmp)), NOP_INSTRUCTION, remain); 878 | } 879 | } 880 | 881 | *ppHookCtx = &pCtx->Context; 882 | 883 | ++g_HookCount; 884 | 885 | result = HOOK_SUCCESS; 886 | 887 | } 888 | 889 | }//try 890 | catch (...) 891 | { 892 | result = HOOK_ERROR_EXCEPTION_RAISED; 893 | } 894 | 895 | }//if 896 | else 897 | { 898 | result = HOOK_ERROR_OUT_OF_MEMORY; 899 | } 900 | 901 | } 902 | else 903 | { 904 | result = HOOK_ERROR_DISASSEMBLE; 905 | } 906 | 907 | //restore original protection 908 | HookEngine_RestoreTargetMemProtection(pTargetFunctionAddress, oldTargetMemProtection); 909 | } 910 | else 911 | { 912 | result = HOOK_ERROR_MEMORY_PROTECT; 913 | } 914 | 915 | } 916 | 917 | return result; 918 | } 919 | 920 | /************************************************************************** 921 | * 922 | * HookEngine_RemoveHook 923 | * 924 | ***************************************************************************/ 925 | extern "C" HOOKRESULT HookEngine_RemoveHook 926 | ( 927 | IN PHOOKCONTEXT pHookCtx 928 | ) 929 | { 930 | //Critical sections can be recursivley locked on the same thread 931 | ScopeLock lock(g_CriticalSection); 932 | 933 | CONST DWORD SensibleMax = 64; 934 | HOOKRESULT result = HOOK_ERROR_INVALID_PARAMETER; 935 | HOOKCONTEXT_INTERNAL* pInternal = (HOOKCONTEXT_INTERNAL*)pHookCtx; 936 | 937 | if (FALSE == IsInitialised() && FALSE == IsInitialising()) 938 | { 939 | return HOOK_ERROR_NOT_INITIALISED; 940 | } 941 | 942 | if (pInternal) 943 | { 944 | //copy function bytes back over the top of the original function 945 | if (pInternal->Context.pTargetFunctionAddress && 946 | pInternal->pbSavedInstructions && 947 | pInternal->cbSavedInstructions && 948 | pInternal->cbSavedInstructions < SensibleMax ) 949 | { 950 | DWORD oldTargetMemProtection = 0; 951 | 952 | if (HookEngine_SetupTargetMemProtection(pInternal->Context.pTargetFunctionAddress, oldTargetMemProtection)) 953 | { 954 | if (pInternal->pbRedirect && pInternal->pbSavedInstructions) 955 | { 956 | HookEngine_Memcpy(pInternal->Context.pTargetFunctionAddress, pInternal->pbSavedInstructions, pInternal->cbSavedInstructions); 957 | } 958 | 959 | HookEngine_RestoreTargetMemProtection(pInternal->Context.pTargetFunctionAddress, oldTargetMemProtection); 960 | HookEngine_FreeContext( pInternal ); 961 | --g_HookCount; 962 | result = HOOK_SUCCESS; 963 | } 964 | else 965 | { 966 | result = HOOK_ERROR_MEMORY_PROTECT; 967 | } 968 | } 969 | } 970 | 971 | return result; 972 | } 973 | 974 | 975 | -------------------------------------------------------------------------------- /HookEngine/HookEngine.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Nettitude 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 | THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef __HOOKENGINE_H__ 31 | #define __HOOKENGINE_H__ 32 | 33 | #include 34 | 35 | #if defined(__cplusplus) 36 | extern "C" { 37 | #endif 38 | 39 | typedef HRESULT HOOKRESULT; 40 | 41 | 42 | #define HOOK_SUCCESS ((HOOKRESULT)(S_OK)) 43 | #define HOOK_ERROR ((HOOKRESULT)(-1)) //General error 44 | #define HOOK_ERROR_INVALID_PARAMETER ((HOOKRESULT)(-2)) //Invalid parameter specified to function call 45 | #define HOOK_ERROR_OUT_OF_MEMORY ((HOOKRESULT)(-3)) //Could not allocate context memory 46 | #define HOOK_ERROR_DISASSEMBLE ((HOOKRESULT)(-4)) //Error disassembling function bytes 47 | #define HOOK_ERROR_MEMORY_PROTECT ((HOOKRESULT)(-5)) //Could not set memory protection flags on target 48 | #define HOOK_ERROR_STILL_HOOKED ((HOOKRESULT)(-6)) //Hook still remains, on shutdown 49 | #define HOOK_ERROR_NOT_INITIALISED ((HOOKRESULT)(-7)) //Hook engine not initialised 50 | #define HOOK_ERROR_EXCEPTION_RAISED ((HOOKRESULT)(-8)) //Exception was reaised 51 | 52 | /** 53 | * Install a hook at the target function location 54 | * the hook will call pUserFunctionAddress 55 | * it is up to the user to call the trampoline if required 56 | */ 57 | typedef struct HOOKCONTEXT_TAG 58 | { 59 | LPVOID pTargetFunctionAddress; 60 | LPVOID pUserFunctionAddress; 61 | LPVOID pTrampoline; 62 | 63 | /* Opaque structure */ 64 | 65 | }HOOKCONTEXT, *PHOOKCONTEXT; 66 | 67 | /** 68 | * HookEngine_Init 69 | * 70 | * Initialise the hooking engine. A corresponding call to 71 | * HookEngine_Shutdown must be made 72 | */ 73 | HOOKRESULT HookEngine_Init(); 74 | 75 | /** 76 | * HookEngine_Shutdown 77 | * 78 | * Shutdown the hooking engine. Installed hooks must still be 79 | * manually removed first with HookEngine_RemoveHook 80 | */ 81 | HOOKRESULT HookEngine_Shutdown(); 82 | 83 | 84 | /** 85 | * Install a hook at the target function location 86 | * the hook will call pUserFunctionAddress and it is then 87 | * up to the user function to call the trampoline if required. 88 | * 89 | * ppHookCtx is allocated and is an opaque structure, in that it 90 | * may be larger than HOOKCONTEXT 91 | * 92 | * pTargetFunctionAddress The target function to hook 93 | * 94 | * pUserFunctionAddress Optional user callback address. 95 | * If NULL is specified then a trampoline is built but the function is 96 | * not hooked. The trampoline can be used to call the function 97 | * if it is subsequently hooked elsewhere. 98 | * 99 | * ppHookCtx pointer to a context that contains information about the hook 100 | * HookEngine_RemoveHook must be called to release the context and 101 | * remove any hook 102 | */ 103 | HOOKRESULT HookEngine_InstallHook 104 | ( 105 | IN LPVOID pTargetFunctionAddress, 106 | IN OPTIONAL LPVOID pUserFunctionAddress, 107 | OUT PHOOKCONTEXT* ppHookCtx 108 | ); 109 | 110 | 111 | /** 112 | * Remove hook and release memory allocated to pHookCtx 113 | * pHookCtx is not valid after this call 114 | */ 115 | HOOKRESULT HookEngine_RemoveHook 116 | ( 117 | IN PHOOKCONTEXT pHookCtx 118 | ); 119 | 120 | 121 | #if defined(__cplusplus) 122 | } 123 | #endif 124 | 125 | 126 | #endif //__HOOKENGINE_H__ -------------------------------------------------------------------------------- /HookEngine/HookEngine.inl: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Nettitude 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 | THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef __HOOKENGINEINL_H__ 31 | #define __HOOKENGINEINL_H__ 32 | 33 | 34 | namespace nettitude 35 | { 36 | const DWORD MAX_THREADS = 255; //arbitrary max thread count... 37 | const BYTE NOP_INSTRUCTION = 0x90; //nop 38 | const BYTE JMP_INSTRUCTION = 0xE9; //jmp 39 | const BYTE INT3_INSTRUCTION = 0xCC; 40 | const UINT32 STUB_PADDING_BYTES = 8; //size of area filled with int3 41 | 42 | const UINT32 MAX_INSTRUCTIONS = 6; 43 | const UINT32 MAX_INSTRUCTION_LEN = 15; 44 | const UINT32 MAX_INSTRUCTION_BUFFER = MAX_INSTRUCTION_LEN * MAX_INSTRUCTIONS; 45 | 46 | struct DISASSEMBLY_DATA 47 | { 48 | DWORD Count; 49 | DWORD Length; 50 | DWORD InstructionLengths[MAX_INSTRUCTIONS]; 51 | struct ud Instructions[MAX_INSTRUCTIONS]; 52 | BYTE InstuctionBuffer[MAX_INSTRUCTION_BUFFER]; 53 | }; 54 | 55 | //make sure that these structures are not padded. 56 | #pragma pack(push,1) 57 | /** 58 | JMP_INSTR_86 59 | 60 | x86 Structure containing the instructions for a relative jump 61 | */ 62 | struct JMP_INSTR_86 63 | { 64 | BYTE jmp; 65 | INT32 target; //relative target address 66 | }; 67 | 68 | /** 69 | JMP_TRAMPOLINE_INSTR_86 70 | 71 | x86 Structure containing the instructions for a direct jump 72 | used by the trampoline and the redirect stub 73 | */ 74 | struct JMP_TRAMPOLINE_INSTR_86 75 | { 76 | BYTE push; 77 | BYTE mov; 78 | INT32 target; 79 | BYTE xcgh[3]; 80 | BYTE ret; 81 | }; 82 | 83 | 84 | const BYTE X86_TRAMPOLINE_INSTRUCTIONS[] = 85 | { 0x50, //push eax 86 | 0xB8, 0xAA, 0xAA, 0xAA, 0xAA, //mov eax, 0xAAAAAAAA 87 | 0x87, 0x04, 0x24, //xchg eax, dword ptr[esp] 88 | 0xC3 }; //ret 89 | 90 | 91 | /** 92 | JMP_INSTR_64 93 | 94 | x64 Structure containing the instructions for a relative jump 95 | used by the trampoline and the redirect stub 96 | */ 97 | struct JMP_INSTR_64 98 | { 99 | BYTE jmp; 100 | INT32 target; 101 | }; 102 | 103 | /** 104 | JMP_TRAMPOLINE_INSTR_64 105 | 106 | x64 Structure containing the instructions for a direct jump 107 | */ 108 | struct JMP_TRAMPOLINE_INSTR_64 109 | { 110 | 111 | BYTE push; 112 | UINT32 loaddr; 113 | BYTE mov[4]; 114 | UINT32 hiaddr; 115 | BYTE ret; 116 | }; 117 | 118 | //asm instructions for direct jump 119 | const BYTE X64_TRAMPOLINE_INSTRUCTIONS[] = 120 | { 0x68, 0xAA, 0xAA, 0xAA, 0xAA, //push 0xAAAAAAAA 121 | 0xC7, 0x44, 0x24, 0x04, 0xBB, 0xBB, 0xBB, 0xBB, //mov dword ptr[ esp+4 ], 0xBBBBBBBB 122 | 0xC3 }; //ret 123 | 124 | #pragma pack(pop) 125 | 126 | /** 127 | HOOKCONTEXT_INTERNAL 128 | 129 | Internal information on the hook, this is returned to the user 130 | as a HOOKCONTEXT 131 | */ 132 | struct HOOKCONTEXT_INTERNAL 133 | { 134 | HOOKCONTEXT Context; 135 | DWORD cbSize; //count of HOOKCONTEXT_INTERNAL total bytes 136 | DWORD cbTrampoline; //size of trampoline 137 | DWORD cbSavedInstructions; //count of saved instruction bytes 138 | DWORD cbRedirect; //count of redirect instruction bytes 139 | PBYTE pbSavedInstructions; //original saved instructions 140 | PBYTE pbRedirect; //original saved instructions 141 | PBYTE pbTrampoline; //pointer to trampoline stub 142 | 143 | }; 144 | 145 | }//namespace 146 | 147 | 148 | #endif -------------------------------------------------------------------------------- /HookTest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Nettitude 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without modification, 5 | # are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, 8 | # this list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # 3. Neither the name of the copyright holder nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 19 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 | # THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | cmake_minimum_required (VERSION 2.6) 30 | 31 | project( HookTest ) 32 | 33 | include_directories( ${CMAKE_SOURCE_DIR}/HookEngine/ ) 34 | 35 | add_executable(${PROJECT_NAME} HookTest.cpp ) 36 | 37 | target_link_libraries( ${PROJECT_NAME} HookEngine ) 38 | -------------------------------------------------------------------------------- /HookTest/HookTest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Nettitude 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 | THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include 31 | #include "HookEngine.h" 32 | 33 | HOOKCONTEXT* g_pMessageABoxHook = NULL; 34 | 35 | typedef int (WINAPI *fpUserMessageBoxA)( 36 | HWND hWnd, 37 | LPCSTR lpText, 38 | LPCSTR lpCaption, 39 | UINT uType 40 | ); 41 | 42 | int 43 | WINAPI 44 | UserMessageBoxA( 45 | HWND hWnd, 46 | LPCSTR lpText, 47 | LPCSTR lpCaption, 48 | UINT uType 49 | ) 50 | { 51 | 52 | static const LPCSTR pMyText = "All your message belong to us!"; 53 | 54 | if (g_pMessageABoxHook) 55 | { 56 | //call function 57 | return ((fpUserMessageBoxA)(g_pMessageABoxHook->pTrampoline))(hWnd, pMyText, lpCaption, uType); 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | int main(int argc, char** argv) 64 | { 65 | LPVOID pTarget = &MessageBoxA; 66 | LPVOID pUser = &UserMessageBoxA; 67 | 68 | if (HOOK_SUCCESS == HookEngine_Init()) 69 | { 70 | if (HOOK_SUCCESS == HookEngine_InstallHook(pTarget, pUser, &g_pMessageABoxHook)) 71 | { 72 | ::MessageBoxA(NULL, "XXXXXXXXXX", "Hello!", MB_OK); 73 | 74 | if (HOOK_SUCCESS == HookEngine_RemoveHook(g_pMessageABoxHook)) 75 | { 76 | ::MessageBoxA(NULL, "Not Hooked", "Hello!", MB_OK); 77 | g_pMessageABoxHook = NULL; 78 | } 79 | } 80 | 81 | HookEngine_Shutdown(); 82 | } 83 | return 0; 84 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # InlineFunctionHooking 3 | Windows Inline function hooking library targeted at MSVC 4 | 5 | 6 | Copyright (c) 2015, Nettitude 7 | All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without modification, 10 | are permitted provided that the following conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright notice, 13 | this list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | 19 | 3. Neither the name of the copyright holder nor the names of its contributors 20 | may be used to endorse or promote products derived from this software without 21 | specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 24 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 31 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 | THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Udis86/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Nettitude 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without modification, 5 | # are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, 8 | # this list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # 3. Neither the name of the copyright holder nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 19 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 | # THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | cmake_minimum_required (VERSION 2.6) 30 | 31 | PROJECT(Udis86) 32 | 33 | SET( SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libudis86 ) 34 | 35 | INCLUDE_DIRECTORIES( ${SRC_DIR} ) 36 | 37 | ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS=1 -DHAVE_STRING_H=1) 38 | 39 | 40 | SET( SOURCE udis86.h 41 | ${SRC_DIR}/itab.c 42 | ${SRC_DIR}/itab.h 43 | ${SRC_DIR}/decode.c 44 | ${SRC_DIR}/decode.h 45 | ${SRC_DIR}/extern.h 46 | ${SRC_DIR}/syn-att.c 47 | ${SRC_DIR}/syn-intel.c 48 | ${SRC_DIR}/syn.c 49 | ${SRC_DIR}/syn.h 50 | ${SRC_DIR}/types.h 51 | ${SRC_DIR}/udint.h 52 | ${SRC_DIR}/udis86.c ) 53 | 54 | ADD_LIBRARY( ${PROJECT_NAME} STATIC ${SOURCE} ) 55 | 56 | -------------------------------------------------------------------------------- /Udis86/libudis86/decode.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/decode.c 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #include "udint.h" 27 | #include "types.h" 28 | #include "extern.h" 29 | #include "decode.h" 30 | 31 | #ifndef __UD_STANDALONE__ 32 | # include 33 | #endif /* __UD_STANDALONE__ */ 34 | 35 | /* The max number of prefixes to an instruction */ 36 | #define MAX_PREFIXES 15 37 | 38 | /* rex prefix bits */ 39 | #define REX_W(r) ( ( 0xF & ( r ) ) >> 3 ) 40 | #define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 ) 41 | #define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 ) 42 | #define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 ) 43 | #define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \ 44 | ( P_REXR(n) << 2 ) | \ 45 | ( P_REXX(n) << 1 ) | \ 46 | ( P_REXB(n) << 0 ) ) 47 | 48 | /* scable-index-base bits */ 49 | #define SIB_S(b) ( ( b ) >> 6 ) 50 | #define SIB_I(b) ( ( ( b ) >> 3 ) & 7 ) 51 | #define SIB_B(b) ( ( b ) & 7 ) 52 | 53 | /* modrm bits */ 54 | #define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 ) 55 | #define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 ) 56 | #define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 ) 57 | #define MODRM_RM(b) ( ( b ) & 7 ) 58 | 59 | static int decode_ext(struct ud *u, uint16_t ptr); 60 | static int decode_opcode(struct ud *u); 61 | 62 | enum reg_class { /* register classes */ 63 | REGCLASS_GPR, 64 | REGCLASS_MMX, 65 | REGCLASS_CR, 66 | REGCLASS_DB, 67 | REGCLASS_SEG, 68 | REGCLASS_XMM 69 | }; 70 | 71 | /* 72 | * inp_start 73 | * Should be called before each de-code operation. 74 | */ 75 | static void 76 | inp_start(struct ud *u) 77 | { 78 | u->inp_ctr = 0; 79 | } 80 | 81 | static uint8_t 82 | inp_peek(struct ud *u) 83 | { 84 | if (u->inp_end == 0) { 85 | if (u->inp_buf != NULL) { 86 | if (u->inp_buf_index < u->inp_buf_size) { 87 | return u->inp_buf[u->inp_buf_index]; 88 | } 89 | } else if (u->inp_peek != UD_EOI) { 90 | return u->inp_peek; 91 | } else { 92 | int c; 93 | if ((c = u->inp_hook(u)) != UD_EOI) { 94 | u->inp_peek = c; 95 | return u->inp_peek; 96 | } 97 | } 98 | } 99 | u->inp_end = 1; 100 | UDERR(u, "byte expected, eoi received\n"); 101 | return 0; 102 | } 103 | 104 | static uint8_t 105 | inp_next(struct ud *u) 106 | { 107 | if (u->inp_end == 0) { 108 | if (u->inp_buf != NULL) { 109 | if (u->inp_buf_index < u->inp_buf_size) { 110 | u->inp_ctr++; 111 | return (u->inp_curr = u->inp_buf[u->inp_buf_index++]); 112 | } 113 | } else { 114 | int c = u->inp_peek; 115 | if (c != UD_EOI || (c = u->inp_hook(u)) != UD_EOI) { 116 | u->inp_peek = UD_EOI; 117 | u->inp_curr = c; 118 | u->inp_sess[u->inp_ctr++] = u->inp_curr; 119 | return u->inp_curr; 120 | } 121 | } 122 | } 123 | u->inp_end = 1; 124 | UDERR(u, "byte expected, eoi received\n"); 125 | return 0; 126 | } 127 | 128 | static uint8_t 129 | inp_curr(struct ud *u) 130 | { 131 | return u->inp_curr; 132 | } 133 | 134 | 135 | /* 136 | * inp_uint8 137 | * int_uint16 138 | * int_uint32 139 | * int_uint64 140 | * Load little-endian values from input 141 | */ 142 | static uint8_t 143 | inp_uint8(struct ud* u) 144 | { 145 | return inp_next(u); 146 | } 147 | 148 | static uint16_t 149 | inp_uint16(struct ud* u) 150 | { 151 | uint16_t r, ret; 152 | 153 | ret = inp_next(u); 154 | r = inp_next(u); 155 | return ret | (r << 8); 156 | } 157 | 158 | static uint32_t 159 | inp_uint32(struct ud* u) 160 | { 161 | uint32_t r, ret; 162 | 163 | ret = inp_next(u); 164 | r = inp_next(u); 165 | ret = ret | (r << 8); 166 | r = inp_next(u); 167 | ret = ret | (r << 16); 168 | r = inp_next(u); 169 | return ret | (r << 24); 170 | } 171 | 172 | static uint64_t 173 | inp_uint64(struct ud* u) 174 | { 175 | uint64_t r, ret; 176 | 177 | ret = inp_next(u); 178 | r = inp_next(u); 179 | ret = ret | (r << 8); 180 | r = inp_next(u); 181 | ret = ret | (r << 16); 182 | r = inp_next(u); 183 | ret = ret | (r << 24); 184 | r = inp_next(u); 185 | ret = ret | (r << 32); 186 | r = inp_next(u); 187 | ret = ret | (r << 40); 188 | r = inp_next(u); 189 | ret = ret | (r << 48); 190 | r = inp_next(u); 191 | return ret | (r << 56); 192 | } 193 | 194 | 195 | static UD_INLINE int 196 | eff_opr_mode(int dis_mode, int rex_w, int pfx_opr) 197 | { 198 | if (dis_mode == 64) { 199 | return rex_w ? 64 : (pfx_opr ? 16 : 32); 200 | } else if (dis_mode == 32) { 201 | return pfx_opr ? 16 : 32; 202 | } else { 203 | UD_ASSERT(dis_mode == 16); 204 | return pfx_opr ? 32 : 16; 205 | } 206 | } 207 | 208 | 209 | static UD_INLINE int 210 | eff_adr_mode(int dis_mode, int pfx_adr) 211 | { 212 | if (dis_mode == 64) { 213 | return pfx_adr ? 32 : 64; 214 | } else if (dis_mode == 32) { 215 | return pfx_adr ? 16 : 32; 216 | } else { 217 | UD_ASSERT(dis_mode == 16); 218 | return pfx_adr ? 32 : 16; 219 | } 220 | } 221 | 222 | 223 | /* 224 | * decode_prefixes 225 | * 226 | * Extracts instruction prefixes. 227 | */ 228 | static int 229 | decode_prefixes(struct ud *u) 230 | { 231 | int done = 0; 232 | uint8_t curr = 0, last = 0; 233 | UD_RETURN_ON_ERROR(u); 234 | 235 | do { 236 | last = curr; 237 | curr = inp_next(u); 238 | UD_RETURN_ON_ERROR(u); 239 | if (u->inp_ctr == MAX_INSN_LENGTH) { 240 | UD_RETURN_WITH_ERROR(u, "max instruction length"); 241 | } 242 | 243 | switch (curr) 244 | { 245 | case 0x2E: 246 | u->pfx_seg = UD_R_CS; 247 | break; 248 | case 0x36: 249 | u->pfx_seg = UD_R_SS; 250 | break; 251 | case 0x3E: 252 | u->pfx_seg = UD_R_DS; 253 | break; 254 | case 0x26: 255 | u->pfx_seg = UD_R_ES; 256 | break; 257 | case 0x64: 258 | u->pfx_seg = UD_R_FS; 259 | break; 260 | case 0x65: 261 | u->pfx_seg = UD_R_GS; 262 | break; 263 | case 0x67: /* adress-size override prefix */ 264 | u->pfx_adr = 0x67; 265 | break; 266 | case 0xF0: 267 | u->pfx_lock = 0xF0; 268 | break; 269 | case 0x66: 270 | u->pfx_opr = 0x66; 271 | break; 272 | case 0xF2: 273 | u->pfx_str = 0xf2; 274 | break; 275 | case 0xF3: 276 | u->pfx_str = 0xf3; 277 | break; 278 | default: 279 | /* consume if rex */ 280 | done = (u->dis_mode == 64 && (curr & 0xF0) == 0x40) ? 0 : 1; 281 | break; 282 | } 283 | } while (!done); 284 | /* rex prefixes in 64bit mode, must be the last prefix */ 285 | if (u->dis_mode == 64 && (last & 0xF0) == 0x40) { 286 | u->pfx_rex = last; 287 | } 288 | return 0; 289 | } 290 | 291 | 292 | /* 293 | * vex_l, vex_w 294 | * Return the vex.L and vex.W bits 295 | */ 296 | static UD_INLINE uint8_t 297 | vex_l(const struct ud *u) 298 | { 299 | UD_ASSERT(u->vex_op != 0); 300 | return ((u->vex_op == 0xc4 ? u->vex_b2 : u->vex_b1) >> 2) & 1; 301 | } 302 | 303 | static UD_INLINE uint8_t 304 | vex_w(const struct ud *u) 305 | { 306 | UD_ASSERT(u->vex_op != 0); 307 | return u->vex_op == 0xc4 ? ((u->vex_b2 >> 7) & 1) : 0; 308 | } 309 | 310 | 311 | static UD_INLINE uint8_t 312 | modrm(struct ud * u) 313 | { 314 | if ( !u->have_modrm ) { 315 | u->modrm = inp_next( u ); 316 | u->modrm_offset = (uint8_t) (u->inp_ctr - 1); 317 | u->have_modrm = 1; 318 | } 319 | return u->modrm; 320 | } 321 | 322 | 323 | static unsigned int 324 | resolve_operand_size(const struct ud* u, ud_operand_size_t osize) 325 | { 326 | switch (osize) { 327 | case SZ_V: 328 | return u->opr_mode; 329 | case SZ_Z: 330 | return u->opr_mode == 16 ? 16 : 32; 331 | case SZ_Y: 332 | return u->opr_mode == 16 ? 32 : u->opr_mode; 333 | case SZ_RDQ: 334 | return u->dis_mode == 64 ? 64 : 32; 335 | case SZ_X: 336 | UD_ASSERT(u->vex_op != 0); 337 | return (P_VEXL(u->itab_entry->prefix) && vex_l(u)) ? SZ_QQ : SZ_DQ; 338 | default: 339 | return osize; 340 | } 341 | } 342 | 343 | 344 | static int resolve_mnemonic( struct ud* u ) 345 | { 346 | /* resolve 3dnow weirdness. */ 347 | if ( u->mnemonic == UD_I3dnow ) { 348 | u->mnemonic = ud_itab[ u->le->table[ inp_curr( u ) ] ].mnemonic; 349 | } 350 | /* SWAPGS is only valid in 64bits mode */ 351 | if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) { 352 | UDERR(u, "swapgs invalid in 64bits mode\n"); 353 | return -1; 354 | } 355 | 356 | if (u->mnemonic == UD_Ixchg) { 357 | if ((u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_AX && 358 | u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_AX) || 359 | (u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_EAX && 360 | u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_EAX)) { 361 | u->operand[0].type = UD_NONE; 362 | u->operand[1].type = UD_NONE; 363 | u->mnemonic = UD_Inop; 364 | } 365 | } 366 | 367 | if (u->mnemonic == UD_Inop && u->pfx_repe) { 368 | u->pfx_repe = 0; 369 | u->mnemonic = UD_Ipause; 370 | } 371 | return 0; 372 | } 373 | 374 | 375 | /* ----------------------------------------------------------------------------- 376 | * decode_a()- Decodes operands of the type seg:offset 377 | * ----------------------------------------------------------------------------- 378 | */ 379 | static void 380 | decode_a(struct ud* u, struct ud_operand *op) 381 | { 382 | if (u->opr_mode == 16) { 383 | /* seg16:off16 */ 384 | op->type = UD_OP_PTR; 385 | op->size = 32; 386 | op->lval.ptr.off = inp_uint16(u); 387 | op->lval.ptr.seg = inp_uint16(u); 388 | } else { 389 | /* seg16:off32 */ 390 | op->type = UD_OP_PTR; 391 | op->size = 48; 392 | op->lval.ptr.off = inp_uint32(u); 393 | op->lval.ptr.seg = inp_uint16(u); 394 | } 395 | } 396 | 397 | /* ----------------------------------------------------------------------------- 398 | * decode_gpr() - Returns decoded General Purpose Register 399 | * ----------------------------------------------------------------------------- 400 | */ 401 | static enum ud_type 402 | decode_gpr(register struct ud* u, unsigned int s, unsigned char rm) 403 | { 404 | switch (s) { 405 | case 64: 406 | return UD_R_RAX + rm; 407 | case 32: 408 | return UD_R_EAX + rm; 409 | case 16: 410 | return UD_R_AX + rm; 411 | case 8: 412 | if (u->dis_mode == 64 && u->pfx_rex) { 413 | if (rm >= 4) 414 | return UD_R_SPL + (rm-4); 415 | return UD_R_AL + rm; 416 | } else return UD_R_AL + rm; 417 | case 0: 418 | /* invalid size in case of a decode error */ 419 | UD_ASSERT(u->error); 420 | return UD_NONE; 421 | default: 422 | UD_ASSERT(!"invalid operand size"); 423 | return UD_NONE; 424 | } 425 | } 426 | 427 | static void 428 | decode_reg(struct ud *u, 429 | struct ud_operand *opr, 430 | int type, 431 | int num, 432 | int size) 433 | { 434 | int reg; 435 | size = resolve_operand_size(u, size); 436 | switch (type) { 437 | case REGCLASS_GPR : reg = decode_gpr(u, size, num); break; 438 | case REGCLASS_MMX : reg = UD_R_MM0 + (num & 7); break; 439 | case REGCLASS_XMM : 440 | reg = num + (size == SZ_QQ ? UD_R_YMM0 : UD_R_XMM0); 441 | break; 442 | case REGCLASS_CR : reg = UD_R_CR0 + num; break; 443 | case REGCLASS_DB : reg = UD_R_DR0 + num; break; 444 | case REGCLASS_SEG : { 445 | /* 446 | * Only 6 segment registers, anything else is an error. 447 | */ 448 | if ((num & 7) > 5) { 449 | UDERR(u, "invalid segment register value\n"); 450 | return; 451 | } else { 452 | reg = UD_R_ES + (num & 7); 453 | } 454 | break; 455 | } 456 | default: 457 | UD_ASSERT(!"invalid register type"); 458 | return; 459 | } 460 | opr->type = UD_OP_REG; 461 | opr->base = reg; 462 | opr->size = size; 463 | } 464 | 465 | 466 | /* 467 | * decode_imm 468 | * 469 | * Decode Immediate values. 470 | */ 471 | static void 472 | decode_imm(struct ud* u, unsigned int size, struct ud_operand *op) 473 | { 474 | op->size = resolve_operand_size(u, size); 475 | op->type = UD_OP_IMM; 476 | 477 | switch (op->size) { 478 | case 8: op->lval.sbyte = inp_uint8(u); break; 479 | case 16: op->lval.uword = inp_uint16(u); break; 480 | case 32: op->lval.udword = inp_uint32(u); break; 481 | case 64: op->lval.uqword = inp_uint64(u); break; 482 | default: return; 483 | } 484 | } 485 | 486 | 487 | /* 488 | * decode_mem_disp 489 | * 490 | * Decode mem address displacement. 491 | */ 492 | static void 493 | decode_mem_disp(struct ud* u, unsigned int size, struct ud_operand *op) 494 | { 495 | switch (size) { 496 | case 8: 497 | op->offset = 8; 498 | op->lval.ubyte = inp_uint8(u); 499 | break; 500 | case 16: 501 | op->offset = 16; 502 | op->lval.uword = inp_uint16(u); 503 | break; 504 | case 32: 505 | op->offset = 32; 506 | op->lval.udword = inp_uint32(u); 507 | break; 508 | case 64: 509 | op->offset = 64; 510 | op->lval.uqword = inp_uint64(u); 511 | break; 512 | default: 513 | return; 514 | } 515 | } 516 | 517 | 518 | /* 519 | * decode_modrm_reg 520 | * 521 | * Decodes reg field of mod/rm byte 522 | * 523 | */ 524 | static UD_INLINE void 525 | decode_modrm_reg(struct ud *u, 526 | struct ud_operand *operand, 527 | unsigned int type, 528 | unsigned int size) 529 | { 530 | uint8_t reg = (REX_R(u->_rex) << 3) | MODRM_REG(modrm(u)); 531 | decode_reg(u, operand, type, reg, size); 532 | } 533 | 534 | 535 | /* 536 | * decode_modrm_rm 537 | * 538 | * Decodes rm field of mod/rm byte 539 | * 540 | */ 541 | static void 542 | decode_modrm_rm(struct ud *u, 543 | struct ud_operand *op, 544 | unsigned char type, /* register type */ 545 | unsigned int size) /* operand size */ 546 | 547 | { 548 | size_t offset = 0; 549 | unsigned char mod, rm; 550 | 551 | /* get mod, r/m and reg fields */ 552 | mod = MODRM_MOD(modrm(u)); 553 | rm = (REX_B(u->_rex) << 3) | MODRM_RM(modrm(u)); 554 | 555 | /* 556 | * If mod is 11b, then the modrm.rm specifies a register. 557 | * 558 | */ 559 | if (mod == 3) { 560 | decode_reg(u, op, type, rm, size); 561 | return; 562 | } 563 | 564 | /* 565 | * !11b => Memory Address 566 | */ 567 | op->type = UD_OP_MEM; 568 | op->size = resolve_operand_size(u, size); 569 | 570 | if (u->adr_mode == 64) { 571 | op->base = UD_R_RAX + rm; 572 | if (mod == 1) { 573 | offset = 8; 574 | } else if (mod == 2) { 575 | offset = 32; 576 | } else if (mod == 0 && (rm & 7) == 5) { 577 | op->base = UD_R_RIP; 578 | offset = 32; 579 | } else { 580 | offset = 0; 581 | } 582 | /* 583 | * Scale-Index-Base (SIB) 584 | */ 585 | if ((rm & 7) == 4) { 586 | inp_next(u); 587 | 588 | op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->_rex) << 3)); 589 | op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->_rex) << 3)); 590 | /* special conditions for base reference */ 591 | if (op->index == UD_R_RSP) { 592 | op->index = UD_NONE; 593 | op->scale = UD_NONE; 594 | } else { 595 | op->scale = (1 << SIB_S(inp_curr(u))) & ~1; 596 | } 597 | 598 | if (op->base == UD_R_RBP || op->base == UD_R_R13) { 599 | if (mod == 0) { 600 | op->base = UD_NONE; 601 | } 602 | if (mod == 1) { 603 | offset = 8; 604 | } else { 605 | offset = 32; 606 | } 607 | } 608 | } else { 609 | op->scale = UD_NONE; 610 | op->index = UD_NONE; 611 | } 612 | } else if (u->adr_mode == 32) { 613 | op->base = UD_R_EAX + rm; 614 | if (mod == 1) { 615 | offset = 8; 616 | } else if (mod == 2) { 617 | offset = 32; 618 | } else if (mod == 0 && rm == 5) { 619 | op->base = UD_NONE; 620 | offset = 32; 621 | } else { 622 | offset = 0; 623 | } 624 | 625 | /* Scale-Index-Base (SIB) */ 626 | if ((rm & 7) == 4) { 627 | inp_next(u); 628 | 629 | op->scale = (1 << SIB_S(inp_curr(u))) & ~1; 630 | op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); 631 | op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); 632 | 633 | if (op->index == UD_R_ESP) { 634 | op->index = UD_NONE; 635 | op->scale = UD_NONE; 636 | } 637 | 638 | /* special condition for base reference */ 639 | if (op->base == UD_R_EBP) { 640 | if (mod == 0) { 641 | op->base = UD_NONE; 642 | } 643 | if (mod == 1) { 644 | offset = 8; 645 | } else { 646 | offset = 32; 647 | } 648 | } 649 | } else { 650 | op->scale = UD_NONE; 651 | op->index = UD_NONE; 652 | } 653 | } else { 654 | const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP, 655 | UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX }; 656 | const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI, 657 | UD_NONE, UD_NONE, UD_NONE, UD_NONE }; 658 | op->base = bases[rm & 7]; 659 | op->index = indices[rm & 7]; 660 | op->scale = UD_NONE; 661 | if (mod == 0 && rm == 6) { 662 | offset = 16; 663 | op->base = UD_NONE; 664 | } else if (mod == 1) { 665 | offset = 8; 666 | } else if (mod == 2) { 667 | offset = 16; 668 | } 669 | } 670 | 671 | if (offset) { 672 | decode_mem_disp(u, offset, op); 673 | } else { 674 | op->offset = 0; 675 | } 676 | } 677 | 678 | 679 | /* 680 | * decode_moffset 681 | * Decode offset-only memory operand 682 | */ 683 | static void 684 | decode_moffset(struct ud *u, unsigned int size, struct ud_operand *opr) 685 | { 686 | opr->type = UD_OP_MEM; 687 | opr->base = UD_NONE; 688 | opr->index = UD_NONE; 689 | opr->scale = UD_NONE; 690 | opr->size = resolve_operand_size(u, size); 691 | decode_mem_disp(u, u->adr_mode, opr); 692 | } 693 | 694 | 695 | static void 696 | decode_vex_vvvv(struct ud *u, struct ud_operand *opr, unsigned size) 697 | { 698 | uint8_t vvvv; 699 | UD_ASSERT(u->vex_op != 0); 700 | vvvv = ((u->vex_op == 0xc4 ? u->vex_b2 : u->vex_b1) >> 3) & 0xf; 701 | decode_reg(u, opr, REGCLASS_XMM, (0xf & ~vvvv), size); 702 | } 703 | 704 | 705 | /* 706 | * decode_vex_immreg 707 | * Decode source operand encoded in immediate byte [7:4] 708 | */ 709 | static int 710 | decode_vex_immreg(struct ud *u, struct ud_operand *opr, unsigned size) 711 | { 712 | uint8_t imm = inp_next(u); 713 | uint8_t mask = u->dis_mode == 64 ? 0xf : 0x7; 714 | UD_RETURN_ON_ERROR(u); 715 | UD_ASSERT(u->vex_op != 0); 716 | decode_reg(u, opr, REGCLASS_XMM, mask & (imm >> 4), size); 717 | return 0; 718 | } 719 | 720 | 721 | /* 722 | * decode_operand 723 | * 724 | * Decodes a single operand. 725 | * Returns the type of the operand (UD_NONE if none) 726 | */ 727 | static int 728 | decode_operand(struct ud *u, 729 | struct ud_operand *operand, 730 | enum ud_operand_code type, 731 | unsigned int size) 732 | { 733 | operand->type = UD_NONE; 734 | operand->_oprcode = type; 735 | 736 | switch (type) { 737 | case OP_A : 738 | decode_a(u, operand); 739 | break; 740 | case OP_MR: 741 | decode_modrm_rm(u, operand, REGCLASS_GPR, 742 | MODRM_MOD(modrm(u)) == 3 ? 743 | Mx_reg_size(size) : Mx_mem_size(size)); 744 | break; 745 | case OP_F: 746 | u->br_far = 1; 747 | /* intended fall through */ 748 | case OP_M: 749 | if (MODRM_MOD(modrm(u)) == 3) { 750 | UDERR(u, "expected modrm.mod != 3\n"); 751 | } 752 | /* intended fall through */ 753 | case OP_E: 754 | decode_modrm_rm(u, operand, REGCLASS_GPR, size); 755 | break; 756 | case OP_G: 757 | decode_modrm_reg(u, operand, REGCLASS_GPR, size); 758 | break; 759 | case OP_sI: 760 | case OP_I: 761 | decode_imm(u, size, operand); 762 | break; 763 | case OP_I1: 764 | operand->type = UD_OP_CONST; 765 | operand->lval.udword = 1; 766 | break; 767 | case OP_N: 768 | if (MODRM_MOD(modrm(u)) != 3) { 769 | UDERR(u, "expected modrm.mod == 3\n"); 770 | } 771 | /* intended fall through */ 772 | case OP_Q: 773 | decode_modrm_rm(u, operand, REGCLASS_MMX, size); 774 | break; 775 | case OP_P: 776 | decode_modrm_reg(u, operand, REGCLASS_MMX, size); 777 | break; 778 | case OP_U: 779 | if (MODRM_MOD(modrm(u)) != 3) { 780 | UDERR(u, "expected modrm.mod == 3\n"); 781 | } 782 | /* intended fall through */ 783 | case OP_W: 784 | decode_modrm_rm(u, operand, REGCLASS_XMM, size); 785 | break; 786 | case OP_V: 787 | decode_modrm_reg(u, operand, REGCLASS_XMM, size); 788 | break; 789 | case OP_H: 790 | decode_vex_vvvv(u, operand, size); 791 | break; 792 | case OP_MU: 793 | decode_modrm_rm(u, operand, REGCLASS_XMM, 794 | MODRM_MOD(modrm(u)) == 3 ? 795 | Mx_reg_size(size) : Mx_mem_size(size)); 796 | break; 797 | case OP_S: 798 | decode_modrm_reg(u, operand, REGCLASS_SEG, size); 799 | break; 800 | case OP_O: 801 | decode_moffset(u, size, operand); 802 | break; 803 | case OP_R0: 804 | case OP_R1: 805 | case OP_R2: 806 | case OP_R3: 807 | case OP_R4: 808 | case OP_R5: 809 | case OP_R6: 810 | case OP_R7: 811 | decode_reg(u, operand, REGCLASS_GPR, 812 | (REX_B(u->_rex) << 3) | (type - OP_R0), size); 813 | break; 814 | case OP_AL: 815 | case OP_AX: 816 | case OP_eAX: 817 | case OP_rAX: 818 | decode_reg(u, operand, REGCLASS_GPR, 0, size); 819 | break; 820 | case OP_CL: 821 | case OP_CX: 822 | case OP_eCX: 823 | decode_reg(u, operand, REGCLASS_GPR, 1, size); 824 | break; 825 | case OP_DL: 826 | case OP_DX: 827 | case OP_eDX: 828 | decode_reg(u, operand, REGCLASS_GPR, 2, size); 829 | break; 830 | case OP_ES: 831 | case OP_CS: 832 | case OP_DS: 833 | case OP_SS: 834 | case OP_FS: 835 | case OP_GS: 836 | /* in 64bits mode, only fs and gs are allowed */ 837 | if (u->dis_mode == 64) { 838 | if (type != OP_FS && type != OP_GS) { 839 | UDERR(u, "invalid segment register in 64bits\n"); 840 | } 841 | } 842 | operand->type = UD_OP_REG; 843 | operand->base = (type - OP_ES) + UD_R_ES; 844 | operand->size = 16; 845 | break; 846 | case OP_J : 847 | decode_imm(u, size, operand); 848 | operand->type = UD_OP_JIMM; 849 | break ; 850 | case OP_R : 851 | if (MODRM_MOD(modrm(u)) != 3) { 852 | UDERR(u, "expected modrm.mod == 3\n"); 853 | } 854 | decode_modrm_rm(u, operand, REGCLASS_GPR, size); 855 | break; 856 | case OP_C: 857 | decode_modrm_reg(u, operand, REGCLASS_CR, size); 858 | break; 859 | case OP_D: 860 | decode_modrm_reg(u, operand, REGCLASS_DB, size); 861 | break; 862 | case OP_I3 : 863 | operand->type = UD_OP_CONST; 864 | operand->lval.sbyte = 3; 865 | break; 866 | case OP_ST0: 867 | case OP_ST1: 868 | case OP_ST2: 869 | case OP_ST3: 870 | case OP_ST4: 871 | case OP_ST5: 872 | case OP_ST6: 873 | case OP_ST7: 874 | operand->type = UD_OP_REG; 875 | operand->base = (type - OP_ST0) + UD_R_ST0; 876 | operand->size = 80; 877 | break; 878 | case OP_L: 879 | decode_vex_immreg(u, operand, size); 880 | break; 881 | default : 882 | operand->type = UD_NONE; 883 | break; 884 | } 885 | return operand->type; 886 | } 887 | 888 | 889 | /* 890 | * decode_operands 891 | * 892 | * Disassemble upto 3 operands of the current instruction being 893 | * disassembled. By the end of the function, the operand fields 894 | * of the ud structure will have been filled. 895 | */ 896 | static int 897 | decode_operands(struct ud* u) 898 | { 899 | decode_operand(u, &u->operand[0], 900 | u->itab_entry->operand1.type, 901 | u->itab_entry->operand1.size); 902 | if (u->operand[0].type != UD_NONE) { 903 | decode_operand(u, &u->operand[1], 904 | u->itab_entry->operand2.type, 905 | u->itab_entry->operand2.size); 906 | } 907 | if (u->operand[1].type != UD_NONE) { 908 | decode_operand(u, &u->operand[2], 909 | u->itab_entry->operand3.type, 910 | u->itab_entry->operand3.size); 911 | } 912 | if (u->operand[2].type != UD_NONE) { 913 | decode_operand(u, &u->operand[3], 914 | u->itab_entry->operand4.type, 915 | u->itab_entry->operand4.size); 916 | } 917 | return 0; 918 | } 919 | 920 | /* ----------------------------------------------------------------------------- 921 | * clear_insn() - clear instruction structure 922 | * ----------------------------------------------------------------------------- 923 | */ 924 | static void 925 | clear_insn(register struct ud* u) 926 | { 927 | u->error = 0; 928 | u->pfx_seg = 0; 929 | u->pfx_opr = 0; 930 | u->pfx_adr = 0; 931 | u->pfx_lock = 0; 932 | u->pfx_repne = 0; 933 | u->pfx_rep = 0; 934 | u->pfx_repe = 0; 935 | u->pfx_rex = 0; 936 | u->pfx_str = 0; 937 | u->mnemonic = UD_Inone; 938 | u->itab_entry = NULL; 939 | u->have_modrm = 0; 940 | u->br_far = 0; 941 | u->vex_op = 0; 942 | u->_rex = 0; 943 | u->operand[0].type = UD_NONE; 944 | u->operand[1].type = UD_NONE; 945 | u->operand[2].type = UD_NONE; 946 | u->operand[3].type = UD_NONE; 947 | } 948 | 949 | 950 | static UD_INLINE int 951 | resolve_pfx_str(struct ud* u) 952 | { 953 | if (u->pfx_str == 0xf3) { 954 | if (P_STR(u->itab_entry->prefix)) { 955 | u->pfx_rep = 0xf3; 956 | } else { 957 | u->pfx_repe = 0xf3; 958 | } 959 | } else if (u->pfx_str == 0xf2) { 960 | u->pfx_repne = 0xf3; 961 | } 962 | return 0; 963 | } 964 | 965 | 966 | static int 967 | resolve_mode( struct ud* u ) 968 | { 969 | int default64; 970 | /* if in error state, bail out */ 971 | if ( u->error ) return -1; 972 | 973 | /* propagate prefix effects */ 974 | if ( u->dis_mode == 64 ) { /* set 64bit-mode flags */ 975 | 976 | /* Check validity of instruction m64 */ 977 | if ( P_INV64( u->itab_entry->prefix ) ) { 978 | UDERR(u, "instruction invalid in 64bits\n"); 979 | return -1; 980 | } 981 | 982 | /* compute effective rex based on, 983 | * - vex prefix (if any) 984 | * - rex prefix (if any, and not vex) 985 | * - allowed prefixes specified by the opcode map 986 | */ 987 | if (u->vex_op == 0xc4) { 988 | /* vex has rex.rxb in 1's complement */ 989 | u->_rex = ((~(u->vex_b1 >> 5) & 0x7) /* rex.0rxb */ | 990 | ((u->vex_b2 >> 4) & 0x8) /* rex.w000 */); 991 | } else if (u->vex_op == 0xc5) { 992 | /* vex has rex.r in 1's complement */ 993 | u->_rex = (~(u->vex_b1 >> 5)) & 4; 994 | } else { 995 | UD_ASSERT(u->vex_op == 0); 996 | u->_rex = u->pfx_rex; 997 | } 998 | u->_rex &= REX_PFX_MASK(u->itab_entry->prefix); 999 | 1000 | /* whether this instruction has a default operand size of 1001 | * 64bit, also hardcoded into the opcode map. 1002 | */ 1003 | default64 = P_DEF64( u->itab_entry->prefix ); 1004 | /* calculate effective operand size */ 1005 | if (REX_W(u->_rex)) { 1006 | u->opr_mode = 64; 1007 | } else if ( u->pfx_opr ) { 1008 | u->opr_mode = 16; 1009 | } else { 1010 | /* unless the default opr size of instruction is 64, 1011 | * the effective operand size in the absence of rex.w 1012 | * prefix is 32. 1013 | */ 1014 | u->opr_mode = default64 ? 64 : 32; 1015 | } 1016 | 1017 | /* calculate effective address size */ 1018 | u->adr_mode = (u->pfx_adr) ? 32 : 64; 1019 | } else if ( u->dis_mode == 32 ) { /* set 32bit-mode flags */ 1020 | u->opr_mode = ( u->pfx_opr ) ? 16 : 32; 1021 | u->adr_mode = ( u->pfx_adr ) ? 16 : 32; 1022 | } else if ( u->dis_mode == 16 ) { /* set 16bit-mode flags */ 1023 | u->opr_mode = ( u->pfx_opr ) ? 32 : 16; 1024 | u->adr_mode = ( u->pfx_adr ) ? 32 : 16; 1025 | } 1026 | 1027 | return 0; 1028 | } 1029 | 1030 | 1031 | static UD_INLINE int 1032 | decode_insn(struct ud *u, uint16_t ptr) 1033 | { 1034 | UD_ASSERT((ptr & 0x8000) == 0); 1035 | u->itab_entry = &ud_itab[ ptr ]; 1036 | u->mnemonic = u->itab_entry->mnemonic; 1037 | return (resolve_pfx_str(u) == 0 && 1038 | resolve_mode(u) == 0 && 1039 | decode_operands(u) == 0 && 1040 | resolve_mnemonic(u) == 0) ? 0 : -1; 1041 | } 1042 | 1043 | 1044 | /* 1045 | * decode_3dnow() 1046 | * 1047 | * Decoding 3dnow is a little tricky because of its strange opcode 1048 | * structure. The final opcode disambiguation depends on the last 1049 | * byte that comes after the operands have been decoded. Fortunately, 1050 | * all 3dnow instructions have the same set of operand types. So we 1051 | * go ahead and decode the instruction by picking an arbitrarily chosen 1052 | * valid entry in the table, decode the operands, and read the final 1053 | * byte to resolve the menmonic. 1054 | */ 1055 | static UD_INLINE int 1056 | decode_3dnow(struct ud* u) 1057 | { 1058 | uint16_t ptr; 1059 | UD_ASSERT(u->le->type == UD_TAB__OPC_3DNOW); 1060 | UD_ASSERT(u->le->table[0xc] != 0); 1061 | decode_insn(u, u->le->table[0xc]); 1062 | inp_next(u); 1063 | if (u->error) { 1064 | return -1; 1065 | } 1066 | ptr = u->le->table[inp_curr(u)]; 1067 | UD_ASSERT((ptr & 0x8000) == 0); 1068 | u->mnemonic = ud_itab[ptr].mnemonic; 1069 | return 0; 1070 | } 1071 | 1072 | 1073 | static int 1074 | decode_ssepfx(struct ud *u) 1075 | { 1076 | uint8_t idx; 1077 | uint8_t pfx; 1078 | 1079 | /* 1080 | * String prefixes (f2, f3) take precedence over operand 1081 | * size prefix (66). 1082 | */ 1083 | pfx = u->pfx_str; 1084 | if (pfx == 0) { 1085 | pfx = u->pfx_opr; 1086 | } 1087 | idx = ((pfx & 0xf) + 1) / 2; 1088 | if (u->le->table[idx] == 0) { 1089 | idx = 0; 1090 | } 1091 | if (idx && u->le->table[idx] != 0) { 1092 | /* 1093 | * "Consume" the prefix as a part of the opcode, so it is no 1094 | * longer exported as an instruction prefix. 1095 | */ 1096 | u->pfx_str = 0; 1097 | if (pfx == 0x66) { 1098 | /* 1099 | * consume "66" only if it was used for decoding, leaving 1100 | * it to be used as an operands size override for some 1101 | * simd instructions. 1102 | */ 1103 | u->pfx_opr = 0; 1104 | } 1105 | } 1106 | return decode_ext(u, u->le->table[idx]); 1107 | } 1108 | 1109 | 1110 | static int 1111 | decode_vex(struct ud *u) 1112 | { 1113 | uint8_t index; 1114 | if (u->dis_mode != 64 && MODRM_MOD(inp_peek(u)) != 0x3) { 1115 | index = 0; 1116 | } else { 1117 | u->vex_op = inp_curr(u); 1118 | u->vex_b1 = inp_next(u); 1119 | if (u->vex_op == 0xc4) { 1120 | uint8_t pp, m; 1121 | /* 3-byte vex */ 1122 | u->vex_b2 = inp_next(u); 1123 | UD_RETURN_ON_ERROR(u); 1124 | m = u->vex_b1 & 0x1f; 1125 | if (m == 0 || m > 3) { 1126 | UD_RETURN_WITH_ERROR(u, "reserved vex.m-mmmm value"); 1127 | } 1128 | pp = u->vex_b2 & 0x3; 1129 | index = (pp << 2) | m; 1130 | } else { 1131 | /* 2-byte vex */ 1132 | UD_ASSERT(u->vex_op == 0xc5); 1133 | index = 0x1 | ((u->vex_b1 & 0x3) << 2); 1134 | } 1135 | } 1136 | return decode_ext(u, u->le->table[index]); 1137 | } 1138 | 1139 | 1140 | /* 1141 | * decode_ext() 1142 | * 1143 | * Decode opcode extensions (if any) 1144 | */ 1145 | static int 1146 | decode_ext(struct ud *u, uint16_t ptr) 1147 | { 1148 | uint8_t idx = 0; 1149 | if ((ptr & 0x8000) == 0) { 1150 | return decode_insn(u, ptr); 1151 | } 1152 | u->le = &ud_lookup_table_list[(~0x8000 & ptr)]; 1153 | if (u->le->type == UD_TAB__OPC_3DNOW) { 1154 | return decode_3dnow(u); 1155 | } 1156 | 1157 | switch (u->le->type) { 1158 | case UD_TAB__OPC_MOD: 1159 | /* !11 = 0, 11 = 1 */ 1160 | idx = (MODRM_MOD(modrm(u)) + 1) / 4; 1161 | break; 1162 | /* disassembly mode/operand size/address size based tables. 1163 | * 16 = 0,, 32 = 1, 64 = 2 1164 | */ 1165 | case UD_TAB__OPC_MODE: 1166 | idx = u->dis_mode != 64 ? 0 : 1; 1167 | break; 1168 | case UD_TAB__OPC_OSIZE: 1169 | idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32; 1170 | break; 1171 | case UD_TAB__OPC_ASIZE: 1172 | idx = eff_adr_mode(u->dis_mode, u->pfx_adr) / 32; 1173 | break; 1174 | case UD_TAB__OPC_X87: 1175 | idx = modrm(u) - 0xC0; 1176 | break; 1177 | case UD_TAB__OPC_VENDOR: 1178 | if (u->vendor == UD_VENDOR_ANY) { 1179 | /* choose a valid entry */ 1180 | idx = (u->le->table[idx] != 0) ? 0 : 1; 1181 | } else if (u->vendor == UD_VENDOR_AMD) { 1182 | idx = 0; 1183 | } else { 1184 | idx = 1; 1185 | } 1186 | break; 1187 | case UD_TAB__OPC_RM: 1188 | idx = MODRM_RM(modrm(u)); 1189 | break; 1190 | case UD_TAB__OPC_REG: 1191 | idx = MODRM_REG(modrm(u)); 1192 | break; 1193 | case UD_TAB__OPC_SSE: 1194 | return decode_ssepfx(u); 1195 | case UD_TAB__OPC_VEX: 1196 | return decode_vex(u); 1197 | case UD_TAB__OPC_VEX_W: 1198 | idx = vex_w(u); 1199 | break; 1200 | case UD_TAB__OPC_VEX_L: 1201 | idx = vex_l(u); 1202 | break; 1203 | case UD_TAB__OPC_TABLE: 1204 | inp_next(u); 1205 | return decode_opcode(u); 1206 | default: 1207 | UD_ASSERT(!"not reached"); 1208 | break; 1209 | } 1210 | 1211 | return decode_ext(u, u->le->table[idx]); 1212 | } 1213 | 1214 | 1215 | static int 1216 | decode_opcode(struct ud *u) 1217 | { 1218 | uint16_t ptr; 1219 | UD_ASSERT(u->le->type == UD_TAB__OPC_TABLE); 1220 | UD_RETURN_ON_ERROR(u); 1221 | ptr = u->le->table[inp_curr(u)]; 1222 | return decode_ext(u, ptr); 1223 | } 1224 | 1225 | 1226 | /* ============================================================================= 1227 | * ud_decode() - Instruction decoder. Returns the number of bytes decoded. 1228 | * ============================================================================= 1229 | */ 1230 | unsigned int 1231 | ud_decode(struct ud *u) 1232 | { 1233 | inp_start(u); 1234 | clear_insn(u); 1235 | u->le = &ud_lookup_table_list[0]; 1236 | u->error = decode_prefixes(u) == -1 || 1237 | decode_opcode(u) == -1 || 1238 | u->error; 1239 | /* Handle decode error. */ 1240 | if (u->error) { 1241 | /* clear out the decode data. */ 1242 | clear_insn(u); 1243 | /* mark the sequence of bytes as invalid. */ 1244 | u->itab_entry = &ud_itab[0]; /* entry 0 is invalid */ 1245 | u->mnemonic = u->itab_entry->mnemonic; 1246 | } 1247 | 1248 | /* maybe this stray segment override byte 1249 | * should be spewed out? 1250 | */ 1251 | if ( !P_SEG( u->itab_entry->prefix ) && 1252 | u->operand[0].type != UD_OP_MEM && 1253 | u->operand[1].type != UD_OP_MEM ) 1254 | u->pfx_seg = 0; 1255 | 1256 | u->insn_offset = u->pc; /* set offset of instruction */ 1257 | u->asm_buf_fill = 0; /* set translation buffer index to 0 */ 1258 | u->pc += u->inp_ctr; /* move program counter by bytes decoded */ 1259 | 1260 | /* return number of bytes disassembled. */ 1261 | return u->inp_ctr; 1262 | } 1263 | 1264 | /* 1265 | vim: set ts=2 sw=2 expandtab 1266 | */ 1267 | -------------------------------------------------------------------------------- /Udis86/libudis86/decode.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/decode.h 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UD_DECODE_H 27 | #define UD_DECODE_H 28 | 29 | #include "types.h" 30 | #include "udint.h" 31 | #include "itab.h" 32 | 33 | #define MAX_INSN_LENGTH 15 34 | 35 | /* itab prefix bits */ 36 | #define P_none ( 0 ) 37 | 38 | #define P_inv64 ( 1 << 0 ) 39 | #define P_INV64(n) ( ( n >> 0 ) & 1 ) 40 | #define P_def64 ( 1 << 1 ) 41 | #define P_DEF64(n) ( ( n >> 1 ) & 1 ) 42 | 43 | #define P_oso ( 1 << 2 ) 44 | #define P_OSO(n) ( ( n >> 2 ) & 1 ) 45 | #define P_aso ( 1 << 3 ) 46 | #define P_ASO(n) ( ( n >> 3 ) & 1 ) 47 | 48 | #define P_rexb ( 1 << 4 ) 49 | #define P_REXB(n) ( ( n >> 4 ) & 1 ) 50 | #define P_rexw ( 1 << 5 ) 51 | #define P_REXW(n) ( ( n >> 5 ) & 1 ) 52 | #define P_rexr ( 1 << 6 ) 53 | #define P_REXR(n) ( ( n >> 6 ) & 1 ) 54 | #define P_rexx ( 1 << 7 ) 55 | #define P_REXX(n) ( ( n >> 7 ) & 1 ) 56 | 57 | #define P_seg ( 1 << 8 ) 58 | #define P_SEG(n) ( ( n >> 8 ) & 1 ) 59 | 60 | #define P_vexl ( 1 << 9 ) 61 | #define P_VEXL(n) ( ( n >> 9 ) & 1 ) 62 | #define P_vexw ( 1 << 10 ) 63 | #define P_VEXW(n) ( ( n >> 10 ) & 1 ) 64 | 65 | #define P_str ( 1 << 11 ) 66 | #define P_STR(n) ( ( n >> 11 ) & 1 ) 67 | #define P_strz ( 1 << 12 ) 68 | #define P_STR_ZF(n) ( ( n >> 12 ) & 1 ) 69 | 70 | /* operand type constants -- order is important! */ 71 | 72 | enum ud_operand_code { 73 | OP_NONE, 74 | 75 | OP_A, OP_E, OP_M, OP_G, 76 | OP_I, OP_F, 77 | 78 | OP_R0, OP_R1, OP_R2, OP_R3, 79 | OP_R4, OP_R5, OP_R6, OP_R7, 80 | 81 | OP_AL, OP_CL, OP_DL, 82 | OP_AX, OP_CX, OP_DX, 83 | OP_eAX, OP_eCX, OP_eDX, 84 | OP_rAX, OP_rCX, OP_rDX, 85 | 86 | OP_ES, OP_CS, OP_SS, OP_DS, 87 | OP_FS, OP_GS, 88 | 89 | OP_ST0, OP_ST1, OP_ST2, OP_ST3, 90 | OP_ST4, OP_ST5, OP_ST6, OP_ST7, 91 | 92 | OP_J, OP_S, OP_O, 93 | OP_I1, OP_I3, OP_sI, 94 | 95 | OP_V, OP_W, OP_Q, OP_P, 96 | OP_U, OP_N, OP_MU, OP_H, 97 | OP_L, 98 | 99 | OP_R, OP_C, OP_D, 100 | 101 | OP_MR 102 | } UD_ATTR_PACKED; 103 | 104 | 105 | /* 106 | * Operand size constants 107 | * 108 | * Symbolic constants for various operand sizes. Some of these constants 109 | * are given a value equal to the width of the data (SZ_B == 8), such 110 | * that they maybe used interchangeably in the internals. Modifying them 111 | * will most certainly break things! 112 | */ 113 | typedef uint16_t ud_operand_size_t; 114 | 115 | #define SZ_NA 0 116 | #define SZ_Z 1 117 | #define SZ_V 2 118 | #define SZ_Y 3 119 | #define SZ_X 4 120 | #define SZ_RDQ 7 121 | #define SZ_B 8 122 | #define SZ_W 16 123 | #define SZ_D 32 124 | #define SZ_Q 64 125 | #define SZ_T 80 126 | #define SZ_O 12 127 | #define SZ_DQ 128 /* double quad */ 128 | #define SZ_QQ 256 /* quad quad */ 129 | 130 | /* 131 | * Complex size types; that encode sizes for operands of type MR (memory or 132 | * register); for internal use only. Id space above 256. 133 | */ 134 | #define SZ_BD ((SZ_B << 8) | SZ_D) 135 | #define SZ_BV ((SZ_B << 8) | SZ_V) 136 | #define SZ_WD ((SZ_W << 8) | SZ_D) 137 | #define SZ_WV ((SZ_W << 8) | SZ_V) 138 | #define SZ_WY ((SZ_W << 8) | SZ_Y) 139 | #define SZ_DY ((SZ_D << 8) | SZ_Y) 140 | #define SZ_WO ((SZ_W << 8) | SZ_O) 141 | #define SZ_DO ((SZ_D << 8) | SZ_O) 142 | #define SZ_QO ((SZ_Q << 8) | SZ_O) 143 | 144 | 145 | /* resolve complex size type. 146 | */ 147 | static UD_INLINE ud_operand_size_t 148 | Mx_mem_size(ud_operand_size_t size) 149 | { 150 | return (size >> 8) & 0xff; 151 | } 152 | 153 | static UD_INLINE ud_operand_size_t 154 | Mx_reg_size(ud_operand_size_t size) 155 | { 156 | return size & 0xff; 157 | } 158 | 159 | /* A single operand of an entry in the instruction table. 160 | * (internal use only) 161 | */ 162 | struct ud_itab_entry_operand 163 | { 164 | enum ud_operand_code type; 165 | ud_operand_size_t size; 166 | }; 167 | 168 | 169 | /* A single entry in an instruction table. 170 | *(internal use only) 171 | */ 172 | struct ud_itab_entry 173 | { 174 | enum ud_mnemonic_code mnemonic; 175 | struct ud_itab_entry_operand operand1; 176 | struct ud_itab_entry_operand operand2; 177 | struct ud_itab_entry_operand operand3; 178 | struct ud_itab_entry_operand operand4; 179 | uint32_t prefix; 180 | }; 181 | 182 | struct ud_lookup_table_list_entry { 183 | const uint16_t *table; 184 | enum ud_table_type type; 185 | const char *meta; 186 | }; 187 | 188 | extern struct ud_itab_entry ud_itab[]; 189 | extern struct ud_lookup_table_list_entry ud_lookup_table_list[]; 190 | 191 | #endif /* UD_DECODE_H */ 192 | 193 | /* vim:cindent 194 | * vim:expandtab 195 | * vim:ts=4 196 | * vim:sw=4 197 | */ 198 | -------------------------------------------------------------------------------- /Udis86/libudis86/extern.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/extern.h 2 | * 3 | * Copyright (c) 2002-2009, 2013 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UD_EXTERN_H 27 | #define UD_EXTERN_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | #include "types.h" 34 | 35 | #if defined(_MSC_VER) && defined(_USRDLL) 36 | # ifdef LIBUDIS86_EXPORTS 37 | # define LIBUDIS86_DLLEXTERN __declspec(dllexport) 38 | # else 39 | # define LIBUDIS86_DLLEXTERN __declspec(dllimport) 40 | # endif 41 | #else 42 | # define LIBUDIS86_DLLEXTERN 43 | #endif 44 | 45 | /* ============================= PUBLIC API ================================= */ 46 | 47 | extern LIBUDIS86_DLLEXTERN void ud_init(struct ud*); 48 | 49 | extern LIBUDIS86_DLLEXTERN void ud_set_mode(struct ud*, uint8_t); 50 | 51 | extern LIBUDIS86_DLLEXTERN void ud_set_pc(struct ud*, uint64_t); 52 | 53 | extern LIBUDIS86_DLLEXTERN void ud_set_input_hook(struct ud*, int (*)(struct ud*)); 54 | 55 | extern LIBUDIS86_DLLEXTERN void ud_set_input_buffer(struct ud*, const uint8_t*, size_t); 56 | 57 | #ifndef __UD_STANDALONE__ 58 | extern LIBUDIS86_DLLEXTERN void ud_set_input_file(struct ud*, FILE*); 59 | #endif /* __UD_STANDALONE__ */ 60 | 61 | extern LIBUDIS86_DLLEXTERN void ud_set_vendor(struct ud*, unsigned); 62 | 63 | extern LIBUDIS86_DLLEXTERN void ud_set_syntax(struct ud*, void (*)(struct ud*)); 64 | 65 | extern LIBUDIS86_DLLEXTERN void ud_input_skip(struct ud*, size_t); 66 | 67 | extern LIBUDIS86_DLLEXTERN int ud_input_end(const struct ud*); 68 | 69 | extern LIBUDIS86_DLLEXTERN unsigned int ud_decode(struct ud*); 70 | 71 | extern LIBUDIS86_DLLEXTERN unsigned int ud_disassemble(struct ud*); 72 | 73 | extern LIBUDIS86_DLLEXTERN void ud_translate_intel(struct ud*); 74 | 75 | extern LIBUDIS86_DLLEXTERN void ud_translate_att(struct ud*); 76 | 77 | extern LIBUDIS86_DLLEXTERN const char* ud_insn_asm(const struct ud* u); 78 | 79 | extern LIBUDIS86_DLLEXTERN const uint8_t* ud_insn_ptr(const struct ud* u); 80 | 81 | extern LIBUDIS86_DLLEXTERN uint64_t ud_insn_off(const struct ud*); 82 | 83 | extern LIBUDIS86_DLLEXTERN const char* ud_insn_hex(struct ud*); 84 | 85 | extern LIBUDIS86_DLLEXTERN unsigned int ud_insn_len(const struct ud* u); 86 | 87 | extern LIBUDIS86_DLLEXTERN const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n); 88 | 89 | extern LIBUDIS86_DLLEXTERN int ud_opr_is_sreg(const struct ud_operand *opr); 90 | 91 | extern LIBUDIS86_DLLEXTERN int ud_opr_is_gpr(const struct ud_operand *opr); 92 | 93 | extern LIBUDIS86_DLLEXTERN enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u); 94 | 95 | extern LIBUDIS86_DLLEXTERN const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); 96 | 97 | extern LIBUDIS86_DLLEXTERN void ud_set_user_opaque_data(struct ud*, void*); 98 | 99 | extern LIBUDIS86_DLLEXTERN void* ud_get_user_opaque_data(const struct ud*); 100 | 101 | extern LIBUDIS86_DLLEXTERN void ud_set_asm_buffer(struct ud *u, char *buf, size_t size); 102 | 103 | extern LIBUDIS86_DLLEXTERN void ud_set_sym_resolver(struct ud *u, 104 | const char* (*resolver)(struct ud*, 105 | uint64_t addr, 106 | int64_t *offset)); 107 | 108 | /* ========================================================================== */ 109 | 110 | #ifdef __cplusplus 111 | } 112 | #endif 113 | #endif /* UD_EXTERN_H */ 114 | -------------------------------------------------------------------------------- /Udis86/libudis86/itab.h: -------------------------------------------------------------------------------- 1 | #ifndef UD_ITAB_H 2 | #define UD_ITAB_H 3 | 4 | /* itab.h -- generated by udis86:scripts/ud_itab.py, do no edit */ 5 | 6 | /* ud_table_type -- lookup table types (see decode.c) */ 7 | enum ud_table_type { 8 | UD_TAB__OPC_MOD, 9 | UD_TAB__OPC_MODE, 10 | UD_TAB__OPC_REG, 11 | UD_TAB__OPC_VEX_L, 12 | UD_TAB__OPC_RM, 13 | UD_TAB__OPC_TABLE, 14 | UD_TAB__OPC_ASIZE, 15 | UD_TAB__OPC_VENDOR, 16 | UD_TAB__OPC_3DNOW, 17 | UD_TAB__OPC_SSE, 18 | UD_TAB__OPC_X87, 19 | UD_TAB__OPC_VEX_W, 20 | UD_TAB__OPC_OSIZE, 21 | UD_TAB__OPC_VEX 22 | }; 23 | 24 | /* ud_mnemonic -- mnemonic constants */ 25 | enum ud_mnemonic_code { 26 | UD_Iaaa, 27 | UD_Iaad, 28 | UD_Iaam, 29 | UD_Iaas, 30 | UD_Iadc, 31 | UD_Iadd, 32 | UD_Iaddpd, 33 | UD_Iaddps, 34 | UD_Iaddsd, 35 | UD_Iaddss, 36 | UD_Iaddsubpd, 37 | UD_Iaddsubps, 38 | UD_Iaesdec, 39 | UD_Iaesdeclast, 40 | UD_Iaesenc, 41 | UD_Iaesenclast, 42 | UD_Iaesimc, 43 | UD_Iaeskeygenassist, 44 | UD_Iand, 45 | UD_Iandnpd, 46 | UD_Iandnps, 47 | UD_Iandpd, 48 | UD_Iandps, 49 | UD_Iarpl, 50 | UD_Iblendpd, 51 | UD_Iblendps, 52 | UD_Iblendvpd, 53 | UD_Iblendvps, 54 | UD_Ibound, 55 | UD_Ibsf, 56 | UD_Ibsr, 57 | UD_Ibswap, 58 | UD_Ibt, 59 | UD_Ibtc, 60 | UD_Ibtr, 61 | UD_Ibts, 62 | UD_Icall, 63 | UD_Icbw, 64 | UD_Icdq, 65 | UD_Icdqe, 66 | UD_Iclc, 67 | UD_Icld, 68 | UD_Iclflush, 69 | UD_Iclgi, 70 | UD_Icli, 71 | UD_Iclts, 72 | UD_Icmc, 73 | UD_Icmova, 74 | UD_Icmovae, 75 | UD_Icmovb, 76 | UD_Icmovbe, 77 | UD_Icmovg, 78 | UD_Icmovge, 79 | UD_Icmovl, 80 | UD_Icmovle, 81 | UD_Icmovno, 82 | UD_Icmovnp, 83 | UD_Icmovns, 84 | UD_Icmovnz, 85 | UD_Icmovo, 86 | UD_Icmovp, 87 | UD_Icmovs, 88 | UD_Icmovz, 89 | UD_Icmp, 90 | UD_Icmppd, 91 | UD_Icmpps, 92 | UD_Icmpsb, 93 | UD_Icmpsd, 94 | UD_Icmpsq, 95 | UD_Icmpss, 96 | UD_Icmpsw, 97 | UD_Icmpxchg, 98 | UD_Icmpxchg16b, 99 | UD_Icmpxchg8b, 100 | UD_Icomisd, 101 | UD_Icomiss, 102 | UD_Icpuid, 103 | UD_Icqo, 104 | UD_Icrc32, 105 | UD_Icvtdq2pd, 106 | UD_Icvtdq2ps, 107 | UD_Icvtpd2dq, 108 | UD_Icvtpd2pi, 109 | UD_Icvtpd2ps, 110 | UD_Icvtpi2pd, 111 | UD_Icvtpi2ps, 112 | UD_Icvtps2dq, 113 | UD_Icvtps2pd, 114 | UD_Icvtps2pi, 115 | UD_Icvtsd2si, 116 | UD_Icvtsd2ss, 117 | UD_Icvtsi2sd, 118 | UD_Icvtsi2ss, 119 | UD_Icvtss2sd, 120 | UD_Icvtss2si, 121 | UD_Icvttpd2dq, 122 | UD_Icvttpd2pi, 123 | UD_Icvttps2dq, 124 | UD_Icvttps2pi, 125 | UD_Icvttsd2si, 126 | UD_Icvttss2si, 127 | UD_Icwd, 128 | UD_Icwde, 129 | UD_Idaa, 130 | UD_Idas, 131 | UD_Idec, 132 | UD_Idiv, 133 | UD_Idivpd, 134 | UD_Idivps, 135 | UD_Idivsd, 136 | UD_Idivss, 137 | UD_Idppd, 138 | UD_Idpps, 139 | UD_Iemms, 140 | UD_Ienter, 141 | UD_Iextractps, 142 | UD_If2xm1, 143 | UD_Ifabs, 144 | UD_Ifadd, 145 | UD_Ifaddp, 146 | UD_Ifbld, 147 | UD_Ifbstp, 148 | UD_Ifchs, 149 | UD_Ifclex, 150 | UD_Ifcmovb, 151 | UD_Ifcmovbe, 152 | UD_Ifcmove, 153 | UD_Ifcmovnb, 154 | UD_Ifcmovnbe, 155 | UD_Ifcmovne, 156 | UD_Ifcmovnu, 157 | UD_Ifcmovu, 158 | UD_Ifcom, 159 | UD_Ifcom2, 160 | UD_Ifcomi, 161 | UD_Ifcomip, 162 | UD_Ifcomp, 163 | UD_Ifcomp3, 164 | UD_Ifcomp5, 165 | UD_Ifcompp, 166 | UD_Ifcos, 167 | UD_Ifdecstp, 168 | UD_Ifdiv, 169 | UD_Ifdivp, 170 | UD_Ifdivr, 171 | UD_Ifdivrp, 172 | UD_Ifemms, 173 | UD_Iffree, 174 | UD_Iffreep, 175 | UD_Ifiadd, 176 | UD_Ificom, 177 | UD_Ificomp, 178 | UD_Ifidiv, 179 | UD_Ifidivr, 180 | UD_Ifild, 181 | UD_Ifimul, 182 | UD_Ifincstp, 183 | UD_Ifist, 184 | UD_Ifistp, 185 | UD_Ifisttp, 186 | UD_Ifisub, 187 | UD_Ifisubr, 188 | UD_Ifld, 189 | UD_Ifld1, 190 | UD_Ifldcw, 191 | UD_Ifldenv, 192 | UD_Ifldl2e, 193 | UD_Ifldl2t, 194 | UD_Ifldlg2, 195 | UD_Ifldln2, 196 | UD_Ifldpi, 197 | UD_Ifldz, 198 | UD_Ifmul, 199 | UD_Ifmulp, 200 | UD_Ifndisi, 201 | UD_Ifneni, 202 | UD_Ifninit, 203 | UD_Ifnop, 204 | UD_Ifnsave, 205 | UD_Ifnsetpm, 206 | UD_Ifnstcw, 207 | UD_Ifnstenv, 208 | UD_Ifnstsw, 209 | UD_Ifpatan, 210 | UD_Ifprem, 211 | UD_Ifprem1, 212 | UD_Ifptan, 213 | UD_Ifrndint, 214 | UD_Ifrstor, 215 | UD_Ifrstpm, 216 | UD_Ifscale, 217 | UD_Ifsin, 218 | UD_Ifsincos, 219 | UD_Ifsqrt, 220 | UD_Ifst, 221 | UD_Ifstp, 222 | UD_Ifstp1, 223 | UD_Ifstp8, 224 | UD_Ifstp9, 225 | UD_Ifsub, 226 | UD_Ifsubp, 227 | UD_Ifsubr, 228 | UD_Ifsubrp, 229 | UD_Iftst, 230 | UD_Ifucom, 231 | UD_Ifucomi, 232 | UD_Ifucomip, 233 | UD_Ifucomp, 234 | UD_Ifucompp, 235 | UD_Ifxam, 236 | UD_Ifxch, 237 | UD_Ifxch4, 238 | UD_Ifxch7, 239 | UD_Ifxrstor, 240 | UD_Ifxsave, 241 | UD_Ifxtract, 242 | UD_Ifyl2x, 243 | UD_Ifyl2xp1, 244 | UD_Igetsec, 245 | UD_Ihaddpd, 246 | UD_Ihaddps, 247 | UD_Ihlt, 248 | UD_Ihsubpd, 249 | UD_Ihsubps, 250 | UD_Iidiv, 251 | UD_Iimul, 252 | UD_Iin, 253 | UD_Iinc, 254 | UD_Iinsb, 255 | UD_Iinsd, 256 | UD_Iinsertps, 257 | UD_Iinsw, 258 | UD_Iint, 259 | UD_Iint1, 260 | UD_Iint3, 261 | UD_Iinto, 262 | UD_Iinvd, 263 | UD_Iinvept, 264 | UD_Iinvlpg, 265 | UD_Iinvlpga, 266 | UD_Iinvvpid, 267 | UD_Iiretd, 268 | UD_Iiretq, 269 | UD_Iiretw, 270 | UD_Ija, 271 | UD_Ijae, 272 | UD_Ijb, 273 | UD_Ijbe, 274 | UD_Ijcxz, 275 | UD_Ijecxz, 276 | UD_Ijg, 277 | UD_Ijge, 278 | UD_Ijl, 279 | UD_Ijle, 280 | UD_Ijmp, 281 | UD_Ijno, 282 | UD_Ijnp, 283 | UD_Ijns, 284 | UD_Ijnz, 285 | UD_Ijo, 286 | UD_Ijp, 287 | UD_Ijrcxz, 288 | UD_Ijs, 289 | UD_Ijz, 290 | UD_Ilahf, 291 | UD_Ilar, 292 | UD_Ilddqu, 293 | UD_Ildmxcsr, 294 | UD_Ilds, 295 | UD_Ilea, 296 | UD_Ileave, 297 | UD_Iles, 298 | UD_Ilfence, 299 | UD_Ilfs, 300 | UD_Ilgdt, 301 | UD_Ilgs, 302 | UD_Ilidt, 303 | UD_Illdt, 304 | UD_Ilmsw, 305 | UD_Ilock, 306 | UD_Ilodsb, 307 | UD_Ilodsd, 308 | UD_Ilodsq, 309 | UD_Ilodsw, 310 | UD_Iloop, 311 | UD_Iloope, 312 | UD_Iloopne, 313 | UD_Ilsl, 314 | UD_Ilss, 315 | UD_Iltr, 316 | UD_Imaskmovdqu, 317 | UD_Imaskmovq, 318 | UD_Imaxpd, 319 | UD_Imaxps, 320 | UD_Imaxsd, 321 | UD_Imaxss, 322 | UD_Imfence, 323 | UD_Iminpd, 324 | UD_Iminps, 325 | UD_Iminsd, 326 | UD_Iminss, 327 | UD_Imonitor, 328 | UD_Imontmul, 329 | UD_Imov, 330 | UD_Imovapd, 331 | UD_Imovaps, 332 | UD_Imovbe, 333 | UD_Imovd, 334 | UD_Imovddup, 335 | UD_Imovdq2q, 336 | UD_Imovdqa, 337 | UD_Imovdqu, 338 | UD_Imovhlps, 339 | UD_Imovhpd, 340 | UD_Imovhps, 341 | UD_Imovlhps, 342 | UD_Imovlpd, 343 | UD_Imovlps, 344 | UD_Imovmskpd, 345 | UD_Imovmskps, 346 | UD_Imovntdq, 347 | UD_Imovntdqa, 348 | UD_Imovnti, 349 | UD_Imovntpd, 350 | UD_Imovntps, 351 | UD_Imovntq, 352 | UD_Imovq, 353 | UD_Imovq2dq, 354 | UD_Imovsb, 355 | UD_Imovsd, 356 | UD_Imovshdup, 357 | UD_Imovsldup, 358 | UD_Imovsq, 359 | UD_Imovss, 360 | UD_Imovsw, 361 | UD_Imovsx, 362 | UD_Imovsxd, 363 | UD_Imovupd, 364 | UD_Imovups, 365 | UD_Imovzx, 366 | UD_Impsadbw, 367 | UD_Imul, 368 | UD_Imulpd, 369 | UD_Imulps, 370 | UD_Imulsd, 371 | UD_Imulss, 372 | UD_Imwait, 373 | UD_Ineg, 374 | UD_Inop, 375 | UD_Inot, 376 | UD_Ior, 377 | UD_Iorpd, 378 | UD_Iorps, 379 | UD_Iout, 380 | UD_Ioutsb, 381 | UD_Ioutsd, 382 | UD_Ioutsw, 383 | UD_Ipabsb, 384 | UD_Ipabsd, 385 | UD_Ipabsw, 386 | UD_Ipackssdw, 387 | UD_Ipacksswb, 388 | UD_Ipackusdw, 389 | UD_Ipackuswb, 390 | UD_Ipaddb, 391 | UD_Ipaddd, 392 | UD_Ipaddq, 393 | UD_Ipaddsb, 394 | UD_Ipaddsw, 395 | UD_Ipaddusb, 396 | UD_Ipaddusw, 397 | UD_Ipaddw, 398 | UD_Ipalignr, 399 | UD_Ipand, 400 | UD_Ipandn, 401 | UD_Ipavgb, 402 | UD_Ipavgusb, 403 | UD_Ipavgw, 404 | UD_Ipblendvb, 405 | UD_Ipblendw, 406 | UD_Ipclmulqdq, 407 | UD_Ipcmpeqb, 408 | UD_Ipcmpeqd, 409 | UD_Ipcmpeqq, 410 | UD_Ipcmpeqw, 411 | UD_Ipcmpestri, 412 | UD_Ipcmpestrm, 413 | UD_Ipcmpgtb, 414 | UD_Ipcmpgtd, 415 | UD_Ipcmpgtq, 416 | UD_Ipcmpgtw, 417 | UD_Ipcmpistri, 418 | UD_Ipcmpistrm, 419 | UD_Ipextrb, 420 | UD_Ipextrd, 421 | UD_Ipextrq, 422 | UD_Ipextrw, 423 | UD_Ipf2id, 424 | UD_Ipf2iw, 425 | UD_Ipfacc, 426 | UD_Ipfadd, 427 | UD_Ipfcmpeq, 428 | UD_Ipfcmpge, 429 | UD_Ipfcmpgt, 430 | UD_Ipfmax, 431 | UD_Ipfmin, 432 | UD_Ipfmul, 433 | UD_Ipfnacc, 434 | UD_Ipfpnacc, 435 | UD_Ipfrcp, 436 | UD_Ipfrcpit1, 437 | UD_Ipfrcpit2, 438 | UD_Ipfrsqit1, 439 | UD_Ipfrsqrt, 440 | UD_Ipfsub, 441 | UD_Ipfsubr, 442 | UD_Iphaddd, 443 | UD_Iphaddsw, 444 | UD_Iphaddw, 445 | UD_Iphminposuw, 446 | UD_Iphsubd, 447 | UD_Iphsubsw, 448 | UD_Iphsubw, 449 | UD_Ipi2fd, 450 | UD_Ipi2fw, 451 | UD_Ipinsrb, 452 | UD_Ipinsrd, 453 | UD_Ipinsrq, 454 | UD_Ipinsrw, 455 | UD_Ipmaddubsw, 456 | UD_Ipmaddwd, 457 | UD_Ipmaxsb, 458 | UD_Ipmaxsd, 459 | UD_Ipmaxsw, 460 | UD_Ipmaxub, 461 | UD_Ipmaxud, 462 | UD_Ipmaxuw, 463 | UD_Ipminsb, 464 | UD_Ipminsd, 465 | UD_Ipminsw, 466 | UD_Ipminub, 467 | UD_Ipminud, 468 | UD_Ipminuw, 469 | UD_Ipmovmskb, 470 | UD_Ipmovsxbd, 471 | UD_Ipmovsxbq, 472 | UD_Ipmovsxbw, 473 | UD_Ipmovsxdq, 474 | UD_Ipmovsxwd, 475 | UD_Ipmovsxwq, 476 | UD_Ipmovzxbd, 477 | UD_Ipmovzxbq, 478 | UD_Ipmovzxbw, 479 | UD_Ipmovzxdq, 480 | UD_Ipmovzxwd, 481 | UD_Ipmovzxwq, 482 | UD_Ipmuldq, 483 | UD_Ipmulhrsw, 484 | UD_Ipmulhrw, 485 | UD_Ipmulhuw, 486 | UD_Ipmulhw, 487 | UD_Ipmulld, 488 | UD_Ipmullw, 489 | UD_Ipmuludq, 490 | UD_Ipop, 491 | UD_Ipopa, 492 | UD_Ipopad, 493 | UD_Ipopcnt, 494 | UD_Ipopfd, 495 | UD_Ipopfq, 496 | UD_Ipopfw, 497 | UD_Ipor, 498 | UD_Iprefetch, 499 | UD_Iprefetchnta, 500 | UD_Iprefetcht0, 501 | UD_Iprefetcht1, 502 | UD_Iprefetcht2, 503 | UD_Ipsadbw, 504 | UD_Ipshufb, 505 | UD_Ipshufd, 506 | UD_Ipshufhw, 507 | UD_Ipshuflw, 508 | UD_Ipshufw, 509 | UD_Ipsignb, 510 | UD_Ipsignd, 511 | UD_Ipsignw, 512 | UD_Ipslld, 513 | UD_Ipslldq, 514 | UD_Ipsllq, 515 | UD_Ipsllw, 516 | UD_Ipsrad, 517 | UD_Ipsraw, 518 | UD_Ipsrld, 519 | UD_Ipsrldq, 520 | UD_Ipsrlq, 521 | UD_Ipsrlw, 522 | UD_Ipsubb, 523 | UD_Ipsubd, 524 | UD_Ipsubq, 525 | UD_Ipsubsb, 526 | UD_Ipsubsw, 527 | UD_Ipsubusb, 528 | UD_Ipsubusw, 529 | UD_Ipsubw, 530 | UD_Ipswapd, 531 | UD_Iptest, 532 | UD_Ipunpckhbw, 533 | UD_Ipunpckhdq, 534 | UD_Ipunpckhqdq, 535 | UD_Ipunpckhwd, 536 | UD_Ipunpcklbw, 537 | UD_Ipunpckldq, 538 | UD_Ipunpcklqdq, 539 | UD_Ipunpcklwd, 540 | UD_Ipush, 541 | UD_Ipusha, 542 | UD_Ipushad, 543 | UD_Ipushfd, 544 | UD_Ipushfq, 545 | UD_Ipushfw, 546 | UD_Ipxor, 547 | UD_Ircl, 548 | UD_Ircpps, 549 | UD_Ircpss, 550 | UD_Ircr, 551 | UD_Irdmsr, 552 | UD_Irdpmc, 553 | UD_Irdrand, 554 | UD_Irdtsc, 555 | UD_Irdtscp, 556 | UD_Irep, 557 | UD_Irepne, 558 | UD_Iret, 559 | UD_Iretf, 560 | UD_Irol, 561 | UD_Iror, 562 | UD_Iroundpd, 563 | UD_Iroundps, 564 | UD_Iroundsd, 565 | UD_Iroundss, 566 | UD_Irsm, 567 | UD_Irsqrtps, 568 | UD_Irsqrtss, 569 | UD_Isahf, 570 | UD_Isalc, 571 | UD_Isar, 572 | UD_Isbb, 573 | UD_Iscasb, 574 | UD_Iscasd, 575 | UD_Iscasq, 576 | UD_Iscasw, 577 | UD_Iseta, 578 | UD_Isetae, 579 | UD_Isetb, 580 | UD_Isetbe, 581 | UD_Isetg, 582 | UD_Isetge, 583 | UD_Isetl, 584 | UD_Isetle, 585 | UD_Isetno, 586 | UD_Isetnp, 587 | UD_Isetns, 588 | UD_Isetnz, 589 | UD_Iseto, 590 | UD_Isetp, 591 | UD_Isets, 592 | UD_Isetz, 593 | UD_Isfence, 594 | UD_Isgdt, 595 | UD_Ishl, 596 | UD_Ishld, 597 | UD_Ishr, 598 | UD_Ishrd, 599 | UD_Ishufpd, 600 | UD_Ishufps, 601 | UD_Isidt, 602 | UD_Iskinit, 603 | UD_Isldt, 604 | UD_Ismsw, 605 | UD_Isqrtpd, 606 | UD_Isqrtps, 607 | UD_Isqrtsd, 608 | UD_Isqrtss, 609 | UD_Istc, 610 | UD_Istd, 611 | UD_Istgi, 612 | UD_Isti, 613 | UD_Istmxcsr, 614 | UD_Istosb, 615 | UD_Istosd, 616 | UD_Istosq, 617 | UD_Istosw, 618 | UD_Istr, 619 | UD_Isub, 620 | UD_Isubpd, 621 | UD_Isubps, 622 | UD_Isubsd, 623 | UD_Isubss, 624 | UD_Iswapgs, 625 | UD_Isyscall, 626 | UD_Isysenter, 627 | UD_Isysexit, 628 | UD_Isysret, 629 | UD_Itest, 630 | UD_Iucomisd, 631 | UD_Iucomiss, 632 | UD_Iud2, 633 | UD_Iunpckhpd, 634 | UD_Iunpckhps, 635 | UD_Iunpcklpd, 636 | UD_Iunpcklps, 637 | UD_Ivaddpd, 638 | UD_Ivaddps, 639 | UD_Ivaddsd, 640 | UD_Ivaddss, 641 | UD_Ivaddsubpd, 642 | UD_Ivaddsubps, 643 | UD_Ivaesdec, 644 | UD_Ivaesdeclast, 645 | UD_Ivaesenc, 646 | UD_Ivaesenclast, 647 | UD_Ivaesimc, 648 | UD_Ivaeskeygenassist, 649 | UD_Ivandnpd, 650 | UD_Ivandnps, 651 | UD_Ivandpd, 652 | UD_Ivandps, 653 | UD_Ivblendpd, 654 | UD_Ivblendps, 655 | UD_Ivblendvpd, 656 | UD_Ivblendvps, 657 | UD_Ivbroadcastsd, 658 | UD_Ivbroadcastss, 659 | UD_Ivcmppd, 660 | UD_Ivcmpps, 661 | UD_Ivcmpsd, 662 | UD_Ivcmpss, 663 | UD_Ivcomisd, 664 | UD_Ivcomiss, 665 | UD_Ivcvtdq2pd, 666 | UD_Ivcvtdq2ps, 667 | UD_Ivcvtpd2dq, 668 | UD_Ivcvtpd2ps, 669 | UD_Ivcvtps2dq, 670 | UD_Ivcvtps2pd, 671 | UD_Ivcvtsd2si, 672 | UD_Ivcvtsd2ss, 673 | UD_Ivcvtsi2sd, 674 | UD_Ivcvtsi2ss, 675 | UD_Ivcvtss2sd, 676 | UD_Ivcvtss2si, 677 | UD_Ivcvttpd2dq, 678 | UD_Ivcvttps2dq, 679 | UD_Ivcvttsd2si, 680 | UD_Ivcvttss2si, 681 | UD_Ivdivpd, 682 | UD_Ivdivps, 683 | UD_Ivdivsd, 684 | UD_Ivdivss, 685 | UD_Ivdppd, 686 | UD_Ivdpps, 687 | UD_Iverr, 688 | UD_Iverw, 689 | UD_Ivextractf128, 690 | UD_Ivextractps, 691 | UD_Ivhaddpd, 692 | UD_Ivhaddps, 693 | UD_Ivhsubpd, 694 | UD_Ivhsubps, 695 | UD_Ivinsertf128, 696 | UD_Ivinsertps, 697 | UD_Ivlddqu, 698 | UD_Ivmaskmovdqu, 699 | UD_Ivmaskmovpd, 700 | UD_Ivmaskmovps, 701 | UD_Ivmaxpd, 702 | UD_Ivmaxps, 703 | UD_Ivmaxsd, 704 | UD_Ivmaxss, 705 | UD_Ivmcall, 706 | UD_Ivmclear, 707 | UD_Ivminpd, 708 | UD_Ivminps, 709 | UD_Ivminsd, 710 | UD_Ivminss, 711 | UD_Ivmlaunch, 712 | UD_Ivmload, 713 | UD_Ivmmcall, 714 | UD_Ivmovapd, 715 | UD_Ivmovaps, 716 | UD_Ivmovd, 717 | UD_Ivmovddup, 718 | UD_Ivmovdqa, 719 | UD_Ivmovdqu, 720 | UD_Ivmovhlps, 721 | UD_Ivmovhpd, 722 | UD_Ivmovhps, 723 | UD_Ivmovlhps, 724 | UD_Ivmovlpd, 725 | UD_Ivmovlps, 726 | UD_Ivmovmskpd, 727 | UD_Ivmovmskps, 728 | UD_Ivmovntdq, 729 | UD_Ivmovntdqa, 730 | UD_Ivmovntpd, 731 | UD_Ivmovntps, 732 | UD_Ivmovq, 733 | UD_Ivmovsd, 734 | UD_Ivmovshdup, 735 | UD_Ivmovsldup, 736 | UD_Ivmovss, 737 | UD_Ivmovupd, 738 | UD_Ivmovups, 739 | UD_Ivmpsadbw, 740 | UD_Ivmptrld, 741 | UD_Ivmptrst, 742 | UD_Ivmread, 743 | UD_Ivmresume, 744 | UD_Ivmrun, 745 | UD_Ivmsave, 746 | UD_Ivmulpd, 747 | UD_Ivmulps, 748 | UD_Ivmulsd, 749 | UD_Ivmulss, 750 | UD_Ivmwrite, 751 | UD_Ivmxoff, 752 | UD_Ivmxon, 753 | UD_Ivorpd, 754 | UD_Ivorps, 755 | UD_Ivpabsb, 756 | UD_Ivpabsd, 757 | UD_Ivpabsw, 758 | UD_Ivpackssdw, 759 | UD_Ivpacksswb, 760 | UD_Ivpackusdw, 761 | UD_Ivpackuswb, 762 | UD_Ivpaddb, 763 | UD_Ivpaddd, 764 | UD_Ivpaddq, 765 | UD_Ivpaddsb, 766 | UD_Ivpaddsw, 767 | UD_Ivpaddusb, 768 | UD_Ivpaddusw, 769 | UD_Ivpaddw, 770 | UD_Ivpalignr, 771 | UD_Ivpand, 772 | UD_Ivpandn, 773 | UD_Ivpavgb, 774 | UD_Ivpavgw, 775 | UD_Ivpblendvb, 776 | UD_Ivpblendw, 777 | UD_Ivpclmulqdq, 778 | UD_Ivpcmpeqb, 779 | UD_Ivpcmpeqd, 780 | UD_Ivpcmpeqq, 781 | UD_Ivpcmpeqw, 782 | UD_Ivpcmpestri, 783 | UD_Ivpcmpestrm, 784 | UD_Ivpcmpgtb, 785 | UD_Ivpcmpgtd, 786 | UD_Ivpcmpgtq, 787 | UD_Ivpcmpgtw, 788 | UD_Ivpcmpistri, 789 | UD_Ivpcmpistrm, 790 | UD_Ivperm2f128, 791 | UD_Ivpermilpd, 792 | UD_Ivpermilps, 793 | UD_Ivpextrb, 794 | UD_Ivpextrd, 795 | UD_Ivpextrq, 796 | UD_Ivpextrw, 797 | UD_Ivphaddd, 798 | UD_Ivphaddsw, 799 | UD_Ivphaddw, 800 | UD_Ivphminposuw, 801 | UD_Ivphsubd, 802 | UD_Ivphsubsw, 803 | UD_Ivphsubw, 804 | UD_Ivpinsrb, 805 | UD_Ivpinsrd, 806 | UD_Ivpinsrq, 807 | UD_Ivpinsrw, 808 | UD_Ivpmaddubsw, 809 | UD_Ivpmaddwd, 810 | UD_Ivpmaxsb, 811 | UD_Ivpmaxsd, 812 | UD_Ivpmaxsw, 813 | UD_Ivpmaxub, 814 | UD_Ivpmaxud, 815 | UD_Ivpmaxuw, 816 | UD_Ivpminsb, 817 | UD_Ivpminsd, 818 | UD_Ivpminsw, 819 | UD_Ivpminub, 820 | UD_Ivpminud, 821 | UD_Ivpminuw, 822 | UD_Ivpmovmskb, 823 | UD_Ivpmovsxbd, 824 | UD_Ivpmovsxbq, 825 | UD_Ivpmovsxbw, 826 | UD_Ivpmovsxwd, 827 | UD_Ivpmovsxwq, 828 | UD_Ivpmovzxbd, 829 | UD_Ivpmovzxbq, 830 | UD_Ivpmovzxbw, 831 | UD_Ivpmovzxdq, 832 | UD_Ivpmovzxwd, 833 | UD_Ivpmovzxwq, 834 | UD_Ivpmuldq, 835 | UD_Ivpmulhrsw, 836 | UD_Ivpmulhuw, 837 | UD_Ivpmulhw, 838 | UD_Ivpmulld, 839 | UD_Ivpmullw, 840 | UD_Ivpor, 841 | UD_Ivpsadbw, 842 | UD_Ivpshufb, 843 | UD_Ivpshufd, 844 | UD_Ivpshufhw, 845 | UD_Ivpshuflw, 846 | UD_Ivpsignb, 847 | UD_Ivpsignd, 848 | UD_Ivpsignw, 849 | UD_Ivpslld, 850 | UD_Ivpslldq, 851 | UD_Ivpsllq, 852 | UD_Ivpsllw, 853 | UD_Ivpsrad, 854 | UD_Ivpsraw, 855 | UD_Ivpsrld, 856 | UD_Ivpsrldq, 857 | UD_Ivpsrlq, 858 | UD_Ivpsrlw, 859 | UD_Ivpsubb, 860 | UD_Ivpsubd, 861 | UD_Ivpsubq, 862 | UD_Ivpsubsb, 863 | UD_Ivpsubsw, 864 | UD_Ivpsubusb, 865 | UD_Ivpsubusw, 866 | UD_Ivpsubw, 867 | UD_Ivptest, 868 | UD_Ivpunpckhbw, 869 | UD_Ivpunpckhdq, 870 | UD_Ivpunpckhqdq, 871 | UD_Ivpunpckhwd, 872 | UD_Ivpunpcklbw, 873 | UD_Ivpunpckldq, 874 | UD_Ivpunpcklqdq, 875 | UD_Ivpunpcklwd, 876 | UD_Ivpxor, 877 | UD_Ivrcpps, 878 | UD_Ivrcpss, 879 | UD_Ivroundpd, 880 | UD_Ivroundps, 881 | UD_Ivroundsd, 882 | UD_Ivroundss, 883 | UD_Ivrsqrtps, 884 | UD_Ivrsqrtss, 885 | UD_Ivshufpd, 886 | UD_Ivshufps, 887 | UD_Ivsqrtpd, 888 | UD_Ivsqrtps, 889 | UD_Ivsqrtsd, 890 | UD_Ivsqrtss, 891 | UD_Ivstmxcsr, 892 | UD_Ivsubpd, 893 | UD_Ivsubps, 894 | UD_Ivsubsd, 895 | UD_Ivsubss, 896 | UD_Ivtestpd, 897 | UD_Ivtestps, 898 | UD_Ivucomisd, 899 | UD_Ivucomiss, 900 | UD_Ivunpckhpd, 901 | UD_Ivunpckhps, 902 | UD_Ivunpcklpd, 903 | UD_Ivunpcklps, 904 | UD_Ivxorpd, 905 | UD_Ivxorps, 906 | UD_Ivzeroall, 907 | UD_Ivzeroupper, 908 | UD_Iwait, 909 | UD_Iwbinvd, 910 | UD_Iwrmsr, 911 | UD_Ixadd, 912 | UD_Ixchg, 913 | UD_Ixcryptcbc, 914 | UD_Ixcryptcfb, 915 | UD_Ixcryptctr, 916 | UD_Ixcryptecb, 917 | UD_Ixcryptofb, 918 | UD_Ixgetbv, 919 | UD_Ixlatb, 920 | UD_Ixor, 921 | UD_Ixorpd, 922 | UD_Ixorps, 923 | UD_Ixrstor, 924 | UD_Ixsave, 925 | UD_Ixsetbv, 926 | UD_Ixsha1, 927 | UD_Ixsha256, 928 | UD_Ixstore, 929 | UD_Iinvalid, 930 | UD_I3dnow, 931 | UD_Inone, 932 | UD_Idb, 933 | UD_Ipause, 934 | UD_MAX_MNEMONIC_CODE 935 | }; 936 | 937 | extern const char * ud_mnemonics_str[]; 938 | 939 | #endif /* UD_ITAB_H */ 940 | -------------------------------------------------------------------------------- /Udis86/libudis86/syn-att.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn-att.c 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #include "types.h" 27 | #include "extern.h" 28 | #include "decode.h" 29 | #include "itab.h" 30 | #include "syn.h" 31 | #include "udint.h" 32 | 33 | /* ----------------------------------------------------------------------------- 34 | * opr_cast() - Prints an operand cast. 35 | * ----------------------------------------------------------------------------- 36 | */ 37 | static void 38 | opr_cast(struct ud* u, struct ud_operand* op) 39 | { 40 | switch(op->size) { 41 | case 16 : case 32 : 42 | ud_asmprintf(u, "*"); break; 43 | default: break; 44 | } 45 | } 46 | 47 | /* ----------------------------------------------------------------------------- 48 | * gen_operand() - Generates assembly output for each operand. 49 | * ----------------------------------------------------------------------------- 50 | */ 51 | static void 52 | gen_operand(struct ud* u, struct ud_operand* op) 53 | { 54 | switch(op->type) { 55 | case UD_OP_CONST: 56 | ud_asmprintf(u, "$0x%x", op->lval.udword); 57 | break; 58 | 59 | case UD_OP_REG: 60 | ud_asmprintf(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); 61 | break; 62 | 63 | case UD_OP_MEM: 64 | if (u->br_far) { 65 | opr_cast(u, op); 66 | } 67 | if (u->pfx_seg) { 68 | ud_asmprintf(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); 69 | } 70 | if (op->offset != 0) { 71 | ud_syn_print_mem_disp(u, op, 0); 72 | } 73 | if (op->base) { 74 | ud_asmprintf(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); 75 | } 76 | if (op->index) { 77 | if (op->base) { 78 | ud_asmprintf(u, ","); 79 | } else { 80 | ud_asmprintf(u, "("); 81 | } 82 | ud_asmprintf(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); 83 | } 84 | if (op->scale) { 85 | ud_asmprintf(u, ",%d", op->scale); 86 | } 87 | if (op->base || op->index) { 88 | ud_asmprintf(u, ")"); 89 | } 90 | break; 91 | 92 | case UD_OP_IMM: 93 | ud_asmprintf(u, "$"); 94 | ud_syn_print_imm(u, op); 95 | break; 96 | 97 | case UD_OP_JIMM: 98 | ud_syn_print_addr(u, ud_syn_rel_target(u, op)); 99 | break; 100 | 101 | case UD_OP_PTR: 102 | switch (op->size) { 103 | case 32: 104 | ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, 105 | op->lval.ptr.off & 0xFFFF); 106 | break; 107 | case 48: 108 | ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, 109 | op->lval.ptr.off); 110 | break; 111 | } 112 | break; 113 | 114 | default: return; 115 | } 116 | } 117 | 118 | /* ============================================================================= 119 | * translates to AT&T syntax 120 | * ============================================================================= 121 | */ 122 | extern void 123 | ud_translate_att(struct ud *u) 124 | { 125 | int size = 0; 126 | int star = 0; 127 | 128 | /* check if P_OSO prefix is used */ 129 | if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { 130 | switch (u->dis_mode) { 131 | case 16: 132 | ud_asmprintf(u, "o32 "); 133 | break; 134 | case 32: 135 | case 64: 136 | ud_asmprintf(u, "o16 "); 137 | break; 138 | } 139 | } 140 | 141 | /* check if P_ASO prefix was used */ 142 | if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { 143 | switch (u->dis_mode) { 144 | case 16: 145 | ud_asmprintf(u, "a32 "); 146 | break; 147 | case 32: 148 | ud_asmprintf(u, "a16 "); 149 | break; 150 | case 64: 151 | ud_asmprintf(u, "a32 "); 152 | break; 153 | } 154 | } 155 | 156 | if (u->pfx_lock) 157 | ud_asmprintf(u, "lock "); 158 | if (u->pfx_rep) { 159 | ud_asmprintf(u, "rep "); 160 | } else if (u->pfx_repe) { 161 | ud_asmprintf(u, "repe "); 162 | } else if (u->pfx_repne) { 163 | ud_asmprintf(u, "repne "); 164 | } 165 | 166 | /* special instructions */ 167 | switch (u->mnemonic) { 168 | case UD_Iretf: 169 | ud_asmprintf(u, "lret "); 170 | break; 171 | case UD_Idb: 172 | ud_asmprintf(u, ".byte 0x%x", u->operand[0].lval.ubyte); 173 | return; 174 | case UD_Ijmp: 175 | case UD_Icall: 176 | if (u->br_far) ud_asmprintf(u, "l"); 177 | if (u->operand[0].type == UD_OP_REG) { 178 | star = 1; 179 | } 180 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 181 | break; 182 | case UD_Ibound: 183 | case UD_Ienter: 184 | if (u->operand[0].type != UD_NONE) 185 | gen_operand(u, &u->operand[0]); 186 | if (u->operand[1].type != UD_NONE) { 187 | ud_asmprintf(u, ","); 188 | gen_operand(u, &u->operand[1]); 189 | } 190 | return; 191 | default: 192 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 193 | } 194 | 195 | if (size == 8) { 196 | ud_asmprintf(u, "b"); 197 | } else if (size == 16) { 198 | ud_asmprintf(u, "w"); 199 | } else if (size == 64) { 200 | ud_asmprintf(u, "q"); 201 | } 202 | 203 | if (star) { 204 | ud_asmprintf(u, " *"); 205 | } else { 206 | ud_asmprintf(u, " "); 207 | } 208 | 209 | if (u->operand[3].type != UD_NONE) { 210 | gen_operand(u, &u->operand[3]); 211 | ud_asmprintf(u, ", "); 212 | } 213 | if (u->operand[2].type != UD_NONE) { 214 | gen_operand(u, &u->operand[2]); 215 | ud_asmprintf(u, ", "); 216 | } 217 | if (u->operand[1].type != UD_NONE) { 218 | gen_operand(u, &u->operand[1]); 219 | ud_asmprintf(u, ", "); 220 | } 221 | if (u->operand[0].type != UD_NONE) { 222 | gen_operand(u, &u->operand[0]); 223 | } 224 | } 225 | 226 | /* 227 | vim: set ts=2 sw=2 expandtab 228 | */ 229 | -------------------------------------------------------------------------------- /Udis86/libudis86/syn-intel.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn-intel.c 2 | * 3 | * Copyright (c) 2002-2013 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #include "types.h" 27 | #include "extern.h" 28 | #include "decode.h" 29 | #include "itab.h" 30 | #include "syn.h" 31 | #include "udint.h" 32 | 33 | /* ----------------------------------------------------------------------------- 34 | * opr_cast() - Prints an operand cast. 35 | * ----------------------------------------------------------------------------- 36 | */ 37 | static void 38 | opr_cast(struct ud* u, struct ud_operand* op) 39 | { 40 | if (u->br_far) { 41 | ud_asmprintf(u, "far "); 42 | } 43 | switch(op->size) { 44 | case 8: ud_asmprintf(u, "byte " ); break; 45 | case 16: ud_asmprintf(u, "word " ); break; 46 | case 32: ud_asmprintf(u, "dword "); break; 47 | case 64: ud_asmprintf(u, "qword "); break; 48 | case 80: ud_asmprintf(u, "tword "); break; 49 | case 128: ud_asmprintf(u, "oword "); break; 50 | case 256: ud_asmprintf(u, "yword "); break; 51 | default: break; 52 | } 53 | } 54 | 55 | /* ----------------------------------------------------------------------------- 56 | * gen_operand() - Generates assembly output for each operand. 57 | * ----------------------------------------------------------------------------- 58 | */ 59 | static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast) 60 | { 61 | switch(op->type) { 62 | case UD_OP_REG: 63 | ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); 64 | break; 65 | 66 | case UD_OP_MEM: 67 | if (syn_cast) { 68 | opr_cast(u, op); 69 | } 70 | ud_asmprintf(u, "["); 71 | if (u->pfx_seg) { 72 | ud_asmprintf(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); 73 | } 74 | if (op->base) { 75 | ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); 76 | } 77 | if (op->index) { 78 | ud_asmprintf(u, "%s%s", op->base != UD_NONE? "+" : "", 79 | ud_reg_tab[op->index - UD_R_AL]); 80 | if (op->scale) { 81 | ud_asmprintf(u, "*%d", op->scale); 82 | } 83 | } 84 | if (op->offset != 0) { 85 | ud_syn_print_mem_disp(u, op, (op->base != UD_NONE || 86 | op->index != UD_NONE) ? 1 : 0); 87 | } 88 | ud_asmprintf(u, "]"); 89 | break; 90 | 91 | case UD_OP_IMM: 92 | ud_syn_print_imm(u, op); 93 | break; 94 | 95 | 96 | case UD_OP_JIMM: 97 | ud_syn_print_addr(u, ud_syn_rel_target(u, op)); 98 | break; 99 | 100 | case UD_OP_PTR: 101 | switch (op->size) { 102 | case 32: 103 | ud_asmprintf(u, "word 0x%x:0x%x", op->lval.ptr.seg, 104 | op->lval.ptr.off & 0xFFFF); 105 | break; 106 | case 48: 107 | ud_asmprintf(u, "dword 0x%x:0x%x", op->lval.ptr.seg, 108 | op->lval.ptr.off); 109 | break; 110 | } 111 | break; 112 | 113 | case UD_OP_CONST: 114 | if (syn_cast) opr_cast(u, op); 115 | ud_asmprintf(u, "%d", op->lval.udword); 116 | break; 117 | 118 | default: return; 119 | } 120 | } 121 | 122 | /* ============================================================================= 123 | * translates to intel syntax 124 | * ============================================================================= 125 | */ 126 | extern void 127 | ud_translate_intel(struct ud* u) 128 | { 129 | /* check if P_OSO prefix is used */ 130 | if (!P_OSO(u->itab_entry->prefix) && u->pfx_opr) { 131 | switch (u->dis_mode) { 132 | case 16: ud_asmprintf(u, "o32 "); break; 133 | case 32: 134 | case 64: ud_asmprintf(u, "o16 "); break; 135 | } 136 | } 137 | 138 | /* check if P_ASO prefix was used */ 139 | if (!P_ASO(u->itab_entry->prefix) && u->pfx_adr) { 140 | switch (u->dis_mode) { 141 | case 16: ud_asmprintf(u, "a32 "); break; 142 | case 32: ud_asmprintf(u, "a16 "); break; 143 | case 64: ud_asmprintf(u, "a32 "); break; 144 | } 145 | } 146 | 147 | if (u->pfx_seg && 148 | u->operand[0].type != UD_OP_MEM && 149 | u->operand[1].type != UD_OP_MEM ) { 150 | ud_asmprintf(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]); 151 | } 152 | 153 | if (u->pfx_lock) { 154 | ud_asmprintf(u, "lock "); 155 | } 156 | if (u->pfx_rep) { 157 | ud_asmprintf(u, "rep "); 158 | } else if (u->pfx_repe) { 159 | ud_asmprintf(u, "repe "); 160 | } else if (u->pfx_repne) { 161 | ud_asmprintf(u, "repne "); 162 | } 163 | 164 | /* print the instruction mnemonic */ 165 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 166 | 167 | if (u->operand[0].type != UD_NONE) { 168 | int cast = 0; 169 | ud_asmprintf(u, " "); 170 | if (u->operand[0].type == UD_OP_MEM) { 171 | if (u->operand[1].type == UD_OP_IMM || 172 | u->operand[1].type == UD_OP_CONST || 173 | u->operand[1].type == UD_NONE || 174 | (u->operand[0].size != u->operand[1].size)) { 175 | cast = 1; 176 | } else if (u->operand[1].type == UD_OP_REG && 177 | u->operand[1].base == UD_R_CL) { 178 | switch (u->mnemonic) { 179 | case UD_Ircl: 180 | case UD_Irol: 181 | case UD_Iror: 182 | case UD_Ircr: 183 | case UD_Ishl: 184 | case UD_Ishr: 185 | case UD_Isar: 186 | cast = 1; 187 | break; 188 | default: break; 189 | } 190 | } 191 | } 192 | gen_operand(u, &u->operand[0], cast); 193 | } 194 | 195 | if (u->operand[1].type != UD_NONE) { 196 | int cast = 0; 197 | ud_asmprintf(u, ", "); 198 | if (u->operand[1].type == UD_OP_MEM && 199 | u->operand[0].size != u->operand[1].size && 200 | !ud_opr_is_sreg(&u->operand[0])) { 201 | cast = 1; 202 | } 203 | gen_operand(u, &u->operand[1], cast); 204 | } 205 | 206 | if (u->operand[2].type != UD_NONE) { 207 | int cast = 0; 208 | ud_asmprintf(u, ", "); 209 | if (u->operand[2].type == UD_OP_MEM && 210 | u->operand[2].size != u->operand[1].size) { 211 | cast = 1; 212 | } 213 | gen_operand(u, &u->operand[2], cast); 214 | } 215 | 216 | if (u->operand[3].type != UD_NONE) { 217 | ud_asmprintf(u, ", "); 218 | gen_operand(u, &u->operand[3], 0); 219 | } 220 | } 221 | 222 | /* 223 | vim: set ts=2 sw=2 expandtab 224 | */ 225 | -------------------------------------------------------------------------------- /Udis86/libudis86/syn.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn.c 2 | * 3 | * Copyright (c) 2002-2013 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #include "types.h" 27 | #include "decode.h" 28 | #include "syn.h" 29 | #include "udint.h" 30 | 31 | /* 32 | * Register Table - Order Matters (types.h)! 33 | * 34 | */ 35 | const char* ud_reg_tab[] = 36 | { 37 | "al", "cl", "dl", "bl", 38 | "ah", "ch", "dh", "bh", 39 | "spl", "bpl", "sil", "dil", 40 | "r8b", "r9b", "r10b", "r11b", 41 | "r12b", "r13b", "r14b", "r15b", 42 | 43 | "ax", "cx", "dx", "bx", 44 | "sp", "bp", "si", "di", 45 | "r8w", "r9w", "r10w", "r11w", 46 | "r12w", "r13w", "r14w", "r15w", 47 | 48 | "eax", "ecx", "edx", "ebx", 49 | "esp", "ebp", "esi", "edi", 50 | "r8d", "r9d", "r10d", "r11d", 51 | "r12d", "r13d", "r14d", "r15d", 52 | 53 | "rax", "rcx", "rdx", "rbx", 54 | "rsp", "rbp", "rsi", "rdi", 55 | "r8", "r9", "r10", "r11", 56 | "r12", "r13", "r14", "r15", 57 | 58 | "es", "cs", "ss", "ds", 59 | "fs", "gs", 60 | 61 | "cr0", "cr1", "cr2", "cr3", 62 | "cr4", "cr5", "cr6", "cr7", 63 | "cr8", "cr9", "cr10", "cr11", 64 | "cr12", "cr13", "cr14", "cr15", 65 | 66 | "dr0", "dr1", "dr2", "dr3", 67 | "dr4", "dr5", "dr6", "dr7", 68 | "dr8", "dr9", "dr10", "dr11", 69 | "dr12", "dr13", "dr14", "dr15", 70 | 71 | "mm0", "mm1", "mm2", "mm3", 72 | "mm4", "mm5", "mm6", "mm7", 73 | 74 | "st0", "st1", "st2", "st3", 75 | "st4", "st5", "st6", "st7", 76 | 77 | "xmm0", "xmm1", "xmm2", "xmm3", 78 | "xmm4", "xmm5", "xmm6", "xmm7", 79 | "xmm8", "xmm9", "xmm10", "xmm11", 80 | "xmm12", "xmm13", "xmm14", "xmm15", 81 | 82 | "ymm0", "ymm1", "ymm2", "ymm3", 83 | "ymm4", "ymm5", "ymm6", "ymm7", 84 | "ymm8", "ymm9", "ymm10", "ymm11", 85 | "ymm12", "ymm13", "ymm14", "ymm15", 86 | 87 | "rip" 88 | }; 89 | 90 | 91 | uint64_t 92 | ud_syn_rel_target(struct ud *u, struct ud_operand *opr) 93 | { 94 | const uint64_t trunc_mask = 0xffffffffffffffffull >> (64 - u->opr_mode); 95 | switch (opr->size) { 96 | case 8 : return (u->pc + opr->lval.sbyte) & trunc_mask; 97 | case 16: return (u->pc + opr->lval.sword) & trunc_mask; 98 | case 32: return (u->pc + opr->lval.sdword) & trunc_mask; 99 | default: UD_ASSERT(!"invalid relative offset size."); 100 | return 0ull; 101 | } 102 | } 103 | 104 | 105 | /* 106 | * asmprintf 107 | * Printf style function for printing translated assembly 108 | * output. Returns the number of characters written and 109 | * moves the buffer pointer forward. On an overflow, 110 | * returns a negative number and truncates the output. 111 | */ 112 | int 113 | ud_asmprintf(struct ud *u, const char *fmt, ...) 114 | { 115 | int ret; 116 | int avail; 117 | va_list ap; 118 | va_start(ap, fmt); 119 | avail = u->asm_buf_size - u->asm_buf_fill - 1 /* nullchar */; 120 | ret = vsnprintf((char*) u->asm_buf + u->asm_buf_fill, avail, fmt, ap); 121 | if (ret < 0 || ret > avail) { 122 | u->asm_buf_fill = u->asm_buf_size - 1; 123 | } else { 124 | u->asm_buf_fill += ret; 125 | } 126 | va_end(ap); 127 | return ret; 128 | } 129 | 130 | 131 | void 132 | ud_syn_print_addr(struct ud *u, uint64_t addr) 133 | { 134 | const char *name = NULL; 135 | if (u->sym_resolver) { 136 | int64_t offset = 0; 137 | name = u->sym_resolver(u, addr, &offset); 138 | if (name) { 139 | if (offset) { 140 | ud_asmprintf(u, "%s%+" FMT64 "d", name, offset); 141 | } else { 142 | ud_asmprintf(u, "%s", name); 143 | } 144 | return; 145 | } 146 | } 147 | ud_asmprintf(u, "0x%" FMT64 "x", addr); 148 | } 149 | 150 | 151 | void 152 | ud_syn_print_imm(struct ud* u, const struct ud_operand *op) 153 | { 154 | uint64_t v; 155 | if (op->_oprcode == OP_sI && op->size != u->opr_mode) { 156 | if (op->size == 8) { 157 | v = (int64_t)op->lval.sbyte; 158 | } else { 159 | UD_ASSERT(op->size == 32); 160 | v = (int64_t)op->lval.sdword; 161 | } 162 | if (u->opr_mode < 64) { 163 | v = v & ((1ull << u->opr_mode) - 1ull); 164 | } 165 | } else { 166 | switch (op->size) { 167 | case 8 : v = op->lval.ubyte; break; 168 | case 16: v = op->lval.uword; break; 169 | case 32: v = op->lval.udword; break; 170 | case 64: v = op->lval.uqword; break; 171 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ 172 | } 173 | } 174 | ud_asmprintf(u, "0x%" FMT64 "x", v); 175 | } 176 | 177 | 178 | void 179 | ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign) 180 | { 181 | UD_ASSERT(op->offset != 0); 182 | if (op->base == UD_NONE && op->index == UD_NONE) { 183 | uint64_t v; 184 | UD_ASSERT(op->scale == UD_NONE && op->offset != 8); 185 | /* unsigned mem-offset */ 186 | switch (op->offset) { 187 | case 16: v = op->lval.uword; break; 188 | case 32: v = op->lval.udword; break; 189 | case 64: v = op->lval.uqword; break; 190 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ 191 | } 192 | ud_asmprintf(u, "0x%" FMT64 "x", v); 193 | } else { 194 | int64_t v; 195 | UD_ASSERT(op->offset != 64); 196 | switch (op->offset) { 197 | case 8 : v = op->lval.sbyte; break; 198 | case 16: v = op->lval.sword; break; 199 | case 32: v = op->lval.sdword; break; 200 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ 201 | } 202 | if (v < 0) { 203 | ud_asmprintf(u, "-0x%" FMT64 "x", -v); 204 | } else if (v > 0) { 205 | ud_asmprintf(u, "%s0x%" FMT64 "x", sign? "+" : "", v); 206 | } 207 | } 208 | } 209 | 210 | /* 211 | vim: set ts=2 sw=2 expandtab 212 | */ 213 | -------------------------------------------------------------------------------- /Udis86/libudis86/syn.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn.h 2 | * 3 | * Copyright (c) 2002-2009 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UD_SYN_H 27 | #define UD_SYN_H 28 | 29 | #include "types.h" 30 | #ifndef __UD_STANDALONE__ 31 | # include 32 | #endif /* __UD_STANDALONE__ */ 33 | 34 | extern const char* ud_reg_tab[]; 35 | 36 | uint64_t ud_syn_rel_target(struct ud*, struct ud_operand*); 37 | 38 | #ifdef __GNUC__ 39 | int ud_asmprintf(struct ud *u, const char *fmt, ...) 40 | __attribute__ ((format (printf, 2, 3))); 41 | #else 42 | int ud_asmprintf(struct ud *u, const char *fmt, ...); 43 | #endif 44 | 45 | void ud_syn_print_addr(struct ud *u, uint64_t addr); 46 | void ud_syn_print_imm(struct ud* u, const struct ud_operand *op); 47 | void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *, int sign); 48 | 49 | #endif /* UD_SYN_H */ 50 | 51 | /* 52 | vim: set ts=2 sw=2 expandtab 53 | */ 54 | -------------------------------------------------------------------------------- /Udis86/libudis86/types.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/types.h 2 | * 3 | * Copyright (c) 2002-2013 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UD_TYPES_H 27 | #define UD_TYPES_H 28 | 29 | #ifdef __KERNEL__ 30 | /* 31 | * -D__KERNEL__ is automatically passed on the command line when 32 | * building something as part of the Linux kernel. Assume standalone 33 | * mode. 34 | */ 35 | # include 36 | # include 37 | # ifndef __UD_STANDALONE__ 38 | # define __UD_STANDALONE__ 1 39 | # endif 40 | #endif /* __KERNEL__ */ 41 | 42 | #if !defined(__UD_STANDALONE__) 43 | # include 44 | # include 45 | #endif 46 | 47 | /* gcc specific extensions */ 48 | #ifdef __GNUC__ 49 | # define UD_ATTR_PACKED __attribute__((packed)) 50 | #else 51 | # define UD_ATTR_PACKED 52 | #endif /* UD_ATTR_PACKED */ 53 | 54 | 55 | /* ----------------------------------------------------------------------------- 56 | * All possible "types" of objects in udis86. Order is Important! 57 | * ----------------------------------------------------------------------------- 58 | */ 59 | enum ud_type 60 | { 61 | UD_NONE, 62 | 63 | /* 8 bit GPRs */ 64 | UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL, 65 | UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH, 66 | UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL, 67 | UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B, 68 | UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B, 69 | 70 | /* 16 bit GPRs */ 71 | UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX, 72 | UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI, 73 | UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W, 74 | UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W, 75 | 76 | /* 32 bit GPRs */ 77 | UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX, 78 | UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI, 79 | UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D, 80 | UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D, 81 | 82 | /* 64 bit GPRs */ 83 | UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX, 84 | UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI, 85 | UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11, 86 | UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15, 87 | 88 | /* segment registers */ 89 | UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS, 90 | UD_R_FS, UD_R_GS, 91 | 92 | /* control registers*/ 93 | UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3, 94 | UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7, 95 | UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11, 96 | UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15, 97 | 98 | /* debug registers */ 99 | UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3, 100 | UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7, 101 | UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11, 102 | UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15, 103 | 104 | /* mmx registers */ 105 | UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3, 106 | UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7, 107 | 108 | /* x87 registers */ 109 | UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3, 110 | UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7, 111 | 112 | /* extended multimedia registers */ 113 | UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3, 114 | UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7, 115 | UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11, 116 | UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15, 117 | 118 | /* 256B multimedia registers */ 119 | UD_R_YMM0, UD_R_YMM1, UD_R_YMM2, UD_R_YMM3, 120 | UD_R_YMM4, UD_R_YMM5, UD_R_YMM6, UD_R_YMM7, 121 | UD_R_YMM8, UD_R_YMM9, UD_R_YMM10, UD_R_YMM11, 122 | UD_R_YMM12, UD_R_YMM13, UD_R_YMM14, UD_R_YMM15, 123 | 124 | UD_R_RIP, 125 | 126 | /* Operand Types */ 127 | UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM, 128 | UD_OP_JIMM, UD_OP_CONST 129 | }; 130 | 131 | #include "itab.h" 132 | 133 | union ud_lval { 134 | int8_t sbyte; 135 | uint8_t ubyte; 136 | int16_t sword; 137 | uint16_t uword; 138 | int32_t sdword; 139 | uint32_t udword; 140 | int64_t sqword; 141 | uint64_t uqword; 142 | struct { 143 | uint16_t seg; 144 | uint32_t off; 145 | } ptr; 146 | }; 147 | 148 | /* ----------------------------------------------------------------------------- 149 | * struct ud_operand - Disassembled instruction Operand. 150 | * ----------------------------------------------------------------------------- 151 | */ 152 | struct ud_operand { 153 | enum ud_type type; 154 | uint16_t size; 155 | enum ud_type base; 156 | enum ud_type index; 157 | uint8_t scale; 158 | uint8_t offset; 159 | union ud_lval lval; 160 | /* 161 | * internal use only 162 | */ 163 | uint64_t _legacy; /* this will be removed in 1.8 */ 164 | uint8_t _oprcode; 165 | }; 166 | 167 | /* ----------------------------------------------------------------------------- 168 | * struct ud - The udis86 object. 169 | * ----------------------------------------------------------------------------- 170 | */ 171 | struct ud 172 | { 173 | /* 174 | * input buffering 175 | */ 176 | int (*inp_hook) (struct ud*); 177 | #ifndef __UD_STANDALONE__ 178 | FILE* inp_file; 179 | #endif 180 | const uint8_t* inp_buf; 181 | size_t inp_buf_size; 182 | size_t inp_buf_index; 183 | uint8_t inp_curr; 184 | size_t inp_ctr; 185 | uint8_t inp_sess[64]; 186 | int inp_end; 187 | int inp_peek; 188 | 189 | void (*translator)(struct ud*); 190 | uint64_t insn_offset; 191 | char insn_hexcode[64]; 192 | 193 | /* 194 | * Assembly output buffer 195 | */ 196 | char *asm_buf; 197 | size_t asm_buf_size; 198 | size_t asm_buf_fill; 199 | char asm_buf_int[128]; 200 | 201 | /* 202 | * Symbol resolver for use in the translation phase. 203 | */ 204 | const char* (*sym_resolver)(struct ud*, uint64_t addr, int64_t *offset); 205 | 206 | uint8_t dis_mode; 207 | uint64_t pc; 208 | uint8_t vendor; 209 | enum ud_mnemonic_code mnemonic; 210 | struct ud_operand operand[4]; 211 | uint8_t error; 212 | uint8_t _rex; 213 | uint8_t pfx_rex; 214 | uint8_t pfx_seg; 215 | uint8_t pfx_opr; 216 | uint8_t pfx_adr; 217 | uint8_t pfx_lock; 218 | uint8_t pfx_str; 219 | uint8_t pfx_rep; 220 | uint8_t pfx_repe; 221 | uint8_t pfx_repne; 222 | uint8_t opr_mode; 223 | uint8_t adr_mode; 224 | uint8_t br_far; 225 | uint8_t br_near; 226 | uint8_t have_modrm; 227 | uint8_t modrm; 228 | uint8_t modrm_offset; 229 | uint8_t vex_op; 230 | uint8_t vex_b1; 231 | uint8_t vex_b2; 232 | uint8_t primary_opcode; 233 | void * user_opaque_data; 234 | struct ud_itab_entry * itab_entry; 235 | struct ud_lookup_table_list_entry *le; 236 | }; 237 | 238 | /* ----------------------------------------------------------------------------- 239 | * Type-definitions 240 | * ----------------------------------------------------------------------------- 241 | */ 242 | typedef enum ud_type ud_type_t; 243 | typedef enum ud_mnemonic_code ud_mnemonic_code_t; 244 | 245 | typedef struct ud ud_t; 246 | typedef struct ud_operand ud_operand_t; 247 | 248 | #define UD_SYN_INTEL ud_translate_intel 249 | #define UD_SYN_ATT ud_translate_att 250 | #define UD_EOI (-1) 251 | #define UD_INP_CACHE_SZ 32 252 | #define UD_VENDOR_AMD 0 253 | #define UD_VENDOR_INTEL 1 254 | #define UD_VENDOR_ANY 2 255 | 256 | #endif 257 | 258 | /* 259 | vim: set ts=2 sw=2 expandtab 260 | */ 261 | -------------------------------------------------------------------------------- /Udis86/libudis86/udint.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/udint.h -- definitions for internal use only 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef _UDINT_H_ 27 | #define _UDINT_H_ 28 | 29 | #include "types.h" 30 | 31 | #ifdef HAVE_CONFIG_H 32 | # include 33 | #endif /* HAVE_CONFIG_H */ 34 | 35 | #if defined(UD_DEBUG) && HAVE_ASSERT_H 36 | # include 37 | # define UD_ASSERT(_x) assert(_x) 38 | #else 39 | # define UD_ASSERT(_x) 40 | #endif /* !HAVE_ASSERT_H */ 41 | 42 | #if defined(UD_DEBUG) 43 | #define UDERR(u, msg) \ 44 | do { \ 45 | (u)->error = 1; \ 46 | fprintf(stderr, "decode-error: %s:%d: %s", \ 47 | __FILE__, __LINE__, (msg)); \ 48 | } while (0) 49 | #else 50 | #define UDERR(u, m) \ 51 | do { \ 52 | (u)->error = 1; \ 53 | } while (0) 54 | #endif /* !LOGERR */ 55 | 56 | #define UD_RETURN_ON_ERROR(u) \ 57 | do { \ 58 | if ((u)->error != 0) { \ 59 | return (u)->error; \ 60 | } \ 61 | } while (0) 62 | 63 | #define UD_RETURN_WITH_ERROR(u, m) \ 64 | do { \ 65 | UDERR(u, m); \ 66 | return (u)->error; \ 67 | } while (0) 68 | 69 | #ifndef __UD_STANDALONE__ 70 | # define UD_NON_STANDALONE(x) x 71 | #else 72 | # define UD_NON_STANDALONE(x) 73 | #endif 74 | 75 | /* printf formatting int64 specifier */ 76 | #ifdef FMT64 77 | # undef FMT64 78 | #endif 79 | #if defined(_MSC_VER) || defined(__BORLANDC__) 80 | # define FMT64 "I64" 81 | #else 82 | # if defined(__APPLE__) 83 | # define FMT64 "ll" 84 | # elif defined(__amd64__) || defined(__x86_64__) 85 | # define FMT64 "l" 86 | # else 87 | # define FMT64 "ll" 88 | # endif /* !x64 */ 89 | #endif 90 | 91 | /* define an inline macro */ 92 | #if defined(_MSC_VER) || defined(__BORLANDC__) 93 | # define UD_INLINE __inline /* MS Visual Studio requires __inline 94 | instead of inline for C code */ 95 | #else 96 | # define UD_INLINE inline 97 | #endif 98 | 99 | #endif /* _UDINT_H_ */ 100 | -------------------------------------------------------------------------------- /Udis86/libudis86/udis86.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/udis86.c 2 | * 3 | * Copyright (c) 2002-2013 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include "udint.h" 28 | #include "extern.h" 29 | #include "decode.h" 30 | 31 | #if !defined(__UD_STANDALONE__) 32 | # if HAVE_STRING_H 33 | # include 34 | # endif 35 | #endif /* !__UD_STANDALONE__ */ 36 | 37 | static void ud_inp_init(struct ud *u); 38 | 39 | /* ============================================================================= 40 | * ud_init 41 | * Initializes ud_t object. 42 | * ============================================================================= 43 | */ 44 | extern void 45 | ud_init(struct ud* u) 46 | { 47 | memset((void*)u, 0, sizeof(struct ud)); 48 | ud_set_mode(u, 16); 49 | u->mnemonic = UD_Iinvalid; 50 | ud_set_pc(u, 0); 51 | #ifndef __UD_STANDALONE__ 52 | ud_set_input_file(u, stdin); 53 | #endif /* __UD_STANDALONE__ */ 54 | 55 | ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); 56 | } 57 | 58 | 59 | /* ============================================================================= 60 | * ud_disassemble 61 | * Disassembles one instruction and returns the number of 62 | * bytes disassembled. A zero means end of disassembly. 63 | * ============================================================================= 64 | */ 65 | extern unsigned int 66 | ud_disassemble(struct ud* u) 67 | { 68 | int len; 69 | if (u->inp_end) { 70 | return 0; 71 | } 72 | if ((len = ud_decode(u)) > 0) { 73 | if (u->translator != NULL) { 74 | u->asm_buf[0] = '\0'; 75 | u->translator(u); 76 | } 77 | } 78 | return len; 79 | } 80 | 81 | 82 | /* ============================================================================= 83 | * ud_set_mode() - Set Disassemly Mode. 84 | * ============================================================================= 85 | */ 86 | extern void 87 | ud_set_mode(struct ud* u, uint8_t m) 88 | { 89 | switch(m) { 90 | case 16: 91 | case 32: 92 | case 64: u->dis_mode = m ; return; 93 | default: u->dis_mode = 16; return; 94 | } 95 | } 96 | 97 | /* ============================================================================= 98 | * ud_set_vendor() - Set vendor. 99 | * ============================================================================= 100 | */ 101 | extern void 102 | ud_set_vendor(struct ud* u, unsigned v) 103 | { 104 | switch(v) { 105 | case UD_VENDOR_INTEL: 106 | u->vendor = v; 107 | break; 108 | case UD_VENDOR_ANY: 109 | u->vendor = v; 110 | break; 111 | default: 112 | u->vendor = UD_VENDOR_AMD; 113 | } 114 | } 115 | 116 | /* ============================================================================= 117 | * ud_set_pc() - Sets code origin. 118 | * ============================================================================= 119 | */ 120 | extern void 121 | ud_set_pc(struct ud* u, uint64_t o) 122 | { 123 | u->pc = o; 124 | } 125 | 126 | /* ============================================================================= 127 | * ud_set_syntax() - Sets the output syntax. 128 | * ============================================================================= 129 | */ 130 | extern void 131 | ud_set_syntax(struct ud* u, void (*t)(struct ud*)) 132 | { 133 | u->translator = t; 134 | } 135 | 136 | /* ============================================================================= 137 | * ud_insn() - returns the disassembled instruction 138 | * ============================================================================= 139 | */ 140 | const char* 141 | ud_insn_asm(const struct ud* u) 142 | { 143 | return u->asm_buf; 144 | } 145 | 146 | /* ============================================================================= 147 | * ud_insn_offset() - Returns the offset. 148 | * ============================================================================= 149 | */ 150 | uint64_t 151 | ud_insn_off(const struct ud* u) 152 | { 153 | return u->insn_offset; 154 | } 155 | 156 | 157 | /* ============================================================================= 158 | * ud_insn_hex() - Returns hex form of disassembled instruction. 159 | * ============================================================================= 160 | */ 161 | const char* 162 | ud_insn_hex(struct ud* u) 163 | { 164 | u->insn_hexcode[0] = 0; 165 | if (!u->error) { 166 | unsigned int i; 167 | const unsigned char *src_ptr = ud_insn_ptr(u); 168 | char* src_hex; 169 | src_hex = (char*) u->insn_hexcode; 170 | /* for each byte used to decode instruction */ 171 | for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2; 172 | ++i, ++src_ptr) { 173 | sprintf(src_hex, "%02x", *src_ptr & 0xFF); 174 | src_hex += 2; 175 | } 176 | } 177 | return u->insn_hexcode; 178 | } 179 | 180 | 181 | /* ============================================================================= 182 | * ud_insn_ptr 183 | * Returns a pointer to buffer containing the bytes that were 184 | * disassembled. 185 | * ============================================================================= 186 | */ 187 | extern const uint8_t* 188 | ud_insn_ptr(const struct ud* u) 189 | { 190 | return (u->inp_buf == NULL) ? 191 | u->inp_sess : u->inp_buf + (u->inp_buf_index - u->inp_ctr); 192 | } 193 | 194 | 195 | /* ============================================================================= 196 | * ud_insn_len 197 | * Returns the count of bytes disassembled. 198 | * ============================================================================= 199 | */ 200 | extern unsigned int 201 | ud_insn_len(const struct ud* u) 202 | { 203 | return u->inp_ctr; 204 | } 205 | 206 | 207 | /* ============================================================================= 208 | * ud_insn_get_opr 209 | * Return the operand struct representing the nth operand of 210 | * the currently disassembled instruction. Returns NULL if 211 | * there's no such operand. 212 | * ============================================================================= 213 | */ 214 | const struct ud_operand* 215 | ud_insn_opr(const struct ud *u, unsigned int n) 216 | { 217 | if (n > 3 || u->operand[n].type == UD_NONE) { 218 | return NULL; 219 | } else { 220 | return &u->operand[n]; 221 | } 222 | } 223 | 224 | 225 | /* ============================================================================= 226 | * ud_opr_is_sreg 227 | * Returns non-zero if the given operand is of a segment register type. 228 | * ============================================================================= 229 | */ 230 | int 231 | ud_opr_is_sreg(const struct ud_operand *opr) 232 | { 233 | return opr->type == UD_OP_REG && 234 | opr->base >= UD_R_ES && 235 | opr->base <= UD_R_GS; 236 | } 237 | 238 | 239 | /* ============================================================================= 240 | * ud_opr_is_sreg 241 | * Returns non-zero if the given operand is of a general purpose 242 | * register type. 243 | * ============================================================================= 244 | */ 245 | int 246 | ud_opr_is_gpr(const struct ud_operand *opr) 247 | { 248 | return opr->type == UD_OP_REG && 249 | opr->base >= UD_R_AL && 250 | opr->base <= UD_R_R15; 251 | } 252 | 253 | 254 | /* ============================================================================= 255 | * ud_set_user_opaque_data 256 | * ud_get_user_opaque_data 257 | * Get/set user opaqute data pointer 258 | * ============================================================================= 259 | */ 260 | void 261 | ud_set_user_opaque_data(struct ud * u, void* opaque) 262 | { 263 | u->user_opaque_data = opaque; 264 | } 265 | 266 | void* 267 | ud_get_user_opaque_data(const struct ud *u) 268 | { 269 | return u->user_opaque_data; 270 | } 271 | 272 | 273 | /* ============================================================================= 274 | * ud_set_asm_buffer 275 | * Allow the user to set an assembler output buffer. If `buf` is NULL, 276 | * we switch back to the internal buffer. 277 | * ============================================================================= 278 | */ 279 | void 280 | ud_set_asm_buffer(struct ud *u, char *buf, size_t size) 281 | { 282 | if (buf == NULL) { 283 | ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); 284 | } else { 285 | u->asm_buf = buf; 286 | u->asm_buf_size = size; 287 | } 288 | } 289 | 290 | 291 | /* ============================================================================= 292 | * ud_set_sym_resolver 293 | * Set symbol resolver for relative targets used in the translation 294 | * phase. 295 | * 296 | * The resolver is a function that takes a uint64_t address and returns a 297 | * symbolic name for the that address. The function also takes a second 298 | * argument pointing to an integer that the client can optionally set to a 299 | * non-zero value for offsetted targets. (symbol+offset) The function may 300 | * also return NULL, in which case the translator only prints the target 301 | * address. 302 | * 303 | * The function pointer maybe NULL which resets symbol resolution. 304 | * ============================================================================= 305 | */ 306 | void 307 | ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*, 308 | uint64_t addr, 309 | int64_t *offset)) 310 | { 311 | u->sym_resolver = resolver; 312 | } 313 | 314 | 315 | /* ============================================================================= 316 | * ud_insn_mnemonic 317 | * Return the current instruction mnemonic. 318 | * ============================================================================= 319 | */ 320 | enum ud_mnemonic_code 321 | ud_insn_mnemonic(const struct ud *u) 322 | { 323 | return u->mnemonic; 324 | } 325 | 326 | 327 | /* ============================================================================= 328 | * ud_lookup_mnemonic 329 | * Looks up mnemonic code in the mnemonic string table. 330 | * Returns NULL if the mnemonic code is invalid. 331 | * ============================================================================= 332 | */ 333 | const char* 334 | ud_lookup_mnemonic(enum ud_mnemonic_code c) 335 | { 336 | if (c < UD_MAX_MNEMONIC_CODE) { 337 | return ud_mnemonics_str[c]; 338 | } else { 339 | return NULL; 340 | } 341 | } 342 | 343 | 344 | /* 345 | * ud_inp_init 346 | * Initializes the input system. 347 | */ 348 | static void 349 | ud_inp_init(struct ud *u) 350 | { 351 | u->inp_hook = NULL; 352 | u->inp_buf = NULL; 353 | u->inp_buf_size = 0; 354 | u->inp_buf_index = 0; 355 | u->inp_curr = 0; 356 | u->inp_ctr = 0; 357 | u->inp_end = 0; 358 | u->inp_peek = UD_EOI; 359 | UD_NON_STANDALONE(u->inp_file = NULL); 360 | } 361 | 362 | 363 | /* ============================================================================= 364 | * ud_inp_set_hook 365 | * Sets input hook. 366 | * ============================================================================= 367 | */ 368 | void 369 | ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) 370 | { 371 | ud_inp_init(u); 372 | u->inp_hook = hook; 373 | } 374 | 375 | /* ============================================================================= 376 | * ud_inp_set_buffer 377 | * Set buffer as input. 378 | * ============================================================================= 379 | */ 380 | void 381 | ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len) 382 | { 383 | ud_inp_init(u); 384 | u->inp_buf = buf; 385 | u->inp_buf_size = len; 386 | u->inp_buf_index = 0; 387 | } 388 | 389 | 390 | #ifndef __UD_STANDALONE__ 391 | /* ============================================================================= 392 | * ud_input_set_file 393 | * Set FILE as input. 394 | * ============================================================================= 395 | */ 396 | static int 397 | inp_file_hook(struct ud* u) 398 | { 399 | return fgetc(u->inp_file); 400 | } 401 | 402 | void 403 | ud_set_input_file(register struct ud* u, FILE* f) 404 | { 405 | ud_inp_init(u); 406 | u->inp_hook = inp_file_hook; 407 | u->inp_file = f; 408 | } 409 | #endif /* __UD_STANDALONE__ */ 410 | 411 | 412 | /* ============================================================================= 413 | * ud_input_skip 414 | * Skip n input bytes. 415 | * ============================================================================ 416 | */ 417 | void 418 | ud_input_skip(struct ud* u, size_t n) 419 | { 420 | if (u->inp_end) { 421 | return; 422 | } 423 | if (u->inp_buf == NULL) { 424 | while (n--) { 425 | int c = u->inp_hook(u); 426 | if (c == UD_EOI) { 427 | goto eoi; 428 | } 429 | } 430 | return; 431 | } else { 432 | if (n > u->inp_buf_size || 433 | u->inp_buf_index > u->inp_buf_size - n) { 434 | u->inp_buf_index = u->inp_buf_size; 435 | goto eoi; 436 | } 437 | u->inp_buf_index += n; 438 | return; 439 | } 440 | eoi: 441 | u->inp_end = 1; 442 | UDERR(u, "cannot skip, eoi received\b"); 443 | return; 444 | } 445 | 446 | 447 | /* ============================================================================= 448 | * ud_input_end 449 | * Returns non-zero on end-of-input. 450 | * ============================================================================= 451 | */ 452 | int 453 | ud_input_end(const struct ud *u) 454 | { 455 | return u->inp_end; 456 | } 457 | 458 | /* vim:set ts=2 sw=2 expandtab */ 459 | -------------------------------------------------------------------------------- /Udis86/udis86.h: -------------------------------------------------------------------------------- 1 | /* udis86 - udis86.h 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UDIS86_H 27 | #define UDIS86_H 28 | 29 | #include "libudis86/types.h" 30 | #include "libudis86/extern.h" 31 | #include "libudis86/itab.h" 32 | 33 | #endif 34 | --------------------------------------------------------------------------------