updates and moves

n/a
This commit is contained in:
vxunderground
2022-04-11 20:00:13 -05:00
parent 1275ea2e03
commit 900263ea6f
809 changed files with 149115 additions and 1594 deletions
@@ -0,0 +1,340 @@
<?xml version="1.0" encoding="gb2312"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="HookDeviceIoControlFile"
ProjectGUID="{DD2262AA-B5AD-411D-99DF-DDD53F92830F}"
RootNamespace="HookDeviceIoControlFile"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
<AssemblyReference
RelativePath="System.dll"
AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
MinFrameworkVersion="131072"
/>
<AssemblyReference
RelativePath="System.Data.dll"
AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
MinFrameworkVersion="131072"
/>
<AssemblyReference
RelativePath="System.Drawing.dll"
AssemblyName="System.Drawing, Version=2.0.0.0, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"
MinFrameworkVersion="131072"
/>
<AssemblyReference
RelativePath="System.Windows.Forms.dll"
AssemblyName="System.Windows.Forms, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
MinFrameworkVersion="131072"
/>
<AssemblyReference
RelativePath="System.XML.dll"
AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
MinFrameworkVersion="131072"
/>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\common.c"
>
</File>
<File
RelativePath=".\common.h"
>
</File>
<File
RelativePath=".\common_asm.h"
>
</File>
<File
RelativePath=".\common_change_asm.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
MinimalRebuild="false"
ExceptionHandling="2"
BasicRuntimeChecks="0"
UsePrecompiledHeader="0"
DebugInformationFormat="3"
CompileAsManaged="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
MinimalRebuild="false"
ExceptionHandling="2"
BasicRuntimeChecks="0"
UsePrecompiledHeader="0"
DebugInformationFormat="3"
CompileAsManaged="1"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\debug.c"
>
</File>
<File
RelativePath=".\debug.h"
>
</File>
<File
RelativePath=".\driver.c"
>
</File>
<File
RelativePath=".\driver.h"
>
</File>
<File
RelativePath=".\drvcomm.h"
>
</File>
<File
RelativePath=".\udis86\extern.h"
>
</File>
<File
RelativePath=".\handlers.c"
>
</File>
<File
RelativePath=".\handlers.h"
>
</File>
<File
RelativePath=".\hook.c"
>
</File>
<File
RelativePath=".\hook.h"
>
</File>
<File
RelativePath=".\log.c"
>
</File>
<File
RelativePath=".\log.h"
>
</File>
<File
RelativePath=".\lst.c"
>
</File>
<File
RelativePath=".\lst.h"
>
</File>
<File
RelativePath=".\rng.c"
>
</File>
<File
RelativePath=".\rng.h"
>
</File>
<File
RelativePath=".\rules.c"
>
</File>
<File
RelativePath=".\rules.h"
>
</File>
<File
RelativePath=".\stdafx.h"
>
</File>
<File
RelativePath=".\udis86\types.h"
>
</File>
<File
RelativePath=".\undocnt.h"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,82 @@
#include <ntifs.h>
#define XALIGN_DOWN(x, align)(x &~ (align - 1))
#define XALIGN_UP(x, align)((x & (align - 1))?XALIGN_DOWN(x, align) + align:x)
#define RVATOVA(_base_, _offset_) ((PUCHAR)(_base_) + (ULONG)(_offset_))
#define M_ALLOC(_size_) ExAllocatePool(NonPagedPool, (_size_))
#define M_FREE(_addr_) ExFreePool((_addr_))
#define XLOWORD(_dw) ((USHORT)(((ULONG)(_dw)) & 0xffff))
#define XHIWORD(_dw) ((USHORT)((((ULONG)(_dw)) >> 16) & 0xffff))
#define ABSOLUTE(wait) (wait)
#define RELATIVE(wait) (-(wait))
#define NANOSECONDS(nanos) \
(((signed __int64)(nanos)) / 100L)
#define MICROSECONDS(micros) \
(((signed __int64)(micros)) * NANOSECONDS(1000L))
#define MILLISECONDS(milli) \
(((signed __int64)(milli)) * MICROSECONDS(1000L))
#define SECONDS(seconds) \
(((signed __int64)(seconds)) * MILLISECONDS(1000L))
#define IFMT32 "0x%.8x"
#define IFMT64 "0x%.16I64x"
#define IFMT32_W L"0x%.8x"
#define IFMT64_W L"0x%.16I64x"
#ifdef _X86_
#define IFMT IFMT32
#define IFMT_W IFMT32_W
#elif _AMD64_
#define IFMT IFMT64
#define IFMT_W IFMT64_W
#endif
BOOLEAN SetObjectSecurityWorld(HANDLE hObject, ACCESS_MASK AccessMask);
PVOID KernelGetModuleBase(char *ModuleName);
ULONG KernelGetExportAddress(PVOID Image, char *lpszFunctionName);
POBJECT_NAME_INFORMATION GetObjectName(PVOID pObject);
POBJECT_NAME_INFORMATION GetObjectNameByHandle(HANDLE hObject);
POBJECT_NAME_INFORMATION GetFullNtPath(PUNICODE_STRING Name);
BOOLEAN GetNormalizedModulePath(PANSI_STRING asPath, PANSI_STRING asNormalizedPath);
PVOID GetSysInf(SYSTEM_INFORMATION_CLASS InfoClass);
BOOLEAN AllocUnicodeString(PUNICODE_STRING us, USHORT MaximumLength);
BOOLEAN AppendUnicodeToString(PUNICODE_STRING Dest, PCWSTR Source, USHORT Len);
ULONG GetFileSize(HANDLE hFile, PULONG FileSizeHigh);
BOOLEAN ReadFromFile(PUNICODE_STRING FileName, PVOID *Data, PULONG DataSize);
BOOLEAN DumpToFile(PUNICODE_STRING FileName, PVOID Data, ULONG DataSize);
BOOLEAN DeleteFile(PUNICODE_STRING usFileName);
BOOLEAN LoadImageAsDataFile(PUNICODE_STRING usName, PVOID *Image, PULONG MappedImageSize);
void __stdcall ClearWp(PVOID Param);
void __stdcall SetWp(PVOID Param);
void ForEachProcessor(PKSTART_ROUTINE Routine, PVOID Param);
ULONG GetSyscallNumber(char *lpszName);
BOOLEAN RegQueryValueKey(HANDLE hKey, PWSTR lpwcName, ULONG Type, PVOID *Data, PULONG DataSize);
BOOLEAN RegSetValueKey(HANDLE hKey, PWSTR lpwcName, ULONG Type, PVOID Data, ULONG DataSize);
BOOLEAN GetProcessFullImagePath(PEPROCESS Process, PUNICODE_STRING ImagePath);
typedef struct _MAPPED_MDL
{
PMDL Mdl;
PVOID Buffer;
PVOID MappedBuffer;
} MAPPED_MDL,
*PMAPPED_MDL;
BOOLEAN AllocateUserMemory(ULONG Size, PMAPPED_MDL MdlInfo);
void FreeUserMemory(PMAPPED_MDL MdlInfo);
BOOLEAN IsWow64Process(PEPROCESS Process, BOOLEAN *bIsWow64);
@@ -0,0 +1,21 @@
#ifdef __cplusplus
extern "C"
{
#endif
void __stdcall _clear_wp(void);
void __stdcall _set_wp(void);
NTSTATUS
NTAPI
_ZwProtectVirtualMemory(
HANDLE ProcessHandle,
PVOID *BaseAddress,
PSIZE_T NumberOfBytesToProtect,
ULONG NewAccessProtection,
PULONG OldAccessProtection
);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,278 @@
#include "stdafx.h"
#define DBGMSG_BUFF_SIZE 0x1000
HANDLE hDbgPipe = NULL, hDbgLogFile = NULL;
KMUTEX DbgMutex;
//--------------------------------------------------------------------------------------
char *GetNameFromFullPath(char *lpszPath)
{
char *lpszName = lpszPath;
size_t i = 0;
for (i = 0; i < strlen(lpszPath); i++)
{
if (lpszPath[i] == '\\' || lpszPath[i] == '/')
{
lpszName = lpszPath + i + 1;
}
}
return lpszName;
}
//--------------------------------------------------------------------------------------
#ifdef DBGMSG_FULL
//--------------------------------------------------------------------------------------
void DbgMsg(char *lpszFile, int Line, char *lpszMsg, ...)
{
va_list mylist;
char *lpszOutBuff = NULL;
char *lpszBuff = (char *)M_ALLOC(DBGMSG_BUFF_SIZE);
if (lpszBuff == NULL)
{
return;
}
lpszOutBuff = (char *)M_ALLOC(DBGMSG_BUFF_SIZE);
if (lpszOutBuff == NULL)
{
M_FREE(lpszBuff);
return;
}
va_start(mylist, lpszMsg);
vsprintf(lpszBuff, lpszMsg, mylist);
va_end(mylist);
sprintf(lpszOutBuff, "%s(%d) : %s", GetNameFromFullPath(lpszFile), Line, lpszBuff);
#ifdef DBGMSG
DbgPrint(lpszOutBuff);
#endif
#if defined(DBGPIPE) || defined(DBGLOGFILE)
if (KeGetCurrentIrql() == PASSIVE_LEVEL)
{
KeWaitForMutexObject(&DbgMutex, Executive, KernelMode, FALSE, NULL);
if (hDbgPipe)
{
// write debug message into pipe
IO_STATUS_BLOCK IoStatusBlock;
ULONG Len = (ULONG)strlen(lpszOutBuff) + 1;
ZwWriteFile(hDbgPipe, 0, NULL, NULL, &IoStatusBlock, (PVOID)&Len, sizeof(Len), NULL, NULL);
ZwWriteFile(hDbgPipe, 0, NULL, NULL, &IoStatusBlock, lpszOutBuff, Len, NULL, NULL);
}
if (hDbgLogFile)
{
// write debug message into logfile
IO_STATUS_BLOCK IoStatusBlock;
ULONG Len = (ULONG)strlen(lpszOutBuff);
ZwWriteFile(hDbgLogFile, 0, NULL, NULL, &IoStatusBlock, lpszOutBuff, Len, NULL, NULL);
}
KeReleaseMutex(&DbgMutex, FALSE);
}
#endif // DBGPIPE/DBGLOGFILE
M_FREE(lpszBuff);
M_FREE(lpszOutBuff);
}
//--------------------------------------------------------------------------------------
#ifdef DBGPIPE
//--------------------------------------------------------------------------------------
void DbgOpenPipe(void)
{
OBJECT_ATTRIBUTES ObjAttr;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING usPipeName;
NTSTATUS status = STATUS_UNSUCCESSFUL;
RtlInitUnicodeString(&usPipeName, L"\\Device\\NamedPipe\\" DBG_PIPE_NAME);
InitializeObjectAttributes(&ObjAttr, &usPipeName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
KeWaitForMutexObject(&DbgMutex, Executive, KernelMode, FALSE, NULL);
// open data pipe by name
status = ZwCreateFile(
&hDbgPipe,
FILE_WRITE_DATA | SYNCHRONIZE,
&ObjAttr,
&IoStatusBlock,
0,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if (!NT_SUCCESS(status))
{
DbgMsg(__FILE__, __LINE__, "ZwCreateFile() fails; status: 0x%.8x\n", status);
}
KeReleaseMutex(&DbgMutex, FALSE);
}
//--------------------------------------------------------------------------------------
void DbgClosePipe(void)
{
KeWaitForMutexObject(&DbgMutex, Executive, KernelMode, FALSE, NULL);
if (hDbgPipe)
{
ZwClose(hDbgPipe);
hDbgPipe = NULL;
}
KeReleaseMutex(&DbgMutex, FALSE);
}
//--------------------------------------------------------------------------------------
#endif // DBGPIPE
//--------------------------------------------------------------------------------------
#ifdef DBGLOGFILE
//--------------------------------------------------------------------------------------
void DbgOpenLogFile(void)
{
OBJECT_ATTRIBUTES ObjAttr;
IO_STATUS_BLOCK StatusBlock;
UNICODE_STRING usFileName;
RtlInitUnicodeString(&usFileName, DBG_LOGFILE_NAME);
InitializeObjectAttributes(&ObjAttr, &usFileName,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE , NULL, NULL);
KeWaitForMutexObject(&DbgMutex, Executive, KernelMode, FALSE, NULL);
NTSTATUS status = ZwCreateFile(
&hDbgLogFile,
FILE_ALL_ACCESS | SYNCHRONIZE,
&ObjAttr,
&StatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if (!NT_SUCCESS(status))
{
DbgMsg(__FILE__, __LINE__, "ZwCreateFile() fails; status: 0x%.8x\n", status);
}
KeReleaseMutex(&DbgMutex, FALSE);
}
//--------------------------------------------------------------------------------------
#endif // DBGLOGFILE
//--------------------------------------------------------------------------------------
void DbgClose(void)
{
KeWaitForMutexObject(&DbgMutex, Executive, KernelMode, FALSE, NULL);
if (hDbgPipe)
{
ZwClose(hDbgPipe);
hDbgPipe = NULL;
}
if (hDbgLogFile)
{
ZwClose(hDbgLogFile);
hDbgLogFile = NULL;
}
KeReleaseMutex(&DbgMutex, FALSE);
}
//--------------------------------------------------------------------------------------
void DbgInit(void)
{
#if defined(DBGPIPE) || defined(DBGLOGFILE)
KeInitializeMutex(&DbgMutex, NULL);
#endif // DBGPIPE/DBGLOGFILE
}
//--------------------------------------------------------------------------------------
#endif // DBGMSG_FULL
//--------------------------------------------------------------------------------------
void DbgHexdump(PUCHAR Data, ULONG Length)
{
ULONG dp = 0, p = 0;
const char trans[] =
"................................ !\"#$%&'()*+,-./0123456789"
":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
"nopqrstuvwxyz{|}~...................................."
"....................................................."
"........................................";
char szBuff[0x100], szChar[10];
RtlZeroMemory(szBuff, sizeof(szBuff));
for (dp = 1; dp <= Length; dp++)
{
sprintf(szChar, "%02x ", Data[dp-1]);
strcat(szBuff, szChar);
if ((dp % 8) == 0)
{
strcat(szBuff, " ");
}
if ((dp % 16) == 0)
{
strcat(szBuff, "| ");
p = dp;
for (dp -= 16; dp < p; dp++)
{
sprintf(szChar, "%c", trans[Data[dp]]);
strcat(szBuff, szChar);
}
DbgMsg(__FILE__, __LINE__, "%.8x: %s\r\n", dp - 16, szBuff);
RtlZeroMemory(szBuff, sizeof(szBuff));
}
}
if ((Length % 16) != 0)
{
p = dp = 16 - (Length % 16);
for (dp = p; dp > 0; dp--)
{
strcat(szBuff, " ");
if (((dp % 8) == 0) && (p != 8))
{
strcat(szBuff, " ");
}
}
strcat(szBuff, " | ");
for (dp = (Length - (16 - p)); dp < Length; dp++)
{
sprintf(szChar, "%c", trans[Data[dp]]);
strcat(szBuff, szChar);
}
DbgMsg(__FILE__, __LINE__, "%.8x: %s\r\n", Length - (Length % 16), szBuff);
}
}
//--------------------------------------------------------------------------------------
// EoF
@@ -0,0 +1,25 @@
#include <ntifs.h>
#ifdef DBGMSG_FULL
void DbgMsg(char *lpszFile, int Line, char *lpszMsg, ...);
void DbgClose(void);
void DbgInit(void);
#else // DBGMSG_FULL
#define DbgMsg
#define DbgClose
#define DbgInit
#endif // DBGMSG_FULL
#ifdef DBGPIPE
void DbgOpenPipe(void);
void DbgClosePipe(void);
#endif
#ifdef DBGLOGFILE
void DbgOpenLogFile(void);
#endif
void DbgHexdump(PUCHAR Data, ULONG Length);
@@ -0,0 +1,2 @@
void SetPreviousMode(KPROCESSOR_MODE Mode);
@@ -0,0 +1,117 @@
#define DEVICE_NAME L"IOCTLfuzzer"
#define DBG_PIPE_NAME L"IOCTLfuzzer"
#define DBG_PIPE_NAME_A "IOCTLfuzzer"
#define IOCTL_DRV_CONTROL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x01, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
#define S_ERROR 0x00
#define S_SUCCESS 0x01
#define C_ADD_DEVICE 0x01
#define C_ADD_DRIVER 0x02
#define C_ADD_IOCTL 0x03
#define C_ADD_PROCESS 0x04
#define C_SET_OPTIONS 0x05
#define C_GET_DEVICE_INFO 0x06
#define C_CHECK_HOOKS 0x07
#define C_DEL_OPTIONS 0x08
#define C_GET_OBJECT_NAME 0x09
// fuzzing options
#define FUZZ_OPT_LOG_IOCTL 0x00000001
#define FUZZ_OPT_LOG_IOCTL_BUFFERS 0x00000002
#define FUZZ_OPT_LOG_IOCTL_GLOBAL 0x00000004
#define FUZZ_OPT_LOG_EXCEPTIONS 0x00000008
#define FUZZ_OPT_LOG_DEBUG 0x00000010
#define FUZZ_OPT_FUZZ 0x00000020
#define FUZZ_OPT_FUZZ_SIZE 0x00000040
#define FUZZ_OPT_FUZZ_FAIR 0x00000080
#define FUZZ_OPT_FUZZ_BOOT 0x00000100
#define FUZZ_OPT_NO_SDT_HOOKS 0x00000200
typedef ULONG FUZZING_TYPE;
#define FuzzingType_Random 0x00000001
#define FuzzingType_Dword 0x00000002
// area to store some variables, that must located in user mode
#pragma pack(push, 1)
typedef struct _USER_MODE_DATA
{
IO_STATUS_BLOCK IoStatus;
} USER_MODE_DATA,
*PUSER_MODE_DATA;
#pragma pack(pop)
#define MAX_REQUEST_STRING 0x100
#pragma pack(push, 1)
typedef struct _REQUEST_BUFFER
{
// operation status (see S_* definitions)
ULONG Status;
// operation code (see C_* definitions)
ULONG Code;
union
{
struct
{
ULONG Options;
ULONG FuzzThreadId;
FUZZING_TYPE FuzzingType;
PUSER_MODE_DATA UserModeData;
ULONG KiDispatchException_Offset;
} Options;
struct
{
PVOID DeviceObjectAddr;
PVOID DriverObjectAddr;
char szDriverObjectName[MAX_REQUEST_STRING];
char szDriverFilePath[MAX_REQUEST_STRING];
} DeviceInfo;
struct
{
// for C_ADD_IOCTL
ULONG IoctlCode;
// for all C_ADD_*
BOOLEAN bAllow;
// for C_ADD_DEVICE, C_ADD_DRIVER and C_ADD_PROCESS
char szObjectName[MAX_REQUEST_STRING];
/*
If TRUE -- debugger command, that stored in Buff[],
must be executed for every IOCTL, that has been matched
by this object.
*/
BOOLEAN bDbgcbAction;
} AddObject;
struct
{
HANDLE hObject;
char szObjectName[MAX_REQUEST_STRING];
} ObjectName;
struct
{
BOOLEAN bHooksInstalled;
} CheckHooks;
};
char Buff[1];
} REQUEST_BUFFER,
*PREQUEST_BUFFER;
#pragma pack(pop)
@@ -0,0 +1,67 @@
/* -----------------------------------------------------------------------------
* extern.h
*
* Copyright (c) 2004, 2005, 2006, Vivek Mohan <vivek@sig9.com>
* All rights reserved. See LICENSE
* -----------------------------------------------------------------------------
*/
#ifndef UD_EXTERN_H
#define UD_EXTERN_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include "types.h"
/* ============================= PUBLIC API ================================= */
extern void ud_init(struct ud*);
extern void ud_set_mode(struct ud*, uint8_t);
extern void ud_set_pc(struct ud*, uint64_t);
extern void ud_set_input_hook(struct ud*, int (*)(struct ud*));
extern void ud_set_input_buffer(struct ud*, uint8_t*, size_t);
#ifndef __UD_STANDALONE__
extern void ud_set_input_file(struct ud*, FILE*);
#endif /* __UD_STANDALONE__ */
extern void ud_set_vendor(struct ud*, unsigned);
extern void ud_set_syntax(struct ud*, void (*)(struct ud*));
extern void ud_input_skip(struct ud*, size_t);
extern int ud_input_end(struct ud*);
extern unsigned int ud_decode(struct ud*);
extern unsigned int ud_disassemble(struct ud*);
extern void ud_translate_intel(struct ud*);
extern void ud_translate_att(struct ud*);
extern char* ud_insn_asm(struct ud* u);
extern uint8_t* ud_insn_ptr(struct ud* u);
extern uint64_t ud_insn_off(struct ud*);
extern char* ud_insn_hex(struct ud*);
extern unsigned int ud_insn_len(struct ud* u);
extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
/* ========================================================================== */
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,563 @@
#include "stdafx.h"
NT_DEVICE_IO_CONTROL_FILE old_NtDeviceIoControlFile = NULL;
/**
* Fuzzing settings
*/
ULONG m_FuzzOptions = 0;
FUZZING_TYPE m_FuzzingType = FuzzingType_Random;
/**
* Exported variables for acessing to the
* last IOCTL request information from the kernel debugger.
*/
PDEVICE_OBJECT currentDeviceObject = NULL;
PDRIVER_OBJECT currentDriverObject = NULL;
ULONG currentIoControlCode = 0;
PVOID currentInputBuffer = NULL;
ULONG currentInputBufferLength = 0;
PVOID currentOutputBuffer = NULL;
ULONG currentOutputBufferLength = 0;
/**
* Handle and objetc pointer of the fuzzer's process (uses for fair fuzzing mode)
*/
HANDLE m_FuzzThreadId = 0;
PEPROCESS m_FuzzProcess = NULL;
PUSER_MODE_DATA m_UserModeData = NULL;
/**
* Some fuzzing parameters
*/
#define RANDOM_FUZZING_ITERATIONS 10
#define BUFFERED_FUZZING_ITERATIONS 5
#define DWORD_FUZZING_MAX_LENGTH 0x2000
#define DWORD_FUZZING_DELTA 4
ULONG g_newDeviceIoControlFileCallCount = 0;
#ifdef _X86_
// pointer values for invalid kernel and user buffers
#define KERNEL_BUFFER_ADDRESS (PVOID)(0xFFFF0000)
#define USER_BUFFER_ADDRESS (PVOID)(0x00001000)
#elif _AMD64_
#define KERNEL_BUFFER_ADDRESS (PVOID)(0xFFFFFFFFFFFF0000)
#define USER_BUFFER_ADDRESS (PVOID)(0x0000000000001000)
#endif
// constants for dword fuzzing
ULONG m_DwordFuzzingConstants[] =
{
0x00000000,
0x00001000,
0xFFFF0000,
0xFFFFFFFF
};
// defined in driver.cpp
extern PDEVICE_OBJECT m_DeviceObject;
extern KMUTEX m_CommonMutex;
extern PCOMMON_LST m_ProcessesList;
//--------------------------------------------------------------------------------------
PCOMMON_LST_ENTRY LookupProcessInfo(PEPROCESS Process)
{
PCOMMON_LST_ENTRY process_entry = NULL;
KIRQL OldIrql;
KeAcquireSpinLock(&m_ProcessesList->ListLock, &OldIrql);
__try
{
PCOMMON_LST_ENTRY e = m_ProcessesList->list_head;
// enumerate all processes
while (e)
{
if (e->Data && e->DataSize == sizeof(LST_PROCESS_INFO))
{
PLST_PROCESS_INFO Info = (PLST_PROCESS_INFO)e->Data;
if (Info->Process == Process)
{
process_entry = e;
break;
}
}
e = e->next;
}
}
__finally
{
KeReleaseSpinLock(&m_ProcessesList->ListLock, OldIrql);
}
return process_entry;
}
//--------------------------------------------------------------------------------------
void FreeProcessInfo(void)
{
KIRQL OldIrql;
KeAcquireSpinLock(&m_ProcessesList->ListLock, &OldIrql);
__try
{
PCOMMON_LST_ENTRY e = m_ProcessesList->list_head;
// enumerate all processes
while (e)
{
if (e->Data && e->DataSize == sizeof(LST_PROCESS_INFO))
{
PLST_PROCESS_INFO Info = (PLST_PROCESS_INFO)e->Data;
if (Info->usImagePath.Buffer)
{
// free process image path
RtlFreeUnicodeString(&Info->usImagePath);
}
}
e = e->next;
}
}
__finally
{
KeReleaseSpinLock(&m_ProcessesList->ListLock, OldIrql);
}
}
//--------------------------------------------------------------------------------------
void NTAPI ProcessNotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
{
PEPROCESS Process;
NTSTATUS ns = PsLookupProcessByProcessId(ProcessId, &Process);
if (NT_SUCCESS(ns))
{
KeWaitForMutexObject(&m_CommonMutex, UserRequest, KernelMode, FALSE, NULL);
__try
{
if (Create)
{
// process has been created
UNICODE_STRING ImagePath;
// get full image path for this process
if (GetProcessFullImagePath(Process, &ImagePath))
{
WCHAR wcProcess[0x200];
UNICODE_STRING usProcess;
LST_PROCESS_INFO Info;
LogData("Process "IFMT" started: '%wZ' (PID: %d)\r\n\r\n", Process, &ImagePath, ProcessId);
swprintf(wcProcess, L"'%wZ' (" IFMT_W L")", &ImagePath, Process);
RtlInitUnicodeString(&usProcess, wcProcess);
Info.Process = Process;
Info.ProcessId = ProcessId;
Info.usImagePath.Buffer = ImagePath.Buffer;
Info.usImagePath.Length = ImagePath.Length;
Info.usImagePath.MaximumLength = ImagePath.MaximumLength;
// add process information into the list
if (LstAddEntry(m_ProcessesList, &usProcess, &Info, sizeof(Info)) == NULL)
{
RtlFreeUnicodeString(&ImagePath);
}
}
}
else
{
PCOMMON_LST_ENTRY process_entry = NULL;
LogData("Process "IFMT" terminated\r\n\r\n", Process);
// process terminating
process_entry = LookupProcessInfo(Process);
if (process_entry)
{
if (process_entry->Data &&
process_entry->DataSize == sizeof(LST_PROCESS_INFO))
{
PLST_PROCESS_INFO Info = (PLST_PROCESS_INFO)process_entry->Data;
if (Info->usImagePath.Buffer)
{
// free process image path
RtlFreeUnicodeString(&Info->usImagePath);
}
}
// delete information about this process from list
LstDelEntry(m_ProcessesList, process_entry);
}
}
}
__finally
{
KeReleaseMutex(&m_CommonMutex, FALSE);
}
ObDereferenceObject(Process);
}
else
{
DbgMsg(__FILE__, __LINE__, "PsLookupProcessByProcessId() fails; status: 0x%.8x\n", ns);
}
}
//--------------------------------------------------------------------------------------
PUNICODE_STRING LookupProcessName(PEPROCESS TargetProcess)
{
PEPROCESS Process = TargetProcess;
PCOMMON_LST_ENTRY process_entry = NULL;
HANDLE ProcessId = NULL;
UNICODE_STRING ImagePath;
PUNICODE_STRING Ret = NULL;
if (Process == NULL)
{
// lookup current process information entry
Process = PsGetCurrentProcess();
}
process_entry = LookupProcessInfo(Process);
if (process_entry)
{
if (process_entry->Data &&
process_entry->DataSize == sizeof(LST_PROCESS_INFO))
{
PLST_PROCESS_INFO Info = (PLST_PROCESS_INFO)process_entry->Data;
if (Info->usImagePath.Buffer)
{
// return process image path
return &Info->usImagePath;
}
}
return NULL;
}
// information entry for current process is not found, allocate it
ProcessId = PsGetCurrentProcessId();
// get full image path for this process
if (GetProcessFullImagePath(Process, &ImagePath))
{
WCHAR wcProcess[0x200];
UNICODE_STRING usProcess;
LST_PROCESS_INFO Info;
swprintf(wcProcess, L"'%wZ' (" IFMT_W L")", &ImagePath, Process);
RtlInitUnicodeString(&usProcess, wcProcess);
Info.Process = Process;
Info.ProcessId = ProcessId;
Info.usImagePath.Buffer = ImagePath.Buffer;
Info.usImagePath.Length = ImagePath.Length;
Info.usImagePath.MaximumLength = ImagePath.MaximumLength;
// add process information into the list
if (process_entry = LstAddEntry(m_ProcessesList, &usProcess, &Info, sizeof(Info)))
{
PLST_PROCESS_INFO pInfo = (PLST_PROCESS_INFO)process_entry->Data;
Ret = &pInfo->usImagePath;
}
else
{
RtlFreeUnicodeString(&ImagePath);
}
}
return Ret;
}
//--------------------------------------------------------------------------------------
BOOLEAN ValidateUnicodeString(PUNICODE_STRING usStr)
{
ULONG i = 0;
if (!MmIsAddressValid(usStr))
{
return FALSE;
}
if (usStr->Buffer == NULL || usStr->Length == 0)
{
return FALSE;
}
for (i = 0; i < usStr->Length; i++)
{
if (!MmIsAddressValid((PUCHAR)usStr->Buffer + i))
{
return FALSE;
}
}
return TRUE;
}
//--------------------------------------------------------------------------------------
NTSTATUS NTAPI new_NtDeviceIoControlFile(
HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength)
{
KPROCESSOR_MODE PrevMode = ExGetPreviousMode();
BOOLEAN bLogOutputBuffer = FALSE;
NTSTATUS status = STATUS_UNSUCCESSFUL;
POBJECT_NAME_INFORMATION DeviceObjectName = NULL, DriverObjectName = NULL;
PFILE_OBJECT pFileObject = NULL;
NTSTATUS ns = 0;
BOOLEAN bProcessEvent = FALSE;
LARGE_INTEGER Timeout;
PVOID pDeviceObject = NULL;
PLDR_DATA_TABLE_ENTRY pModuleEntry = NULL;
PEPROCESS Process;
HANDLE ProcessId;
_InterlockedIncrement(&g_newDeviceIoControlFileCallCount);
// get device object by handle
ns = ObReferenceObjectByHandle(
FileHandle,
0, 0,
KernelMode,
(PVOID *)&pFileObject,
NULL
);
if(!NT_SUCCESS(ns))
goto end;
// validate pointer to device object
if (MmIsAddressValid(pFileObject->DeviceObject))
{
pDeviceObject = pFileObject->DeviceObject;
}
else
{
goto end;
}
if (pDeviceObject == m_DeviceObject)
{
// don't handle requests to our driver
goto end;
}
// validate pointer to driver object
if (!MmIsAddressValid(pFileObject->DeviceObject->DriverObject))
{
goto end;
}
// get loader information entry for the driver module
pModuleEntry = (PLDR_DATA_TABLE_ENTRY)
pFileObject->DeviceObject->DriverObject->DriverSection;
if (pModuleEntry == NULL)
{
goto end;
}
// validate pointer to loader's table and data from it
if (!MmIsAddressValid(pModuleEntry) ||
!ValidateUnicodeString(&pModuleEntry->FullDllName))
{
goto end;
}
// get device name by poinet
DeviceObjectName = GetObjectName(pDeviceObject);
if(!DeviceObjectName)
goto end;
DriverObjectName = GetObjectName(pFileObject->DeviceObject->DriverObject);
if(!DriverObjectName)
goto end;
Process = PsGetCurrentProcess();
ProcessId = PsGetCurrentProcessId();
Timeout.QuadPart = RELATIVE(SECONDS(5));
ns = KeWaitForMutexObject(&m_CommonMutex, Executive, KernelMode, FALSE, &Timeout);
if (ns == STATUS_TIMEOUT)
{
DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Wait timeout\n");
goto end;
}
__try
{
PWSTR Methods[] =
{
L"METHOD_BUFFERED",
L"METHOD_IN_DIRECT",
L"METHOD_OUT_DIRECT",
L"METHOD_NEITHER"
};
PWSTR lpwcMethod = Methods[IoControlCode & 3];
char *lpszKdCommand = NULL;
LARGE_INTEGER Time;
// get process image path
PUNICODE_STRING ProcessImagePath = LookupProcessName(NULL);
if(!ProcessImagePath)
__leave;
KeQuerySystemTime(&Time);
// get text name of the method
currentDeviceObject = pFileObject->DeviceObject;
currentDriverObject = pFileObject->DeviceObject->DriverObject;
currentIoControlCode = IoControlCode;
currentInputBuffer = InputBuffer;
currentInputBufferLength = InputBufferLength;
currentOutputBuffer = OutputBuffer;
currentOutputBufferLength = OutputBufferLength;
// if (m_FuzzOptions & FUZZ_OPT_LOG_IOCTL_GLOBAL)
// {
// // log IOCTL information into the global log
// LogDataIoctls("timestamp=0x%.8x%.8x\r\n", Time.HighPart, Time.LowPart);
// LogDataIoctls("process_id=%d\r\n", ProcessId);
// LogDataIoctls("process_path=%wZ\r\n", ProcessImagePath);
// LogDataIoctls("device=%wZ\r\n", &DeviceObjectName->Name);
// LogDataIoctls("driver=%wZ\r\n", &DriverObjectName->Name);
// LogDataIoctls("image_file=%wZ\r\n", &pModuleEntry->FullDllName);
// LogDataIoctls("code=0x%.8x\r\n", IoControlCode);
// LogDataIoctls("method=%ws\r\n", lpwcMethod);
// LogDataIoctls("in_size=%d\r\n", InputBufferLength);
// LogDataIoctls("out_size=%d\r\n", OutputBufferLength);
// LogDataIoctls("\r\n");
// }
// get debugger command, that can be associated with this IOCTL
lpszKdCommand = FltGetKdCommand(
&DeviceObjectName->Name,
&DriverObjectName->Name/*pModuleEntry->FullDllName*/,
IoControlCode,
ProcessImagePath
);
bProcessEvent = FltIsMatchedRequest(
&DeviceObjectName->Name,
&pModuleEntry->FullDllName,
IoControlCode,
ProcessImagePath
);
if ((bProcessEvent || lpszKdCommand) &&
(m_FuzzOptions & FUZZ_OPT_LOG_IOCTL))
{
LogDataIoctls(
"timestamp=0x%.8x%.8x\r\n \
process_id=%d\r\n \
process_path=%wZ\r\n \
device=%wZ\r\n \
driver=%wZ\r\n \
image_file=%wZ\r\n \
code=0x%.8x\r\n \
method=%ws\r\n \
in_size=%d\r\n \
out_size=%d\r\n \
\r\n",
Time.HighPart, Time.LowPart,
ProcessId,
ProcessImagePath,
&DeviceObjectName->Name,
&DriverObjectName->Name,
&pModuleEntry->FullDllName,
IoControlCode,
lpwcMethod,
InputBufferLength,
OutputBufferLength);
if (m_FuzzOptions & FUZZ_OPT_LOG_IOCTL_BUFFERS)
{
// log output buffer information
LogDataIoctls(" OutBuff: "IFMT", OutSize: 0x%.8x\r\n",
OutputBuffer,
OutputBufferLength);
// log input buffer information
LogDataIoctls(" InBuff: "IFMT", InSize: 0x%.8x\r\n",
InputBuffer,
InputBufferLength);
// print input buffer contents
LogDataIoctls("--------------------------------------------------------------------\r\n");
LogDataHexdump((PUCHAR)InputBuffer, min(InputBufferLength, MAX_IOCTL_BUFFER_LEGTH));
LogDataIoctls("\r\n");
}
}
}
__finally
{
KeReleaseMutex(&m_CommonMutex, FALSE);
}
end:
if(pFileObject)
ObDereferenceObject(pFileObject);
if(DriverObjectName)
ExFreePool(DriverObjectName);
if(DeviceObjectName)
ExFreePool(DeviceObjectName);
// restore KTHREAD::PreviousMode
SetPreviousMode(PrevMode);
// call original function
status = old_NtDeviceIoControlFile(
FileHandle,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength
);
_InterlockedDecrement( &g_newDeviceIoControlFileCallCount );
return status;
}
VOID WaitHookRemoveComplete()
{
LONG Count = 0;
const LARGE_INTEGER WaitTime = {(ULONG)(-50 * 1000 * 10), -1};
do
{
KeDelayExecutionThread( KernelMode , FALSE , (PLARGE_INTEGER)&WaitTime );
_InterlockedExchange( &Count , g_newDeviceIoControlFileCallCount );
} while (Count != 0 );
return;
}
//--------------------------------------------------------------------------------------
// EoF
@@ -0,0 +1,43 @@
typedef struct _LST_PROCESS_INFO
{
PEPROCESS Process;
HANDLE ProcessId;
UNICODE_STRING usImagePath;
} LST_PROCESS_INFO,
*PLST_PROCESS_INFO;
void FreeProcessInfo(void);
void NTAPI ProcessNotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create);
PUNICODE_STRING LookupProcessName(PEPROCESS TargetProcess);
typedef NTSTATUS (NTAPI * NT_DEVICE_IO_CONTROL_FILE)(
HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength
);
NTSTATUS NTAPI new_NtDeviceIoControlFile(
HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength
);
BOOLEAN ValidateUnicodeString(PUNICODE_STRING usStr);
VOID WaitHookRemoveComplete();
@@ -0,0 +1,152 @@
#include "stdafx.h"
//--------------------------------------------------------------------------------------
PVOID Hook(PVOID Function, PVOID Handler, PULONG pBytesPatched)
{
#ifdef _X86_
#define SIZEOFJUMP 6
#elif _AMD64_
#define SIZEOFJUMP 14
#endif
ULONG Size = 0, CollectedSpace = 0;
PUCHAR pInst = (PUCHAR)Function;
ud_t ud_obj;
PVOID CallGate = NULL;
ULONG CallGateSize = 0;
if (pBytesPatched)
{
*pBytesPatched = 0;
}
// initialize disassembler engine
ud_init(&ud_obj);
// set mode, syntax and vendor
ud_set_mode(&ud_obj, UD_MODE);
ud_set_syntax(&ud_obj, UD_SYN_INTEL);
ud_set_vendor(&ud_obj, UD_VENDOR_INTEL);
while (CollectedSpace < SIZEOFJUMP)
{
ULONG dwInstLen = 0;
int i = 0;
ud_set_input_buffer(&ud_obj, pInst, MAX_INST_LEN);
// get length of instruction
dwInstLen = ud_disassemble(&ud_obj);
if (dwInstLen == 0)
{
// error while disassembling instruction
DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ERROR: Can't disassemble instruction at "IFMT"\n", pInst);
return NULL;
}
if (ud_obj.mnemonic == UD_Ijmp ||
ud_obj.mnemonic == UD_Icall)
{
// call/jmp with relative address
DbgMsg(__FILE__, __LINE__, __FUNCTION__"() call/jmp/jxx instruction at "IFMT"\n", pInst);
return NULL;
}
for (i = 0; i < 3; i++)
{
if (ud_obj.operand[i].type == UD_OP_JIMM)
{
// jxx with relative address
DbgMsg(__FILE__, __LINE__, __FUNCTION__"() jxx instruction at "IFMT"\n", pInst);
return NULL;
}
}
pInst += dwInstLen;
CollectedSpace += dwInstLen;
if (ud_obj.mnemonic == UD_Iret ||
ud_obj.mnemonic == UD_Iretf ||
ud_obj.mnemonic == UD_Iiretw ||
ud_obj.mnemonic == UD_Iiretq ||
ud_obj.mnemonic == UD_Iiretd)
{
// end of the function thunk?
DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ret/retn/iret instruction at "IFMT"\n", pInst);
break;
}
}
if (SIZEOFJUMP > CollectedSpace)
{
DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ERROR: not enough memory for jump\n");
return NULL;
}
CallGateSize = CollectedSpace + SIZEOFJUMP;
// allocate memory for callgate
CallGate = M_ALLOC(CallGateSize);
if (CallGate)
{
// generate callgate
memset(CallGate, 0x90, CallGateSize);
// save begining of the function
memcpy(CallGate, Function, CollectedSpace);
#ifdef _X86_
// jump from callgate to function body
// push imm32
*(PUCHAR)((PUCHAR)CallGate + CollectedSpace) = 0x68;
*(PUCHAR *)((PUCHAR)CallGate + CollectedSpace + 1) = (PUCHAR)Function + SIZEOFJUMP;
// ret
*(PUCHAR)((PUCHAR)CallGate + CollectedSpace + 5) = 0xC3;
#elif _AMD64_
// jmp qword [addr]
*(PUSHORT)((PUCHAR)CallGate + CollectedSpace) = 0x25FF;
*(PULONG)((PUCHAR)CallGate + CollectedSpace + 2) = 0;
// addr dq XXXh
*(PULONGLONG)((PUCHAR)CallGate + CollectedSpace + 6) = (ULONGLONG)Function + SIZEOFJUMP;
#endif
// jump from the function to callgate
memset(Function, 0x90, CollectedSpace);
#ifdef _X86_
// push imm32
*(PUCHAR)Function = 0x68;
*(PUCHAR *)((PUCHAR)Function + 1) = (PUCHAR)Handler;
// ret
*(PUCHAR)((PUCHAR)Function + 5) = 0xC3;
#elif _AMD64_
// jmp qword [addr]
*(PUSHORT)Function = 0x25FF;
*(PULONG)((PUCHAR)Function + 2) = 0;
// addr dq XXXh
*(PULONGLONG)((PUCHAR)Function + 6) = (ULONGLONG)Handler;
#endif
*pBytesPatched = CollectedSpace;
return CallGate;
}
else
{
DbgMsg(__FILE__, __LINE__, "M_ALLOC() fails\n");
}
return NULL;
}
//--------------------------------------------------------------------------------------
// EoF
@@ -0,0 +1,13 @@
#ifdef _X86_
#define MAX_INST_LEN 16
#define UD_MODE 32
#elif _AMD64_
#define MAX_INST_LEN 24
#define UD_MODE 64
#endif
PVOID Hook(PVOID Function, PVOID Handler, PULONG pBytesPatched);
@@ -0,0 +1,266 @@
#include "stdafx.h"
// defined in handlers.cpp
extern ULONG m_FuzzOptions;
// defined in debug.cpp
extern HANDLE hDbgPipe;
extern KMUTEX DbgMutex;
#define LOG_BUFF_SIZE 0x1000
HANDLE m_hIoctlsLogFile = NULL;
WCHAR m_wcIoctlsLogFilePath[MAX_REQUEST_STRING];
UNICODE_STRING m_usIoctlsLogFilePath;
//--------------------------------------------------------------------------------------
void LogData(char *lpszFormat, ...)
{
IO_STATUS_BLOCK IoStatusBlock;
va_list mylist;
char *lpszBuff = (char *)M_ALLOC(LOG_BUFF_SIZE);
if (lpszBuff == NULL)
{
DbgMsg(__FILE__, __LINE__, "M_ALLOC() fails\n");
return;
}
va_start(mylist, lpszFormat);
vsprintf(lpszBuff, lpszFormat, mylist);
va_end(mylist);
if (m_FuzzOptions & FUZZ_OPT_LOG_DEBUG)
{
// post message into debug output
DbgPrint(lpszBuff);
}
#ifdef DBGPIPE
if (KeGetCurrentIrql() == PASSIVE_LEVEL)
{
KeWaitForMutexObject(&DbgMutex, Executive, KernelMode, FALSE, NULL);
if (hDbgPipe)
{
// write debug message into pipe
IO_STATUS_BLOCK IoStatusBlock;
ULONG Len = (ULONG)strlen(lpszBuff) + 1;
ZwWriteFile(hDbgPipe, 0, NULL, NULL, &IoStatusBlock, (PVOID)&Len, sizeof(Len), NULL, NULL);
ZwWriteFile(hDbgPipe, 0, NULL, NULL, &IoStatusBlock, lpszBuff, Len, NULL, NULL);
}
KeReleaseMutex(&DbgMutex, FALSE);
}
#endif // DBGPIPE
M_FREE(lpszBuff);
}
//--------------------------------------------------------------------------------------
BOOLEAN LogDataIoctlsInitLogFile(void)
{
BOOLEAN bRet = FALSE;
UNICODE_STRING usNtdllPath;
OBJECT_ATTRIBUTES ObjAttr;
HANDLE hNtdll = NULL;
IO_STATUS_BLOCK StatusBlock;
NTSTATUS ns = STATUS_UNSUCCESSFUL;
RtlInitUnicodeString(&usNtdllPath, L"\\SystemRoot\\system32\\ntdll.dll");
InitializeObjectAttributes(&ObjAttr, &usNtdllPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE , NULL, NULL);
// get file handle
ns = ZwOpenFile(
&hNtdll,
FILE_READ_DATA | SYNCHRONIZE,
&ObjAttr,
&StatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_SYNCHRONOUS_IO_NONALERT
);
if (NT_SUCCESS(ns))
{
PFILE_OBJECT FileObject = NULL;
// get file object by handle
ns = ObReferenceObjectByHandle(hNtdll, 0, 0, KernelMode, (PVOID *)&FileObject, NULL);
if (NT_SUCCESS(ns))
{
// get DOS path for file object
POBJECT_NAME_INFORMATION ObjectNameInfo;
ns = IoQueryFileDosDeviceName(FileObject, &ObjectNameInfo);
if (NT_SUCCESS(ns))
{
size_t DosDriveLen = wcslen(L"C:\\");
RtlZeroMemory(m_wcIoctlsLogFilePath, sizeof(m_wcIoctlsLogFilePath));
// check for valid DOS path
if (ObjectNameInfo &&
ObjectNameInfo->Name.Length > (DosDriveLen * sizeof(WCHAR)) &&
ObjectNameInfo->Name.Buffer[1] == L':' &&
ObjectNameInfo->Name.Buffer[2] == L'\\')
{
UNICODE_STRING usXmlPath;
wcscpy(m_wcIoctlsLogFilePath, L"\\??\\");
wcsncat(m_wcIoctlsLogFilePath, ObjectNameInfo->Name.Buffer, DosDriveLen);
wcscat(m_wcIoctlsLogFilePath, IOCTLS_LOG_NAME);
RtlInitUnicodeString(&m_usIoctlsLogFilePath, m_wcIoctlsLogFilePath);
InitializeObjectAttributes(&ObjAttr, &m_usIoctlsLogFilePath,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE , NULL, NULL);
// open IOCTLs log file
ns = ZwCreateFile(
&m_hIoctlsLogFile,
FILE_ALL_ACCESS | SYNCHRONIZE,
&ObjAttr,
&StatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0
);
if (NT_SUCCESS(ns))
{
DbgMsg(__FILE__, __LINE__, "[+] IOCTLs log started: \"%wZ\"\n\n", &m_usIoctlsLogFilePath);
bRet = TRUE;
}
else
{
DbgMsg(__FILE__, __LINE__, "ZwCreateFile() fails; status: 0x%.8x\n", ns);
}
}
}
else
{
DbgMsg(__FILE__, __LINE__, "IoQueryFileDosDeviceName() fails; status: 0x%.8x\n", ns);
}
ObDereferenceObject(FileObject);
}
else
{
DbgMsg(__FILE__, __LINE__, "ObReferenceObjectByHandle() fails; status: 0x%.8x\n", ns);
}
ZwClose(hNtdll);
}
else
{
DbgMsg(__FILE__, __LINE__, "ZwOpenFile() fails; status: 0x%.8x\n", ns);
}
return bRet;
}
//--------------------------------------------------------------------------------------
void LogDataIoctls(char *lpszFormat, ...)
{
IO_STATUS_BLOCK IoStatusBlock;
va_list mylist;
char *lpszBuff = (char *)M_ALLOC(LOG_BUFF_SIZE);
if (lpszBuff == NULL)
{
DbgMsg(__FILE__, __LINE__, "M_ALLOC() fails\n");
return;
}
if (KeGetCurrentIrql() > PASSIVE_LEVEL)
{
// IRQL is too high
return;
}
if ((m_FuzzOptions & FUZZ_OPT_LOG_IOCTL_GLOBAL) && m_hIoctlsLogFile == NULL)
{
// log file is not initialized, try to create it
if (!LogDataIoctlsInitLogFile())
{
// ... fails
return;
}
}
va_start(mylist, lpszFormat);
vsprintf(lpszBuff, lpszFormat, mylist);
va_end(mylist);
// write string into the log file
ZwWriteFile(m_hIoctlsLogFile, 0, NULL, NULL, &IoStatusBlock, lpszBuff, (ULONG)strlen(lpszBuff), NULL, NULL);
M_FREE(lpszBuff);
}
//--------------------------------------------------------------------------------------
void LogDataHexdump(PUCHAR Data, ULONG Size)
{
unsigned int dp = 0, p = 0;
const char trans[] =
"................................ !\"#$%&'()*+,-./0123456789"
":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
"nopqrstuvwxyz{|}~...................................."
"....................................................."
"........................................";
char szBuff[0x100], szChr[10];
RtlZeroMemory(szBuff, sizeof(szBuff));
for (dp = 1; dp <= Size; dp++)
{
sprintf(szChr, "%02x ", Data[dp-1]);
strcat(szBuff, szChr);
if ((dp % 8) == 0)
{
strcat(szBuff, " ");
}
if ((dp % 16) == 0)
{
strcat(szBuff, "| ");
p = dp;
for (dp -= 16; dp < p; dp++)
{
sprintf(szChr, "%c", trans[Data[dp]]);
strcat(szBuff, szChr);
}
LogDataIoctls("%s\r\n", szBuff);
RtlZeroMemory(szBuff, sizeof(szBuff));
}
}
if ((Size % 16) != 0)
{
p = dp = 16 - (Size % 16);
for (dp = p; dp > 0; dp--)
{
strcat(szBuff, " ");
if (((dp % 8) == 0) && (p != 8))
{
strcat(szBuff, " ");
}
}
strcat(szBuff, " | ");
for (dp = (Size - (16 - p)); dp < Size; dp++)
{
sprintf(szChr, "%c", trans[Data[dp]]);
strcat(szBuff, szChr);
}
LogDataIoctls("%s\r\n", szBuff);
}
LogDataIoctls("\r\n");
}
//--------------------------------------------------------------------------------------
// EoF
@@ -0,0 +1,4 @@
void LogData(char *lpszFormat, ...);
void LogDataIoctls(char *lpszFormat, ...);
void LogDataHexdump(PUCHAR Data, ULONG Size);
@@ -0,0 +1,222 @@
#include "stdafx.h"
//--------------------------------------------------------------------------------------
PCOMMON_LST_ENTRY LstFindEntry(
PCOMMON_LST list,
PUNICODE_STRING ObjectName)
{
PCOMMON_LST_ENTRY ret = NULL;
KIRQL OldIrql;
KeAcquireSpinLock(&list->ListLock, &OldIrql);
__try
{
PCOMMON_LST_ENTRY e = list->list_head;
while (e)
{
// for empty object name - just return first entry
if (ObjectName == NULL ||
RtlEqualUnicodeString(&e->ObjectName, ObjectName, TRUE))
{
ret = e;
break;
}
e = e->next;
}
}
__finally
{
KeReleaseSpinLock(&list->ListLock, OldIrql);
}
return ret;
}
//--------------------------------------------------------------------------------------
PCOMMON_LST_ENTRY LstAddEntry(
PCOMMON_LST list,
PUNICODE_STRING ObjectName,
PVOID Data,
ULONG DataSize)
{
PCOMMON_LST_ENTRY ret = NULL;
KIRQL OldIrql;
KeAcquireSpinLock(&list->ListLock, &OldIrql);
__try
{
// allocate single list entry
PCOMMON_LST_ENTRY e = (PCOMMON_LST_ENTRY)M_ALLOC(sizeof(COMMON_LST_ENTRY));
if (e)
{
RtlZeroMemory(e, sizeof(COMMON_LST_ENTRY));
if (Data && DataSize > 0)
{
// allocate memory for custom data
if (e->Data = M_ALLOC(DataSize))
{
e->DataSize = DataSize;
RtlCopyMemory(e->Data, Data, DataSize);
}
else
{
DbgMsg(__FILE__, __LINE__, "M_ALLOC() fails\n");
M_FREE(e);
return NULL;
}
}
// allocate and copy string name
if (AllocUnicodeString(&e->ObjectName, ObjectName->MaximumLength))
{
RtlCopyUnicodeString(&e->ObjectName, ObjectName);
}
else
{
if (e->Data)
{
M_FREE(e->Data);
}
M_FREE(e);
return NULL;
}
// add it to list
if (list->list_end)
{
list->list_end->next = e;
e->prev = list->list_end;
list->list_end = e;
}
else
{
list->list_end = list->list_head = e;
}
ret = e;
}
else
{
DbgMsg(__FILE__, __LINE__, "M_ALLOC() fails\n");
}
}
__finally
{
KeReleaseSpinLock(&list->ListLock, OldIrql);
}
return ret;
}
//--------------------------------------------------------------------------------------
void LstFlush(PCOMMON_LST list)
{
KIRQL OldIrql;
KeAcquireSpinLock(&list->ListLock, &OldIrql);
__try
{
// delete all entries from list
PCOMMON_LST_ENTRY e = list->list_head;
while (e)
{
PCOMMON_LST_ENTRY e_tmp = e->next;
// delete single entry from list
if (e->prev)
e->prev->next = e->next;
if (e->next)
e->next->prev = e->prev;
if (list->list_head == e)
list->list_head = e->next;
if (list->list_end == e)
list->list_end = e->prev;
if (e->Data)
{
// delete data, if present
M_FREE(e->Data);
}
// free name string
RtlFreeUnicodeString(&e->ObjectName);
M_FREE(e);
e = e_tmp;
}
list->list_head = NULL;
list->list_end = NULL;
}
__finally
{
KeReleaseSpinLock(&list->ListLock, OldIrql);
}
}
//--------------------------------------------------------------------------------------
void LstDelEntry(PCOMMON_LST list, PCOMMON_LST_ENTRY e)
{
KIRQL OldIrql;
KeAcquireSpinLock(&list->ListLock, &OldIrql);
__try
{
// delete single entry from list
if (e->prev)
e->prev->next = e->next;
if (e->next)
e->next->prev = e->prev;
if (list->list_head == e)
list->list_head = e->next;
if (list->list_end == e)
list->list_end = e->prev;
if (e->Data)
{
// delete data, if present
M_FREE(e->Data);
}
// free name string
RtlFreeUnicodeString(&e->ObjectName);
M_FREE(e);
}
__finally
{
KeReleaseSpinLock(&list->ListLock, OldIrql);
}
}
//--------------------------------------------------------------------------------------
PCOMMON_LST LstInit(void)
{
// allocate new list
PCOMMON_LST ret = (PCOMMON_LST)M_ALLOC(sizeof(COMMON_LST));
if (ret)
{
ret->list_head = ret->list_end = NULL;
KeInitializeSpinLock(&ret->ListLock);
return ret;
}
else
{
DbgMsg(__FILE__, __LINE__, "M_ALLOC() fails\n");
}
return NULL;
}
//--------------------------------------------------------------------------------------
void LstFree(PCOMMON_LST list)
{
// flust list and free list descriptor
LstFlush(list);
M_FREE(list);
}
//--------------------------------------------------------------------------------------
// EoF
@@ -0,0 +1,45 @@
/*
Common linked lists structures
*/
typedef struct _COMMON_LST_ENTRY
{
UNICODE_STRING ObjectName;
ULONG ObjectType;
PVOID Data;
ULONG DataSize;
struct _COMMON_LST_ENTRY *next, *prev;
} COMMON_LST_ENTRY,
*PCOMMON_LST_ENTRY;
typedef struct _COMMON_LST
{
KSPIN_LOCK ListLock;
PCOMMON_LST_ENTRY list_head, list_end;
} COMMON_LST,
*PCOMMON_LST;
/*
Common linked lists routines
*/
PCOMMON_LST_ENTRY LstFindEntry(
PCOMMON_LST list,
PUNICODE_STRING ObjectName
);
PCOMMON_LST_ENTRY LstAddEntry(
PCOMMON_LST list,
PUNICODE_STRING ObjectName,
PVOID Data,
ULONG DataSize
);
void LstFlush(PCOMMON_LST list);
void LstDelEntry(PCOMMON_LST list, PCOMMON_LST_ENTRY e);
PCOMMON_LST LstInit(void);
void LstFree(PCOMMON_LST list);
@@ -0,0 +1,44 @@
/**
* Program information, copyright, etc.
*/
#define PROGRAM_NAME "IOCTL Fuzzer"
#define PROGRAM_AUTHOR "by Oleksiuk Dmytro (aka Cr4sh) :: dmitry@esagelab.com"
#define PROGRAM_COPYRIGHT "(c) 2011 Esage Lab :: http://www.esagelab.com/"
/**
* Log file name to store all IOCTLs requests information.
*/
#define IOCTLS_LOG_NAME L"ioctls.log"
/**
* Main application log file name.
*/
#define IOCTLFUZZER_LOG_FILE "ioctlfuzzer.log"
/**
* File and service name for the kernel driver.
*/
#define DRIVER_SERVICE_NAME "IOCTL_fuzzer"
#define DRIVER_FILE_NAME "IOCTL_fuzzer.sys"
/**
* Directory name to store downloaded debug symbols.
*/
#define SYMBOLS_DIR_NAME "Symbols"
/**
* Default value for fuzzing type option.
*/
#define DEFAULT_FUZZING_TYPE FuzzingType_Random
/**
* IOCTL buffer length limit for dumping into the
* application log or debugger output.
*/
#define MAX_IOCTL_BUFFER_LEGTH 0x1000
/**
* Maximum number of lines in console window.
*/
#define CONSOLE_BUFFER_HEIGHT 0x1000
@@ -0,0 +1,142 @@
/*
A C-program for MT19937, with initialization improved 2002/1/26.
Coded by Takuji Nishimura and Makoto Matsumoto.
Before using, initialize the state by using init_genrand(seed)
or init_by_array(init_key, key_length).
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Any feedback is very welcome.
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
*/
#include <stdio.h>
/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
static unsigned long mt[N]; /* the array for the state vector */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
/* initializes mt[N] with a seed */
void init_genrand(unsigned long s)
{
mt[0]= s & 0xffffffffUL;
for (mti=1; mti<N; mti++) {
mt[mti] =
(1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
mt[mti] &= 0xffffffffUL;
/* for >32 bit machines */
}
}
/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
void init_by_array(unsigned long init_key[], int key_length)
{
int i, j, k;
init_genrand(19650218UL);
i=1; j=0;
k = (N>key_length ? N : key_length);
for (; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+ init_key[j] + j; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++; j++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
if (j>=key_length) j=0;
}
for (k=N-1; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
- i; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
}
mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
}
/* generates a random number on [0,0xffffffff]-interval */
unsigned long genrand_int32(void)
{
unsigned long y;
static unsigned long mag01[2]={0x0UL, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
if (mti >= N) { /* generate N words at one time */
int kk;
if (mti == N+1) /* if init_genrand() has not been called, */
init_genrand(5489UL); /* a default initial seed is used */
for (kk=0;kk<N-M;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
for (;kk<N-1;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
mti = 0;
}
y = mt[mti++];
/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return y;
}
unsigned long getrand(unsigned long min, unsigned long max)
{
return (genrand_int32() % (max - min + 1)) + min;
}
@@ -0,0 +1,4 @@
void init_genrand(unsigned long s);
void init_by_array(unsigned long init_key[], int key_length);
unsigned long genrand_int32(void);
unsigned long getrand(unsigned long min, unsigned long max);
@@ -0,0 +1,695 @@
#include "stdafx.h"
// defined in driver.cpp
extern UNICODE_STRING m_RegistryPath;
extern KMUTEX m_CommonMutex;
BOOLEAN g_RuleInited = FALSE;
ERESOURCE g_RuleResource;
LIST_ENTRY g_DenyRuleList;
LIST_ENTRY g_AllowRuleList;
LIST_ENTRY g_DbgcbRuleList;
FORCEINLINE
VOID
RuleLock(
__in BOOLEAN Exclusive
)
{
KeEnterCriticalRegion();
if (Exclusive)
ExAcquireResourceExclusiveLite(&g_RuleResource, TRUE);
else
ExAcquireResourceSharedLite(&g_RuleResource, TRUE);
}
FORCEINLINE
VOID
RuleUnlock()
{
ExReleaseResourceLite(&g_RuleResource);
KeLeaveCriticalRegion();
}
NTSTATUS FltInitRuleList()
{
NTSTATUS Status = 0;
InitializeListHead( &g_DenyRuleList );
InitializeListHead( &g_AllowRuleList );
InitializeListHead( &g_DbgcbRuleList );
Status = ExInitializeResourceLite( &g_RuleResource );
if(!NT_SUCCESS(Status))
return Status;
g_RuleInited = TRUE;
return STATUS_SUCCESS;
}
VOID FltUnInitRuleList()
{
if(!g_RuleInited)
return;
FltFlushAllList();
g_RuleInited = FALSE;
ExDeleteResourceLite(&g_RuleResource);
}
//--------------------------------------------------------------------------------------
wchar_t xchrlower_w(wchar_t chr)
{
if ((chr >= 'A') && (chr <= 'Z'))
{
return chr + ('a'-'A');
}
return chr;
}
//--------------------------------------------------------------------------------------
BOOLEAN EqualUnicodeString_r(PUNICODE_STRING Str1, PUNICODE_STRING Str2, BOOLEAN CaseInSensitive)
{
USHORT CmpLen = min(Str1->Length, Str2->Length) / sizeof(WCHAR);
USHORT i = 0;
for ( i = 1; i < CmpLen; i++)
{
WCHAR Chr1 = Str1->Buffer[Str1->Length / sizeof(WCHAR) - i],
Chr2 = Str2->Buffer[Str2->Length / sizeof(WCHAR) - i];
if (CaseInSensitive)
{
Chr1 = xchrlower_w(Chr1);
Chr2 = xchrlower_w(Chr2);
}
if (Chr1 != Chr2)
{
return FALSE;
}
}
return TRUE;
}
PIOCTL_FILTER FltAdd(PIOCTL_FILTER f, PLIST_ENTRY ListEntry, ULONG KdCommandLength)
{
ULONG Length = 0;
PIOCTL_FILTER f_entry = NULL;
if(!g_RuleInited || !ListEntry || !f)
return NULL;
Length = KdCommandLength + sizeof(IOCTL_FILTER);
f_entry = (PIOCTL_FILTER)ExAllocatePool(NonPagedPool, Length);
if (f_entry)
{
RtlZeroMemory(f_entry, Length);
RtlCopyMemory(f_entry, f, sizeof(IOCTL_FILTER));
InsertHeadList(ListEntry, &f_entry->List);
return f_entry;
}
else
{
DbgMsg(__FILE__, __LINE__, "ExAllocatePool() fails\n");
}
return NULL;
}
VOID DeferenceRuleCount(PIOCTL_FILTER Item)
{
if(!g_RuleInited)
return;
RuleLock(TRUE);
Item->ReferenceCount--;
RuleUnlock();
}
PIOCTL_FILTER FltAddDenyRule(PIOCTL_FILTER f, ULONG KdCommandLength)
{
PIOCTL_FILTER Item = NULL;
if(!g_RuleInited)
return NULL;
RuleLock(TRUE);
Item = FltAdd(f, &g_DenyRuleList, KdCommandLength);
Item->ReferenceCount +=1 ;
RuleUnlock();
return Item;
}
PIOCTL_FILTER FltAddAllowRule(PIOCTL_FILTER f, ULONG KdCommandLength)
{
PIOCTL_FILTER Item = NULL;
if(!g_RuleInited)
return NULL;
RuleLock(TRUE);
Item = FltAdd(f, &g_AllowRuleList, KdCommandLength);
Item->ReferenceCount +=1 ;
RuleUnlock();
return Item;
}
PIOCTL_FILTER FltAddDbgcbRule(PIOCTL_FILTER f, ULONG KdCommandLength)
{
PIOCTL_FILTER Item = NULL;
if(!g_RuleInited)
return NULL;
RuleLock(TRUE);
Item = FltAdd(f, &g_DbgcbRuleList, KdCommandLength);
Item->ReferenceCount +=1 ;
RuleUnlock();
return Item;
}
//--------------------------------------------------------------------------------------
void FltFlushList(PLIST_ENTRY ListEntryHead)
{
PLIST_ENTRY ListEntry = NULL;
PLIST_ENTRY ListRemove = NULL;
PIOCTL_FILTER RuleItem = NULL;
if(!g_RuleInited || !ListEntryHead)
return;
ListEntry = ListEntryHead->Flink;
while(ListEntry != ListEntryHead)
{
RuleItem = CONTAINING_RECORD(ListEntry, IOCTL_FILTER, List);
if(RuleItem->ReferenceCount != 0)
{
ListEntry = ListEntry->Flink;
continue;
}
if (RuleItem->Type == FLT_DEVICE_NAME ||
RuleItem->Type == FLT_DRIVER_NAME ||
RuleItem->Type == FLT_PROCESS_PATH)
{
RtlFreeUnicodeString(&RuleItem->usName);
}
ListRemove = ListEntry;
ListEntry = ListEntry->Flink;
RemoveEntryList(ListRemove);
ExFreePool(RuleItem);
}
}
void FltFlushAllList()
{
if(!g_RuleInited)
return ;
RuleLock(TRUE);
FltFlushList(&g_DenyRuleList);
FltFlushList(&g_AllowRuleList);
FltFlushList(&g_DbgcbRuleList);
RuleUnlock();
}
//--------------------------------------------------------------------------------------
PIOCTL_FILTER FltMatch(
PLIST_ENTRY ListEntryHead,
PUNICODE_STRING fDeviceName,
PUNICODE_STRING fDriverName,
ULONG IoControlCode,
PUNICODE_STRING fProcessName)
{
PIOCTL_FILTER ret = NULL;
PIOCTL_FILTER RuleItem = NULL;
PLIST_ENTRY ListEntry = NULL;
if(!ListEntryHead)
return NULL;
// match parameters by filter list
ListEntry = ListEntryHead->Flink;
while (ListEntry != ListEntryHead)
{
RuleItem = CONTAINING_RECORD(ListEntry, IOCTL_FILTER, List);
if (RuleItem->bDbgcbAction)
{
// skip entries with debugger commands
goto next;
}
if (RuleItem->Type == FLT_DEVICE_NAME)
{
if (EqualUnicodeString_r(&RuleItem->usName, fDeviceName, TRUE))
{
ret = RuleItem;
break;
}
}
else if (RuleItem->Type == FLT_DRIVER_NAME)
{
if (EqualUnicodeString_r(&RuleItem->usName, fDriverName, TRUE))
{
ret = RuleItem;
break;
}
}
else if (RuleItem->Type == FLT_IOCTL_CODE)
{
if (RuleItem->IoctlCode == IoControlCode)
{
ret = RuleItem;
break;
}
}
else if (RuleItem->Type == FLT_PROCESS_PATH)
{
if (EqualUnicodeString_r(&RuleItem->usName, fProcessName, TRUE))
{
ret = RuleItem;
break;
}
}
next:
ListEntry = ListEntry->Flink;
}
return ret;
}
BOOLEAN FltMatchDeny(
PUNICODE_STRING fDeviceName,
PUNICODE_STRING fDriverName,
ULONG IoControlCode,
PUNICODE_STRING fProcessName)
{
PIOCTL_FILTER Rule = NULL;
if(!g_RuleInited)
return FALSE;
RuleLock(FALSE);
Rule = FltMatch(&g_DenyRuleList, fDeviceName, fDriverName, IoControlCode, fProcessName);
RuleUnlock();
if(Rule)
return TRUE;
else
return FALSE;
}
BOOLEAN FltMatchAllow(
PUNICODE_STRING fDeviceName,
PUNICODE_STRING fDriverName,
ULONG IoControlCode,
PUNICODE_STRING fProcessName)
{
PIOCTL_FILTER Rule = NULL;
if(!g_RuleInited)
return FALSE;
RuleLock(FALSE);
if(IsListEmpty(&g_AllowRuleList))
return TRUE;
Rule = FltMatch(&g_AllowRuleList, fDeviceName, fDriverName, IoControlCode, fProcessName);
RuleUnlock();
if(Rule)
return TRUE;
else
return FALSE;
}
//--------------------------------------------------------------------------------------
char *FltGetKdCommand(
PUNICODE_STRING fDeviceName,
PUNICODE_STRING fDriverName,
ULONG IoControlCode,
PUNICODE_STRING fProcessName)
{
char *lpszCmd = NULL;
PLIST_ENTRY ListEntry = NULL;
PIOCTL_FILTER RuleItem = NULL;
if(!g_RuleInited)
return NULL;
RuleLock(FALSE);
// match parameters by filter list
ListEntry = g_DbgcbRuleList.Flink;
while (ListEntry != &g_DbgcbRuleList)
{
RuleItem = CONTAINING_RECORD(ListEntry, IOCTL_FILTER, List);
if (!RuleItem->bDbgcbAction)
{
// skip entries with debugger commands
goto next;
}
if (RuleItem->Type == FLT_DEVICE_NAME)
{
if (EqualUnicodeString_r(&RuleItem->usName, fDeviceName, TRUE))
{
lpszCmd = RuleItem->szKdCommand;
break;
}
}
else if (RuleItem->Type == FLT_DRIVER_NAME)
{
if (EqualUnicodeString_r(&RuleItem->usName, fDriverName, TRUE))
{
lpszCmd = RuleItem->szKdCommand;
break;
}
}
else if (RuleItem->Type == FLT_IOCTL_CODE)
{
if (RuleItem->IoctlCode == IoControlCode)
{
lpszCmd = RuleItem->szKdCommand;
break;
}
}
else if (RuleItem->Type == FLT_PROCESS_PATH)
{
if (EqualUnicodeString_r(&RuleItem->usName, fProcessName, TRUE))
{
lpszCmd = RuleItem->szKdCommand;
break;
}
}
next:
ListEntry = ListEntry->Flink;
}
RuleUnlock();
return lpszCmd;
}
//--------------------------------------------------------------------------------------
BOOLEAN FltIsMatchedRequest(
PUNICODE_STRING fDeviceName,
PUNICODE_STRING fDriverName,
ULONG IoControlCode,
PUNICODE_STRING fProcessName)
{
if(!g_RuleInited)
return FALSE;
// match process by allow/deny list
if (FltMatchAllow(fDeviceName, fDriverName, IoControlCode, fProcessName) &&
FltMatchDeny(fDeviceName, fDriverName, IoControlCode, fProcessName) == FALSE)
{
return TRUE;
}
return FALSE;
}
//--------------------------------------------------------------------------------------
BOOLEAN SaveRules(PLIST_ENTRY ListEntryHead, HANDLE hKey, PUNICODE_STRING usValueName)
{
BOOLEAN bRet = FALSE;
ULONG BuffSize = 0, RulesToSerialize = 0;
PLIST_ENTRY ListEntry = NULL;
PIOCTL_FILTER RuleItem = NULL;
if(!ListEntryHead)
return FALSE;
// calculate reqired buffer size
ListEntry = ListEntryHead->Flink;
while (ListEntry != ListEntryHead)
{
RuleItem = CONTAINING_RECORD(ListEntry, IOCTL_FILTER, List);
if (!RuleItem->bDbgcbAction)
{
BuffSize += sizeof(IOCTL_FILTER_SERIALIZED);
if (RuleItem->Type == FLT_DEVICE_NAME ||
RuleItem->Type == FLT_DRIVER_NAME ||
RuleItem->Type == FLT_PROCESS_PATH)
{
// we an have object name
BuffSize += RuleItem->usName.Length;
}
RulesToSerialize++;
}
ListEntry = ListEntry->Flink;
}
if (BuffSize > 0)
{
// allocate memory for serialized rules
PUCHAR Buff = (PUCHAR)M_ALLOC(BuffSize);
if (Buff)
{
NTSTATUS ns = STATUS_UNSUCCESSFUL;
PIOCTL_FILTER_SERIALIZED f_s = NULL;
RtlZeroMemory(Buff, BuffSize);
f_s = (PIOCTL_FILTER_SERIALIZED)Buff;
// serialize available entries
ListEntry = ListEntryHead->Flink;
while (ListEntry != ListEntryHead)
{
RuleItem = CONTAINING_RECORD(ListEntry, IOCTL_FILTER, List);
if (!RuleItem->bDbgcbAction)
{
ULONG NextEntryOffset = sizeof(IOCTL_FILTER_SERIALIZED);
f_s->Type = RuleItem->Type;
f_s->IoctlCode = RuleItem->IoctlCode;
if (RuleItem->Type == FLT_DEVICE_NAME ||
RuleItem->Type == FLT_DRIVER_NAME ||
RuleItem->Type == FLT_PROCESS_PATH)
{
// we have an object name
f_s->NameLen = RuleItem->usName.Length;
NextEntryOffset += f_s->NameLen;
memcpy(&f_s->Name, RuleItem->usName.Buffer, f_s->NameLen);
}
// go to the next serialized entry
f_s = (PIOCTL_FILTER_SERIALIZED)((PUCHAR)f_s + NextEntryOffset);
}
ListEntry = ListEntry->Flink;
}
ns = ZwSetValueKey(hKey, usValueName, 0, REG_BINARY, Buff, BuffSize);
if (NT_SUCCESS(ns))
{
bRet = TRUE;
DbgMsg(
__FILE__, __LINE__,
__FUNCTION__"(): %d rules (%d bytes) saved in '%wZ'\n",
RulesToSerialize, BuffSize, usValueName
);
}
else
{
DbgMsg(__FILE__, __LINE__, "ZwSetValueKey() fails; status: 0x%.8x\n", ns);
}
M_FREE(Buff);
}
else
{
DbgMsg(__FILE__, __LINE__, "M_ALLOC() fails\n");
}
}
return bRet;
}
BOOLEAN SaveDenyRules(HANDLE hKey, PUNICODE_STRING usValueName)
{
BOOLEAN bRet = FALSE;
if(!g_RuleInited)
return FALSE;
RuleLock(FALSE);
bRet = SaveRules(&g_DenyRuleList, hKey, usValueName);
RuleUnlock();
return bRet;
}
BOOLEAN SaveAllowRules(HANDLE hKey, PUNICODE_STRING usValueName)
{
BOOLEAN bRet = FALSE;
if(!g_RuleInited)
return FALSE;
RuleLock(FALSE);
bRet = SaveRules(&g_AllowRuleList, hKey, usValueName);
RuleUnlock();
return bRet;
}
//--------------------------------------------------------------------------------------
BOOLEAN LoadRules(PLIST_ENTRY ListEntryHead, HANDLE hKey, PUNICODE_STRING usValueName)
{
BOOLEAN bRet = FALSE;
PKEY_VALUE_FULL_INFORMATION KeyInfo = NULL;
ULONG Length = 0, RulesLoaded = 0;
NTSTATUS ns = 0;
if(!ListEntryHead)
return FALSE;
// query buffer size
ns = ZwQueryValueKey(
hKey,
usValueName,
KeyValueFullInformation,
KeyInfo,
0,
&Length
);
if (ns == STATUS_BUFFER_OVERFLOW ||
ns == STATUS_BUFFER_TOO_SMALL)
{
// allocate buffer
PKEY_VALUE_FULL_INFORMATION KeyInfo = (PKEY_VALUE_FULL_INFORMATION)M_ALLOC(Length);
if (KeyInfo)
{
// query value
ns = ZwQueryValueKey(
hKey,
usValueName,
KeyValueFullInformation,
KeyInfo,
Length,
&Length
);
if (NT_SUCCESS(ns))
{
if (KeyInfo->DataLength > 0)
{
// deserialize rules
PUCHAR Buff = (PUCHAR)KeyInfo + KeyInfo->DataOffset;
PIOCTL_FILTER_SERIALIZED f_s = (PIOCTL_FILTER_SERIALIZED)Buff;
while ((ULONG)((PUCHAR)f_s - Buff) < KeyInfo->DataLength)
{
// add rule into list
IOCTL_FILTER Flt;
RtlZeroMemory(&Flt, sizeof(Flt));
Flt.Type = f_s->Type;
Flt.IoctlCode = f_s->IoctlCode;
if ((f_s->Type == FLT_DEVICE_NAME ||
f_s->Type == FLT_DRIVER_NAME ||
f_s->Type == FLT_PROCESS_PATH) &&
f_s->NameLen > 0)
{
// we have an object name
if (AllocUnicodeString(&Flt.usName, (USHORT)f_s->NameLen))
{
Flt.usName.Length = (USHORT)f_s->NameLen;
memcpy(Flt.usName.Buffer, &f_s->Name, f_s->NameLen);
DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): '%wZ'\n", &Flt.usName);
}
else
{
goto err;
}
}
if (!FltAdd(&Flt, ListEntryHead, 0))
{
if (Flt.usName.Buffer)
{
RtlFreeUnicodeString(&Flt.usName);
}
}
else
{
RulesLoaded++;
}
err:
// go to the next serialized entry
f_s = (PIOCTL_FILTER_SERIALIZED)((PUCHAR)f_s +
sizeof(IOCTL_FILTER_SERIALIZED) + f_s->NameLen);
}
}
DbgMsg(
__FILE__, __LINE__,
__FUNCTION__"(): %d rules loaded from '%wZ'\n",
RulesLoaded, usValueName
);
bRet = TRUE;
}
else
{
DbgMsg(__FILE__, __LINE__, "ZwQueryValueKey() fails; status: 0x%.8x\n", ns);
}
M_FREE(KeyInfo);
}
else
{
DbgMsg(__FILE__, __LINE__, "M_ALLOC() fails\n");
}
}
else
{
DbgMsg(__FILE__, __LINE__, __FUNCTION__"() WARNING: '%wZ' value is not set\n", usValueName);
}
return bRet;
}
BOOLEAN LoadDenyRules(HANDLE hKey, PUNICODE_STRING usValueName)
{
BOOLEAN bRet = FALSE;
if(!g_RuleInited)
return FALSE;
RuleLock(TRUE);
bRet = LoadRules(&g_DenyRuleList, hKey, usValueName);
RuleUnlock();
return bRet;
}
BOOLEAN LoadAllowRules(HANDLE hKey, PUNICODE_STRING usValueName)
{
BOOLEAN bRet = FALSE;
if(!g_RuleInited)
return FALSE;
RuleLock(TRUE);
bRet = LoadRules(&g_AllowRuleList, hKey, usValueName);
RuleUnlock();
return bRet;
}
//--------------------------------------------------------------------------------------
@@ -0,0 +1,88 @@
/**
* Structures and defines for IOCTL filtering
*/
#define FLT_DEVICE_NAME 1
#define FLT_DRIVER_NAME 2
#define FLT_IOCTL_CODE 3
#define FLT_PROCESS_PATH 4
typedef struct _IOCTL_FILTER
{
LIST_ENTRY List;
ULONG ReferenceCount;
ULONG Type;
UNICODE_STRING usName;
ULONG IoctlCode;
BOOLEAN bDbgcbAction;
char szKdCommand[1];
} IOCTL_FILTER, *PIOCTL_FILTER;
typedef struct _IOCTL_FILTER_SERIALIZED
{
ULONG Type;
ULONG IoctlCode;
ULONG NameLen;
WCHAR Name[];
} IOCTL_FILTER_SERIALIZED,
*PIOCTL_FILTER_SERIALIZED;
PIOCTL_FILTER FltAdd(PIOCTL_FILTER f, PLIST_ENTRY ListEntry, ULONG KdCommandLength);
BOOLEAN FltIsMatchedRequest(
PUNICODE_STRING fDeviceName,
PUNICODE_STRING fDriverName,
ULONG IoControlCode,
PUNICODE_STRING fProcessName
);
char *FltGetKdCommand(
PUNICODE_STRING fDeviceName,
PUNICODE_STRING fDriverName,
ULONG IoControlCode,
PUNICODE_STRING fProcessName
);
BOOLEAN SaveRules(PLIST_ENTRY ListEntryHead, HANDLE hKey, PUNICODE_STRING usValueName);
BOOLEAN LoadRules(PLIST_ENTRY ListEntryHead, HANDLE hKey, PUNICODE_STRING usValueName);
/**
* Macro defines for allow/deny lists of IOCTL filtering
*/
// #define FltAllowMatch(_drv_, _dev_, _c_, _p_) FltMatch(&f_allow_head, (_drv_), (_dev_), (_c_), (_p_))
//
// #define FltDenyMatch(_drv_, _dev_, _c_, _p_) FltMatch(&f_deny_head, (_drv_), (_dev_), (_c_), (_p_))
//
NTSTATUS FltInitRuleList();
VOID FltUnInitRuleList();
PIOCTL_FILTER FltAddDbgcbRule(PIOCTL_FILTER f, ULONG KdCommandLength);
PIOCTL_FILTER FltAddDenyRule(PIOCTL_FILTER f, ULONG KdCommandLength);
PIOCTL_FILTER FltAddAllowRule(PIOCTL_FILTER f, ULONG KdCommandLength);
void FltFlushAllList();
BOOLEAN FltMatchAllow(
PUNICODE_STRING fDeviceName,
PUNICODE_STRING fDriverName,
ULONG IoControlCode,
PUNICODE_STRING fProcessName);
BOOLEAN FltMatchDeny(
PUNICODE_STRING fDeviceName,
PUNICODE_STRING fDriverName,
ULONG IoControlCode,
PUNICODE_STRING fProcessName);
BOOLEAN SaveDenyRules(HANDLE hKey, PUNICODE_STRING usValueName);
BOOLEAN SaveAllowRules(HANDLE hKey, PUNICODE_STRING usValueName);
BOOLEAN LoadDenyRules(HANDLE hKey, PUNICODE_STRING usValueName);
BOOLEAN LoadAllowRules(HANDLE hKey, PUNICODE_STRING usValueName);
VOID DeferenceRuleCount(PIOCTL_FILTER Item);
@@ -0,0 +1,22 @@
TARGETNAME=IOCTL_fuzzer
TARGETTYPE=DRIVER
DRIVERTYPE=FS
TARGETLIBS=$(TARGETLIBS) \
.\udis86\udis86_i386.lib \
.\udis86\udis86_amd64.lib
SOURCES=driver.c \
common.c \
debug.c \
handlers.c \
hook.c \
log.c \
lst.c \
rng.c \
rules.c \
version.rc
@@ -0,0 +1,39 @@
//extern "C"
//{
#include <ntifs.h>
#include <stdio.h>
#include <stdarg.h>
#include <ntimage.h>
#include "undocnt.h"
//}
#define WP_STUFF
#include "debug.h"
#include "common.h"
#include "lst.h"
#include "options.h"
#include "common_asm.h"
#include "drvcomm.h"
#include "rng.h"
#include "driver.h"
#include "handlers.h"
#include "hook.h"
#include "log.h"
#include "rules.h"
// udis86 disasm engine
#include "udis86/extern.h"
// kernel debugger communication engine (dbgcb) client
//#include "../../dbgcb/common/dbgcb_api.h"
#ifdef _X86_
#pragma comment(lib,"../udis86/udis86_i386.lib")
#elif _AMD64_
#pragma comment(lib,"../udis86/udis86_amd64.lib")
#endif
@@ -0,0 +1,3 @@
@echo off
nmake /f makefile_i386
nmake /f makefile_i386 clean
@@ -0,0 +1,3 @@
@echo off
nmake /f makefile_amd64
nmake /f makefile_amd64 clean
@@ -0,0 +1,67 @@
/* -----------------------------------------------------------------------------
* extern.h
*
* Copyright (c) 2004, 2005, 2006, Vivek Mohan <vivek@sig9.com>
* All rights reserved. See LICENSE
* -----------------------------------------------------------------------------
*/
#ifndef UD_EXTERN_H
#define UD_EXTERN_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include "types.h"
/* ============================= PUBLIC API ================================= */
extern void ud_init(struct ud*);
extern void ud_set_mode(struct ud*, uint8_t);
extern void ud_set_pc(struct ud*, uint64_t);
extern void ud_set_input_hook(struct ud*, int (*)(struct ud*));
extern void ud_set_input_buffer(struct ud*, uint8_t*, size_t);
#ifndef __UD_STANDALONE__
extern void ud_set_input_file(struct ud*, FILE*);
#endif /* __UD_STANDALONE__ */
extern void ud_set_vendor(struct ud*, unsigned);
extern void ud_set_syntax(struct ud*, void (*)(struct ud*));
extern void ud_input_skip(struct ud*, size_t);
extern int ud_input_end(struct ud*);
extern unsigned int ud_decode(struct ud*);
extern unsigned int ud_disassemble(struct ud*);
extern void ud_translate_intel(struct ud*);
extern void ud_translate_att(struct ud*);
extern char* ud_insn_asm(struct ud* u);
extern uint8_t* ud_insn_ptr(struct ud* u);
extern uint64_t ud_insn_off(struct ud*);
extern char* ud_insn_hex(struct ud*);
extern unsigned int ud_insn_len(struct ud* u);
extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
/* ========================================================================== */
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,719 @@
/* itab.h -- auto generated by opgen.py, do not edit. */
#ifndef UD_ITAB_H
#define UD_ITAB_H
enum ud_itab_vendor_index {
ITAB__VENDOR_INDX__AMD,
ITAB__VENDOR_INDX__INTEL,
};
enum ud_itab_mode_index {
ITAB__MODE_INDX__16,
ITAB__MODE_INDX__32,
ITAB__MODE_INDX__64
};
enum ud_itab_mod_index {
ITAB__MOD_INDX__NOT_11,
ITAB__MOD_INDX__11
};
enum ud_itab_index {
ITAB__0F,
ITAB__0F__OP_00__REG,
ITAB__0F__OP_01__REG,
ITAB__0F__OP_01__REG__OP_00__MOD,
ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM,
ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_01__VENDOR,
ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_03__VENDOR,
ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_04__VENDOR,
ITAB__0F__OP_01__REG__OP_01__MOD,
ITAB__0F__OP_01__REG__OP_01__MOD__OP_01__RM,
ITAB__0F__OP_01__REG__OP_02__MOD,
ITAB__0F__OP_01__REG__OP_03__MOD,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_00__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_01__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_02__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_03__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_04__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_05__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_06__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_07__VENDOR,
ITAB__0F__OP_01__REG__OP_04__MOD,
ITAB__0F__OP_01__REG__OP_06__MOD,
ITAB__0F__OP_01__REG__OP_07__MOD,
ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM,
ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM__OP_01__VENDOR,
ITAB__0F__OP_0D__REG,
ITAB__0F__OP_18__REG,
ITAB__0F__OP_71__REG,
ITAB__0F__OP_72__REG,
ITAB__0F__OP_73__REG,
ITAB__0F__OP_AE__REG,
ITAB__0F__OP_AE__REG__OP_05__MOD,
ITAB__0F__OP_AE__REG__OP_05__MOD__OP_01__RM,
ITAB__0F__OP_AE__REG__OP_06__MOD,
ITAB__0F__OP_AE__REG__OP_06__MOD__OP_01__RM,
ITAB__0F__OP_AE__REG__OP_07__MOD,
ITAB__0F__OP_AE__REG__OP_07__MOD__OP_01__RM,
ITAB__0F__OP_BA__REG,
ITAB__0F__OP_C7__REG,
ITAB__0F__OP_C7__REG__OP_00__VENDOR,
ITAB__0F__OP_C7__REG__OP_07__VENDOR,
ITAB__0F__OP_D9__MOD,
ITAB__0F__OP_D9__MOD__OP_01__X87,
ITAB__1BYTE,
ITAB__1BYTE__OP_60__OSIZE,
ITAB__1BYTE__OP_61__OSIZE,
ITAB__1BYTE__OP_63__MODE,
ITAB__1BYTE__OP_6D__OSIZE,
ITAB__1BYTE__OP_6F__OSIZE,
ITAB__1BYTE__OP_80__REG,
ITAB__1BYTE__OP_81__REG,
ITAB__1BYTE__OP_82__REG,
ITAB__1BYTE__OP_83__REG,
ITAB__1BYTE__OP_8F__REG,
ITAB__1BYTE__OP_98__OSIZE,
ITAB__1BYTE__OP_99__OSIZE,
ITAB__1BYTE__OP_9C__MODE,
ITAB__1BYTE__OP_9C__MODE__OP_00__OSIZE,
ITAB__1BYTE__OP_9C__MODE__OP_01__OSIZE,
ITAB__1BYTE__OP_9D__MODE,
ITAB__1BYTE__OP_9D__MODE__OP_00__OSIZE,
ITAB__1BYTE__OP_9D__MODE__OP_01__OSIZE,
ITAB__1BYTE__OP_A5__OSIZE,
ITAB__1BYTE__OP_A7__OSIZE,
ITAB__1BYTE__OP_AB__OSIZE,
ITAB__1BYTE__OP_AD__OSIZE,
ITAB__1BYTE__OP_AE__MOD,
ITAB__1BYTE__OP_AE__MOD__OP_00__REG,
ITAB__1BYTE__OP_AF__OSIZE,
ITAB__1BYTE__OP_C0__REG,
ITAB__1BYTE__OP_C1__REG,
ITAB__1BYTE__OP_C6__REG,
ITAB__1BYTE__OP_C7__REG,
ITAB__1BYTE__OP_CF__OSIZE,
ITAB__1BYTE__OP_D0__REG,
ITAB__1BYTE__OP_D1__REG,
ITAB__1BYTE__OP_D2__REG,
ITAB__1BYTE__OP_D3__REG,
ITAB__1BYTE__OP_D8__MOD,
ITAB__1BYTE__OP_D8__MOD__OP_00__REG,
ITAB__1BYTE__OP_D8__MOD__OP_01__X87,
ITAB__1BYTE__OP_D9__MOD,
ITAB__1BYTE__OP_D9__MOD__OP_00__REG,
ITAB__1BYTE__OP_D9__MOD__OP_01__X87,
ITAB__1BYTE__OP_DA__MOD,
ITAB__1BYTE__OP_DA__MOD__OP_00__REG,
ITAB__1BYTE__OP_DA__MOD__OP_01__X87,
ITAB__1BYTE__OP_DB__MOD,
ITAB__1BYTE__OP_DB__MOD__OP_00__REG,
ITAB__1BYTE__OP_DB__MOD__OP_01__X87,
ITAB__1BYTE__OP_DC__MOD,
ITAB__1BYTE__OP_DC__MOD__OP_00__REG,
ITAB__1BYTE__OP_DC__MOD__OP_01__X87,
ITAB__1BYTE__OP_DD__MOD,
ITAB__1BYTE__OP_DD__MOD__OP_00__REG,
ITAB__1BYTE__OP_DD__MOD__OP_01__X87,
ITAB__1BYTE__OP_DE__MOD,
ITAB__1BYTE__OP_DE__MOD__OP_00__REG,
ITAB__1BYTE__OP_DE__MOD__OP_01__X87,
ITAB__1BYTE__OP_DF__MOD,
ITAB__1BYTE__OP_DF__MOD__OP_00__REG,
ITAB__1BYTE__OP_DF__MOD__OP_01__X87,
ITAB__1BYTE__OP_E3__ASIZE,
ITAB__1BYTE__OP_F6__REG,
ITAB__1BYTE__OP_F7__REG,
ITAB__1BYTE__OP_FE__REG,
ITAB__1BYTE__OP_FF__REG,
ITAB__3DNOW,
ITAB__PFX_SSE66__0F,
ITAB__PFX_SSE66__0F__OP_71__REG,
ITAB__PFX_SSE66__0F__OP_72__REG,
ITAB__PFX_SSE66__0F__OP_73__REG,
ITAB__PFX_SSE66__0F__OP_C7__REG,
ITAB__PFX_SSE66__0F__OP_C7__REG__OP_00__VENDOR,
ITAB__PFX_SSEF2__0F,
ITAB__PFX_SSEF3__0F,
ITAB__PFX_SSEF3__0F__OP_C7__REG,
ITAB__PFX_SSEF3__0F__OP_C7__REG__OP_07__VENDOR,
};
enum ud_mnemonic_code {
UD_I3dnow,
UD_Iaaa,
UD_Iaad,
UD_Iaam,
UD_Iaas,
UD_Iadc,
UD_Iadd,
UD_Iaddpd,
UD_Iaddps,
UD_Iaddsd,
UD_Iaddss,
UD_Iaddsubpd,
UD_Iaddsubps,
UD_Iand,
UD_Iandpd,
UD_Iandps,
UD_Iandnpd,
UD_Iandnps,
UD_Iarpl,
UD_Imovsxd,
UD_Ibound,
UD_Ibsf,
UD_Ibsr,
UD_Ibswap,
UD_Ibt,
UD_Ibtc,
UD_Ibtr,
UD_Ibts,
UD_Icall,
UD_Icbw,
UD_Icwde,
UD_Icdqe,
UD_Iclc,
UD_Icld,
UD_Iclflush,
UD_Iclgi,
UD_Icli,
UD_Iclts,
UD_Icmc,
UD_Icmovo,
UD_Icmovno,
UD_Icmovb,
UD_Icmovae,
UD_Icmovz,
UD_Icmovnz,
UD_Icmovbe,
UD_Icmova,
UD_Icmovs,
UD_Icmovns,
UD_Icmovp,
UD_Icmovnp,
UD_Icmovl,
UD_Icmovge,
UD_Icmovle,
UD_Icmovg,
UD_Icmp,
UD_Icmppd,
UD_Icmpps,
UD_Icmpsb,
UD_Icmpsw,
UD_Icmpsd,
UD_Icmpsq,
UD_Icmpss,
UD_Icmpxchg,
UD_Icmpxchg8b,
UD_Icomisd,
UD_Icomiss,
UD_Icpuid,
UD_Icvtdq2pd,
UD_Icvtdq2ps,
UD_Icvtpd2dq,
UD_Icvtpd2pi,
UD_Icvtpd2ps,
UD_Icvtpi2ps,
UD_Icvtpi2pd,
UD_Icvtps2dq,
UD_Icvtps2pi,
UD_Icvtps2pd,
UD_Icvtsd2si,
UD_Icvtsd2ss,
UD_Icvtsi2ss,
UD_Icvtss2si,
UD_Icvtss2sd,
UD_Icvttpd2pi,
UD_Icvttpd2dq,
UD_Icvttps2dq,
UD_Icvttps2pi,
UD_Icvttsd2si,
UD_Icvtsi2sd,
UD_Icvttss2si,
UD_Icwd,
UD_Icdq,
UD_Icqo,
UD_Idaa,
UD_Idas,
UD_Idec,
UD_Idiv,
UD_Idivpd,
UD_Idivps,
UD_Idivsd,
UD_Idivss,
UD_Iemms,
UD_Ienter,
UD_If2xm1,
UD_Ifabs,
UD_Ifadd,
UD_Ifaddp,
UD_Ifbld,
UD_Ifbstp,
UD_Ifchs,
UD_Ifclex,
UD_Ifcmovb,
UD_Ifcmove,
UD_Ifcmovbe,
UD_Ifcmovu,
UD_Ifcmovnb,
UD_Ifcmovne,
UD_Ifcmovnbe,
UD_Ifcmovnu,
UD_Ifucomi,
UD_Ifcom,
UD_Ifcom2,
UD_Ifcomp3,
UD_Ifcomi,
UD_Ifucomip,
UD_Ifcomip,
UD_Ifcomp,
UD_Ifcomp5,
UD_Ifcompp,
UD_Ifcos,
UD_Ifdecstp,
UD_Ifdiv,
UD_Ifdivp,
UD_Ifdivr,
UD_Ifdivrp,
UD_Ifemms,
UD_Iffree,
UD_Iffreep,
UD_Ificom,
UD_Ificomp,
UD_Ifild,
UD_Ifncstp,
UD_Ifninit,
UD_Ifiadd,
UD_Ifidivr,
UD_Ifidiv,
UD_Ifisub,
UD_Ifisubr,
UD_Ifist,
UD_Ifistp,
UD_Ifisttp,
UD_Ifld,
UD_Ifld1,
UD_Ifldl2t,
UD_Ifldl2e,
UD_Ifldlpi,
UD_Ifldlg2,
UD_Ifldln2,
UD_Ifldz,
UD_Ifldcw,
UD_Ifldenv,
UD_Ifmul,
UD_Ifmulp,
UD_Ifimul,
UD_Ifnop,
UD_Ifpatan,
UD_Ifprem,
UD_Ifprem1,
UD_Ifptan,
UD_Ifrndint,
UD_Ifrstor,
UD_Ifnsave,
UD_Ifscale,
UD_Ifsin,
UD_Ifsincos,
UD_Ifsqrt,
UD_Ifstp,
UD_Ifstp1,
UD_Ifstp8,
UD_Ifstp9,
UD_Ifst,
UD_Ifnstcw,
UD_Ifnstenv,
UD_Ifnstsw,
UD_Ifsub,
UD_Ifsubp,
UD_Ifsubr,
UD_Ifsubrp,
UD_Iftst,
UD_Ifucom,
UD_Ifucomp,
UD_Ifucompp,
UD_Ifxam,
UD_Ifxch,
UD_Ifxch4,
UD_Ifxch7,
UD_Ifxrstor,
UD_Ifxsave,
UD_Ifpxtract,
UD_Ifyl2x,
UD_Ifyl2xp1,
UD_Ihaddpd,
UD_Ihaddps,
UD_Ihlt,
UD_Ihsubpd,
UD_Ihsubps,
UD_Iidiv,
UD_Iin,
UD_Iimul,
UD_Iinc,
UD_Iinsb,
UD_Iinsw,
UD_Iinsd,
UD_Iint1,
UD_Iint3,
UD_Iint,
UD_Iinto,
UD_Iinvd,
UD_Iinvlpg,
UD_Iinvlpga,
UD_Iiretw,
UD_Iiretd,
UD_Iiretq,
UD_Ijo,
UD_Ijno,
UD_Ijb,
UD_Ijae,
UD_Ijz,
UD_Ijnz,
UD_Ijbe,
UD_Ija,
UD_Ijs,
UD_Ijns,
UD_Ijp,
UD_Ijnp,
UD_Ijl,
UD_Ijge,
UD_Ijle,
UD_Ijg,
UD_Ijcxz,
UD_Ijecxz,
UD_Ijrcxz,
UD_Ijmp,
UD_Ilahf,
UD_Ilar,
UD_Ilddqu,
UD_Ildmxcsr,
UD_Ilds,
UD_Ilea,
UD_Iles,
UD_Ilfs,
UD_Ilgs,
UD_Ilidt,
UD_Ilss,
UD_Ileave,
UD_Ilfence,
UD_Ilgdt,
UD_Illdt,
UD_Ilmsw,
UD_Ilock,
UD_Ilodsb,
UD_Ilodsw,
UD_Ilodsd,
UD_Ilodsq,
UD_Iloopnz,
UD_Iloope,
UD_Iloop,
UD_Ilsl,
UD_Iltr,
UD_Imaskmovq,
UD_Imaxpd,
UD_Imaxps,
UD_Imaxsd,
UD_Imaxss,
UD_Imfence,
UD_Iminpd,
UD_Iminps,
UD_Iminsd,
UD_Iminss,
UD_Imonitor,
UD_Imov,
UD_Imovapd,
UD_Imovaps,
UD_Imovd,
UD_Imovddup,
UD_Imovdqa,
UD_Imovdqu,
UD_Imovdq2q,
UD_Imovhpd,
UD_Imovhps,
UD_Imovlhps,
UD_Imovlpd,
UD_Imovlps,
UD_Imovhlps,
UD_Imovmskpd,
UD_Imovmskps,
UD_Imovntdq,
UD_Imovnti,
UD_Imovntpd,
UD_Imovntps,
UD_Imovntq,
UD_Imovq,
UD_Imovqa,
UD_Imovq2dq,
UD_Imovsb,
UD_Imovsw,
UD_Imovsd,
UD_Imovsq,
UD_Imovsldup,
UD_Imovshdup,
UD_Imovss,
UD_Imovsx,
UD_Imovupd,
UD_Imovups,
UD_Imovzx,
UD_Imul,
UD_Imulpd,
UD_Imulps,
UD_Imulsd,
UD_Imulss,
UD_Imwait,
UD_Ineg,
UD_Inop,
UD_Inot,
UD_Ior,
UD_Iorpd,
UD_Iorps,
UD_Iout,
UD_Ioutsb,
UD_Ioutsw,
UD_Ioutsd,
UD_Ioutsq,
UD_Ipacksswb,
UD_Ipackssdw,
UD_Ipackuswb,
UD_Ipaddb,
UD_Ipaddw,
UD_Ipaddq,
UD_Ipaddsb,
UD_Ipaddsw,
UD_Ipaddusb,
UD_Ipaddusw,
UD_Ipand,
UD_Ipandn,
UD_Ipause,
UD_Ipavgb,
UD_Ipavgw,
UD_Ipcmpeqb,
UD_Ipcmpeqw,
UD_Ipcmpeqd,
UD_Ipcmpgtb,
UD_Ipcmpgtw,
UD_Ipcmpgtd,
UD_Ipextrw,
UD_Ipinsrw,
UD_Ipmaddwd,
UD_Ipmaxsw,
UD_Ipmaxub,
UD_Ipminsw,
UD_Ipminub,
UD_Ipmovmskb,
UD_Ipmulhuw,
UD_Ipmulhw,
UD_Ipmullw,
UD_Ipmuludq,
UD_Ipop,
UD_Ipopa,
UD_Ipopad,
UD_Ipopfw,
UD_Ipopfd,
UD_Ipopfq,
UD_Ipor,
UD_Iprefetch,
UD_Iprefetchnta,
UD_Iprefetcht0,
UD_Iprefetcht1,
UD_Iprefetcht2,
UD_Ipsadbw,
UD_Ipshufd,
UD_Ipshufhw,
UD_Ipshuflw,
UD_Ipshufw,
UD_Ipslldq,
UD_Ipsllw,
UD_Ipslld,
UD_Ipsllq,
UD_Ipsraw,
UD_Ipsrad,
UD_Ipsrlw,
UD_Ipsrld,
UD_Ipsrlq,
UD_Ipsrldq,
UD_Ipsubb,
UD_Ipsubw,
UD_Ipsubd,
UD_Ipsubq,
UD_Ipsubsb,
UD_Ipsubsw,
UD_Ipsubusb,
UD_Ipsubusw,
UD_Ipunpckhbw,
UD_Ipunpckhwd,
UD_Ipunpckhdq,
UD_Ipunpckhqdq,
UD_Ipunpcklbw,
UD_Ipunpcklwd,
UD_Ipunpckldq,
UD_Ipunpcklqdq,
UD_Ipi2fw,
UD_Ipi2fd,
UD_Ipf2iw,
UD_Ipf2id,
UD_Ipfnacc,
UD_Ipfpnacc,
UD_Ipfcmpge,
UD_Ipfmin,
UD_Ipfrcp,
UD_Ipfrsqrt,
UD_Ipfsub,
UD_Ipfadd,
UD_Ipfcmpgt,
UD_Ipfmax,
UD_Ipfrcpit1,
UD_Ipfrspit1,
UD_Ipfsubr,
UD_Ipfacc,
UD_Ipfcmpeq,
UD_Ipfmul,
UD_Ipfrcpit2,
UD_Ipmulhrw,
UD_Ipswapd,
UD_Ipavgusb,
UD_Ipush,
UD_Ipusha,
UD_Ipushad,
UD_Ipushfw,
UD_Ipushfd,
UD_Ipushfq,
UD_Ipxor,
UD_Ircl,
UD_Ircr,
UD_Irol,
UD_Iror,
UD_Ircpps,
UD_Ircpss,
UD_Irdmsr,
UD_Irdpmc,
UD_Irdtsc,
UD_Irdtscp,
UD_Irepne,
UD_Irep,
UD_Iret,
UD_Iretf,
UD_Irsm,
UD_Irsqrtps,
UD_Irsqrtss,
UD_Isahf,
UD_Isal,
UD_Isalc,
UD_Isar,
UD_Ishl,
UD_Ishr,
UD_Isbb,
UD_Iscasb,
UD_Iscasw,
UD_Iscasd,
UD_Iscasq,
UD_Iseto,
UD_Isetno,
UD_Isetb,
UD_Isetnb,
UD_Isetz,
UD_Isetnz,
UD_Isetbe,
UD_Iseta,
UD_Isets,
UD_Isetns,
UD_Isetp,
UD_Isetnp,
UD_Isetl,
UD_Isetge,
UD_Isetle,
UD_Isetg,
UD_Isfence,
UD_Isgdt,
UD_Ishld,
UD_Ishrd,
UD_Ishufpd,
UD_Ishufps,
UD_Isidt,
UD_Isldt,
UD_Ismsw,
UD_Isqrtps,
UD_Isqrtpd,
UD_Isqrtsd,
UD_Isqrtss,
UD_Istc,
UD_Istd,
UD_Istgi,
UD_Isti,
UD_Iskinit,
UD_Istmxcsr,
UD_Istosb,
UD_Istosw,
UD_Istosd,
UD_Istosq,
UD_Istr,
UD_Isub,
UD_Isubpd,
UD_Isubps,
UD_Isubsd,
UD_Isubss,
UD_Iswapgs,
UD_Isyscall,
UD_Isysenter,
UD_Isysexit,
UD_Isysret,
UD_Itest,
UD_Iucomisd,
UD_Iucomiss,
UD_Iud2,
UD_Iunpckhpd,
UD_Iunpckhps,
UD_Iunpcklps,
UD_Iunpcklpd,
UD_Iverr,
UD_Iverw,
UD_Ivmcall,
UD_Ivmclear,
UD_Ivmxon,
UD_Ivmptrld,
UD_Ivmptrst,
UD_Ivmresume,
UD_Ivmxoff,
UD_Ivmrun,
UD_Ivmmcall,
UD_Ivmload,
UD_Ivmsave,
UD_Iwait,
UD_Iwbinvd,
UD_Iwrmsr,
UD_Ixadd,
UD_Ixchg,
UD_Ixlatb,
UD_Ixor,
UD_Ixorpd,
UD_Ixorps,
UD_Idb,
UD_Iinvalid,
UD_Id3vil,
UD_Ina,
UD_Igrp_reg,
UD_Igrp_rm,
UD_Igrp_vendor,
UD_Igrp_x87,
UD_Igrp_mode,
UD_Igrp_osize,
UD_Igrp_asize,
UD_Igrp_mod,
UD_Inone,
};
extern const char* ud_mnemonics_str[];;
extern struct ud_itab_entry* ud_itab_list[];
#endif
@@ -0,0 +1,22 @@
decode.obj: src/decode.c
$(CC) $(CFLAGS) src/decode.c
input.obj: src/input.c
$(CC) $(CFLAGS) src/input.c
itab.obj: src/itab.c
$(CC) $(CFLAGS) src/itab.c
syn.obj: src/syn.c
$(CC) $(CFLAGS) src/syn.c
syn-att.obj: src/syn-att.c
$(CC) $(CFLAGS) src/syn-att.c
syn-intel.obj: src/syn-intel.c
$(CC) $(CFLAGS) src/syn-intel.c
udis86.obj: src/udis86.c
$(CC) $(CFLAGS) src/udis86.c
LOBJS = decode.obj input.obj itab.obj syn.obj syn-att.obj syn-intel.obj udis86.obj
@@ -0,0 +1,20 @@
OUTNAME = udis86_amd64
ALL: $(OUTNAME).lib
CC = cl.exe
CFLAGS = /nologo -I".\src" -I"$(CRT_INC_PATH)" -D__UD_STANDALONE__ -D_AMD64_=1 -D_M_AMD64 /Gz /c
include Makefile.inc
LN = lib.exe
LFLAGS = /LIBPATH:$(CRT_LIB_PATH)\..\amd64 /out:$(OUTNAME).lib
$(OUTNAME).lib: $(LOBJS)
$(LN) $(LFLAGS) $(LOBJS)
clean:
@del *.obj
@@ -0,0 +1,19 @@
OUTNAME = udis86_i386
ALL: $(OUTNAME).lib
CC = cl.exe
CFLAGS=/nologo -I".\src" -I"$(CRT_INC_PATH)" -D__UD_STANDALONE__ -D_X86_=1 /Gz /c
include Makefile.inc
LN = lib.exe
LFLAGS = /LIBPATH:$(CRT_LIB_PATH)\..\i386 /out:$(OUTNAME).lib
$(OUTNAME).lib: $(LOBJS)
$(LN) $(LFLAGS) $(LOBJS)
clean:
@del *.obj
@@ -0,0 +1,275 @@
#ifndef UD_DECODE_H
#define UD_DECODE_H
#define MAX_INSN_LENGTH 15
/* register classes */
#define T_NONE 0
#define T_GPR 1
#define T_MMX 2
#define T_CRG 3
#define T_DBG 4
#define T_SEG 5
#define T_XMM 6
/* itab prefix bits */
#define P_none ( 0 )
#define P_c1 ( 1 << 0 )
#define P_C1(n) ( ( n >> 0 ) & 1 )
#define P_rexb ( 1 << 1 )
#define P_REXB(n) ( ( n >> 1 ) & 1 )
#define P_depM ( 1 << 2 )
#define P_DEPM(n) ( ( n >> 2 ) & 1 )
#define P_c3 ( 1 << 3 )
#define P_C3(n) ( ( n >> 3 ) & 1 )
#define P_inv64 ( 1 << 4 )
#define P_INV64(n) ( ( n >> 4 ) & 1 )
#define P_rexw ( 1 << 5 )
#define P_REXW(n) ( ( n >> 5 ) & 1 )
#define P_c2 ( 1 << 6 )
#define P_C2(n) ( ( n >> 6 ) & 1 )
#define P_def64 ( 1 << 7 )
#define P_DEF64(n) ( ( n >> 7 ) & 1 )
#define P_rexr ( 1 << 8 )
#define P_REXR(n) ( ( n >> 8 ) & 1 )
#define P_oso ( 1 << 9 )
#define P_OSO(n) ( ( n >> 9 ) & 1 )
#define P_aso ( 1 << 10 )
#define P_ASO(n) ( ( n >> 10 ) & 1 )
#define P_rexx ( 1 << 11 )
#define P_REXX(n) ( ( n >> 11 ) & 1 )
#define P_ImpAddr ( 1 << 12 )
#define P_IMPADDR(n) ( ( n >> 12 ) & 1 )
/* rex prefix bits */
#define REX_W(r) ( ( 0xF & ( r ) ) >> 3 )
#define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 )
#define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 )
#define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 )
#define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \
( P_REXR(n) << 2 ) | \
( P_REXX(n) << 1 ) | \
( P_REXB(n) << 0 ) )
/* scable-index-base bits */
#define SIB_S(b) ( ( b ) >> 6 )
#define SIB_I(b) ( ( ( b ) >> 3 ) & 7 )
#define SIB_B(b) ( ( b ) & 7 )
/* modrm bits */
#define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 )
#define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 )
#define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 )
#define MODRM_RM(b) ( ( b ) & 7 )
/* operand type constants -- order is important! */
enum ud_operand_code {
OP_NONE,
OP_A, OP_E, OP_M, OP_G,
OP_I,
OP_AL, OP_CL, OP_DL, OP_BL,
OP_AH, OP_CH, OP_DH, OP_BH,
OP_ALr8b, OP_CLr9b, OP_DLr10b, OP_BLr11b,
OP_AHr12b, OP_CHr13b, OP_DHr14b, OP_BHr15b,
OP_AX, OP_CX, OP_DX, OP_BX,
OP_SI, OP_DI, OP_SP, OP_BP,
OP_rAX, OP_rCX, OP_rDX, OP_rBX,
OP_rSP, OP_rBP, OP_rSI, OP_rDI,
OP_rAXr8, OP_rCXr9, OP_rDXr10, OP_rBXr11,
OP_rSPr12, OP_rBPr13, OP_rSIr14, OP_rDIr15,
OP_eAX, OP_eCX, OP_eDX, OP_eBX,
OP_eSP, OP_eBP, OP_eSI, OP_eDI,
OP_ES, OP_CS, OP_SS, OP_DS,
OP_FS, OP_GS,
OP_ST0, OP_ST1, OP_ST2, OP_ST3,
OP_ST4, OP_ST5, OP_ST6, OP_ST7,
OP_J, OP_S, OP_O,
OP_I1, OP_I3,
OP_V, OP_W, OP_Q, OP_P,
OP_R, OP_C, OP_D, OP_VR, OP_PR
};
/* operand size constants */
enum ud_operand_size {
SZ_NA = 0,
SZ_Z = 1,
SZ_V = 2,
SZ_P = 3,
SZ_WP = 4,
SZ_DP = 5,
SZ_MDQ = 6,
SZ_RDQ = 7,
/* the following values are used as is,
* and thus hard-coded. changing them
* will break internals
*/
SZ_B = 8,
SZ_W = 16,
SZ_D = 32,
SZ_Q = 64,
SZ_T = 80,
};
/* itab entry operand definitions */
#define O_rSPr12 { OP_rSPr12, SZ_NA }
#define O_BL { OP_BL, SZ_NA }
#define O_BH { OP_BH, SZ_NA }
#define O_BP { OP_BP, SZ_NA }
#define O_AHr12b { OP_AHr12b, SZ_NA }
#define O_BX { OP_BX, SZ_NA }
#define O_Jz { OP_J, SZ_Z }
#define O_Jv { OP_J, SZ_V }
#define O_Jb { OP_J, SZ_B }
#define O_rSIr14 { OP_rSIr14, SZ_NA }
#define O_GS { OP_GS, SZ_NA }
#define O_D { OP_D, SZ_NA }
#define O_rBPr13 { OP_rBPr13, SZ_NA }
#define O_Ob { OP_O, SZ_B }
#define O_P { OP_P, SZ_NA }
#define O_Ow { OP_O, SZ_W }
#define O_Ov { OP_O, SZ_V }
#define O_Gw { OP_G, SZ_W }
#define O_Gv { OP_G, SZ_V }
#define O_rDX { OP_rDX, SZ_NA }
#define O_Gx { OP_G, SZ_MDQ }
#define O_Gd { OP_G, SZ_D }
#define O_Gb { OP_G, SZ_B }
#define O_rBXr11 { OP_rBXr11, SZ_NA }
#define O_rDI { OP_rDI, SZ_NA }
#define O_rSI { OP_rSI, SZ_NA }
#define O_ALr8b { OP_ALr8b, SZ_NA }
#define O_eDI { OP_eDI, SZ_NA }
#define O_Gz { OP_G, SZ_Z }
#define O_eDX { OP_eDX, SZ_NA }
#define O_DHr14b { OP_DHr14b, SZ_NA }
#define O_rSP { OP_rSP, SZ_NA }
#define O_PR { OP_PR, SZ_NA }
#define O_NONE { OP_NONE, SZ_NA }
#define O_rCX { OP_rCX, SZ_NA }
#define O_jWP { OP_J, SZ_WP }
#define O_rDXr10 { OP_rDXr10, SZ_NA }
#define O_Md { OP_M, SZ_D }
#define O_C { OP_C, SZ_NA }
#define O_G { OP_G, SZ_NA }
#define O_Mb { OP_M, SZ_B }
#define O_Mt { OP_M, SZ_T }
#define O_S { OP_S, SZ_NA }
#define O_Mq { OP_M, SZ_Q }
#define O_W { OP_W, SZ_NA }
#define O_ES { OP_ES, SZ_NA }
#define O_rBX { OP_rBX, SZ_NA }
#define O_Ed { OP_E, SZ_D }
#define O_DLr10b { OP_DLr10b, SZ_NA }
#define O_Mw { OP_M, SZ_W }
#define O_Eb { OP_E, SZ_B }
#define O_Ex { OP_E, SZ_MDQ }
#define O_Ez { OP_E, SZ_Z }
#define O_Ew { OP_E, SZ_W }
#define O_Ev { OP_E, SZ_V }
#define O_Ep { OP_E, SZ_P }
#define O_FS { OP_FS, SZ_NA }
#define O_Ms { OP_M, SZ_W }
#define O_rAXr8 { OP_rAXr8, SZ_NA }
#define O_eBP { OP_eBP, SZ_NA }
#define O_Isb { OP_I, SZ_SB }
#define O_eBX { OP_eBX, SZ_NA }
#define O_rCXr9 { OP_rCXr9, SZ_NA }
#define O_jDP { OP_J, SZ_DP }
#define O_CH { OP_CH, SZ_NA }
#define O_CL { OP_CL, SZ_NA }
#define O_R { OP_R, SZ_RDQ }
#define O_V { OP_V, SZ_NA }
#define O_CS { OP_CS, SZ_NA }
#define O_CHr13b { OP_CHr13b, SZ_NA }
#define O_eCX { OP_eCX, SZ_NA }
#define O_eSP { OP_eSP, SZ_NA }
#define O_SS { OP_SS, SZ_NA }
#define O_SP { OP_SP, SZ_NA }
#define O_BLr11b { OP_BLr11b, SZ_NA }
#define O_SI { OP_SI, SZ_NA }
#define O_eSI { OP_eSI, SZ_NA }
#define O_DL { OP_DL, SZ_NA }
#define O_DH { OP_DH, SZ_NA }
#define O_DI { OP_DI, SZ_NA }
#define O_DX { OP_DX, SZ_NA }
#define O_rBP { OP_rBP, SZ_NA }
#define O_Gvw { OP_G, SZ_MDQ }
#define O_I1 { OP_I1, SZ_NA }
#define O_I3 { OP_I3, SZ_NA }
#define O_DS { OP_DS, SZ_NA }
#define O_ST4 { OP_ST4, SZ_NA }
#define O_ST5 { OP_ST5, SZ_NA }
#define O_ST6 { OP_ST6, SZ_NA }
#define O_ST7 { OP_ST7, SZ_NA }
#define O_ST0 { OP_ST0, SZ_NA }
#define O_ST1 { OP_ST1, SZ_NA }
#define O_ST2 { OP_ST2, SZ_NA }
#define O_ST3 { OP_ST3, SZ_NA }
#define O_E { OP_E, SZ_NA }
#define O_AH { OP_AH, SZ_NA }
#define O_M { OP_M, SZ_NA }
#define O_AL { OP_AL, SZ_NA }
#define O_CLr9b { OP_CLr9b, SZ_NA }
#define O_Q { OP_Q, SZ_NA }
#define O_eAX { OP_eAX, SZ_NA }
#define O_VR { OP_VR, SZ_NA }
#define O_AX { OP_AX, SZ_NA }
#define O_rAX { OP_rAX, SZ_NA }
#define O_Iz { OP_I, SZ_Z }
#define O_rDIr15 { OP_rDIr15, SZ_NA }
#define O_Iw { OP_I, SZ_W }
#define O_Iv { OP_I, SZ_V }
#define O_Ap { OP_A, SZ_P }
#define O_CX { OP_CX, SZ_NA }
#define O_Ib { OP_I, SZ_B }
#define O_BHr15b { OP_BHr15b, SZ_NA }
/* A single operand of an entry in the instruction table.
* (internal use only)
*/
struct ud_itab_entry_operand
{
enum ud_operand_code type;
enum ud_operand_size size;
};
/* A single entry in an instruction table.
*(internal use only)
*/
struct ud_itab_entry
{
enum ud_mnemonic_code mnemonic;
struct ud_itab_entry_operand operand1;
struct ud_itab_entry_operand operand2;
struct ud_itab_entry_operand operand3;
uint32_t prefix;
};
extern const char * ud_lookup_mnemonic( enum ud_mnemonic_code c );
#endif /* UD_DECODE_H */
/* vim:cindent
* vim:expandtab
* vim:ts=4
* vim:sw=4
*/
@@ -0,0 +1,67 @@
/* -----------------------------------------------------------------------------
* extern.h
*
* Copyright (c) 2004, 2005, 2006, Vivek Mohan <vivek@sig9.com>
* All rights reserved. See LICENSE
* -----------------------------------------------------------------------------
*/
#ifndef UD_EXTERN_H
#define UD_EXTERN_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include "types.h"
/* ============================= PUBLIC API ================================= */
extern void ud_init(struct ud*);
extern void ud_set_mode(struct ud*, uint8_t);
extern void ud_set_pc(struct ud*, uint64_t);
extern void ud_set_input_hook(struct ud*, int (*)(struct ud*));
extern void ud_set_input_buffer(struct ud*, uint8_t*, size_t);
#ifndef __UD_STANDALONE__
extern void ud_set_input_file(struct ud*, FILE*);
#endif /* __UD_STANDALONE__ */
extern void ud_set_vendor(struct ud*, unsigned);
extern void ud_set_syntax(struct ud*, void (*)(struct ud*));
extern void ud_input_skip(struct ud*, size_t);
extern int ud_input_end(struct ud*);
extern unsigned int ud_decode(struct ud*);
extern unsigned int ud_disassemble(struct ud*);
extern void ud_translate_intel(struct ud*);
extern void ud_translate_att(struct ud*);
extern char* ud_insn_asm(struct ud* u);
extern uint8_t* ud_insn_ptr(struct ud* u);
extern uint64_t ud_insn_off(struct ud*);
extern char* ud_insn_hex(struct ud*);
extern unsigned int ud_insn_len(struct ud* u);
extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
/* ========================================================================== */
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,226 @@
/* -----------------------------------------------------------------------------
* input.c
*
* Copyright (c) 2004, 2005, 2006, Vivek Mohan <vivek@sig9.com>
* All rights reserved. See LICENSE
* -----------------------------------------------------------------------------
*/
#include "extern.h"
#include "types.h"
#include "input.h"
/* -----------------------------------------------------------------------------
* inp_buff_hook() - Hook for buffered inputs.
* -----------------------------------------------------------------------------
*/
static int
inp_buff_hook(struct ud* u)
{
if (u->inp_buff < u->inp_buff_end)
return *u->inp_buff++;
else return -1;
}
#ifndef __UD_STANDALONE__
/* -----------------------------------------------------------------------------
* inp_file_hook() - Hook for FILE inputs.
* -----------------------------------------------------------------------------
*/
static int
inp_file_hook(struct ud* u)
{
return fgetc(u->inp_file);
}
#endif /* __UD_STANDALONE__*/
/* =============================================================================
* ud_inp_set_hook() - Sets input hook.
* =============================================================================
*/
extern void
ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*))
{
u->inp_hook = hook;
inp_init(u);
}
/* =============================================================================
* ud_inp_set_buffer() - Set buffer as input.
* =============================================================================
*/
extern void
ud_set_input_buffer(register struct ud* u, uint8_t* buf, size_t len)
{
u->inp_hook = inp_buff_hook;
u->inp_buff = buf;
u->inp_buff_end = buf + len;
inp_init(u);
}
#ifndef __UD_STANDALONE__
/* =============================================================================
* ud_input_set_file() - Set buffer as input.
* =============================================================================
*/
extern void
ud_set_input_file(register struct ud* u, FILE* f)
{
u->inp_hook = inp_file_hook;
u->inp_file = f;
inp_init(u);
}
#endif /* __UD_STANDALONE__ */
/* =============================================================================
* ud_input_skip() - Skip n input bytes.
* =============================================================================
*/
extern void
ud_input_skip(struct ud* u, size_t n)
{
while (n--) {
u->inp_hook(u);
}
}
/* =============================================================================
* ud_input_end() - Test for end of input.
* =============================================================================
*/
extern int
ud_input_end(struct ud* u)
{
return (u->inp_curr == u->inp_fill) && u->inp_end;
}
/* -----------------------------------------------------------------------------
* inp_next() - Loads and returns the next byte from input.
*
* inp_curr and inp_fill are pointers to the cache. The program is written based
* on the property that they are 8-bits in size, and will eventually wrap around
* forming a circular buffer. So, the size of the cache is 256 in size, kind of
* unnecessary yet optimized.
*
* A buffer inp_sess stores the bytes disassembled for a single session.
* -----------------------------------------------------------------------------
*/
extern uint8_t inp_next(struct ud* u)
{
int c = -1;
/* if current pointer is not upto the fill point in the
* input cache.
*/
if ( u->inp_curr != u->inp_fill ) {
c = u->inp_cache[ ++u->inp_curr ];
/* if !end-of-input, call the input hook and get a byte */
} else if ( u->inp_end || ( c = u->inp_hook( u ) ) == -1 ) {
/* end-of-input, mark it as an error, since the decoder,
* expected a byte more.
*/
u->error = 1;
/* flag end of input */
u->inp_end = 1;
return 0;
} else {
/* increment pointers, we have a new byte. */
u->inp_curr = ++u->inp_fill;
/* add the byte to the cache */
u->inp_cache[ u->inp_fill ] = c;
}
/* record bytes input per decode-session. */
u->inp_sess[ u->inp_ctr++ ] = c;
/* return byte */
return ( uint8_t ) c;
}
/* -----------------------------------------------------------------------------
* inp_back() - Move back a single byte in the stream.
* -----------------------------------------------------------------------------
*/
extern void
inp_back(struct ud* u)
{
if ( u->inp_ctr > 0 ) {
--u->inp_curr;
--u->inp_ctr;
}
}
/* -----------------------------------------------------------------------------
* inp_peek() - Peek into the next byte in source.
* -----------------------------------------------------------------------------
*/
extern uint8_t
inp_peek(struct ud* u)
{
uint8_t r = inp_next(u);
if ( !u->error ) inp_back(u); /* Don't backup if there was an error */
return r;
}
/* -----------------------------------------------------------------------------
* inp_move() - Move ahead n input bytes.
* -----------------------------------------------------------------------------
*/
extern void
inp_move(struct ud* u, size_t n)
{
while (n--)
inp_next(u);
}
/*------------------------------------------------------------------------------
* inp_uintN() - return uintN from source.
*------------------------------------------------------------------------------
*/
extern uint8_t
inp_uint8(struct ud* u)
{
return inp_next(u);
}
extern uint16_t
inp_uint16(struct ud* u)
{
uint16_t r, ret;
ret = inp_next(u);
r = inp_next(u);
return ret | (r << 8);
}
extern uint32_t
inp_uint32(struct ud* u)
{
uint32_t r, ret;
ret = inp_next(u);
r = inp_next(u);
ret = ret | (r << 8);
r = inp_next(u);
ret = ret | (r << 16);
r = inp_next(u);
return ret | (r << 24);
}
extern uint64_t
inp_uint64(struct ud* u)
{
uint64_t r, ret;
ret = inp_next(u);
r = inp_next(u);
ret = ret | (r << 8);
r = inp_next(u);
ret = ret | (r << 16);
r = inp_next(u);
ret = ret | (r << 24);
r = inp_next(u);
ret = ret | (r << 32);
r = inp_next(u);
ret = ret | (r << 40);
r = inp_next(u);
ret = ret | (r << 48);
r = inp_next(u);
return ret | (r << 56);
}
@@ -0,0 +1,49 @@
/* -----------------------------------------------------------------------------
* input.h
*
* Copyright (c) 2006, Vivek Mohan <vivek@sig9.com>
* All rights reserved. See LICENSE
* -----------------------------------------------------------------------------
*/
#ifndef UD_INPUT_H
#define UD_INPUT_H
#include "types.h"
uint8_t inp_next(struct ud*);
uint8_t inp_peek(struct ud*);
uint8_t inp_uint8(struct ud*);
uint16_t inp_uint16(struct ud*);
uint32_t inp_uint32(struct ud*);
uint64_t inp_uint64(struct ud*);
void inp_move(struct ud*, size_t);
void inp_back(struct ud*);
/* inp_init() - Initializes the input system. */
#define inp_init(u) \
do { \
u->inp_curr = 0; \
u->inp_fill = 0; \
u->inp_ctr = 0; \
u->inp_end = 0; \
} while (0)
/* inp_start() - Should be called before each de-code operation. */
#define inp_start(u) u->inp_ctr = 0
/* inp_back() - Resets the current pointer to its position before the current
* instruction disassembly was started.
*/
#define inp_reset(u) \
do { \
u->inp_curr -= u->inp_ctr; \
u->inp_ctr = 0; \
} while (0)
/* inp_sess() - Returns the pointer to current session. */
#define inp_sess(u) (u->inp_sess)
/* inp_cur() - Returns the current input byte. */
#define inp_curr(u) ((u)->inp_cache[(u)->inp_curr])
#endif
@@ -0,0 +1,719 @@
/* itab.h -- auto generated by opgen.py, do not edit. */
#ifndef UD_ITAB_H
#define UD_ITAB_H
enum ud_itab_vendor_index {
ITAB__VENDOR_INDX__AMD,
ITAB__VENDOR_INDX__INTEL,
};
enum ud_itab_mode_index {
ITAB__MODE_INDX__16,
ITAB__MODE_INDX__32,
ITAB__MODE_INDX__64
};
enum ud_itab_mod_index {
ITAB__MOD_INDX__NOT_11,
ITAB__MOD_INDX__11
};
enum ud_itab_index {
ITAB__0F,
ITAB__0F__OP_00__REG,
ITAB__0F__OP_01__REG,
ITAB__0F__OP_01__REG__OP_00__MOD,
ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM,
ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_01__VENDOR,
ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_03__VENDOR,
ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_04__VENDOR,
ITAB__0F__OP_01__REG__OP_01__MOD,
ITAB__0F__OP_01__REG__OP_01__MOD__OP_01__RM,
ITAB__0F__OP_01__REG__OP_02__MOD,
ITAB__0F__OP_01__REG__OP_03__MOD,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_00__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_01__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_02__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_03__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_04__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_05__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_06__VENDOR,
ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_07__VENDOR,
ITAB__0F__OP_01__REG__OP_04__MOD,
ITAB__0F__OP_01__REG__OP_06__MOD,
ITAB__0F__OP_01__REG__OP_07__MOD,
ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM,
ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM__OP_01__VENDOR,
ITAB__0F__OP_0D__REG,
ITAB__0F__OP_18__REG,
ITAB__0F__OP_71__REG,
ITAB__0F__OP_72__REG,
ITAB__0F__OP_73__REG,
ITAB__0F__OP_AE__REG,
ITAB__0F__OP_AE__REG__OP_05__MOD,
ITAB__0F__OP_AE__REG__OP_05__MOD__OP_01__RM,
ITAB__0F__OP_AE__REG__OP_06__MOD,
ITAB__0F__OP_AE__REG__OP_06__MOD__OP_01__RM,
ITAB__0F__OP_AE__REG__OP_07__MOD,
ITAB__0F__OP_AE__REG__OP_07__MOD__OP_01__RM,
ITAB__0F__OP_BA__REG,
ITAB__0F__OP_C7__REG,
ITAB__0F__OP_C7__REG__OP_00__VENDOR,
ITAB__0F__OP_C7__REG__OP_07__VENDOR,
ITAB__0F__OP_D9__MOD,
ITAB__0F__OP_D9__MOD__OP_01__X87,
ITAB__1BYTE,
ITAB__1BYTE__OP_60__OSIZE,
ITAB__1BYTE__OP_61__OSIZE,
ITAB__1BYTE__OP_63__MODE,
ITAB__1BYTE__OP_6D__OSIZE,
ITAB__1BYTE__OP_6F__OSIZE,
ITAB__1BYTE__OP_80__REG,
ITAB__1BYTE__OP_81__REG,
ITAB__1BYTE__OP_82__REG,
ITAB__1BYTE__OP_83__REG,
ITAB__1BYTE__OP_8F__REG,
ITAB__1BYTE__OP_98__OSIZE,
ITAB__1BYTE__OP_99__OSIZE,
ITAB__1BYTE__OP_9C__MODE,
ITAB__1BYTE__OP_9C__MODE__OP_00__OSIZE,
ITAB__1BYTE__OP_9C__MODE__OP_01__OSIZE,
ITAB__1BYTE__OP_9D__MODE,
ITAB__1BYTE__OP_9D__MODE__OP_00__OSIZE,
ITAB__1BYTE__OP_9D__MODE__OP_01__OSIZE,
ITAB__1BYTE__OP_A5__OSIZE,
ITAB__1BYTE__OP_A7__OSIZE,
ITAB__1BYTE__OP_AB__OSIZE,
ITAB__1BYTE__OP_AD__OSIZE,
ITAB__1BYTE__OP_AE__MOD,
ITAB__1BYTE__OP_AE__MOD__OP_00__REG,
ITAB__1BYTE__OP_AF__OSIZE,
ITAB__1BYTE__OP_C0__REG,
ITAB__1BYTE__OP_C1__REG,
ITAB__1BYTE__OP_C6__REG,
ITAB__1BYTE__OP_C7__REG,
ITAB__1BYTE__OP_CF__OSIZE,
ITAB__1BYTE__OP_D0__REG,
ITAB__1BYTE__OP_D1__REG,
ITAB__1BYTE__OP_D2__REG,
ITAB__1BYTE__OP_D3__REG,
ITAB__1BYTE__OP_D8__MOD,
ITAB__1BYTE__OP_D8__MOD__OP_00__REG,
ITAB__1BYTE__OP_D8__MOD__OP_01__X87,
ITAB__1BYTE__OP_D9__MOD,
ITAB__1BYTE__OP_D9__MOD__OP_00__REG,
ITAB__1BYTE__OP_D9__MOD__OP_01__X87,
ITAB__1BYTE__OP_DA__MOD,
ITAB__1BYTE__OP_DA__MOD__OP_00__REG,
ITAB__1BYTE__OP_DA__MOD__OP_01__X87,
ITAB__1BYTE__OP_DB__MOD,
ITAB__1BYTE__OP_DB__MOD__OP_00__REG,
ITAB__1BYTE__OP_DB__MOD__OP_01__X87,
ITAB__1BYTE__OP_DC__MOD,
ITAB__1BYTE__OP_DC__MOD__OP_00__REG,
ITAB__1BYTE__OP_DC__MOD__OP_01__X87,
ITAB__1BYTE__OP_DD__MOD,
ITAB__1BYTE__OP_DD__MOD__OP_00__REG,
ITAB__1BYTE__OP_DD__MOD__OP_01__X87,
ITAB__1BYTE__OP_DE__MOD,
ITAB__1BYTE__OP_DE__MOD__OP_00__REG,
ITAB__1BYTE__OP_DE__MOD__OP_01__X87,
ITAB__1BYTE__OP_DF__MOD,
ITAB__1BYTE__OP_DF__MOD__OP_00__REG,
ITAB__1BYTE__OP_DF__MOD__OP_01__X87,
ITAB__1BYTE__OP_E3__ASIZE,
ITAB__1BYTE__OP_F6__REG,
ITAB__1BYTE__OP_F7__REG,
ITAB__1BYTE__OP_FE__REG,
ITAB__1BYTE__OP_FF__REG,
ITAB__3DNOW,
ITAB__PFX_SSE66__0F,
ITAB__PFX_SSE66__0F__OP_71__REG,
ITAB__PFX_SSE66__0F__OP_72__REG,
ITAB__PFX_SSE66__0F__OP_73__REG,
ITAB__PFX_SSE66__0F__OP_C7__REG,
ITAB__PFX_SSE66__0F__OP_C7__REG__OP_00__VENDOR,
ITAB__PFX_SSEF2__0F,
ITAB__PFX_SSEF3__0F,
ITAB__PFX_SSEF3__0F__OP_C7__REG,
ITAB__PFX_SSEF3__0F__OP_C7__REG__OP_07__VENDOR,
};
enum ud_mnemonic_code {
UD_I3dnow,
UD_Iaaa,
UD_Iaad,
UD_Iaam,
UD_Iaas,
UD_Iadc,
UD_Iadd,
UD_Iaddpd,
UD_Iaddps,
UD_Iaddsd,
UD_Iaddss,
UD_Iaddsubpd,
UD_Iaddsubps,
UD_Iand,
UD_Iandpd,
UD_Iandps,
UD_Iandnpd,
UD_Iandnps,
UD_Iarpl,
UD_Imovsxd,
UD_Ibound,
UD_Ibsf,
UD_Ibsr,
UD_Ibswap,
UD_Ibt,
UD_Ibtc,
UD_Ibtr,
UD_Ibts,
UD_Icall,
UD_Icbw,
UD_Icwde,
UD_Icdqe,
UD_Iclc,
UD_Icld,
UD_Iclflush,
UD_Iclgi,
UD_Icli,
UD_Iclts,
UD_Icmc,
UD_Icmovo,
UD_Icmovno,
UD_Icmovb,
UD_Icmovae,
UD_Icmovz,
UD_Icmovnz,
UD_Icmovbe,
UD_Icmova,
UD_Icmovs,
UD_Icmovns,
UD_Icmovp,
UD_Icmovnp,
UD_Icmovl,
UD_Icmovge,
UD_Icmovle,
UD_Icmovg,
UD_Icmp,
UD_Icmppd,
UD_Icmpps,
UD_Icmpsb,
UD_Icmpsw,
UD_Icmpsd,
UD_Icmpsq,
UD_Icmpss,
UD_Icmpxchg,
UD_Icmpxchg8b,
UD_Icomisd,
UD_Icomiss,
UD_Icpuid,
UD_Icvtdq2pd,
UD_Icvtdq2ps,
UD_Icvtpd2dq,
UD_Icvtpd2pi,
UD_Icvtpd2ps,
UD_Icvtpi2ps,
UD_Icvtpi2pd,
UD_Icvtps2dq,
UD_Icvtps2pi,
UD_Icvtps2pd,
UD_Icvtsd2si,
UD_Icvtsd2ss,
UD_Icvtsi2ss,
UD_Icvtss2si,
UD_Icvtss2sd,
UD_Icvttpd2pi,
UD_Icvttpd2dq,
UD_Icvttps2dq,
UD_Icvttps2pi,
UD_Icvttsd2si,
UD_Icvtsi2sd,
UD_Icvttss2si,
UD_Icwd,
UD_Icdq,
UD_Icqo,
UD_Idaa,
UD_Idas,
UD_Idec,
UD_Idiv,
UD_Idivpd,
UD_Idivps,
UD_Idivsd,
UD_Idivss,
UD_Iemms,
UD_Ienter,
UD_If2xm1,
UD_Ifabs,
UD_Ifadd,
UD_Ifaddp,
UD_Ifbld,
UD_Ifbstp,
UD_Ifchs,
UD_Ifclex,
UD_Ifcmovb,
UD_Ifcmove,
UD_Ifcmovbe,
UD_Ifcmovu,
UD_Ifcmovnb,
UD_Ifcmovne,
UD_Ifcmovnbe,
UD_Ifcmovnu,
UD_Ifucomi,
UD_Ifcom,
UD_Ifcom2,
UD_Ifcomp3,
UD_Ifcomi,
UD_Ifucomip,
UD_Ifcomip,
UD_Ifcomp,
UD_Ifcomp5,
UD_Ifcompp,
UD_Ifcos,
UD_Ifdecstp,
UD_Ifdiv,
UD_Ifdivp,
UD_Ifdivr,
UD_Ifdivrp,
UD_Ifemms,
UD_Iffree,
UD_Iffreep,
UD_Ificom,
UD_Ificomp,
UD_Ifild,
UD_Ifncstp,
UD_Ifninit,
UD_Ifiadd,
UD_Ifidivr,
UD_Ifidiv,
UD_Ifisub,
UD_Ifisubr,
UD_Ifist,
UD_Ifistp,
UD_Ifisttp,
UD_Ifld,
UD_Ifld1,
UD_Ifldl2t,
UD_Ifldl2e,
UD_Ifldlpi,
UD_Ifldlg2,
UD_Ifldln2,
UD_Ifldz,
UD_Ifldcw,
UD_Ifldenv,
UD_Ifmul,
UD_Ifmulp,
UD_Ifimul,
UD_Ifnop,
UD_Ifpatan,
UD_Ifprem,
UD_Ifprem1,
UD_Ifptan,
UD_Ifrndint,
UD_Ifrstor,
UD_Ifnsave,
UD_Ifscale,
UD_Ifsin,
UD_Ifsincos,
UD_Ifsqrt,
UD_Ifstp,
UD_Ifstp1,
UD_Ifstp8,
UD_Ifstp9,
UD_Ifst,
UD_Ifnstcw,
UD_Ifnstenv,
UD_Ifnstsw,
UD_Ifsub,
UD_Ifsubp,
UD_Ifsubr,
UD_Ifsubrp,
UD_Iftst,
UD_Ifucom,
UD_Ifucomp,
UD_Ifucompp,
UD_Ifxam,
UD_Ifxch,
UD_Ifxch4,
UD_Ifxch7,
UD_Ifxrstor,
UD_Ifxsave,
UD_Ifpxtract,
UD_Ifyl2x,
UD_Ifyl2xp1,
UD_Ihaddpd,
UD_Ihaddps,
UD_Ihlt,
UD_Ihsubpd,
UD_Ihsubps,
UD_Iidiv,
UD_Iin,
UD_Iimul,
UD_Iinc,
UD_Iinsb,
UD_Iinsw,
UD_Iinsd,
UD_Iint1,
UD_Iint3,
UD_Iint,
UD_Iinto,
UD_Iinvd,
UD_Iinvlpg,
UD_Iinvlpga,
UD_Iiretw,
UD_Iiretd,
UD_Iiretq,
UD_Ijo,
UD_Ijno,
UD_Ijb,
UD_Ijae,
UD_Ijz,
UD_Ijnz,
UD_Ijbe,
UD_Ija,
UD_Ijs,
UD_Ijns,
UD_Ijp,
UD_Ijnp,
UD_Ijl,
UD_Ijge,
UD_Ijle,
UD_Ijg,
UD_Ijcxz,
UD_Ijecxz,
UD_Ijrcxz,
UD_Ijmp,
UD_Ilahf,
UD_Ilar,
UD_Ilddqu,
UD_Ildmxcsr,
UD_Ilds,
UD_Ilea,
UD_Iles,
UD_Ilfs,
UD_Ilgs,
UD_Ilidt,
UD_Ilss,
UD_Ileave,
UD_Ilfence,
UD_Ilgdt,
UD_Illdt,
UD_Ilmsw,
UD_Ilock,
UD_Ilodsb,
UD_Ilodsw,
UD_Ilodsd,
UD_Ilodsq,
UD_Iloopnz,
UD_Iloope,
UD_Iloop,
UD_Ilsl,
UD_Iltr,
UD_Imaskmovq,
UD_Imaxpd,
UD_Imaxps,
UD_Imaxsd,
UD_Imaxss,
UD_Imfence,
UD_Iminpd,
UD_Iminps,
UD_Iminsd,
UD_Iminss,
UD_Imonitor,
UD_Imov,
UD_Imovapd,
UD_Imovaps,
UD_Imovd,
UD_Imovddup,
UD_Imovdqa,
UD_Imovdqu,
UD_Imovdq2q,
UD_Imovhpd,
UD_Imovhps,
UD_Imovlhps,
UD_Imovlpd,
UD_Imovlps,
UD_Imovhlps,
UD_Imovmskpd,
UD_Imovmskps,
UD_Imovntdq,
UD_Imovnti,
UD_Imovntpd,
UD_Imovntps,
UD_Imovntq,
UD_Imovq,
UD_Imovqa,
UD_Imovq2dq,
UD_Imovsb,
UD_Imovsw,
UD_Imovsd,
UD_Imovsq,
UD_Imovsldup,
UD_Imovshdup,
UD_Imovss,
UD_Imovsx,
UD_Imovupd,
UD_Imovups,
UD_Imovzx,
UD_Imul,
UD_Imulpd,
UD_Imulps,
UD_Imulsd,
UD_Imulss,
UD_Imwait,
UD_Ineg,
UD_Inop,
UD_Inot,
UD_Ior,
UD_Iorpd,
UD_Iorps,
UD_Iout,
UD_Ioutsb,
UD_Ioutsw,
UD_Ioutsd,
UD_Ioutsq,
UD_Ipacksswb,
UD_Ipackssdw,
UD_Ipackuswb,
UD_Ipaddb,
UD_Ipaddw,
UD_Ipaddq,
UD_Ipaddsb,
UD_Ipaddsw,
UD_Ipaddusb,
UD_Ipaddusw,
UD_Ipand,
UD_Ipandn,
UD_Ipause,
UD_Ipavgb,
UD_Ipavgw,
UD_Ipcmpeqb,
UD_Ipcmpeqw,
UD_Ipcmpeqd,
UD_Ipcmpgtb,
UD_Ipcmpgtw,
UD_Ipcmpgtd,
UD_Ipextrw,
UD_Ipinsrw,
UD_Ipmaddwd,
UD_Ipmaxsw,
UD_Ipmaxub,
UD_Ipminsw,
UD_Ipminub,
UD_Ipmovmskb,
UD_Ipmulhuw,
UD_Ipmulhw,
UD_Ipmullw,
UD_Ipmuludq,
UD_Ipop,
UD_Ipopa,
UD_Ipopad,
UD_Ipopfw,
UD_Ipopfd,
UD_Ipopfq,
UD_Ipor,
UD_Iprefetch,
UD_Iprefetchnta,
UD_Iprefetcht0,
UD_Iprefetcht1,
UD_Iprefetcht2,
UD_Ipsadbw,
UD_Ipshufd,
UD_Ipshufhw,
UD_Ipshuflw,
UD_Ipshufw,
UD_Ipslldq,
UD_Ipsllw,
UD_Ipslld,
UD_Ipsllq,
UD_Ipsraw,
UD_Ipsrad,
UD_Ipsrlw,
UD_Ipsrld,
UD_Ipsrlq,
UD_Ipsrldq,
UD_Ipsubb,
UD_Ipsubw,
UD_Ipsubd,
UD_Ipsubq,
UD_Ipsubsb,
UD_Ipsubsw,
UD_Ipsubusb,
UD_Ipsubusw,
UD_Ipunpckhbw,
UD_Ipunpckhwd,
UD_Ipunpckhdq,
UD_Ipunpckhqdq,
UD_Ipunpcklbw,
UD_Ipunpcklwd,
UD_Ipunpckldq,
UD_Ipunpcklqdq,
UD_Ipi2fw,
UD_Ipi2fd,
UD_Ipf2iw,
UD_Ipf2id,
UD_Ipfnacc,
UD_Ipfpnacc,
UD_Ipfcmpge,
UD_Ipfmin,
UD_Ipfrcp,
UD_Ipfrsqrt,
UD_Ipfsub,
UD_Ipfadd,
UD_Ipfcmpgt,
UD_Ipfmax,
UD_Ipfrcpit1,
UD_Ipfrspit1,
UD_Ipfsubr,
UD_Ipfacc,
UD_Ipfcmpeq,
UD_Ipfmul,
UD_Ipfrcpit2,
UD_Ipmulhrw,
UD_Ipswapd,
UD_Ipavgusb,
UD_Ipush,
UD_Ipusha,
UD_Ipushad,
UD_Ipushfw,
UD_Ipushfd,
UD_Ipushfq,
UD_Ipxor,
UD_Ircl,
UD_Ircr,
UD_Irol,
UD_Iror,
UD_Ircpps,
UD_Ircpss,
UD_Irdmsr,
UD_Irdpmc,
UD_Irdtsc,
UD_Irdtscp,
UD_Irepne,
UD_Irep,
UD_Iret,
UD_Iretf,
UD_Irsm,
UD_Irsqrtps,
UD_Irsqrtss,
UD_Isahf,
UD_Isal,
UD_Isalc,
UD_Isar,
UD_Ishl,
UD_Ishr,
UD_Isbb,
UD_Iscasb,
UD_Iscasw,
UD_Iscasd,
UD_Iscasq,
UD_Iseto,
UD_Isetno,
UD_Isetb,
UD_Isetnb,
UD_Isetz,
UD_Isetnz,
UD_Isetbe,
UD_Iseta,
UD_Isets,
UD_Isetns,
UD_Isetp,
UD_Isetnp,
UD_Isetl,
UD_Isetge,
UD_Isetle,
UD_Isetg,
UD_Isfence,
UD_Isgdt,
UD_Ishld,
UD_Ishrd,
UD_Ishufpd,
UD_Ishufps,
UD_Isidt,
UD_Isldt,
UD_Ismsw,
UD_Isqrtps,
UD_Isqrtpd,
UD_Isqrtsd,
UD_Isqrtss,
UD_Istc,
UD_Istd,
UD_Istgi,
UD_Isti,
UD_Iskinit,
UD_Istmxcsr,
UD_Istosb,
UD_Istosw,
UD_Istosd,
UD_Istosq,
UD_Istr,
UD_Isub,
UD_Isubpd,
UD_Isubps,
UD_Isubsd,
UD_Isubss,
UD_Iswapgs,
UD_Isyscall,
UD_Isysenter,
UD_Isysexit,
UD_Isysret,
UD_Itest,
UD_Iucomisd,
UD_Iucomiss,
UD_Iud2,
UD_Iunpckhpd,
UD_Iunpckhps,
UD_Iunpcklps,
UD_Iunpcklpd,
UD_Iverr,
UD_Iverw,
UD_Ivmcall,
UD_Ivmclear,
UD_Ivmxon,
UD_Ivmptrld,
UD_Ivmptrst,
UD_Ivmresume,
UD_Ivmxoff,
UD_Ivmrun,
UD_Ivmmcall,
UD_Ivmload,
UD_Ivmsave,
UD_Iwait,
UD_Iwbinvd,
UD_Iwrmsr,
UD_Ixadd,
UD_Ixchg,
UD_Ixlatb,
UD_Ixor,
UD_Ixorpd,
UD_Ixorps,
UD_Idb,
UD_Iinvalid,
UD_Id3vil,
UD_Ina,
UD_Igrp_reg,
UD_Igrp_rm,
UD_Igrp_vendor,
UD_Igrp_x87,
UD_Igrp_mode,
UD_Igrp_osize,
UD_Igrp_asize,
UD_Igrp_mod,
UD_Inone,
};
extern const char* ud_mnemonics_str[];;
extern struct ud_itab_entry* ud_itab_list[];
#endif
@@ -0,0 +1,211 @@
/* -----------------------------------------------------------------------------
* syn-att.c
*
* Copyright (c) 2004, 2005, 2006 Vivek Mohan <vivek@sig9.com>
* All rights reserved. See (LICENSE)
* -----------------------------------------------------------------------------
*/
#include "types.h"
#include "extern.h"
#include "decode.h"
#include "itab.h"
#include "syn.h"
/* -----------------------------------------------------------------------------
* opr_cast() - Prints an operand cast.
* -----------------------------------------------------------------------------
*/
static void
opr_cast(struct ud* u, struct ud_operand* op)
{
switch(op->size) {
case 16 : case 32 :
mkasm(u, "*"); break;
default: break;
}
}
/* -----------------------------------------------------------------------------
* gen_operand() - Generates assembly output for each operand.
* -----------------------------------------------------------------------------
*/
static void
gen_operand(struct ud* u, struct ud_operand* op)
{
switch(op->type) {
case UD_OP_REG:
mkasm(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]);
break;
case UD_OP_MEM:
if (u->br_far) opr_cast(u, op);
if (u->pfx_seg)
mkasm(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
if (op->offset == 8) {
if (op->lval.sbyte < 0)
mkasm(u, "-0x%x", (-op->lval.sbyte) & 0xff);
else mkasm(u, "0x%x", op->lval.sbyte);
}
else if (op->offset == 16)
mkasm(u, "0x%x", op->lval.uword);
else if (op->offset == 32)
mkasm(u, "0x%lx", op->lval.udword);
else if (op->offset == 64)
mkasm(u, "0x" FMT64 "x", op->lval.uqword);
if (op->base)
mkasm(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]);
if (op->index) {
if (op->base)
mkasm(u, ",");
else mkasm(u, "(");
mkasm(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]);
}
if (op->scale)
mkasm(u, ",%d", op->scale);
if (op->base || op->index)
mkasm(u, ")");
break;
case UD_OP_IMM:
switch (op->size) {
case 8: mkasm(u, "$0x%x", op->lval.ubyte); break;
case 16: mkasm(u, "$0x%x", op->lval.uword); break;
case 32: mkasm(u, "$0x%lx", op->lval.udword); break;
case 64: mkasm(u, "$0x" FMT64 "x", op->lval.uqword); break;
default: break;
}
break;
case UD_OP_JIMM:
switch (op->size) {
case 8:
mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte);
break;
case 16:
mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sword);
break;
case 32:
mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sdword);
break;
default:break;
}
break;
case UD_OP_PTR:
switch (op->size) {
case 32:
mkasm(u, "$0x%x, $0x%x", op->lval.ptr.seg,
op->lval.ptr.off & 0xFFFF);
break;
case 48:
mkasm(u, "$0x%x, $0x%lx", op->lval.ptr.seg,
op->lval.ptr.off);
break;
}
break;
default: return;
}
}
/* =============================================================================
* translates to AT&T syntax
* =============================================================================
*/
extern void
ud_translate_att(struct ud *u)
{
int size = 0;
/* check if P_OSO prefix is used */
if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
switch (u->dis_mode) {
case 16:
mkasm(u, "o32 ");
break;
case 32:
case 64:
mkasm(u, "o16 ");
break;
}
}
/* check if P_ASO prefix was used */
if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
switch (u->dis_mode) {
case 16:
mkasm(u, "a32 ");
break;
case 32:
mkasm(u, "a16 ");
break;
case 64:
mkasm(u, "a32 ");
break;
}
}
if (u->pfx_lock)
mkasm(u, "lock ");
if (u->pfx_rep)
mkasm(u, "rep ");
if (u->pfx_repne)
mkasm(u, "repne ");
/* special instructions */
switch (u->mnemonic) {
case UD_Iretf:
mkasm(u, "lret ");
break;
case UD_Idb:
mkasm(u, ".byte 0x%x", u->operand[0].lval.ubyte);
return;
case UD_Ijmp:
case UD_Icall:
if (u->br_far) mkasm(u, "l");
mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic));
break;
case UD_Ibound:
case UD_Ienter:
if (u->operand[0].type != UD_NONE)
gen_operand(u, &u->operand[0]);
if (u->operand[1].type != UD_NONE) {
mkasm(u, ",");
gen_operand(u, &u->operand[1]);
}
return;
default:
mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic));
}
if (u->c1)
size = u->operand[0].size;
else if (u->c2)
size = u->operand[1].size;
else if (u->c3)
size = u->operand[2].size;
if (size == 8)
mkasm(u, "b");
else if (size == 16)
mkasm(u, "w");
else if (size == 64)
mkasm(u, "q");
mkasm(u, " ");
if (u->operand[2].type != UD_NONE) {
gen_operand(u, &u->operand[2]);
mkasm(u, ", ");
}
if (u->operand[1].type != UD_NONE) {
gen_operand(u, &u->operand[1]);
mkasm(u, ", ");
}
if (u->operand[0].type != UD_NONE)
gen_operand(u, &u->operand[0]);
}
@@ -0,0 +1,208 @@
/* -----------------------------------------------------------------------------
* syn-intel.c
*
* Copyright (c) 2002, 2003, 2004 Vivek Mohan <vivek@sig9.com>
* All rights reserved. See (LICENSE)
* -----------------------------------------------------------------------------
*/
#include "types.h"
#include "extern.h"
#include "decode.h"
#include "itab.h"
#include "syn.h"
/* -----------------------------------------------------------------------------
* opr_cast() - Prints an operand cast.
* -----------------------------------------------------------------------------
*/
static void
opr_cast(struct ud* u, struct ud_operand* op)
{
switch(op->size) {
case 8: mkasm(u, "byte " ); break;
case 16: mkasm(u, "word " ); break;
case 32: mkasm(u, "dword "); break;
case 64: mkasm(u, "qword "); break;
case 80: mkasm(u, "tword "); break;
default: break;
}
if (u->br_far)
mkasm(u, "far ");
else if (u->br_near)
mkasm(u, "near ");
}
/* -----------------------------------------------------------------------------
* gen_operand() - Generates assembly output for each operand.
* -----------------------------------------------------------------------------
*/
static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast)
{
switch(op->type) {
case UD_OP_REG:
mkasm(u, ud_reg_tab[op->base - UD_R_AL]);
break;
case UD_OP_MEM: {
int op_f = 0;
if (syn_cast)
opr_cast(u, op);
mkasm(u, "[");
if (u->pfx_seg)
mkasm(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
if (op->base) {
mkasm(u, "%s", ud_reg_tab[op->base - UD_R_AL]);
op_f = 1;
}
if (op->index) {
if (op_f)
mkasm(u, "+");
mkasm(u, "%s", ud_reg_tab[op->index - UD_R_AL]);
op_f = 1;
}
if (op->scale)
mkasm(u, "*%d", op->scale);
if (op->offset == 8) {
if (op->lval.sbyte < 0)
mkasm(u, "-0x%x", -op->lval.sbyte);
else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sbyte);
}
else if (op->offset == 16)
mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.uword);
else if (op->offset == 32) {
if (u->adr_mode == 64) {
if (op->lval.sdword < 0)
mkasm(u, "-0x%x", -op->lval.sdword);
else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sdword);
}
else mkasm(u, "%s0x%lx", (op_f) ? "+" : "", op->lval.udword);
}
else if (op->offset == 64)
mkasm(u, "%s0x" FMT64 "x", (op_f) ? "+" : "", op->lval.uqword);
mkasm(u, "]");
break;
}
case UD_OP_IMM:
if (syn_cast) opr_cast(u, op);
switch (op->size) {
case 8: mkasm(u, "0x%x", op->lval.ubyte); break;
case 16: mkasm(u, "0x%x", op->lval.uword); break;
case 32: mkasm(u, "0x%lx", op->lval.udword); break;
case 64: mkasm(u, "0x" FMT64 "x", op->lval.uqword); break;
default: break;
}
break;
case UD_OP_JIMM:
if (syn_cast) opr_cast(u, op);
switch (op->size) {
case 8:
mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte);
break;
case 16:
mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sword);
break;
case 32:
mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sdword);
break;
default:break;
}
break;
case UD_OP_PTR:
switch (op->size) {
case 32:
mkasm(u, "word 0x%x:0x%x", op->lval.ptr.seg,
op->lval.ptr.off & 0xFFFF);
break;
case 48:
mkasm(u, "dword 0x%x:0x%lx", op->lval.ptr.seg,
op->lval.ptr.off);
break;
}
break;
case UD_OP_CONST:
if (syn_cast) opr_cast(u, op);
mkasm(u, "%d", op->lval.udword);
break;
default: return;
}
}
/* =============================================================================
* translates to intel syntax
* =============================================================================
*/
extern void ud_translate_intel(struct ud* u)
{
/* -- prefixes -- */
/* check if P_OSO prefix is used */
if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
switch (u->dis_mode) {
case 16:
mkasm(u, "o32 ");
break;
case 32:
case 64:
mkasm(u, "o16 ");
break;
}
}
/* check if P_ASO prefix was used */
if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
switch (u->dis_mode) {
case 16:
mkasm(u, "a32 ");
break;
case 32:
mkasm(u, "a16 ");
break;
case 64:
mkasm(u, "a32 ");
break;
}
}
if (u->pfx_lock)
mkasm(u, "lock ");
if (u->pfx_rep)
mkasm(u, "rep ");
if (u->pfx_repne)
mkasm(u, "repne ");
if (u->implicit_addr && u->pfx_seg)
mkasm(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]);
/* print the instruction mnemonic */
mkasm(u, "%s ", ud_lookup_mnemonic(u->mnemonic));
/* operand 1 */
if (u->operand[0].type != UD_NONE) {
gen_operand(u, &u->operand[0], u->c1);
}
/* operand 2 */
if (u->operand[1].type != UD_NONE) {
mkasm(u, ", ");
gen_operand(u, &u->operand[1], u->c2);
}
/* operand 3 */
if (u->operand[2].type != UD_NONE) {
mkasm(u, ", ");
gen_operand(u, &u->operand[2], u->c3);
}
}
@@ -0,0 +1,61 @@
/* -----------------------------------------------------------------------------
* syn.c
*
* Copyright (c) 2002, 2003, 2004 Vivek Mohan <vivek@sig9.com>
* All rights reserved. See (LICENSE)
* -----------------------------------------------------------------------------
*/
/* -----------------------------------------------------------------------------
* Intel Register Table - Order Matters (types.h)!
* -----------------------------------------------------------------------------
*/
const char* ud_reg_tab[] =
{
"al", "cl", "dl", "bl",
"ah", "ch", "dh", "bh",
"spl", "bpl", "sil", "dil",
"r8b", "r9b", "r10b", "r11b",
"r12b", "r13b", "r14b", "r15b",
"ax", "cx", "dx", "bx",
"sp", "bp", "si", "di",
"r8w", "r9w", "r10w", "r11w",
"r12w", "r13W" , "r14w", "r15w",
"eax", "ecx", "edx", "ebx",
"esp", "ebp", "esi", "edi",
"r8d", "r9d", "r10d", "r11d",
"r12d", "r13d", "r14d", "r15d",
"rax", "rcx", "rdx", "rbx",
"rsp", "rbp", "rsi", "rdi",
"r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15",
"es", "cs", "ss", "ds",
"fs", "gs",
"cr0", "cr1", "cr2", "cr3",
"cr4", "cr5", "cr6", "cr7",
"cr8", "cr9", "cr10", "cr11",
"cr12", "cr13", "cr14", "cr15",
"dr0", "dr1", "dr2", "dr3",
"dr4", "dr5", "dr6", "dr7",
"dr8", "dr9", "dr10", "dr11",
"dr12", "dr13", "dr14", "dr15",
"mm0", "mm1", "mm2", "mm3",
"mm4", "mm5", "mm6", "mm7",
"st0", "st1", "st2", "st3",
"st4", "st5", "st6", "st7",
"xmm0", "xmm1", "xmm2", "xmm3",
"xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11",
"xmm12", "xmm13", "xmm14", "xmm15",
"rip"
};
@@ -0,0 +1,25 @@
/* -----------------------------------------------------------------------------
* syn.h
*
* Copyright (c) 2006, Vivek Mohan <vivek@sig9.com>
* All rights reserved. See LICENSE
* -----------------------------------------------------------------------------
*/
#ifndef UD_SYN_H
#define UD_SYN_H
#include <stdio.h>
#include <stdarg.h>
#include "types.h"
extern const char* ud_reg_tab[];
static void mkasm(struct ud* u, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
u->insn_fill += vsprintf((char*) u->insn_buffer + u->insn_fill, fmt, ap);
va_end(ap);
}
#endif
@@ -0,0 +1,200 @@
/* -----------------------------------------------------------------------------
* types.h
*
* Copyright (c) 2006, Vivek Mohan <vivek@sig9.com>
* All rights reserved. See LICENSE
* -----------------------------------------------------------------------------
*/
#ifndef UD_TYPES_H
#define UD_TYPES_H
#include <stdio.h>
#ifdef _MSC_VER
# define FMT64 "%I64"
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
#else
# define FMT64 "%ll"
# include <inttypes.h>
#endif
#include "itab.h"
/* -----------------------------------------------------------------------------
* All possible "types" of objects in udis86. Order is Important!
* -----------------------------------------------------------------------------
*/
enum ud_type
{
UD_NONE,
/* 8 bit GPRs */
UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL,
UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH,
UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL,
UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B,
UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B,
/* 16 bit GPRs */
UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX,
UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI,
UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W,
UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W,
/* 32 bit GPRs */
UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX,
UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI,
UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D,
UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D,
/* 64 bit GPRs */
UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX,
UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI,
UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11,
UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15,
/* segment registers */
UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS,
UD_R_FS, UD_R_GS,
/* control registers*/
UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3,
UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7,
UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11,
UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15,
/* debug registers */
UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3,
UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7,
UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11,
UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15,
/* mmx registers */
UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3,
UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7,
/* x87 registers */
UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3,
UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7,
/* extended multimedia registers */
UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3,
UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7,
UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11,
UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15,
UD_R_RIP,
/* Operand Types */
UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM,
UD_OP_JIMM, UD_OP_CONST
};
/* -----------------------------------------------------------------------------
* struct ud_operand - Disassembled instruction Operand.
* -----------------------------------------------------------------------------
*/
struct ud_operand
{
enum ud_type type;
uint8_t size;
union {
int8_t sbyte;
uint8_t ubyte;
int16_t sword;
uint16_t uword;
int32_t sdword;
uint32_t udword;
int64_t sqword;
uint64_t uqword;
struct {
uint16_t seg;
uint32_t off;
} ptr;
} lval;
enum ud_type base;
enum ud_type index;
uint8_t offset;
uint8_t scale;
};
/* -----------------------------------------------------------------------------
* struct ud - The udis86 object.
* -----------------------------------------------------------------------------
*/
struct ud
{
int (*inp_hook) (struct ud*);
uint8_t inp_curr;
uint8_t inp_fill;
FILE* inp_file;
uint8_t inp_ctr;
uint8_t* inp_buff;
uint8_t* inp_buff_end;
uint8_t inp_end;
void (*translator)(struct ud*);
uint64_t insn_offset;
char insn_hexcode[32];
char insn_buffer[64];
unsigned int insn_fill;
uint8_t dis_mode;
uint64_t pc;
uint8_t vendor;
struct map_entry* mapen;
enum ud_mnemonic_code mnemonic;
struct ud_operand operand[3];
uint8_t error;
uint8_t pfx_rex;
uint8_t pfx_seg;
uint8_t pfx_opr;
uint8_t pfx_adr;
uint8_t pfx_lock;
uint8_t pfx_rep;
uint8_t pfx_repe;
uint8_t pfx_repne;
uint8_t pfx_insn;
uint8_t default64;
uint8_t opr_mode;
uint8_t adr_mode;
uint8_t br_far;
uint8_t br_near;
uint8_t implicit_addr;
uint8_t c1;
uint8_t c2;
uint8_t c3;
uint8_t inp_cache[256];
uint8_t inp_sess[64];
struct ud_itab_entry * itab_entry;
};
/* -----------------------------------------------------------------------------
* Type-definitions
* -----------------------------------------------------------------------------
*/
typedef enum ud_type ud_type_t;
typedef enum ud_mnemonic_code ud_mnemonic_code_t;
typedef struct ud ud_t;
typedef struct ud_operand ud_operand_t;
#define UD_SYN_INTEL ud_translate_intel
#define UD_SYN_ATT ud_translate_att
#define UD_EOI -1
#define UD_INP_CACHE_SZ 32
#define UD_VENDOR_AMD 0
#define UD_VENDOR_INTEL 1
#define bail_out(ud,error_code) longjmp( (ud)->bailout, error_code )
#define try_decode(ud) if ( setjmp( (ud)->bailout ) == 0 )
#define catch_error() else
#endif
@@ -0,0 +1,154 @@
/* -----------------------------------------------------------------------------
* udis86.c
*
* Copyright (c) 2004, 2005, 2006, Vivek Mohan <vivek@sig9.com>
* All rights reserved. See LICENSE
* -----------------------------------------------------------------------------
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "input.h"
#include "extern.h"
/* =============================================================================
* ud_init() - Initializes ud_t object.
* =============================================================================
*/
extern void
ud_init(struct ud* u)
{
memset((void*)u, 0, sizeof(struct ud));
ud_set_mode(u, 16);
u->mnemonic = UD_Iinvalid;
ud_set_pc(u, 0);
#ifndef __UD_STANDALONE__
ud_set_input_file(u, stdin);
#endif /* __UD_STANDALONE__ */
}
/* =============================================================================
* ud_disassemble() - disassembles one instruction and returns the number of
* bytes disassembled. A zero means end of disassembly.
* =============================================================================
*/
extern unsigned int
ud_disassemble(struct ud* u)
{
if (ud_input_end(u))
return 0;
u->insn_buffer[0] = u->insn_hexcode[0] = 0;
if (ud_decode(u) == 0)
return 0;
if (u->translator)
u->translator(u);
return ud_insn_len(u);
}
/* =============================================================================
* ud_set_mode() - Set Disassemly Mode.
* =============================================================================
*/
extern void
ud_set_mode(struct ud* u, uint8_t m)
{
switch(m) {
case 16:
case 32:
case 64: u->dis_mode = m ; return;
default: u->dis_mode = 16; return;
}
}
/* =============================================================================
* ud_set_vendor() - Set vendor.
* =============================================================================
*/
extern void
ud_set_vendor(struct ud* u, unsigned v)
{
switch(v) {
case UD_VENDOR_INTEL:
u->vendor = v;
break;
default:
u->vendor = UD_VENDOR_AMD;
}
}
/* =============================================================================
* ud_set_pc() - Sets code origin.
* =============================================================================
*/
extern void
ud_set_pc(struct ud* u, uint64_t o)
{
u->pc = o;
}
/* =============================================================================
* ud_set_syntax() - Sets the output syntax.
* =============================================================================
*/
extern void
ud_set_syntax(struct ud* u, void (*t)(struct ud*))
{
u->translator = t;
}
/* =============================================================================
* ud_insn() - returns the disassembled instruction
* =============================================================================
*/
extern char*
ud_insn_asm(struct ud* u)
{
return u->insn_buffer;
}
/* =============================================================================
* ud_insn_offset() - Returns the offset.
* =============================================================================
*/
extern uint64_t
ud_insn_off(struct ud* u)
{
return u->insn_offset;
}
/* =============================================================================
* ud_insn_hex() - Returns hex form of disassembled instruction.
* =============================================================================
*/
extern char*
ud_insn_hex(struct ud* u)
{
return u->insn_hexcode;
}
/* =============================================================================
* ud_insn_ptr() - Returns code disassembled.
* =============================================================================
*/
extern uint8_t*
ud_insn_ptr(struct ud* u)
{
return u->inp_sess;
}
/* =============================================================================
* ud_insn_len() - Returns the count of bytes disassembled.
* =============================================================================
*/
extern unsigned int
ud_insn_len(struct ud* u)
{
return u->inp_ctr;
}
@@ -0,0 +1,200 @@
/* -----------------------------------------------------------------------------
* types.h
*
* Copyright (c) 2006, Vivek Mohan <vivek@sig9.com>
* All rights reserved. See LICENSE
* -----------------------------------------------------------------------------
*/
#ifndef UD_TYPES_H
#define UD_TYPES_H
#include <stdio.h>
#ifdef _MSC_VER
# define FMT64 "%I64"
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
#else
# define FMT64 "%ll"
# include <inttypes.h>
#endif
#include "itab.h"
/* -----------------------------------------------------------------------------
* All possible "types" of objects in udis86. Order is Important!
* -----------------------------------------------------------------------------
*/
enum ud_type
{
UD_NONE,
/* 8 bit GPRs */
UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL,
UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH,
UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL,
UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B,
UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B,
/* 16 bit GPRs */
UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX,
UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI,
UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W,
UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W,
/* 32 bit GPRs */
UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX,
UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI,
UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D,
UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D,
/* 64 bit GPRs */
UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX,
UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI,
UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11,
UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15,
/* segment registers */
UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS,
UD_R_FS, UD_R_GS,
/* control registers*/
UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3,
UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7,
UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11,
UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15,
/* debug registers */
UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3,
UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7,
UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11,
UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15,
/* mmx registers */
UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3,
UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7,
/* x87 registers */
UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3,
UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7,
/* extended multimedia registers */
UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3,
UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7,
UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11,
UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15,
UD_R_RIP,
/* Operand Types */
UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM,
UD_OP_JIMM, UD_OP_CONST
};
/* -----------------------------------------------------------------------------
* struct ud_operand - Disassembled instruction Operand.
* -----------------------------------------------------------------------------
*/
struct ud_operand
{
enum ud_type type;
uint8_t size;
union {
int8_t sbyte;
uint8_t ubyte;
int16_t sword;
uint16_t uword;
int32_t sdword;
uint32_t udword;
int64_t sqword;
uint64_t uqword;
struct {
uint16_t seg;
uint32_t off;
} ptr;
} lval;
enum ud_type base;
enum ud_type index;
uint8_t offset;
uint8_t scale;
};
/* -----------------------------------------------------------------------------
* struct ud - The udis86 object.
* -----------------------------------------------------------------------------
*/
struct ud
{
int (*inp_hook) (struct ud*);
uint8_t inp_curr;
uint8_t inp_fill;
FILE* inp_file;
uint8_t inp_ctr;
uint8_t* inp_buff;
uint8_t* inp_buff_end;
uint8_t inp_end;
void (*translator)(struct ud*);
uint64_t insn_offset;
char insn_hexcode[32];
char insn_buffer[64];
unsigned int insn_fill;
uint8_t dis_mode;
uint64_t pc;
uint8_t vendor;
struct map_entry* mapen;
enum ud_mnemonic_code mnemonic;
struct ud_operand operand[3];
uint8_t error;
uint8_t pfx_rex;
uint8_t pfx_seg;
uint8_t pfx_opr;
uint8_t pfx_adr;
uint8_t pfx_lock;
uint8_t pfx_rep;
uint8_t pfx_repe;
uint8_t pfx_repne;
uint8_t pfx_insn;
uint8_t default64;
uint8_t opr_mode;
uint8_t adr_mode;
uint8_t br_far;
uint8_t br_near;
uint8_t implicit_addr;
uint8_t c1;
uint8_t c2;
uint8_t c3;
uint8_t inp_cache[256];
uint8_t inp_sess[64];
struct ud_itab_entry * itab_entry;
};
/* -----------------------------------------------------------------------------
* Type-definitions
* -----------------------------------------------------------------------------
*/
typedef enum ud_type ud_type_t;
typedef enum ud_mnemonic_code ud_mnemonic_code_t;
typedef struct ud ud_t;
typedef struct ud_operand ud_operand_t;
#define UD_SYN_INTEL ud_translate_intel
#define UD_SYN_ATT ud_translate_att
#define UD_EOI -1
#define UD_INP_CACHE_SZ 32
#define UD_VENDOR_AMD 0
#define UD_VENDOR_INTEL 1
#define bail_out(ud,error_code) longjmp( (ud)->bailout, error_code )
#define try_decode(ud) if ( setjmp( (ud)->bailout ) == 0 )
#define catch_error() else
#endif
@@ -0,0 +1,718 @@
// ********************************************************
// some user-mode structures
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
LIST_ENTRY HashLinks;
PVOID SectionPointer;
ULONG CheckSum;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY,
*PLDR_DATA_TABLE_ENTRY;
typedef struct _PEB_LDR_DATA
{
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY ModuleListLoadOrder;
LIST_ENTRY ModuleListMemoryOrder;
LIST_ENTRY ModuleListInitOrder;
} PEB_LDR_DATA,
*PPEB_LDR_DATA;
// ********************************************************
typedef struct SERVICE_DESCRIPTOR_ENTRY
{
PVOID *ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfServices;
PUCHAR ParamTableBase;
} SERVICE_DESCRIPTOR_ENTRY,
*PSERVICE_DESCRIPTOR_ENTRY;
typedef struct _SERVICE_DESCRIPTOR_TABLE
{
SERVICE_DESCRIPTOR_ENTRY Entry[2];
} SERVICE_DESCRIPTOR_TABLE,
*PSERVICE_DESCRIPTOR_TABLE;
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation,
SystemProcessorInformation, // obsolete...delete
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemPathInformation,
SystemProcessInformation,
SystemCallCountInformation,
SystemDeviceInformation,
SystemProcessorPerformanceInformation,
SystemFlagsInformation,
SystemCallTimeInformation,
SystemModuleInformation,
SystemLocksInformation,
SystemStackTraceInformation,
SystemPagedPoolInformation,
SystemNonPagedPoolInformation,
SystemHandleInformation,
SystemObjectInformation,
SystemPageFileInformation,
SystemVdmInstemulInformation,
SystemVdmBopInformation,
SystemFileCacheInformation,
SystemPoolTagInformation,
SystemInterruptInformation,
SystemDpcBehaviorInformation,
SystemFullMemoryInformation,
SystemLoadGdiDriverInformation,
SystemUnloadGdiDriverInformation,
SystemTimeAdjustmentInformation,
SystemSummaryMemoryInformation,
SystemMirrorMemoryInformation,
SystemPerformanceTraceInformation,
SystemObsolete0,
SystemExceptionInformation,
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
SystemContextSwitchInformation,
SystemRegistryQuotaInformation,
SystemExtendServiceTableInformation,
SystemPrioritySeperation,
SystemVerifierAddDriverInformation,
SystemVerifierRemoveDriverInformation,
SystemProcessorIdleInformation,
SystemLegacyDriverInformation,
SystemCurrentTimeZoneInformation,
SystemLookasideInformation,
SystemTimeSlipNotification,
SystemSessionCreate,
SystemSessionDetach,
SystemSessionInformation,
SystemRangeStartInformation,
SystemVerifierInformation,
SystemVerifierThunkExtend,
SystemSessionProcessInformation,
SystemLoadGdiDriverInSystemSpace,
SystemNumaProcessorMap,
SystemPrefetcherInformation,
SystemExtendedProcessInformation,
SystemRecommendedSharedDataAlignment,
SystemComPlusPackage,
SystemNumaAvailableMemory,
SystemProcessorPowerInformation,
SystemEmulationBasicInformation,
SystemEmulationProcessorInformation,
SystemExtendedHandleInformation,
SystemLostDelayedWriteInformation,
SystemBigPoolInformation,
SystemSessionPoolTagInformation,
SystemSessionMappedViewInformation,
SystemHotpatchInformation,
SystemObjectSecurityMode,
SystemWatchdogTimerHandler,
SystemWatchdogTimerInformation,
SystemLogicalProcessorInformation,
SystemWow64SharedInformation,
SystemRegisterFirmwareTableInformationHandler,
SystemFirmwareTableInformation,
SystemModuleInformationEx,
SystemVerifierTriageInformation,
SystemSuperfetchInformation,
SystemMemoryListInformation,
SystemFileCacheInformationEx,
MaxSystemInfoClass // MaxSystemInfoClass should always be the last enum
} SYSTEM_INFORMATION_CLASS;
typedef struct _RTL_PROCESS_MODULE_INFORMATION
{
HANDLE Section; // Not filled in
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[ 256 ];
} RTL_PROCESS_MODULE_INFORMATION,
*PRTL_PROCESS_MODULE_INFORMATION;
typedef struct _RTL_PROCESS_MODULES
{
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[ 1 ];
} RTL_PROCESS_MODULES,
*PRTL_PROCESS_MODULES;
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
USHORT UniqueProcessId;
USHORT CreatorBackTraceIndex;
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
PVOID Object;
ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO,
*PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[ 1 ];
} SYSTEM_HANDLE_INFORMATION,
*PSYSTEM_HANDLE_INFORMATION;
#ifndef _NTIFS_INCLUDED_
typedef struct _FILE_DIRECTORY_INFORMATION
{
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_DIRECTORY_INFORMATION,
*PFILE_DIRECTORY_INFORMATION;
typedef struct _FILE_NAMES_INFORMATION
{
ULONG NextEntryOffset;
ULONG FileIndex;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAMES_INFORMATION,
*PFILE_NAMES_INFORMATION;
#endif
typedef struct _FILE_FULL_DIRECTORY_INFORMATION
{
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
WCHAR FileName[1];
} FILE_FULL_DIRECTORY_INFORMATION,
*PFILE_FULL_DIRECTORY_INFORMATION;
typedef struct _FILE_BOTH_DIRECTORY_INFORMATION
{
ULONG NextEntryOffset;
ULONG Unknown;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaInformationLength;
UCHAR AlternateNameLength;
WCHAR AlternateName[12];
WCHAR FileName[1];
} FILE_BOTH_DIRECTORY_INFORMATION,
*PFILE_BOTH_DIRECTORY_INFORMATION;
typedef struct _FILE_ID_BOTH_DIRECTORY_INFORMATION
{
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
CCHAR ShortNameLength;
WCHAR ShortName[12];
LARGE_INTEGER FileId;
WCHAR FileName[1];
} FILE_ID_BOTH_DIRECTORY_INFORMATION,
*PFILE_ID_BOTH_DIRECTORY_INFORMATION;
typedef struct _FILE_ID_FULL_DIRECTORY_INFORMATION
{
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
LARGE_INTEGER FileId;
WCHAR FileName[1];
} FILE_ID_FULL_DIRECTORY_INFORMATION,
*PFILE_ID_FULL_DIRECTORY_INFORMATION;
typedef struct _SYSTEM_OBJECT_TYPE_INFORMATION
{
ULONG NextEntryOffset;
ULONG ObjectCount;
ULONG HandleCount;
ULONG TypeNumber;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ACCESS_MASK ValidAccessMask;
POOL_TYPE PoolType;
UCHAR Unknown;
UNICODE_STRING Name;
} SYSTEM_OBJECT_TYPE_INFORMATION,
*PSYSTEM_OBJECT_TYPE_INFORMATION;
typedef struct _SYSTEM_OBJECT_INFORMATION
{
ULONG NextEntryOffset;
PVOID Object;
ULONG CreatorProcessId;
USHORT Unknown;
USHORT Flags;
ULONG PointerCount;
ULONG HandleCount;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
ULONG ExclusiveProcessId;
PSECURITY_DESCRIPTOR SecurityDescriptor;
UNICODE_STRING Name;
} SYSTEM_OBJECT_INFORMATION,
*PSYSTEM_OBJECT_INFORMATION;
NTSYSAPI
NTSTATUS
NTAPI
ZwQueryDirectoryFile(
HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation,
ULONG FileInformationLength,
FILE_INFORMATION_CLASS FileInformationClass,
BOOLEAN ReturnSingleEntry,
PUNICODE_STRING FileName,
BOOLEAN RestartScan
);
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER SpareLi1;
LARGE_INTEGER SpareLi2;
LARGE_INTEGER SpareLi3;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
HANDLE InheritedFromUniqueProcessId;
ULONG HandleCount;
ULONG SessionId;
ULONG_PTR PageDirectoryBase;
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER ReadOperationCount;
LARGE_INTEGER WriteOperationCount;
LARGE_INTEGER OtherOperationCount;
LARGE_INTEGER ReadTransferCount;
LARGE_INTEGER WriteTransferCount;
LARGE_INTEGER OtherTransferCount;
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
typedef struct THREAD_BASIC_INFORMATION
{
NTSTATUS ExitStatus;
PVOID TebBaseAddress;
CLIENT_ID ClientId;
KAFFINITY AffinityMask;
KPRIORITY Priority;
KPRIORITY BasePriority;
} THREAD_BASIC_INFORMATION,
*PTHREAD_BASIC_INFORMATION;
NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
NTSYSAPI
NTSTATUS
NTAPI
ZwQueryInformationProcess(
HANDLE ProcessHandle,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength
);
NTSYSAPI
NTSTATUS
NTAPI
ZwOpenThread(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId
);
NTSYSAPI
NTSTATUS
NTAPI
ZwDeviceIoControlFile(
HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength
);
NTSYSAPI
NTSTATUS
NTAPI
ZwFsControlFile(
HANDLE FileHandle,
HANDLE Event OPTIONAL,
PIO_APC_ROUTINE ApcRoutine OPTIONAL,
PVOID ApcContext OPTIONAL,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG FsControlCode,
PVOID InputBuffer OPTIONAL,
ULONG InputBufferLength,
PVOID OutputBuffer OPTIONAL,
ULONG OutputBufferLength
);
NTSYSAPI
NTSTATUS
NTAPI
ZwSaveKey(
HANDLE KeyHandle,
HANDLE FileHandle
);
NTSYSAPI
NTSTATUS
NTAPI
ZwQueryVolumeInformationFile(
HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FsInformation,
ULONG Length,
FS_INFORMATION_CLASS FsInformationClass
);
NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySecurityObject(
HANDLE Handle,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR SecurityDescriptor,
ULONG Length,
PULONG LengthNeeded
);
NTSYSAPI
NTSTATUS
NTAPI
ZwSetSecurityObject(
HANDLE Handle,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR SecurityDescriptor
);
NTSYSAPI
NTSTATUS
NTAPI
ZwDuplicateObject(
HANDLE SourceProcessHandle,
HANDLE SourceHandle,
HANDLE TargetProcessHandle,
PHANDLE TargetHandle,
ACCESS_MASK DesiredAccess,
ULONG HandleAttributes,
ULONG Options
);
NTSYSAPI
NTSTATUS
NTAPI
RtlGetDaclSecurityDescriptor(
PSECURITY_DESCRIPTOR SecurityDescriptor,
PBOOLEAN DaclPresent,
PACL *Dacl,
PBOOLEAN DaclDefaulted
);
#ifndef _NTIFS_INCLUDED_
typedef struct _SID_IDENTIFIER_AUTHORITY
{
UCHAR Value[ 6 ];
} SID_IDENTIFIER_AUTHORITY;
typedef struct _SID_IDENTIFIER_AUTHORITY *PSID_IDENTIFIER_AUTHORITY;
#endif
NTSYSAPI
NTSTATUS
NTAPI
RtlInitializeSid(
PSID Sid,
PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
UCHAR SubAuthorityCount
);
NTSYSAPI
ULONG
NTAPI
RtlLengthSid(
PSID Sid
);
NTSYSAPI
NTSTATUS
NTAPI
RtlAddAccessAllowedAce(
PACL Acl,
ULONG AceRevision,
ACCESS_MASK AccessMask,
PSID Sid
);
NTSYSAPI
NTSTATUS
NTAPI
RtlSetDaclSecurityDescriptor(
OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
BOOLEAN DaclPresent,
PACL Dacl,
BOOLEAN DaclDefaulted
);
NTSYSAPI
NTSTATUS
NTAPI
RtlSelfRelativeToAbsoluteSD2(
PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
PULONG pBufferSize
);
NTSYSAPI
BOOLEAN
NTAPI
RtlValidSid(
PSID Sid
);
#ifndef _NTIFS_INCLUDED_
typedef struct _KAPC_STATE
{
LIST_ENTRY ApcListHead[2];
PVOID Process;
BOOLEAN KernelApcInProgress;
BOOLEAN KernelApcPending;
BOOLEAN UserApcPending;
} KAPC_STATE,
*PKAPC_STATE;
#endif
NTSYSAPI
VOID
NTAPI
KeStackAttachProcess(
PEPROCESS Process,
PKAPC_STATE ApcState
);
NTSYSAPI
VOID
NTAPI
KeUnstackDetachProcess(
PKAPC_STATE ApcState
);
NTSYSAPI
NTSTATUS
NTAPI
PsLookupProcessByProcessId(
HANDLE ProcessId,
PEPROCESS *Process
);
NTSYSAPI
NTSTATUS
NTAPI
PsLookupThreadByThreadId(
HANDLE ThreadId,
PETHREAD *Thread
);
NTSYSAPI
NTSTATUS
NTAPI
ObOpenObjectByPointer(
PVOID Object,
ULONG HandleAttributes,
PACCESS_STATE PassedAccessState,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
PHANDLE Handle
);
NTSYSAPI
NTSTATUS
NTAPI
ObOpenObjectByName(
POBJECT_ATTRIBUTES ObjectAttributes,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
PACCESS_STATE AccessState,
ACCESS_MASK DesiredAccess,
PVOID ParseContext,
PHANDLE Handle
);
NTSYSAPI
NTSTATUS
NTAPI
ObReferenceObjectByName(
PUNICODE_STRING ObjectPath,
ULONG Attributes,
PACCESS_STATE PassedAccessState,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
PVOID ParseContext,
PVOID *ObjectPtr
);
NTKERNELAPI
NTSTATUS
ObQueryNameString(
PVOID Object,
POBJECT_NAME_INFORMATION ObjectNameInfo,
ULONG Length,
PULONG ReturnLength
);
NTKERNELAPI
VOID
KeSetSystemAffinityThread(
KAFFINITY Affinity
);
typedef enum
{
OriginalApcEnvironment,
AttachedApcEnvironment,
CurrentApcEnvironment
} KAPC_ENVIRONMENT;
NTKERNELAPI
VOID
KeInitializeApc(
PRKAPC Apc,
PRKTHREAD Thread,
KAPC_ENVIRONMENT Environment,
PKKERNEL_ROUTINE KernelRoutine,
PKRUNDOWN_ROUTINE RundownRoutine,
PKNORMAL_ROUTINE NormalRoutine,
KPROCESSOR_MODE ApcMode,
PVOID NormalContext
);
NTKERNELAPI
BOOLEAN
KeInsertQueueApc(
PKAPC Apc,
PVOID SystemArgument1,
PVOID SystemArgument2,
KPRIORITY Increment
);
@@ -0,0 +1,124 @@
//Microsoft Developer Studio generated resource script.
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_COMMAND_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
#include "ntverp.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Chinese (P.R.C.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif //_WIN32
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,5
PRODUCTVERSION 1,0,0,5
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x3L
FILESUBTYPE 0x7L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "Comments", "Fuzzer\0"
VALUE "CompanyName", "\0"
VALUE "FileDescription", "IOCTL Fuzzer\0"
VALUE "FileVersion", "1.0.0.5\0"
VALUE "InternalName", "IOCTL_fuzzer.sys\0"
VALUE "LegalCopyright", "\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "IOCTL_fuzzer.sys\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "Fuzzer\0"
VALUE "ProductVersion", "1.0.0.5\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200
END
END
#endif // !_MAC
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE MOVEABLE PURE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE MOVEABLE PURE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""ntverp.h""\r\n"
"\0"
END
3 TEXTINCLUDE MOVEABLE PURE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Chinese (P.R.C.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED