Results 1 to 5 of 5
  1. #1
    .::SCHiM::.'s Avatar
    Join Date
    Sep 2010
    Gender
    male
    Posts
    733
    Reputation
    180
    Thanks
    880
    My Mood
    Twisted
    I proudly present to you: the kernel to user mode disassembler!!!!

    Intro

    I hope someone will find this intresting enough to acutally test it. I worked hard and long to further my knowledge about the windows kernel and this is the result of my studies.

    With this tool you can disassemble (any) binary file running in your systems' memory. This tool can be easily tweaked to dump files on your disk as well.
    I take credits for the driver and the conversion of the disassembler source (it was originally made to work with PE files on the disk)

    The disassembly part itself was made by somebody else.

    Warning

    The driver posted below is FAR FROM SAVE use it as your own risk.

    I'm not responsible for ANY damage to your system or yourself or those around you.

    Usage

    After the driver has been loaded into memory you can obtain a handle to it by calling GreateFile(). Using this handle you can now read an write data to the driver (ReadFile/WriteFile). Using WriteFile() You can send commands to the driver, this is a list of all available commands:

    char LoggerStart[sizeof("PROC_LOG_START")] = "PROC_LOG_START";

    Starts logging the creation of processes. Every time a new process is created it can be obtained by calling ReadFile(). If no new process has been created between ReadFile() calls, no data is returned.

    char LoggerStop[sizeof("PROC_LOG_STOP")] = "PROC_LOG_STOP";

    Stops logging the creation of processes.

    char PayloadStart[sizeof("PAYLOAD_SET")] = "PAYLOAD_SET";

    Does nothing anymore.

    char Target[sizeof("TARGET_SET")] = "TARGET_SET";

    Sets the target to dump. The target must be the full process name, case sensitive.

    char DumpData[sizeof("DUMP_DATA_SET")] = "DUMP_DATA_SET";

    Provides data to dump: The address and the size to dump.

    char DumpWhenPossible[sizeof("DUMP_DUMP")] = "DUMP_DUMP";

    Dump when possible. This command will dump the target module.

    char ResetFlags[sizeof("ERR_RESET")] = "ERR_RESET";

    Cancels all operations and resets internal driver flags.
    Directly after a command has been sent, the usermode application must send the arguments to that specific command. For example, if the usermode applications sends the WriteFile(TARGET_SET") the next write file must contain the target name.

    The driver must be loaded before the target is, the TARGET_SET, DUMP_DATA_SET, PROC_LOG_START must be set first. When you're ready to dump the file, send DUMP_DUMP wait a few seconds and call ReadFile() on the driver. The data returned are the copied instructions at the specified offset with the specified length.

    S0rc3S!!!
    Finally the fun part

    DriverMain.c

    Code:
    #include <Ntifs.h>
    #include <wdm.h>
    #include <Ntddk.h>
    #include <Ntstrsafe.h>
    
    #define IO_TYPE 0
    #define USE_WRITE_FUNCTION  WriteNeither    
    	
    VOID Unload(PDRIVER_OBJECT  DriverObject);    
    NTSTATUS DriverEntry(PDRIVER_OBJECT  pDriverObject, PUNICODE_STRING  pRegistryPath); 
    NTSTATUS Create(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS Close(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS IoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS ReadNeither(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS WriteNeither(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS UnSupportedFunction(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    BOOLEAN IsStringTerminated(PCHAR pString, unsigned int uiLength);
    BOOLEAN CompareStrings(PCHAR pString1, PCHAR pString2);
    void ModuleDumperThread();
    void INIT_ProcessCallback(IN HANDLE  hParentId, IN HANDLE  hProcessId, IN BOOLEAN bCreate);
    void ClearBuffer(PCHAR Buffer, unsigned int Length);
    void Timeout(INT64 Timout);
    unsigned int StrLenKernelSafe(PCHAR pString);
    
    typedef PCHAR (*GET_PROCESS_IMAGE_NAME) (PEPROCESS Process); 
    typedef NTSTATUS (*QUERY_INFO_PROCESS)  (HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength); 
    typedef NTSTATUS (*ZWREADVIRTUAL) (HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, ULONG BufferLength, PULONG ReturnLength); 
    
    QUERY_INFO_PROCESS gZwQueryprocess; 
    GET_PROCESS_IMAGE_NAME gGetProcessImageFileName; 
    ZWREADVIRTUAL gZwReadVirtualMemory;
    
    BOOLEAN IsLoggerOn = FALSE;
    BOOLEAN Print = FALSE;
    BOOLEAN IsPayloadCall = FALSE;
    BOOLEAN IsRegisterTarget = FALSE;
    BOOLEAN IsSupplyDumpData = FALSE;
    BOOLEAN IsDumpWhenPossible = FALSE;
    BOOLEAN IsDumpDumped = FALSE;
    
    typedef struct _RTL_USER_PROCESS_PARAMETERS {
      CHAR           Reserved1[16];
      PVOID          Reserved2[10];
      UNICODE_STRING ImagePathName;
      UNICODE_STRING CommandLine;
    } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
    typedef struct _PEB_LDR_DATA {
    ULONG Length;
    BOOLEAN Initialized;
    PVOID SsHandle;
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
    } PEB_LDR_DATA, *PPEB_LDR_DATA;
    typedef struct _LDR_DATA_TABLE_ENTRY {
        LIST_ENTRY     LoadOrder;
        LIST_ENTRY     MemoryOrder;
        LIST_ENTRY     InitializationOrder;
        PVOID          ModuleBaseAddress;
        PVOID          EntryPoint;
        ULONG          ModuleSize;
        UNICODE_STRING FullModuleName;
        UNICODE_STRING ModuleName;
        ULONG          Flags;
        USHORT         LoadCount;
        USHORT         TlsIndex;
        union {
            LIST_ENTRY Hash;
            struct {
                PVOID SectionPointer;
                ULONG CheckSum;
            };
        };
        ULONG   TimeStamp;
    } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
    typedef struct _PEB {
      CHAR                          Reserved1[2];
      CHAR                          BeingDebugged;
      CHAR                          Reserved2[1];
      PVOID							Reserved;
      PVOID                         ImageBaseAddress;
      PPEB_LDR_DATA                 Ldr;
      PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
      CHAR                          Reserved4[104];
      PVOID                         Reserved5[52];
      PVOID                         PostProcessInitRoutine;
      CHAR                          Reserved6[128];
      PVOID                         Reserved7[1];
      ULONG                         SessionId;
    } PEB, *PPEB;
    
    	HANDLE hThreadHandle; 
    	HANDLE hgtPid;
    	
    	ULONG SizeOfDump;
    	ULONG AddressOfDump;
    	
    CHAR Target[100];
    CHAR Buffer1[200];
    PCHAR TargetDump;
    
    NTSTATUS DriverEntry(PDRIVER_OBJECT  pDriverObject, PUNICODE_STRING  pRegistryPath){
        NTSTATUS NtStatus = STATUS_SUCCESS;
        unsigned int uiIndex = 0;
        PDEVICE_OBJECT pDeviceObject = NULL;
        UNICODE_STRING usDriverName, usDosDeviceName, sPsGetProcessImageFileName, routineName, sZwReadVirtualMemory;
    
        DbgPrint("DriverEntry Called \r\n");
    	
    	RtlInitUnicodeString(&sPsGetProcessImageFileName, L"PsGetProcessImageFileName" );
    	RtlInitUnicodeString(&sZwReadVirtualMemory, L"NtReadVirtualMemory");
    	RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess" );
        RtlInitUnicodeString(&usDriverName, L"\\Device\\SCHiMDev");
        RtlInitUnicodeString(&usDosDeviceName, L"\\DosDevices\\SCHiMDev"); 
    
        NtStatus = IoCreateDevice(pDriverObject, 0, &usDriverName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject);
    
        if(NtStatus == STATUS_SUCCESS){
    
            for(uiIndex = 0; uiIndex < IRP_MJ_MAXIMUM_FUNCTION; uiIndex++)
                 pDriverObject->MajorFunction[uiIndex] = UnSupportedFunction;
        
            pDriverObject->MajorFunction[IRP_MJ_CLOSE]             = Close;
            pDriverObject->MajorFunction[IRP_MJ_CREATE]            = Create;
            pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]    = IoControl;
            pDriverObject->MajorFunction[IRP_MJ_READ]              = ReadNeither;
            pDriverObject->MajorFunction[IRP_MJ_WRITE]             = USE_WRITE_FUNCTION;
        
          
            pDriverObject->DriverUnload =  Unload; 
            pDeviceObject->Flags |= IO_TYPE;
            pDeviceObject->Flags &= (~DO_DEVICE_INITIALIZING);
            IoCreateSymbolicLink(&usDosDeviceName, &usDriverName);
        }
    
    	
    	
    	gGetProcessImageFileName = (GET_PROCESS_IMAGE_NAME) MmGetSystemRoutineAddress( &sPsGetProcessImageFileName ); 
        gZwQueryprocess = (QUERY_INFO_PROCESS) MmGetSystemRoutineAddress(&routineName); 
    	gZwReadVirtualMemory = (ZWREADVIRTUAL)MmGetSystemRoutineAddress(&sZwReadVirtualMemory);
        return NtStatus;
    }
    
    /**********************************************************************
     * 
     *  Unload
     *
     *    This is an optional unload function which is called when the
     *    driver is unloaded.
     *
     **********************************************************************/
    VOID Unload(PDRIVER_OBJECT  DriverObject){    
        
        UNICODE_STRING usDosDeviceName;
        
        DbgPrint("Unload Called \r\n");
        
        RtlInitUnicodeString(&usDosDeviceName, L"\\DosDevices\\SCHiMDev");
        IoDeleteSymbolicLink(&usDosDeviceName);
    
    	if( IsLoggerOn == TRUE){
    		PsSetCreateProcessNotifyRoutine(&INIT_ProcessCallback, TRUE);
    	}
    	
        IoDeleteDevice(DriverObject->DeviceObject);
    }
    
    NTSTATUS Create(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
        NTSTATUS NtStatus = STATUS_SUCCESS;
        DbgPrint("Create Called \r\n");
    
        return NtStatus;
    }
    
    /**********************************************************************
     * 
     *  Close
     *
     *    This is called when an instance of this driver is closed (CloseHandle)
     *
     **********************************************************************/
    NTSTATUS Close(PDEVICE_OBJECT DeviceObject, PIRP Irp){
        NTSTATUS NtStatus = STATUS_SUCCESS;
        DbgPrint("Close Called \r\n");
    
        return NtStatus;
    }
    
    /**********************************************************************
     * 
     *  IoControl
     *
     *    This is called when an IOCTL is issued on the device handle (DeviceIoControl)
     *
     **********************************************************************/
    NTSTATUS IoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
        NTSTATUS NtStatus = STATUS_SUCCESS;
        DbgPrint("IoControl Called \r\n");
    
        return NtStatus;
    }
    
    /**********************************************************************
     * 
     *  Read
     *
     *    This is called when a read is issued on the device handle (ReadFile/ReadFileEx)
     *
     **********************************************************************/
    NTSTATUS Read(PDEVICE_OBJECT DeviceObject, PIRP Irp){
        NTSTATUS NtStatus = STATUS_SUCCESS;
        DbgPrint("Read Called \r\n");
    
        return NtStatus;
    }
    
    /**********************************************************************
     * 
     *  WriteNeither
     *
     *    This is called when a write is issued on the device handle (WriteFile/WriteFileEx)
     *
     *    This version uses Neither buffered or direct I/O.  User mode memory is
     *    read directly.
     *
     **********************************************************************/
    NTSTATUS WriteNeither(PDEVICE_OBJECT DeviceObject, PIRP Irp){
        NTSTATUS NtStatus = STATUS_SUCCESS;
        PIO_STACK_LOCATION pIoStackIrp = NULL;
        PCHAR pWriteDataBuffer;
    	PULONG pLongPointer; 
    	unsigned int uii = 0;
    	PCHAR Buffer[5];
    	PCHAR ARG_START_LOG = "PROC_LOG_START";
    	PCHAR ARG_STOP_LOG = "PROC_LOG_STOP";
    	PCHAR ARG_PAYLOAD_INCOMMING = "PAYLOAD_SET";
    	PCHAR ARG_TARGET_INCOMMING = "TARGET_SET";
    	PCHAR ARG_TARGET_DUMP_ADDRESS = "DUMP_DATA_SET";
    	PCHAR ARG_DUMP_WHEN_POSSIBLE = "DUMP_DUMP";
    	PCHAR ARG_RESET = "ERR_RESET";
    
    
        pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);
        
        if(pIoStackIrp){
    
            __try {
                   if(IsSupplyDumpData != TRUE){
    			   ProbeForRead(Irp->UserBuffer, pIoStackIrp->Parameters.Write.Length, TYPE_ALIGNMENT(char));
                    pWriteDataBuffer = Irp->UserBuffer;
    				} else {
    				ProbeForRead(Irp->UserBuffer, pIoStackIrp->Parameters.Write.Length, TYPE_ALIGNMENT(ULONG));
                    pLongPointer = Irp->UserBuffer;
    				}
                    if( pWriteDataBuffer){                             
    
    					 
    					 			if(IsPayloadCall == TRUE){
    										IsPayloadCall = FALSE;
    																					
    									
    									
    								}else if(IsSupplyDumpData == TRUE){
    										IsSupplyDumpData = FALSE;
    								
    												AddressOfDump = pLongPointer[0];
    												SizeOfDump = pLongPointer[1];
    					
    								DbgPrint("Address: 0x%x\nSize: 0x%x\n", AddressOfDump, SizeOfDump);
    			
    								}else if(IsRegisterTarget == TRUE) {
    									IsRegisterTarget = FALSE;
    										
    										for(uii = 0; uii != pIoStackIrp->Parameters.Write.Length; uii++){
    										Target[uii] = pWriteDataBuffer[uii];
    										} 
    				
    								
    								}else if(IsStringTerminated( pWriteDataBuffer, pIoStackIrp->Parameters.Write.Length)){
    	
    								if( CompareStrings(pWriteDataBuffer, ARG_START_LOG) == TRUE){
    	   
    										NtStatus = PsSetCreateProcessNotifyRoutine(&INIT_ProcessCallback, FALSE);
    										IsLoggerOn = TRUE;
    	   							}
    								if( CompareStrings(pWriteDataBuffer, ARG_RESET) == TRUE){
    	   									
    									if( IsLoggerOn == TRUE){
    										PsSetCreateProcessNotifyRoutine(&INIT_ProcessCallback, TRUE);
    									}
    									if( IsDumpDumped == TRUE){
    										ExFreePool(TargetDump);
    									}
    											
    											IsLoggerOn = FALSE;
    											Print = FALSE;
    											IsPayloadCall = FALSE;
    											IsRegisterTarget = FALSE;
    											IsSupplyDumpData = FALSE;
    											IsDumpWhenPossible = FALSE;
    											IsDumpDumped = FALSE;
    											
    											ClearBuffer((PCHAR)&Buffer1[0], sizeof(Buffer1)); 
    											ClearBuffer((PCHAR)&Target[0], sizeof(Target));
    											
    												AddressOfDump = 0;
    												SizeOfDump = 0;		
    												
    										 hThreadHandle = 0; 
    										 hgtPid = 0;
    											
    	   							} 								
    								if( CompareStrings(pWriteDataBuffer, ARG_DUMP_WHEN_POSSIBLE) == TRUE){
    										IsDumpWhenPossible = TRUE;
    
    	   							} 
    								if( CompareStrings(pWriteDataBuffer, ARG_TARGET_DUMP_ADDRESS) == TRUE){
    	   								
    										IsSupplyDumpData = TRUE;
    	   							}
    								if( CompareStrings(pWriteDataBuffer, ARG_STOP_LOG) == TRUE){
    	    
    										PsSetCreateProcessNotifyRoutine(&INIT_ProcessCallback, TRUE);
    										IsLoggerOn = FALSE;										
    	 	   						}
    								if( CompareStrings (pWriteDataBuffer, ARG_TARGET_INCOMMING) == TRUE){
    										IsRegisterTarget = TRUE;
    								}
    								
    								if( CompareStrings(pWriteDataBuffer, ARG_PAYLOAD_INCOMMING) == TRUE){
    	    								IsPayloadCall = TRUE;							
    	 	   						}
    						
    						}	
                    }
    
            } __except( EXCEPTION_EXECUTE_HANDLER ) {
    			DbgPrint("Exception occured in the write function");
                  NtStatus = GetExceptionCode();     
            }
    
        }
    
        return NtStatus;
    }
    
    NTSTATUS ReadNeither(PDEVICE_OBJECT DeviceObject, PIRP Irp){   // for incomming reads
        NTSTATUS NtStatus = STATUS_SUCCESS;
        PIO_STACK_LOCATION pIoStackIrp = NULL;
    	unsigned int FindNextDump = 0;
        PCHAR pWriteDataBuffer;
    	UNICODE_STRING NotEnoughSpace; 
    	RtlInitUnicodeString(&NotEnoughSpace, L"Nes");
       
    	
        /*
         * Each time the IRP is passed down the driver stack a new stack location is added
         * specifying certain parameters for the IRP to the driver.
         */
        pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);
        try{
    	                      ProbeForWrite(Irp->UserBuffer, pIoStackIrp->Parameters.Read.Length, TYPE_ALIGNMENT(char));
                    pWriteDataBuffer = Irp->UserBuffer;
                
                    if(pWriteDataBuffer){     
    				
    						if( Print == TRUE){
    							memcpy((PVOID)pWriteDataBuffer, (PVOID)&Buffer1[0], 200);
    							ClearBuffer((PCHAR)&Buffer1[0], 200);
    							Print = FALSE;
    						}
    						if( IsDumpWhenPossible == TRUE ){
    							if( IsDumpDumped == TRUE ){
    								memcpy((PVOID)pWriteDataBuffer, (PVOID)TargetDump, pIoStackIrp->Parameters.Read.Length);
    								ExFreePool(TargetDump);
    								IsDumpWhenPossible = FALSE;
    								IsDumpDumped = FALSE;
    							}
    						
    						}
    						
    						
    					
    	DbgPrint("Read Called! \r\n");
                    }
            } __except( EXCEPTION_EXECUTE_HANDLER ) {
    			  DbgPrint("Something went wrong inside the read function! Print: %d\r\n",Print );
                  NtStatus = GetExceptionCode();     
            }
    	
    	 return NtStatus;
    	}
    
       
    /**********************************************************************
     * 
     *  UnSupportedFunction
     *
     *    This is called when a major function is issued that isn't supported.
     *
     **********************************************************************/
     
    NTSTATUS UnSupportedFunction(PDEVICE_OBJECT DeviceObject, PIRP Irp){
        NTSTATUS NtStatus = STATUS_NOT_SUPPORTED;
        DbgPrint("UnSupportedFunction Called \r\n");
    
        return NtStatus;
    }
    
    /**********************************************************************
     * 
     *  IsStringTerminated
     *
     *    Simple function to determine a string is NULL terminated.
     *
     **** We could validate also the characters in the string are printable! ***
     *
     **********************************************************************/
     
     BOOLEAN CompareStrings(PCHAR pString1, PCHAR pString2){
     
     unsigned int uiIndex = 0;
     unsigned int uiLength1 = 0;
     unsigned int uiLength2 = 0;
     
     uiLength1 = StrLenKernelSafe(pString1);
     uiLength2 = StrLenKernelSafe(pString2);
      
      if(uiLength1 != uiLength2){
      DbgPrint("Invailid length! %d != %d\n", uiLength1, uiLength2);
        return FALSE;
      }
     
     while( uiLength1 > uiIndex ){
     		if(pString1[uiIndex] != pString2[uiIndex]){
    		  DbgPrint("Strings don't match!\n");
    			return FALSE;
    		} else {
    		 uiIndex++;
    		}
    }
      return TRUE;
      }
      
      unsigned int StrLenKernelSafe(PCHAR pString){
        unsigned int uiIndex = 0;
      
      __try{
    			while(pString != NULL && pString[uiIndex] != '\0'){
      			uiIndex++;
    		   
    		  }
    	
    		} __except( EXCEPTION_EXECUTE_HANDLER ) {
    		    DbgPrint("StrLenKernelSafe exception\n");
    		}
      return uiIndex;
      
      }
     
    BOOLEAN IsStringTerminated(PCHAR pString, unsigned int uiLength){
    
        BOOLEAN bStringIsTerminated = FALSE;
        unsigned int uiIndex = 0;
    
        while(uiIndex < uiLength && bStringIsTerminated == FALSE)
        {
            if(pString[uiIndex] == '\0')
            {
                bStringIsTerminated = TRUE;
            }
            else
            {
               uiIndex++;
            }
        }
    
        return bStringIsTerminated;
    }
    
    VOID INIT_ProcessCallback( IN HANDLE  hParentId, IN HANDLE hProcessId, IN BOOLEAN bCreate) {
    
    PEPROCESS pParentEP = NULL;
    PEPROCESS pChildEP = NULL;
    NTSTATUS Status = STATUS_SUCCESS;
    ACCESS_MASK DesiredAccess = PROCESS_ALL_ACCESS;
    OBJECT_ATTRIBUTES ObjectAttributes;
    
    InitializeObjectAttributes (&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
    
    
    
    
    /********************************
    PsLookupProcessByProcessId(
      __in   HANDLE ProcessId,
      __out  PEPROCESS *Process
     *******************************/
     __try{
    PsLookupProcessByProcessId(hParentId, &pParentEP);
    PsLookupProcessByProcessId(hProcessId, &pChildEP);
      } __except( EXCEPTION_EXECUTE_HANDLER ) {
      
      ObDereferenceObject((PVOID)pParentEP);
      ObDereferenceObject((PVOID)pChildEP);
                  DbgPrint("Something went very wrong!\n");    
    			  return;
            }
    
     if( gGetProcessImageFileName != NULL ){ 
     PCHAR pParentImageName = gGetProcessImageFileName(pParentEP);
     PCHAR pChildImageName = gGetProcessImageFileName(pChildEP);
    		__try{	
    		
    		if(Target != NULL){
    	       if( CompareStrings((PCHAR)&Target[0], pChildImageName) == TRUE){
    				
    			if(bCreate == 1){
    					hgtPid = hProcessId;
    					
    				Status = PsCreateSystemThread(&hThreadHandle, DesiredAccess, &ObjectAttributes, NULL, NULL, (PKSTART_ROUTINE)&ModuleDumperThread, NULL);
    
    						if(Status != STATUS_SUCCESS){
    								DbgPrint("PsCreateSystemThread failed\n");
    								DbgPrint("NtStatus: 0x%x\n", Status);
    						}			
    			}
    			}
    		
    		}else if( pParentImageName != NULL &&  pChildImageName != NULL ) { 
    			
    				if(bCreate == 1){
    DbgPrint("%s With pid[%x] created process %s with pid[%x]", pParentImageName, hParentId, pChildImageName, hProcessId);
    	            RtlStringCbPrintfA((PCHAR)&Buffer1[0], sizeof("%s With pid[%x] created process %s with pid[%x]\n")+StrLenKernelSafe(pChildImageName)+StrLenKernelSafe(pParentImageName), "%s With pid[%x] created process %s with pid[%x]\n", pParentImageName, hParentId, pChildImageName, hProcessId);
    				Print = TRUE;
    				} else {
    DbgPrint("%s With pid[%x] terminated process %s with pid[%x]", pParentImageName, hParentId, pChildImageName, hProcessId);
    				RtlStringCbPrintfA((PCHAR)&Buffer1[0], sizeof("%s With pid[%x] terminated process %s with pid[%x]\n")+StrLenKernelSafe(pChildImageName)+StrLenKernelSafe(pParentImageName), "%s With pid[%x] terminated process %s with pid[%x]\n", pParentImageName, hParentId, pChildImageName, hProcessId);
    				Print = TRUE;
    	
    			
    				}
    			} 
    		}__except( EXCEPTION_EXECUTE_HANDLER ) {
      
      ObDereferenceObject((PVOID)pParentEP);
      ObDereferenceObject((PVOID)pChildEP);
                  DbgPrint("Exception at formatstring\n");    
    			  return;
            }
      }
      
       
      
      ObDereferenceObject((PVOID)pParentEP);
      ObDereferenceObject((PVOID)pChildEP);
      
    return;
    }
    
    void ClearBuffer(PCHAR Buffer, unsigned int Length){
    
    unsigned int uii = 0;
    __try{
    	  for(uii; uii != Length; uii++){
    		 Buffer[uii] = '\0';
    	  }
    	}__except( EXCEPTION_EXECUTE_HANDLER ) {
                   DbgPrint("Exception at ClearBuffer\n");    
    			  return;
            }
    
    return; 
    }
    
    void Timeout(INT64 Timout){
    INT64 MyTimeout = 0;
    for( MyTimeout = 0; MyTimeout != Timout; MyTimeout++){}
    return;
    }
    
    void Dump(PEPROCESS ep){
    
    TargetDump = (PCHAR) ExAllocatePoolWithTag(NonPagedPool,SizeOfDump,"brak");
    
    	if(TargetDump == NULL){
    		IsDumpDumped = FALSE;
    		return;
    	}
    
    KeAttachProcess(ep);
    __try{
    memcpy((PVOID)TargetDump, (PVOID)AddressOfDump, SizeOfDump);
    }__except( EXCEPTION_EXECUTE_HANDLER ) {
                    DbgPrint("Exception while copying the dump\n");
    				IsDumpDumped = FALSE;
            }
    		IsDumpDumped = TRUE;
    KeDetachProcess();
    return;
    }
    
    
    void ModuleDumperThread(){
    
    NTSTATUS Status = STATUS_SUCCESS;
    HANDLE hProcessHandle = NULL;
    PLIST_ENTRY Next;
    PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
    CLIENT_ID clientID; 
    ACCESS_MASK DesiredAccess = PROCESS_ALL_ACCESS;
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE hProcessId = hgtPid;
    PROCESS_BASIC_INFORMATION BasicInfoReal;
    ULONG SizeReturned;
    PEPROCESS ep = NULL;
    unsigned int Index = 0;
    InitializeObjectAttributes (&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
    
       clientID.UniqueProcess = hProcessId;  
       clientID.UniqueThread = NULL; 
    
     
    __try{
    
    	Status = ZwOpenProcess(&hProcessHandle, DesiredAccess, &ObjectAttributes, &clientID);
    	
    				if(Status != STATUS_SUCCESS){
    						DbgPrint("Failed to open process\n");
    						DbgPrint("NtStatus: 0x%x", Status);
    						return;
    				}
    		
    			Status = gZwQueryprocess(hProcessHandle, ProcessBasicInformation, (PVOID)&BasicInfoReal, sizeof(PROCESS_BASIC_INFORMATION), &SizeReturned);
    			
    					if(Status != STATUS_SUCCESS){
    								DbgPrint("gZwQueryprocess failed\n"); 
    								DbgPrint("Size returned: 0x%x\nNtStatus: 0x%x\n", SizeReturned, Status);
    								ZwClose(hProcessHandle);
    								return;
    					}
    
    					Status = PsLookupProcessByProcessId(hProcessId, &ep);
    		
    					if(Status != STATUS_SUCCESS){
    								DbgPrint("PsLookupProcessByProcessId failed\n");
    								DbgPrint("NtStatus: 0x%x\n", Status);
    								ZwClose(hProcessHandle);
    								return;
    					}
    					
    	while(IsDumpWhenPossible!=TRUE){				
    Timeout((INT64)0x3FFFFFF);    // wait until the process is fully loaded
    }
    if(IsDumpWhenPossible == TRUE){
    Dump(ep);
    }
    
    			/*
    KeAttachProcess(ep);
    __try{
       DbgPrint("ImageBaseAddress of notepad.exe: 0x%x\n", BasicInfoReal.PebBaseAddress->ImageBaseAddress);
    
    	Next = BasicInfoReal.PebBaseAddress->Ldr->InLoadOrderModuleList.Blink;
    	LdrDataTableEntry = CONTAINING_RECORD( Next, LDR_DATA_TABLE_ENTRY, LoadOrder);
        
       
        for(Index = 0; Index != 17; Index++){
    	   DbgPrint("%d: ImageBase of %wZ in Notepad.exe: 0x%x\n", Index, &(LdrDataTableEntry->ModuleName), LdrDataTableEntry->ModuleBaseAddress);
    	   Next = Next->Blink;
    	   LdrDataTableEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, LoadOrder);
        }
    
       
       }__except( EXCEPTION_EXECUTE_HANDLER ) {
                    DbgPrint("Exception while accessing the LDR\n");
            }
    	
    KeDetachProcess();
    */
    	}__except( EXCEPTION_EXECUTE_HANDLER ) {
                    DbgPrint("Exception in ModuleDumper\n");
            }
    		ObDereferenceObject((PVOID)ep);
    		ZwClose(hProcessHandle);	
    		
    
    return;
    }
    SOURCES

    Code:
    TARGETNAME = DriverTest
    TARGETPATH = obj
    TARGETTYPE = DRIVER
    LIBS = ntoskrnl.lib
    SOURCES    = DriverMain.c
    MAKEFILE

    Code:
    !INCLUDE $(NTMAKEENV)\makefile.def
    Example usage of the driver

    main.cpp

    Code:
    #include <windows.h>
    #include <winnt.h>
    #include <string.h>
    #include <stdio.h>
    #include <iostream>
    #include "disasm.h"
    
    #define EXTRACT_DISASM			0x00010
    
        HANDLE hFile;
    
    	char LoggerStart[sizeof("PROC_LOG_START")] = "PROC_LOG_START";
    	char LoggerStop[sizeof("PROC_LOG_STOP")] = "PROC_LOG_STOP";
    	char PayloadStart[sizeof("PAYLOAD_SET")] = "PAYLOAD_SET";
    	char Target[sizeof("TARGET_SET")] = "TARGET_SET";
    	char DumpData[sizeof("DUMP_DATA_SET")] = "DUMP_DATA_SET";
    	char DumpWhenPossible[sizeof("DUMP_DUMP")] = "DUMP_DUMP";
    	char ResetFlags[sizeof("ERR_RESET")] = "ERR_RESET";
    	char RealTarget[sizeof("notepad.exe")] = "Engine.exe";
    
    	DWORD NumberOfBytesRead = (DWORD) NULL;
        DWORD Address = NULL;
    	DWORD DSize = NULL;
    	void LoggerThread();
    
    
    	ULONG Data[] = {(ULONG)0x485F60, (ULONG)0x200 };
    	char buffer[0x205] = ""; 
    
    void Diasm(char* pLoadAddress, unsigned char* pStart, unsigned char* pEnd);
    
    int StartDriver(){
    
    //System("bcdedit /set nointegritychecks ON) windows vista and up must reboot to take effect
    
    SC_HANDLE MyDriverInstallation = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
    
    if( MyDriverInstallation == NULL){
    	printf("An error has occured while opening the SCManager: 0x%x\n", GetLastError());
    	return -1;
    }
    
    printf("OpenSCManager last error code: 0x%x\n", GetLastError());
    
    SC_HANDLE MyDriverHandle = CreateService(MyDriverInstallation, "SCHiMDriver", "SCHiMDriver", SC_MANAGER_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, "C:\\Driver\\De.sys", NULL, NULL, NULL, NULL, NULL);
    
    if( MyDriverHandle == NULL){
    	printf("An error occured while installing the driver: 0x%x\n", GetLastError());
    		if( GetLastError() == 0x431 ){
    			printf("Trying to open the existing service\n");
    			  MyDriverHandle = OpenService(MyDriverInstallation, "SCHiMDriver", SERVICE_ALL_ACCESS);
    				if( MyDriverHandle == 0 ){
    					 printf("An error occured while opening the driver: 0x%x\n", GetLastError());	
    					 return -4;
    				}
    
    
    		} else {
    	return -2;
    		}
    }
    
    DWORD ret = StartService(MyDriverHandle,0,NULL);
    
    if( ret == NULL){
        printf("An error has occured while starting the service: 0x%x\n", GetLastError());
        return -3;
    }
    
    printf("Installation succesfull\nDriver started\n");
    
    return 0;
    //System("bcdedit /set nointegritychecks OFF) windows vista and up
    }
    
    int main(void){
    
    
    
    int Succes = StartDriver();
    if( Succes != 0){
    	printf("Installation failed, aborting!\n");
    	std::cin.get();
    	return -1;
    }
    
    
    
    
        DWORD dwReturn;
    
        hFile = CreateFile("\\\\.\\SCHiMDev", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    
    
    	if(hFile){
    		
    		WriteFile(hFile, Target, sizeof(Target), &dwReturn, NULL);
    		WriteFile(hFile, RealTarget, sizeof(RealTarget), &dwReturn, NULL);
    		WriteFile(hFile, DumpData, sizeof(DumpData), &dwReturn, NULL);
    		WriteFile(hFile, (void*)&Data[0], sizeof(Data), &dwReturn, NULL);
    		WriteFile(hFile, LoggerStart, sizeof(LoggerStart), &dwReturn, NULL);
    		std::cin.get();
    		WriteFile(hFile, DumpWhenPossible, sizeof(DumpWhenPossible), &dwReturn, NULL);
    	    std::cin.get();
    		ReadFile(hFile, (PVOID)&buffer, sizeof(buffer), &dwReturn, NULL);
            WriteFile(hFile, ResetFlags, sizeof(ResetFlags), &dwReturn, NULL);
    	}
    
    	Diasm((char*)Data[0], (unsigned char*)&buffer[0], (unsigned char*)&buffer[0x200]);
    
    	printf("\nWritten\n");
    	std::cin.get();
    return 0;
    }
    
    
    void Diasm(char* pLoadAddress, unsigned char* pStart, unsigned char* pEnd ){
    	
    	Disassemble((char*)pLoadAddress, (DefaultOperationSizeAttrib)32,pStart,pEnd);
    return;
    }
    diasm.cpp
    Credits to: Isaac Sigasa

    Code:
    /*
     *
     * File Name: 
     *
     *		disasm.c
     *
     * Summary:
     *
     *		This file was created to be included within a 'disassembler' project for PE 
     *		image files running on x86 and x86-compatible processors.
     *
     *		File contains functions for disassembling IA32 binary instructions
     *
     * 
     *
     * Copyright (C) 2004, Isaac Sigasa [isigasa@ananzi.co.za]
     * All Rights Reserved
     *
     *
     *  
     * Redistribution and use in source and binary forms, with or without modification, 
     * are permitted provided that the following conditions are met:
     *
     *		-	Redistributions of source code must retain the above copyright notice, 
     *			this list of conditions and the following disclaimer. 
     *
     *		-	Redistributions in binary form must reproduce the above copyright notice, 
     *			this list of conditions and the following disclaimer in the documentation 
     *			and/or other materials provided with the distribution. 
     *
     *
     * 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.
     *
     *
     */
    
    #include <stdio.h>
    #include <string.h>
    #include <windows.h>
    
    #include "Disasm.h"
    
    
    extern InstructionTemplate _11OpcodeExtensions[0x10][0x8][0x3];
    extern InstructionTemplate _1ByteOpcode[0x10][0x10];
    extern InstructionTemplate _2ByteOpcode[0x10][0x10][0x5];
    extern InstructionTemplate MemOpcodeExtensions[0x10][0x8][0x3];
    extern InstructionTemplate FPUModRMReg[0x8][0x8];
    
    extern InstructionTemplate FPUModRMFullD8[0x4][0x10];
    extern InstructionTemplate FPUModRMFullD9[0x4][0x10];
    extern InstructionTemplate FPUModRMFullDA[0x4][0x10];
    extern InstructionTemplate FPUModRMFullDB[0x4][0x10];
    extern InstructionTemplate FPUModRMFullDC[0x4][0x10];
    extern InstructionTemplate FPUModRMFullDD[0x4][0x10];
    extern InstructionTemplate FPUModRMFullDE[0x4][0x10];
    extern InstructionTemplate FPUModRMFullDF[0x4][0x10];
    
    
    int IsIA32InstructionPrefix(unsigned char c)
    {
    	switch(c)
    	{
    		case 0xF0:
    		case 0xF2:
    		case 0xF3:
    		case 0x2E:
    		case 0x36:
    		case 0x3E:
    		case 0x26:
    		case 0x64:
    		case 0x65:
    		case 0x66:
    		case 0x67:
    			return 1;
    	};
    	return 0;
    };
    
    
    void FetchOperandDescriptors(const InstructionTemplate *pInstructionTemplate, IA32InstructionDecode *pIA32Decode)
    {
    	int iCol = 0, iTemp = 0;
    
    	if(pInstructionTemplate->strOperandsDescr == N)
    		return;
    	if(!strlen(pIA32Decode->SIA32InstructionDescription.strOperandA))
    	{
    		while((pInstructionTemplate->strOperandsDescr[iCol] != 0) && (pInstructionTemplate->strOperandsDescr[iCol] != ','))
    		{		
    			pIA32Decode->SIA32InstructionDescription.strOperandA[iTemp++] = pInstructionTemplate->strOperandsDescr[iCol];
    			iCol++;
    		}
    	}
    	else
    		iCol = 0;
    	iTemp = 0;
    	if(pInstructionTemplate->strOperandsDescr[iCol] == ',')
    		iCol++;
    	if(!strlen(pIA32Decode->SIA32InstructionDescription.strOperandB))
    	{
    		while((pInstructionTemplate->strOperandsDescr[iCol] != 0) && (pInstructionTemplate->strOperandsDescr[iCol] != ','))
    		{		
    			pIA32Decode->SIA32InstructionDescription.strOperandB[iTemp++] = pInstructionTemplate->strOperandsDescr[iCol];
    			iCol++;
    		};
    	}
    	else
    		iCol = 0;
    	iTemp = 0;
    	if(pInstructionTemplate->strOperandsDescr[iCol] == ',')
    		iCol++;
    	if(!strlen(pIA32Decode->SIA32InstructionDescription.strOperandC))
    		while((pInstructionTemplate->strOperandsDescr[iCol] != 0) && (pInstructionTemplate->strOperandsDescr[iCol] != ','))
    		{			
    			pIA32Decode->SIA32InstructionDescription.strOperandC[iTemp++] = pInstructionTemplate->strOperandsDescr[iCol];
    			iCol++;
    		};
    };
    
    
    unsigned char GetSegmentOverride(IA32InstructionDecode *pIA32Decode)
    {
    	int i;
    	char strSegOverrides[] = {0x2E,0x36,0x3E,0x26,0x64,0x65,0};
    
    	for(i = 0; i < pIA32Decode->SIA32InstructionHelper.cbRawPrefixes; i++)
    		if(strchr(strSegOverrides,pIA32Decode->SIA32RawInstruction.caRawPrefixes[i]))
    			return pIA32Decode->SIA32RawInstruction.caRawPrefixes[i];
    	return 0;
    };
    
    
    void GetSegmentOverrideStr(unsigned char sreg, char*strBuffer, int cbBuffer)
    {
    	ZeroMemory(strBuffer,cbBuffer);
    	switch(sreg)
    	{
    		case 0x2E:
    			strncpy(strBuffer,"cs",cbBuffer);
    			break;
    		case 0x36:
    			strncpy(strBuffer,"ss",cbBuffer);
    			break;
    		case 0x3E:
    			strncpy(strBuffer,"ds",cbBuffer);
    			break;
    		case 0x26:
    			strncpy(strBuffer,"es",cbBuffer);
    			break;
    		case 0x64:
    			strncpy(strBuffer,"fs",cbBuffer);
    			break;
    		case 0x65:
    			strncpy(strBuffer,"gs",cbBuffer);
    			break;
    	};
    };
    
    
    int FetchPrefixes(const unsigned char *pStart, IA32InstructionDecode *pIA32Decode)
    {
    	int i;
    
    	ZeroMemory(pIA32Decode->SIA32InstructionDescription.strPrefix,sizeof(pIA32Decode->SIA32InstructionDescription.strPrefix));
    	ZeroMemory(pIA32Decode->SIA32RawInstruction.caRawPrefixes,sizeof(pIA32Decode->SIA32RawInstruction.caRawPrefixes));
    	pIA32Decode->SIA32InstructionHelper.cbRawPrefixes = 0;
    	
    	strcat(pIA32Decode->SIA32InstructionDescription.strPrefix,"");
    
    	// Instruction prefixes can only be up to four, so let's probe for at most four times 	
    	for(i = 0; i < 4; i++)
    	{
    		switch(pStart[i])
    		{
    			case 0xF0:
    				if(strlen(pIA32Decode->SIA32InstructionDescription.strPrefix))
    					strcat(pIA32Decode->SIA32InstructionDescription.strPrefix," lock");
    				else
    					strcat(pIA32Decode->SIA32InstructionDescription.strPrefix,"lock");
    				break;
    			case 0xF2:
    				if(strlen(pIA32Decode->SIA32InstructionDescription.strPrefix))
    					strcat(pIA32Decode->SIA32InstructionDescription.strPrefix," repne");
    				else
    					strcat(pIA32Decode->SIA32InstructionDescription.strPrefix,"repne");
    				break;
    			case 0xF3:
    				if(strlen(pIA32Decode->SIA32InstructionDescription.strPrefix))
    					strcat(pIA32Decode->SIA32InstructionDescription.strPrefix," rep");
    				else
    					strcat(pIA32Decode->SIA32InstructionDescription.strPrefix,"rep");
    				break;
    			case 0x2E:
    			case 0x36:
    			case 0x3E:
    			case 0x26:
    			case 0x64:
    			case 0x65:
    			case 0x66:
    			case 0x67:				
    				break;
    			default:
    				return i;
    		};
    		pIA32Decode->SIA32RawInstruction.caRawPrefixes[i] = pStart[i];
    		pIA32Decode->SIA32InstructionHelper.cbRawPrefixes++;			
    	};
    	return i;
    };
    
    
    int IA32InstructionPrefixExists(unsigned char cPrefix, IA32InstructionDecode *pIA32Decode)
    {
    	int i;
    
    	for(i = 0; i < pIA32Decode->SIA32InstructionHelper.cbRawPrefixes; i++)
    		if(pIA32Decode->SIA32RawInstruction.caRawPrefixes[i] == cPrefix)
    			return 1;
    	return 0;
    };
    
    
    int FetchFPUInstruction(IA32InstructionDecode *pIA32Decode)
    {
    	unsigned char ModRM = pIA32Decode->SIA32RawInstruction.ModRM;
    	int iRow;
    	int iCol;
    	InstructionTemplate *pInstructionTemplate = NULL;
    
    	if((ModRM >= 0) && (ModRM <= 0xBF))
    	{
    		iRow = pIA32Decode->SIA32RawInstruction.URawOpcode.cByteRawOpcode - 0xD8;
    		iCol = (ModRM & 0x38) >> 3;
    
    		pInstructionTemplate = &FPUModRMReg[iRow][iCol];
    		if(pInstructionTemplate->strOpcode == N)
    			return 1;
    		strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,pInstructionTemplate->strOpcode);
    		FetchOperandDescriptors(pInstructionTemplate,pIA32Decode);
    		return 1;
    	};
    	iRow = (ModRM & 0xF0) >> 4;
    	iRow -= 0x0B + 1;
    	iCol = ModRM & 0x0F;
    
    	switch(pIA32Decode->SIA32RawInstruction.URawOpcode.cByteRawOpcode)
    	{
    	case 0xD8:
    		pInstructionTemplate = &FPUModRMFullD8[iRow][iCol];
    		break;
    	case 0xD9:
    		pInstructionTemplate = &FPUModRMFullD9[iRow][iCol];
    		break;
    	case 0xDA:
    		pInstructionTemplate = &FPUModRMFullDA[iRow][iCol];
    		break;
    	case 0xDB:
    		pInstructionTemplate = &FPUModRMFullDB[iRow][iCol];
    		break;
    	case 0xDC:
    		pInstructionTemplate = &FPUModRMFullDC[iRow][iCol];
    		break;
    	case 0xDD:
    		pInstructionTemplate = &FPUModRMFullDD[iRow][iCol];
    		break;
    	case 0xDE:
    		pInstructionTemplate = &FPUModRMFullDE[iRow][iCol];
    		break;
    	case 0xDF:
    		pInstructionTemplate = &FPUModRMFullDF[iRow][iCol];
    		break;
    	};
    
    	if(((ModRM & 0xF0) >> 4) < 0x0B)
    		return 1;
    	iRow = (ModRM & 0xF0) >> 4;
    	iRow -= 0x0B + 1;
    	iCol = ModRM & 0x0F;
    	if(pInstructionTemplate->strOpcode == N)
    			return 1;
    	
    	strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,pInstructionTemplate->strOpcode);
    	FetchOperandDescriptors(pInstructionTemplate,pIA32Decode);	
    
    	return 1;
    };
    
    
    int FetchInstructionFrom1ByteOpcodeTable(const unsigned char *pStart,IA32InstructionDecode *pIA32Decode)
    {
    	unsigned int iRow, iCol;
    	InstructionTemplate *pInstructionTemplate;
    	unsigned char ucTemp;
    	unsigned char ModRM;
    	char *pchr1;
    	char *pchr2;
    	char strTemp[64];
    
    	ucTemp = pIA32Decode->SIA32RawInstruction.URawOpcode.cByteRawOpcode = pStart[0];
    	pIA32Decode->SIA32InstructionHelper.cbRawOpcode = 1;
    
    	/* FPU encodings are in 1 byte opcode table and are running from 0xD8 to 0xDF
    	 * Let's check if we have an FP instruction and deal with it
    	 */
    	if((ucTemp >= 0xD8) && (ucTemp <= 0xDF))
    	{
    		/* if it's an FP instruction - we have an ModRM byte */
    		ModRM = pIA32Decode->SIA32RawInstruction.ModRM = pStart[1];
    		pIA32Decode->SIA32InstructionHelper.boolModRMExists = 1;
    		FetchFPUInstruction(pIA32Decode);
    		return 1;
    	}
    	iRow = (unsigned int)(pStart[0] >> 4);
    	iCol = (unsigned int)(pStart[0] & 0x0F);
    	pInstructionTemplate = &_1ByteOpcode[iRow][iCol];	
    	if(pInstructionTemplate->strOpcode == N)
    		return 1;		
    	if(!strnicmp(pInstructionTemplate->strOpcode,"__G",strlen("__G")))
    	{
    		pIA32Decode->SIA32RawInstruction.ModRM = pStart[1];
    		pIA32Decode->SIA32InstructionHelper.boolModRMExists = 1;
    		pchr1 = pInstructionTemplate->strOpcode + strlen("__G");
    		ucTemp = (unsigned char)strtoul(pchr1,&pchr2,10);
    		if((ucTemp == 0) || (*pchr2 != 0))
    			return 0;
    
    		if((pIA32Decode->SIA32RawInstruction.ModRM & 0xC0) == 0xC0)
    			FetchInstructionFromOpcodeExtensionsTable(ucTemp,pStart,_11OpcodeExtensions,pIA32Decode);
    		else
    			FetchInstructionFromOpcodeExtensionsTable(ucTemp,pStart,MemOpcodeExtensions,pIA32Decode);
    	}
    	else
    		strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,pInstructionTemplate->strOpcode);
    	FetchOperandDescriptors(pInstructionTemplate,pIA32Decode);
    	if(strchr(pIA32Decode->SIA32InstructionDescription.strOperandA,'/'))
    		if(!strcmp(pIA32Decode->SIA32InstructionDescription.strOpcode,"test"))
    		{
    			/*
    			 * layout of 0xF6 'test' instruction is violating the intergrity provided
    			 * by the layout of opcode tables,
    			 * so let's treat the 0xF6 opcode separately.
    			 * we basically need to swap the operands
    			 *
    			 */
    			strcpy(strTemp,pIA32Decode->SIA32InstructionDescription.strOperandA);
    			strcpy(pIA32Decode->SIA32InstructionDescription.strOperandA,pIA32Decode->SIA32InstructionDescription.strOperandB);
    			strcpy(pIA32Decode->SIA32InstructionDescription.strOperandB,strTemp);
    		}			
    
    	if(strchr(pIA32Decode->SIA32InstructionDescription.strOperandA,'/'))
    	{
    		pchr1 = pIA32Decode->SIA32InstructionDescription.strOperandB;
    		while((*pchr1) && isupper(*pchr1))
    			pchr1++;
    		if(GetOperandTypeSize(pchr1) == 1)
    		{
    			pchr1 = strchr(pIA32Decode->SIA32InstructionDescription.strOperandA,'/');
    			if(pchr1)
    				*pchr1 = 0;
    		}
    		else
    		{
    			strcpy(strTemp,strchr(pIA32Decode->SIA32InstructionDescription.strOperandA,'/') + 1);
    			strcpy(pIA32Decode->SIA32InstructionDescription.strOperandA,strTemp);
    		}
    	}
    	if(strchr(pIA32Decode->SIA32InstructionDescription.strOperandB,'/'))
    	{
    		pchr1 = pIA32Decode->SIA32InstructionDescription.strOperandA;
    		while((*pchr1) && isupper(*pchr1))
    			pchr1++;
    		if(GetOperandTypeSize(pchr1) == 1)
    		{
    			pchr1 = strchr(pIA32Decode->SIA32InstructionDescription.strOperandB,'/');
    			if(pchr1)
    				*pchr1 = 0;
    		}
    		else
    		{
    			strcpy(strTemp,strchr(pIA32Decode->SIA32InstructionDescription.strOperandB,'/') + 1);
    			strcpy(pIA32Decode->SIA32InstructionDescription.strOperandB,strTemp);
    		}
    	}
    	return 1;
    };
    
    
    int FetchInstructionFrom2ByteOpcodeTable(const unsigned char *pStart,IA32InstructionDecode *pIA32Decode)
    {
    	int iRow, iCol, i;
    	InstructionTemplate *pInstructionTemplate;
    	char *pchr1;
    	char *pchr2;
    	unsigned char ModRM;
    	unsigned char ucPrefix;
    	unsigned char ucTemp;
    
    	CopyMemory(pIA32Decode->SIA32RawInstruction.URawOpcode.ca2ByteRawOpcode,pStart,2);
    	pIA32Decode->SIA32InstructionHelper.cbRawOpcode = 2;
    	iRow = pStart[1] >> 4;
    	iCol = pStart[1] & 0x0F;
    
    	if(_2ByteOpcode[iRow][iCol][0].strOpcode == N)
    		return 1;
    
    	for(i = 0; i < 5; i++)
    	{
    		pInstructionTemplate = &_2ByteOpcode[iRow][iCol][i];
    		if(pInstructionTemplate->strOpcode == N)
    			return 1;
    		if(!strnicmp(pInstructionTemplate->strOpcode,"__G",strlen("__G")))
    		{
    			ModRM = pStart[pIA32Decode->SIA32InstructionHelper.cbRawPrefixes + 2];
    			pIA32Decode->SIA32RawInstruction.ModRM = ModRM;
    			pIA32Decode->SIA32InstructionHelper.boolModRMExists = 1;
    			pchr1 = pInstructionTemplate->strOpcode + strlen("__G");
    			ucTemp = (unsigned char)strtoul(pchr1,&pchr2,10);
    			if((ucTemp == 0) || (*pchr2 != 0))
    				return 0;
    			if((ModRM & 0xC0) == 0xC0)
    				FetchInstructionFromOpcodeExtensionsTable(ucTemp,pStart,_11OpcodeExtensions,pIA32Decode);
    			else
    				FetchInstructionFromOpcodeExtensionsTable(ucTemp,pStart,MemOpcodeExtensions,pIA32Decode);
    			FetchOperandDescriptors(pInstructionTemplate,pIA32Decode);
    			return 1;
    		};
    		if(strchr(pInstructionTemplate->strOpcode,'('))
    		{
    			pchr1 = strchr(pInstructionTemplate->strOpcode,'(') + 1;
    			ucPrefix = (unsigned char)strtoul(pchr1,&pchr2,0x10);
    			if((*pchr2 != ')') || (ucPrefix == 0))
    				return 0;
    			if(!IA32InstructionPrefixExists(ucPrefix,pIA32Decode))
    				return 1;
    			strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,pInstructionTemplate->strOpcode);
    			pchr1 = strchr(pIA32Decode->SIA32InstructionDescription.strOpcode,'(');
    			*pchr1 = 0;
    			FetchOperandDescriptors(pInstructionTemplate,pIA32Decode);
    			return 1;
    		};
    		if(strstr(pInstructionTemplate->strOpcode,"[M]")||strstr(pInstructionTemplate->strOpcode,"[R]"))
    		{
    			pIA32Decode->SIA32InstructionHelper.boolModRMExists = 1;
    			ModRM = pStart[pIA32Decode->SIA32InstructionHelper.cbRawPrefixes + 2];
    			pIA32Decode->SIA32RawInstruction.ModRM = ModRM;
    			if(strstr(pInstructionTemplate->strOpcode,"[R]"))
    				if((ModRM & 0xC0) != 0xC0)
    					return 1;
    			if(strstr(pInstructionTemplate->strOpcode,"[M]"))
    				if((ModRM & 0xC0) == 0xC0)
    					return 1;
    			strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,pInstructionTemplate->strOpcode);
    			pchr1 = strchr(pIA32Decode->SIA32InstructionDescription.strOpcode,'[');
    			*pchr1 = 0;
    			FetchOperandDescriptors(pInstructionTemplate,pIA32Decode);
    			return 1;
    		};
    		strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,pInstructionTemplate->strOpcode);
    		FetchOperandDescriptors(pInstructionTemplate,pIA32Decode);
    	};
    	return 1;
    };
    
    
    int GetInstructionLength(IA32InstructionDecode *pIA32Decode)
    {
    	return	pIA32Decode->SIA32InstructionHelper.boolModRMExists + 
    			pIA32Decode->SIA32InstructionHelper.boolSIBExists +
    			pIA32Decode->SIA32InstructionHelper.cbRawDisplacement +
    			pIA32Decode->SIA32InstructionHelper.cbRawImmediate + 
    			pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    			pIA32Decode->SIA32InstructionHelper.cbRawPrefixes;
    };
    
    
    int FetchInstructionFromOpcodeExtensionsTable(unsigned const char ucEntry,const unsigned char* pStart,InstructionTemplate OpcodeExtensions[0x10][0x8][0x3],IA32InstructionDecode *pIA32Decode)
    {
    	unsigned char ModRM;
    	int i, iCol;
    	const int iRow = ucEntry - 1;
    	InstructionTemplate *pInstructionTemplate;
    	char *pchr1;
    	char *pchr2;
    	unsigned char ucPrefix;
    	unsigned char ucTemp;
    
    	/* In case we forgot to do some crucial steps somewhere - let's revisit the decode */
    	if(!pIA32Decode->SIA32InstructionHelper.boolModRMExists)
    	{
    		pIA32Decode->SIA32InstructionHelper.boolModRMExists = 1;
    		if(pStart[pIA32Decode->SIA32InstructionHelper.cbRawPrefixes] == 0x0F)
    			pIA32Decode->SIA32RawInstruction.ModRM = pStart[pIA32Decode->SIA32InstructionHelper.cbRawPrefixes + 2];
    		else
    			pIA32Decode->SIA32RawInstruction.ModRM = pStart[pIA32Decode->SIA32InstructionHelper.cbRawPrefixes + 1];
    	};
    	ModRM = pIA32Decode->SIA32RawInstruction.ModRM;
    	iCol = (ModRM & 0x38) >> 3;
    
    	pInstructionTemplate = &OpcodeExtensions[iRow][iCol][0];
    	if(pInstructionTemplate->strOpcode == N)
    		return 1;
    	
    	for(i = 0; i < 3; i++)
    	{
    		pInstructionTemplate = &OpcodeExtensions[iRow][iCol][i];
    		if(pInstructionTemplate->strOpcode == N)
    			return 1;
    		if(strchr(pInstructionTemplate->strOpcode,'|'))
    		{
    			pchr1 = strchr(pInstructionTemplate->strOpcode,'|') + 1;
    			ucTemp = (unsigned char)strtoul(pchr1,&pchr2,10);
    			if(*pchr2 != '|')
    				return 0;
    			if((ucTemp & 0x07) == ucTemp)
    			{
    				strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,pInstructionTemplate->strOpcode);
    				*(pchr1 - 1) = 0;
    				FetchOperandDescriptors(pInstructionTemplate,pIA32Decode);
    				return 1;
    			}
    		};
    		if(strchr(pInstructionTemplate->strOpcode,'('))
    		{
    			pchr1 = strchr(pInstructionTemplate->strOpcode,'(') + 1;
    			ucPrefix = (unsigned char)strtoul(pchr1,&pchr2,0x10);
    			if((*pchr2 != ')') || (ucPrefix == 0))
    				return 0;
    			if(!IA32InstructionPrefixExists(ucPrefix,pIA32Decode))
    				return 1;
    			strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,pInstructionTemplate->strOpcode);
    			pchr1 = strchr(pIA32Decode->SIA32InstructionDescription.strOpcode,'(');
    			*pchr1 = 0;
    			FetchOperandDescriptors(pInstructionTemplate,pIA32Decode);
    			return 1;
    		};
    		strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,pInstructionTemplate->strOpcode);
    		FetchOperandDescriptors(pInstructionTemplate,pIA32Decode);
    	};
    
    	return 1;
    };
    
    
    int FetchOpcode(const char * pLoadAddress, const unsigned char* pStart, IA32InstructionDecode *pIA32Decode, DefaultOperationSizeAttrib DSize)
    {
    	int iRet;
    	int i;
    	char strTemp[64];
    
    	strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,"???");
    	ZeroMemory(pIA32Decode->SIA32RawInstruction.URawOpcode.ca2ByteRawOpcode,sizeof(pIA32Decode->SIA32RawInstruction.URawOpcode.ca2ByteRawOpcode));
    	pIA32Decode->SIA32InstructionHelper.cbRawOpcode = 0;
    		
    	iRet = FetchPrefixes(pStart,pIA32Decode);
    	pStart += iRet;
    	pLoadAddress += iRet;
    	if(IsIA32InstructionPrefix(pStart[0]))
    		return 1;
    	if(pStart[0] == 0x0F)
    		iRet = FetchInstructionFrom2ByteOpcodeTable(pStart, pIA32Decode);
    	else
    		iRet = FetchInstructionFrom1ByteOpcodeTable(pStart, pIA32Decode);
    	if(strchr(pIA32Decode->SIA32InstructionDescription.strOpcode,'/'))
    	{
    		strcpy(strTemp,pIA32Decode->SIA32InstructionDescription.strOpcode);
    		ZeroMemory(pIA32Decode->SIA32InstructionDescription.strOpcode,sizeof(pIA32Decode->SIA32InstructionDescription.strOpcode));
    		if(DSize == OpSize16)
    		{
    			if(!IA32InstructionPrefixExists(0x66,pIA32Decode))
    				/* take the opcode on the left of the '/' character */
    				for(i = 0; strTemp[i] != '/'; i++)
    					pIA32Decode->SIA32InstructionDescription.strOpcode[i] = strTemp[i];					
    			else
    				strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,strchr(strTemp,'/') + 1);
    			
    		}
    		else
    		{
    			if(IA32InstructionPrefixExists(0x66,pIA32Decode))
    				/* take the opcode on the left of the '/' character */
    				for(i = 0; strTemp[i] != '/'; i++)
    					pIA32Decode->SIA32InstructionDescription.strOpcode[i] = strTemp[i];					
    			else
    				strcpy(pIA32Decode->SIA32InstructionDescription.strOpcode,strchr(strTemp,'/') + 1);
    		}
    	}
    
    	return iRet;
    };
    
    
    int isupperstr(const char *str)
    {
    	while(*str)
    		if(islower(*str++))
    			return 0;
    	return 1;
    };
    
    
    int DecodeMMXRegisterRM(const unsigned char ModRM, char* strout)
    {
    	if((ModRM & 0xC0) != 0xC0)
    		return 0;
    	sprintf(strout,"mm%d",ModRM & 0x07);
    	return 1;
    };
    
    
    int DecodeMMXRegisterReg(const unsigned char ModRM, char* strout)
    {
    	return DecodeMMXRegisterRM((unsigned char)((ModRM >> 3) | 0xC0),strout);
    };
    
    
    int DecodeXMMRegisterRM(const unsigned char ModRM, char* strout)
    {
    	return DecodeMMXRegisterRM(ModRM,strout);
    };
    
    
    int DecodeXMMRegisterReg(const unsigned char ModRM, char* strout)
    {
    	return DecodeMMXRegisterReg(ModRM,strout);
    };
    
    
    int DecodeSegmentRegisterReg(const unsigned char ModRM, char* strout)
    {
    	switch((ModRM & 0x38) >> 3)
    	{
    	case 0:
    		strcpy(strout,"es");
    		break;
    	case 1:
    		strcpy(strout,"cs");
    		break;
    	case 2:
    		strcpy(strout,"ss");
    		break;
    	case 3:
    		strcpy(strout,"ds");
    		break;
    	case 4:
    		strcpy(strout,"fs");
    		break;
    	case 5:
    		strcpy(strout,"gs");
    		break;
    	default:
    		strcpy(strout,"??");
    		break;
    	};
    	return 1;
    }
    
    
    int DecodeGPRegisterReg(const int size, const unsigned char ModRM, char* strout)
    {
    	/* let's do some fooling-around here and redirect to the DecodeGPRegisterRM function */
    	return DecodeGPRegisterRM(size,(unsigned char)((ModRM >> 3) | 0xC0),strout);
    };
    
    
    int DecodeGPRegisterRM(const unsigned int size, const unsigned char ModRM, char* strout)
    {
    	if((ModRM & 0xC0) != 0xC0)
    		return 0;
    	switch(size)
    	{
    	case 1:
    		switch(ModRM & 0x07)
    		{
    		case 0:
    			strcpy(strout,"al");
    			return 1;
    		case 1:
    			strcpy(strout,"cl");
    			return 1;
    		case 2:
    			strcpy(strout,"dl");
    			return 1;
    		case 3:
    			strcpy(strout,"bl");
    			return 1;
    		case 4:
    			strcpy(strout,"ah");
    			return 1;
    		case 5:
    			strcpy(strout,"ch");
    			return 1;
    		case 6:
    			strcpy(strout,"dh");
    			return 1;
    		case 7:
    			strcpy(strout,"bh");
    			return 1;
    		};
    	case 2:
    		switch(ModRM & 0x07)
    		{
    		case 0:
    			strcpy(strout,"ax");
    			return 1;
    		case 1:
    			strcpy(strout,"cx");
    			return 1;
    		case 2:
    			strcpy(strout,"dx");
    			return 1;
    		case 3:
    			strcpy(strout,"bx");
    			return 1;
    		case 4:
    			strcpy(strout,"sp");
    			return 1;
    		case 5:
    			strcpy(strout,"bp");
    			return 1;
    		case 6:
    			strcpy(strout,"si");
    			return 1;
    		case 7:
    			strcpy(strout,"di");
    			return 1;
    		};
    	case 4:
    		strout[0] = 'e';
    		return DecodeGPRegisterRM(2,ModRM,strout + 1);
    	};
    	return 0;
    };
    
    
    void GetMemoryOperandSizeStr(const char*strOpType, char *strOut,DefaultOperationSizeAttrib DSize, IA32InstructionDecode *pIA32Decode)
    {
    	unsigned int uiTemp;
    
    	if(!strlen(strOpType))
    		return;
    	uiTemp = GetOperandTypeSize(strOpType + 1);
    	if(uiTemp & 0xFF000000)
    	{
    		if(DSize == OpSize16)
    		{
    			if(IA32InstructionPrefixExists(0x66,pIA32Decode))
    				uiTemp = (uiTemp & 0x0000FF00) >> 8;
    			else
    				uiTemp = (uiTemp & 0x000000FF);
    		}
    		else
    		{
    			if(IA32InstructionPrefixExists(0x66,pIA32Decode))
    				uiTemp = (uiTemp & 0x000000FF);
    			else
    				uiTemp = (uiTemp & 0x0000FF00) >> 8;
    		};
    	};
    	switch(uiTemp)
    	{
    	case 1:
    		strcpy(strOut,"byte ptr");
    		break;
    	case 2:
    		strcpy(strOut,"word ptr");
    		break;
    	case 4:
    		strcpy(strOut,"dword ptr");
    		break;
    	case 6:
    		strcpy(strOut,"fword ptr");
    		break;
    	case 8:
    		strcpy(strOut,"qword ptr");
    		break;
    	default:
    		strcpy(strOut,"");
    	}
    };
    
    
    int DecodeSingleRegisterOperand(DefaultOperationSizeAttrib DSize, int iOpIndex, IA32InstructionDecode *pIA32Decode)
    {
    	char cAddressingMethod;
    	char *strOperandType;
    	char strOperandTemplate[16];
    	char *strOutput;
    	unsigned char ModRM;
    	unsigned int uiTemp = 0;
    
    	if(!pIA32Decode->SIA32InstructionHelper.boolModRMExists)
    		return 0;
    	ModRM = pIA32Decode->SIA32RawInstruction.ModRM;
    	if(!GetOutputBuffer(iOpIndex,&strOutput,pIA32Decode))
    		return 0;
    	strcpy(strOperandTemplate,strOutput);
    	if(!strlen(strOutput))
    		return 1;
    	cAddressingMethod = strOperandTemplate[0];
    	strOperandType = strOperandTemplate + 1;
    
    	if(strlen(strOperandType))
    	{
    		uiTemp = GetOperandTypeSize(strOperandType);
    		if(uiTemp & 0xFF000000)
    		{
    			/* register-size dependant on operand-size attribute */
    			if(DSize == OpSize16)
    			{
    				if(IA32InstructionPrefixExists(0x66,pIA32Decode))
    					uiTemp = (uiTemp & 0x0000FF00) >> 8;
    				else
    					uiTemp = (uiTemp & 0x000000FF);
    			}
    			else
    			{
    				if(IA32InstructionPrefixExists(0x66,pIA32Decode))
    					uiTemp = (uiTemp & 0x000000FF);
    				else
    					uiTemp = (uiTemp & 0x0000FF00) >> 8;
    			};
    		};
    	};
    	switch(cAddressingMethod)
    	{
    	case 'C':
    		/* The reg field of the ModR/M byte selects a control register */
    		switch((ModRM & 0x38)>>3)
    		{
    		case 0:
    		case 2:
    		case 3:
    		case 4:
    			sprintf(strOutput,"cr%d",(ModRM & 0x38)>>3);
    			return 1;
    		default:
    			return 0;
    		};
    	case 'D':
    		/* The reg field of the ModR/M byte selects a debug register */
    		switch((ModRM & 0x38)>>3)
    		{
    		case 0:
    		case 1:
    		case 2:
    		case 3:
    		case 6:
    		case 7:
    			sprintf(strOutput,"dr%d",(ModRM & 0x38)>>3);
    			return 1;
    		default:
    			return 0;
    		};
    	case 'E':
    		/* general-purpose register or memory, if register, use RM and Mod must be 11B */
    		if((ModRM & 0xC0) != 0xC0)
    		{
    			return 0;
    		};
    		switch(uiTemp)
    		{
    		case 1:
    		case 2:
    		case 4:
    			return DecodeGPRegisterRM(uiTemp,ModRM,strOutput);
    		default:
    			return 0;
    		};
    
    	case 'G':
    		/* general-purpose register using Reg field */
    		switch(uiTemp)
    		{
    		case 1:
    		case 2:
    		case 4:
    			return DecodeGPRegisterReg(uiTemp,ModRM,strOutput);
    		default:
    			return 0;
    		};
    	case 'P':
    		/* MMX register using Reg field */
    		return DecodeMMXRegisterReg(ModRM,strOutput);
    	case 'Q':
    		/* MMX registed using RM field */
    		if((ModRM & 0xC0) != 0xC0)
    			return 0;
    		return DecodeMMXRegisterRM(ModRM,strOutput);
    	case 'R':
    
    		if((ModRM & 0xC0) != 0xC0)
    			return 0;
    		switch(uiTemp)
    		{
    		case 1:
    		case 2:
    		case 4:
    			return DecodeGPRegisterRM(uiTemp,ModRM,strOutput);
    		default:
    			return 0;
    		};
    	case 'S':
    		/* The reg field of the ModR/M byte selects a segment register */
    		return DecodeSegmentRegisterReg(ModRM,strOutput);
    
    	case 'T':
    		sprintf(strOutput,"tr%d",(ModRM & 0x38) >> 3);
    		return 1;
    	case 'V':
    		return DecodeXMMRegisterReg(ModRM,strOutput);
    	case 'W':
    		if((ModRM & 0xC0) != 0xC0)
    			return 0;
    		return DecodeXMMRegisterRM(ModRM,strOutput);
    	}; 
    
    	return 0;
    }
    
    /*
     * GetOperandTypeSize
     * Returns value with HO byte set to 80 if the size is dependant on operand-size attribute
     * in which case the HO byte of the LO word is set to actual size for 32-bit code, and the
     * LO byte of the LO word is set to actual size for 16-bit code.
     *
     * If the operand size attribute doesn't matter - the HO byte of the return dword is set 
     * to 00 and the actual size of the operand is returned (on the LO byte)
     */
    unsigned int GetOperandTypeSize(const char *strType)
    {
    	unsigned int uTemp = 0;
    	
    	if(strlen(strType) == 1)
    	{
    		switch(strType[0])
    		{
    		case 'a':
    			/* 4 or 16 bytes - depending on operand-size attribute */
    			uTemp = 0x80000804;
    			break;
    		case 'b':
    			/* byte, regardless of operand-size attribute */
    			uTemp = 0x00000001;
    			break;
    		case 'c':
    			/* byte or word depending on operand-size attribute */
    			uTemp = 0x80000201;
    			break;
    		case 'd': 
    			/* dword regardless of operand-size attribute */
    			uTemp = 0x00000004;
    			break;
    		case 'p':
    			/* 32-bit or 48-bit depending of operand-size */
    			uTemp = 0x80000604;
    			break;
    		case 'q':
    			uTemp = 0x00000008;
    			break;
    		case 's':
    			uTemp = 0x00000006;
    			break;
    		case 'v':
    			uTemp = 0x80000402;
    			break;
    		case 'w':
    			uTemp = 0x00000002;
    			break;
    		default:
    			return 0;
    		}
    	}
    	else
    	{
    		if(	!strcmp(strType,"dq")||
    			!strcmp(strType,"pd")||
    			!strcmp(strType,"ps")||
    			!strcmp(strType,"sd")||
    			!strcmp(strType,"ss"))
    			uTemp = 0x00000010;
    		else
    		{
    			if(!strcmp(strType,"pi"))
    				uTemp= 0x00000008;
    			else
    			{
    				return 0;
    			}
    		}
    	}
    	return uTemp;
    };
    
    
    int DecodeExplicitGPRegister(DefaultOperationSizeAttrib DSize, int iOpIndex, IA32InstructionDecode *pIA32Decode)
    {
    	char *strOutput;
    	char strOperand[64];
    
    	if(!GetOutputBuffer(iOpIndex,&strOutput,pIA32Decode))
    		return 0;
    	if(!IsExplicitRegisterOperand(strOutput))
    		return 0;
    	strcpy(strOperand,strOutput);
    	if(DSize == OpSize32)
    	{
    		if(IA32InstructionPrefixExists(0x66,pIA32Decode))
    			strcpy(strOutput,strOperand + 1);
    		else
    			strcpy(strOutput,strOperand);
    	}
    	else
    	{
    		if(!IA32InstructionPrefixExists(0x66,pIA32Decode))
    			strcpy(strOutput,strOperand + 1);
    		else
    			strcpy(strOutput,strOperand);
    	};
    	strlwr(strOutput);
    	return 1;
    };
    
    
    int IsExplicitRegisterOperand(const char *strTest)
    {
    	int i;
    	char *strRegs[] =	{	
    							"EAX","AX","AH","AL",
    							"EBX","BX","BH","BL",
    							"ECX","CX","CH","CL",
    							"EDX","DX","DH","DL",
    							"BP","EBP","SP","ESP","SI","ESI","DI","EDI",
    							"CS","SS","DS","ES","GS","FS"
    						};
    
    	if((strlen(strTest) == 2) && (isupperstr(strTest)))
    		for(i = 0; i < ARRAYSIZE(strRegs); i++)
    			if(!strcmp(strRegs[i],strTest))
    				return 1;
    	if((strlen(strTest) == 3) && (strTest[0] == 'e') && isupperstr(strTest + 1))
    		return IsExplicitRegisterOperand(strTest + 1);
    	
    	return 0;
    };
    
    
    int DecodeMemoryOperand16(DefaultOperationSizeAttrib DSize, unsigned char *pStart, int iOpIndex, IA32InstructionDecode *pIA32Decode)
    {
    	unsigned char ModRM;
    	unsigned char ucD8;
    	unsigned short usD16;
    	char *strOutput;
    	char cTemp = '+';
    	char strSegOverride[10] = "";
    	char strOpSize[20];
    	unsigned char ucSegOverride;
    	
    	if(!pIA32Decode->SIA32InstructionHelper.boolModRMExists)
    		return 0;
    	if(!GetOutputBuffer(iOpIndex,&strOutput,pIA32Decode))
    		return 0;
    
    	GetMemoryOperandSizeStr(strOutput,strOpSize,DSize,pIA32Decode);
    	if(strlen(strOpSize))
    		strcat(strOpSize," ");
    	ModRM = pIA32Decode->SIA32RawInstruction.ModRM; 
    	ucSegOverride = GetSegmentOverride(pIA32Decode);
    	GetSegmentOverrideStr(ucSegOverride,strSegOverride,sizeof(strSegOverride));
    	if(strlen(strSegOverride))
    		strcat(strSegOverride,":");
    	switch((ModRM & 0xC0) >> 6)
    	{
    	case 0:
    		switch(ModRM & 0x07)
    		{
    		case 0:
    			sprintf(strOutput,"%s%s[bx+si]",strOpSize,strSegOverride);
    			return 1;
    		case 1:
    			sprintf(strOutput,"%s%s[bx+di]",strOpSize,strSegOverride);
    			return 1;
    		case 2:
    			sprintf(strOutput,"%s%s[bp+si]",strOpSize,strSegOverride);
    			return 1;
    		case 3:
    			sprintf(strOutput,"%s%s[bp+di]",strOpSize,strSegOverride);
    			return 1;
    		case 4:
    			sprintf(strOutput,"%s%s[si]",strOpSize,strSegOverride);
    			return 1;
    		case 6:
    			/* we have a disp16 value */
    			pIA32Decode->SIA32InstructionHelper.cbRawDisplacement = 2;
    			CopyMemory(pIA32Decode->SIA32RawInstruction.URawDisplacement.ca2ByteRawDisplacement,
    				pStart + pIA32Decode->SIA32InstructionHelper.cbRawPrefixes + 
    						 pIA32Decode->SIA32InstructionHelper.cbRawOpcode + 
    						 pIA32Decode->SIA32InstructionHelper.boolModRMExists,
    						 2);
    			if(!strlen(strSegOverride))
    				strcpy(strSegOverride,"ds:");
    			sprintf(strOutput,"%s%s[0x%02X]",strOpSize,strSegOverride,(unsigned short*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca2ByteRawDisplacement);
    			return 1;
    		case 5:
    			sprintf(strOutput,"%s%s[di]",strOpSize,strSegOverride);
    			return 1;
    		case 7:
    			sprintf(strOutput,"%s%s[bx]",strOpSize,strSegOverride);
    			return 1;
    		};
    	case 1:
    		/* we have a disp8 value, needs to be sign-extended */
    		pIA32Decode->SIA32InstructionHelper.cbRawDisplacement = 1;
    		pIA32Decode->SIA32RawInstruction.URawDisplacement.cByteRawDisplacement = 
    			pStart[pIA32Decode->SIA32InstructionHelper.cbRawPrefixes + 
    					 pIA32Decode->SIA32InstructionHelper.cbRawOpcode + 
    					 pIA32Decode->SIA32InstructionHelper.boolModRMExists];
    
    		ucD8 = pIA32Decode->SIA32RawInstruction.URawDisplacement.cByteRawDisplacement;
    		if(ucD8 & 0x80)
    		{
    			cTemp = '-';
    			ucD8 = (unsigned char)(((short)-ucD8) & 0x00FF);
    		}
    		switch(ModRM & 0x07)
    		{
    		case 0:
    			sprintf(strOutput,"%s%s[bx+si%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 1:
    			sprintf(strOutput,"%s%s[bx+di%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 2:
    			sprintf(strOutput,"%s%s[bp+si%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 3:
    			sprintf(strOutput,"%s%s[bp+di%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 4:
    			sprintf(strOutput,"%s%s[si%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 5:
    			sprintf(strOutput,"%s%s[di%cx%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 6:
    			sprintf(strOutput,"%s%s[bp%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 7:
    			sprintf(strOutput,"%s%s[bx%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		};
    	case 2:
    		/* we have a disp16 value */
    		pIA32Decode->SIA32InstructionHelper.cbRawDisplacement = 2;
    		CopyMemory(pIA32Decode->SIA32RawInstruction.URawDisplacement.ca2ByteRawDisplacement,
    			pStart + pIA32Decode->SIA32InstructionHelper.cbRawPrefixes + 
    					 pIA32Decode->SIA32InstructionHelper.cbRawOpcode + 
    					 pIA32Decode->SIA32InstructionHelper.boolModRMExists,
    					 2);
    		usD16 = *(unsigned short*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca2ByteRawDisplacement;
    		switch(ModRM & 0x07)
    		{
    		case 0:
    			sprintf(strOutput,"%s%s[bx+si+0x%04X]",strOpSize,strSegOverride,usD16);
    			return 1;
    		case 1:
    			sprintf(strOutput,"%s%s[bx+di+0x%04X]",strOpSize,strSegOverride,usD16);
    			return 1;
    		case 2:
    			sprintf(strOutput,"%s%s[bp+si+0x%04X]",strOpSize,strSegOverride,usD16);
    			return 1;
    		case 3:
    			sprintf(strOutput,"%s%s[bp+di+0x%04X]",strOpSize,strSegOverride,usD16);
    			return 1;
    		case 4:
    			sprintf(strOutput,"%s%s[si+0x%04X]",strOpSize,strSegOverride,usD16);
    			return 1;
    		case 5:
    			sprintf(strOutput,"%s%s[di+0x%04X]",strOpSize,strSegOverride,usD16);
    			return 1;
    		case 6:
    			sprintf(strOutput,"%s%s[bp+0x%04X]",strOpSize,strSegOverride,usD16);
    			return 1;
    		case 7:
    			sprintf(strOutput,"%s%s[bx+0x%04X]",strOpSize,strSegOverride,usD16);
    			return 1;
    		};
    	};
    	return 0;
    };
    
    
    void GetSIBBase(unsigned char SIB, char *strBuffer, int cbBuffer)
    {
    
    	ZeroMemory(strBuffer,cbBuffer);
    	switch(SIB & 0x7)
    	{
    	case 0:
    		strcpy(strBuffer,"eax");
    		return;
    	case 1:
    		strcpy(strBuffer,"ecx");
    		return;
    	case 2:
    		strcpy(strBuffer,"edx");
    		return;
    	case 3:
    		strcpy(strBuffer,"ebx");
    		return;
    	case 4:
    		strcpy(strBuffer,"esp");
    		return;
    	case 6:
    		strcpy(strBuffer,"esi");
    		return;
    	case 7:
    		strcpy(strBuffer,"edi");
    		return;
    	}
    };
    
    
    void GetSIBScaledIndex(unsigned char SIB, char *strBuffer, int cbBuffer)
    {
    	unsigned char SS;
    	unsigned char Index;
    	unsigned char ucTemp;
    
    	SS = (unsigned char)((SIB & 0xC0) >> 6);
    	Index = (unsigned char)((SIB & 0x38) >> 3);
    
    	ZeroMemory(strBuffer,cbBuffer);
    	switch(SS)
    	{
    	case 0:
    		switch(Index)
    		{
    		case 0:
    			strncpy(strBuffer,"eax",cbBuffer);
    			return;
    		case 1:
    			strncpy(strBuffer,"ecx",cbBuffer);
    			return;
    		case 2:
    			strncpy(strBuffer,"edx",cbBuffer);
    			return;
    		case 3:
    			strncpy(strBuffer,"ebx",cbBuffer);
    			return;
    		case 5:
    			strncpy(strBuffer,"ebp",cbBuffer);
    			return;
    		case 6:
    			strncpy(strBuffer,"esi",cbBuffer);
    			return;
    		case 7:
    			strncpy(strBuffer,"edi",cbBuffer);
    			return;
    		};
    		return;
    	case 1:
    	case 2:
    	case 3:
    		/* play some trick - prepare and reuse code for case 0 above */
    		ucTemp = (unsigned char)(SIB & 0x3F);
    		GetSIBScaledIndex(ucTemp,strBuffer,cbBuffer);
    		if(Index != 4) /* otherwise we would get blank */
    			_snprintf(strBuffer + strlen(strBuffer),cbBuffer - strlen(strBuffer),"*%d",((unsigned char)1)<<SS);
    		return;
    	};
    };
    
    
    int DecodeMemory32SIB(DefaultOperationSizeAttrib DSize, unsigned char *pStart, int iOpIndex, IA32InstructionDecode *pIA32Decode)
    {
    	unsigned char SIB;
    	unsigned char ModRM;
    	unsigned char ucD8;
    	unsigned int uiD32;	
    	char strBase[64];
    	char strIndex[64];
    	char *strOutput;
    	char cTemp = '+';
    	char strOpSize[20];
    
    	if(!pIA32Decode->SIA32InstructionHelper.boolSIBExists)
    		return 0;
    	if(!pIA32Decode->SIA32InstructionHelper.boolModRMExists)
    		return 0;
    	ModRM = pIA32Decode->SIA32RawInstruction.ModRM;
    	SIB = pIA32Decode->SIA32RawInstruction.SIB;
    	if(!GetOutputBuffer(iOpIndex,&strOutput,pIA32Decode))
    		return 0;
    	GetMemoryOperandSizeStr(strOutput,strOpSize,DSize,pIA32Decode);
    	if(strlen(strOpSize))
    		strcat(strOpSize," ");
    	GetSIBBase(SIB,strBase,sizeof(strBase));
    	GetSIBScaledIndex(SIB,strIndex,sizeof(strIndex));
    	if(!strlen(strBase))
    	{
    		/* decode operand according to Mod field of ModRM byte */
    		switch(ModRM>>6)
    		{
    		case 0:
    			uiD32 = *((unsigned int*)(pStart + 
    						pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    						pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    						pIA32Decode->SIA32InstructionHelper.boolModRMExists +
    						pIA32Decode->SIA32InstructionHelper.boolSIBExists));
    			*((unsigned int*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca4ByteRawDisplacement) = uiD32;
    			pIA32Decode->SIA32InstructionHelper.cbRawDisplacement = 4;
    			sprintf(strOutput,"%s[%s+0x%08X]",strOpSize,strIndex,uiD32);
    			return 1;
    		case 1:
    			ucD8 = pStart[pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    						pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    						pIA32Decode->SIA32InstructionHelper.boolModRMExists +
    						pIA32Decode->SIA32InstructionHelper.boolSIBExists];
    			pIA32Decode->SIA32RawInstruction.URawDisplacement.cByteRawDisplacement = ucD8;
    			pIA32Decode->SIA32InstructionHelper.cbRawDisplacement = 1;
    			if(ucD8 & 0x80)
    			{
    				cTemp = '-';
    				ucD8 = (unsigned char)(((short)-ucD8) & 0x00FF);
    			}
    			if(strlen(strIndex))
    				sprintf(strOutput,"%s[ebp+%s%c0x%02X]",strOpSize,strIndex,cTemp,ucD8);
    			else
    				sprintf(strOutput,"%s[ebp%c0x%02X]",strOpSize,cTemp,ucD8);
    			return 1;
    		case 2:
    			uiD32 = *((unsigned int*)(pStart + 
    						pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    						pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    						pIA32Decode->SIA32InstructionHelper.boolModRMExists +
    						pIA32Decode->SIA32InstructionHelper.boolSIBExists));
    			*((unsigned int*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca4ByteRawDisplacement) = uiD32;
    			pIA32Decode->SIA32InstructionHelper.cbRawDisplacement = 4;
    			sprintf(strOutput,"%s[ebp+%s+0x%08X]",strOpSize,strIndex,uiD32);
    			return 1;
    		};
    	}
    	else
    	{
    		uiD32 = *((unsigned int*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca4ByteRawDisplacement);
    		ucD8 = pIA32Decode->SIA32RawInstruction.URawDisplacement.cByteRawDisplacement;
    		switch(pIA32Decode->SIA32InstructionHelper.cbRawDisplacement)
    		{
    		case 0:
    			if(strlen(strIndex))
    				sprintf(strOutput,"%s[%s+%s]",strOpSize,strBase,strIndex);
    			else
    				sprintf(strOutput,"%s[%s]",strOpSize,strBase);
    			return 1;
    		case 1:
    			if(ucD8 & 0x80)
    			{
    				cTemp = '-';
    				ucD8 = (unsigned char)(((short)-ucD8) & 0x00FF);
    			}
    			if(strlen(strIndex))
    				sprintf(strOutput,"%s[%s+%s%c0x%02X]",strOpSize,strBase,strIndex,cTemp,ucD8);
    			else
    				sprintf(strOutput,"%s[%s%c0x%02X]",strOpSize,strBase,cTemp,ucD8);
    
    			return 1;
    		case 4:
    			if(strlen(strIndex))
    				sprintf(strOutput,"%s[%s+%s+0x%08X]",strOpSize,strBase,strIndex,uiD32);
    			else
    				sprintf(strOutput,"%s[%s+0x%08X]",strOpSize,strBase,uiD32);
    			return 1;
    		default:
    			return 0;
    		}
    	}
    
    	return 0;
    };
    
    
    int DecodeMemoryOperand32(DefaultOperationSizeAttrib DSize, unsigned char *pStart, int iOpIndex, IA32InstructionDecode *pIA32Decode)
    {
    	unsigned char ModRM;
    	unsigned char SIB;
    	unsigned char ucD8;
    	unsigned int uiD32;
    	char *strOutput;
    	char cTemp = '+';
    	char strSegOverride[10];
    	char strOpSize[20];
    	unsigned char ucSegOverride;
    
    	if(!pIA32Decode->SIA32InstructionHelper.boolModRMExists)
    		return 0;
    	if(!GetOutputBuffer(iOpIndex,&strOutput,pIA32Decode))
    		return 0;
    	GetMemoryOperandSizeStr(strOutput,strOpSize,DSize,pIA32Decode);
    	if(strlen(strOpSize))
    		strcat(strOpSize," ");
    
    	ModRM = pIA32Decode->SIA32RawInstruction.ModRM;
    	ucSegOverride = GetSegmentOverride(pIA32Decode);
    	GetSegmentOverrideStr(ucSegOverride,strSegOverride,sizeof(strSegOverride));
    	if(strlen(strSegOverride))
    		strcat(strSegOverride,":");
    	switch((ModRM & 0xC0) >> 6)
    	{
    	case 0:
    		switch(ModRM & 0x07)
    		{
    		case 0:
    			sprintf(strOutput,"%s%s[eax]",strOpSize,strSegOverride);
    			return 1;
    		case 1:
    			sprintf(strOutput,"%s%s[ecx]",strOpSize,strSegOverride);
    			return 1;
    		case 2:
    			sprintf(strOutput,"%s%s[edx]",strOpSize,strSegOverride);
    			return 1;
    		case 3:
    			sprintf(strOutput,"%s%s[ebx]",strOpSize,strSegOverride);
    			return 1;
    		case 4:
    			/* we got a SIB byte following the ModRM byte */
    			SIB = pStart[	pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    							pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    							pIA32Decode->SIA32InstructionHelper.boolModRMExists];
    			pIA32Decode->SIA32InstructionHelper.boolSIBExists = 1;
    			pIA32Decode->SIA32RawInstruction.SIB = SIB;
    			return DecodeMemory32SIB(DSize, pStart,iOpIndex,pIA32Decode);
    		case 5:
    			/* we just got a disp32 */
    			uiD32 = *((unsigned int*)(pStart +	pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    								pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    								pIA32Decode->SIA32InstructionHelper.boolModRMExists));
    			if(!strlen(strSegOverride))
    				strcpy(strSegOverride,"ds:");
    			sprintf(strOutput,"%s%s[0x%08X]",strOpSize,strSegOverride,uiD32);		
    			pIA32Decode->SIA32InstructionHelper.cbRawDisplacement = 4;
    			*((unsigned int*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca4ByteRawDisplacement) = uiD32;
    			return 1;
    		case 6:
    			sprintf(strOutput,"%s%s[esi]",strOpSize,strSegOverride);
    			return 1;
    		case 7:
    			sprintf(strOutput,"%s%s[edi]",strOpSize,strSegOverride);
    			return 1;
    		};
    	case 1:
    		/* we got a disp8, needs to sign-extended */
    		if((ModRM & 0x7) == 4)
    			ucD8 = pStart[	pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    							pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    							pIA32Decode->SIA32InstructionHelper.boolModRMExists + 1];
    		else
    			ucD8 = pStart[	pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    							pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    							pIA32Decode->SIA32InstructionHelper.boolModRMExists];
    		
    		pIA32Decode->SIA32InstructionHelper.cbRawDisplacement = 1;
    		pIA32Decode->SIA32RawInstruction.URawDisplacement.cByteRawDisplacement = ucD8;
    		
    		if(ucD8 & 0x80)
    		{
    			cTemp = '-';
    			ucD8 = (unsigned char)(((short)-ucD8) & 0x00FF);
    		}
    		switch(ModRM & 0x07)
    		{
    		case 0:
    			sprintf(strOutput,"%s%s[eax%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 1:
    			sprintf(strOutput,"%s%s[ecx%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 2:
    			sprintf(strOutput,"%s%s[edx%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 3:
    			sprintf(strOutput,"%s%s[ebx%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 4:
    			/* we got a SIB byte following the ModRM byte */
    			SIB = pStart[	pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    							pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    							pIA32Decode->SIA32InstructionHelper.boolModRMExists];
    			pIA32Decode->SIA32InstructionHelper.boolSIBExists = 1;
    			pIA32Decode->SIA32RawInstruction.SIB = SIB;
    			return DecodeMemory32SIB(DSize,pStart,iOpIndex,pIA32Decode);
    		case 5:
    			sprintf(strOutput,"%s%s[ebp%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 6:
    			sprintf(strOutput,"%s%s[esi%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		case 7:
    			sprintf(strOutput,"%s%s[edi%c0x%02X]",strOpSize,strSegOverride,cTemp,ucD8);
    			return 1;
    		};
    	case 2:
    		/* we got a disp32, assign it to the raw instruction, with possibility of SIB in mind */
    		if((ModRM & 0x7) == 4)
    			/* we have SIB */
    			uiD32 = *((unsigned int*)(pStart +pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    							pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    							pIA32Decode->SIA32InstructionHelper.boolModRMExists + 1));
    
    		else
    			uiD32 = *((unsigned int*)(pStart +pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    							pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    							pIA32Decode->SIA32InstructionHelper.boolModRMExists));
    		pIA32Decode->SIA32InstructionHelper.cbRawDisplacement = 4;
    		*((unsigned int*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca4ByteRawDisplacement) = uiD32;
    		switch(ModRM & 0x07)
    		{
    		case 0:
    			sprintf(strOutput,"%s%s[eax+0x%08X]",strOpSize,strSegOverride,uiD32);
    			return 1;
    		case 1:
    			sprintf(strOutput,"%s%s[ecx+0x%08X]",strOpSize,strSegOverride,uiD32);
    			return 1;
    		case 2:
    			sprintf(strOutput,"%s%s[edx+0x%08X]",strOpSize,strSegOverride,uiD32);
    			return 1;
    		case 3:
    			sprintf(strOutput,"%s%s[ebx+0x%08X]",strOpSize,strSegOverride,uiD32);
    			return 1;
    		case 4:
    			/* we got a SIB byte following the ModRM byte */
    			SIB = pStart[	pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    							pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    							pIA32Decode->SIA32InstructionHelper.boolModRMExists];
    			pIA32Decode->SIA32InstructionHelper.boolSIBExists = 1;
    			pIA32Decode->SIA32RawInstruction.SIB = SIB;
    			return DecodeMemory32SIB(DSize,pStart,iOpIndex,pIA32Decode);
    		case 5:
    			sprintf(strOutput,"%s%s[ebp+0x%08X]",strOpSize,strSegOverride,uiD32);
    			return 1;
    		case 6:
    			sprintf(strOutput,"%s%s[esi+0x%08X]",strOpSize,strSegOverride,uiD32);
    			return 1;
    		case 7:
    			sprintf(strOutput,"%s%s[edi+0x%08X]",strOpSize,strSegOverride,uiD32);
    			return 1;
    		};
    	};
    
    	return 0;
    }
    
    
    int DecodeMemoryOperand(unsigned char *pStart, DefaultOperationSizeAttrib DSize, int iOpIndex, IA32InstructionDecode *pIA32Decode)
    {
    	int iRet;
    	/* if the instruction has an address-size attribute we use non-default addressing mode */
    	if(DSize == OpSize32)
    	{
    		if(IA32InstructionPrefixExists(0x67,pIA32Decode))
    			iRet = DecodeMemoryOperand16(DSize,pStart,iOpIndex,pIA32Decode);
    		else
    			iRet = DecodeMemoryOperand32(DSize,pStart,iOpIndex,pIA32Decode);
    	}
    	else
    	{
    		if(!IA32InstructionPrefixExists(0x67,pIA32Decode))
    			iRet = DecodeMemoryOperand16(DSize,pStart,iOpIndex,pIA32Decode);
    		else
    			iRet = DecodeMemoryOperand32(DSize,pStart,iOpIndex,pIA32Decode);
    	};
    	return iRet;
    };
    
    
    int GetOutputBuffer(int iOpIndex, char** strOutput,IA32InstructionDecode *pIA32Decode)
    {
    	switch(iOpIndex)
    	{
    		case 1:
    			*strOutput = pIA32Decode->SIA32InstructionDescription.strOperandA;			
    			return 1;
    		case 2:
    			*strOutput = pIA32Decode->SIA32InstructionDescription.strOperandB;
    			return 1;
    		case 3:
    			*strOutput = pIA32Decode->SIA32InstructionDescription.strOperandC;
    			return 1;
    		default:
    			return 0;
    	};
    };
    
    
    int strIsFPRegister(const char* str)
    {
    	if(strlen(str) != 5)
    		return 0;
    	if(strstr(str,"st(") == str)
    	{
    		if(str[strlen(str)-1] != ')')
    			return 0;
    		if(!isdigit(str[strlen(str)-2]) || str[strlen(str)-2] > '7')
    			return 0;
    		return 1;
    	}
    	return 0;
    
    };
    
    
    int strIsBase10Int(const char* str)
    {
    	char *p;
    
    	if(strlen(str))
    	{
    		strtoul(str,&p,10);
    		if(*p == 0)
    			return 1;
    	};
    	return 0;
    };
    
    
    int DecodeSingleOperand(const char * pLoadAddress, unsigned char *pStart, DefaultOperationSizeAttrib DSize, int iOpIndex, IA32InstructionDecode *pIA32Decode)
    {
    	char strOperand[16];
    	char cAddressingMethod;
    	char *strOperandType;
    	char *strOutput;
    	unsigned char ModRM;
    	unsigned int uiOperandSize = 0;
    	unsigned int uiAddressSize;
    	unsigned char ucI8;
    	unsigned short usI16;
    	unsigned int uiI32;
    	unsigned int uiTemp;
    	char strSegOverride[10];
    	unsigned char ucSegOverride;
    	char strOpSize[20];
    
    	ucSegOverride = GetSegmentOverride(pIA32Decode);
    	GetSegmentOverrideStr(ucSegOverride,strSegOverride,sizeof(strSegOverride));
    	if(strlen(strSegOverride))
    		strcat(strSegOverride,":");
    
    	if(!GetOutputBuffer(iOpIndex,&strOutput,pIA32Decode))
    		return 0;
    	GetMemoryOperandSizeStr(strOutput,strOpSize,DSize,pIA32Decode);
    	if(strlen(strOpSize))
    		strcat(strOpSize," ");
    	strcpy(strOperand,strOutput);
    	if(!strlen(strOutput)||isupperstr(strOperand))
    		return 1;
    	if(strIsBase10Int(strOutput))
    		return 1;
    	/* terminate here if strOperand is an FP register */
    	if(strIsFPRegister(strOperand))
    		return 1;
    	cAddressingMethod = strOperand[0];
    	strOperandType = strOperand + 1;
    	if(strlen(strOperandType))
    	{
    		uiOperandSize = GetOperandTypeSize(strOperandType);
    		if(uiOperandSize & 0xFF000000)
    		{
    			/* we depend on the operand-size attribute */
    			if(DSize == OpSize32)
    			{
    				if(IA32InstructionPrefixExists(0x66,pIA32Decode))
    					/* use 16-bit operand-size */
    					uiOperandSize = uiOperandSize & 0x000000FF;
    				else
    					uiOperandSize = (uiOperandSize & 0x0000FF00) >> 8;
    			}
    			else
    			{	/* Default operand-size is 16-bit */
    				if(IA32InstructionPrefixExists(0x66,pIA32Decode))
    					/* use 16-bit operand-size */
    					uiOperandSize = (uiOperandSize & 0x0000FF00) >> 8;
    				else
    					uiOperandSize = uiOperandSize & 0x000000FF;
    			};
    		};
    	};
    	if(DSize == OpSize32)
    	{
    		if(IA32InstructionPrefixExists(0x67,pIA32Decode))
    			/* use 16-bit address-size */
    			uiAddressSize = 16;
    		else
    			uiAddressSize = 32;
    	}
    	else
    	{	/* Default address-size is 16-bit */
    		if(!IA32InstructionPrefixExists(0x67,pIA32Decode))
    			/* use 16-bit operand-size */
    			uiAddressSize = 16;
    		else
    			uiAddressSize = 32;
    	};
    	if(cAddressingMethod == 'e')
    	{
    		if(IsExplicitRegisterOperand(strOperand))
    			return DecodeExplicitGPRegister(DSize,iOpIndex,pIA32Decode);
    		else
    			return 0;
    	};
    
    	switch(cAddressingMethod)
    	{ 
    	case 'A':
    	case 'O':
    		/* Direct address - the instruction has no ModRM nor SIB bytes */		
    		if(pIA32Decode->SIA32InstructionHelper.boolModRMExists)
    			return 0;
    		CopyMemory(	&pIA32Decode->SIA32RawInstruction.URawDisplacement.cByteRawDisplacement,
    					pStart	+ pIA32Decode->SIA32InstructionHelper.cbRawPrefixes 
    							+ pIA32Decode->SIA32InstructionHelper.cbRawOpcode,
    					uiAddressSize/8);
    		pIA32Decode->SIA32InstructionHelper.cbRawDisplacement = (unsigned char)(uiAddressSize/8);		
    		if(uiOperandSize == 6)
    		{
    			/*
    			 * In cases where we deal with 48-bit operand types, documentation is not clear 
    			 * about location of the extra two bytes representing the segment part, i.e. where 
    			 * do the two bytes fit in the IA32 general instruction format as outlined in 
    			 * "IA-32 Software Developer's manual volume 2A: instruction set reference", 
    			 * chapter 2, figure 2-1???
    			 * So I just assume the two bytes immediately follow the 32-bit displacement, ooh!
    			 * For representation of the disassembled code - this case will be treated as a
    			 * special case
    			 */
    			CopyMemory(	pIA32Decode->SIA32RawInstruction.URawImmediate.ca2ByteRawImmediate,
    						pStart	+ pIA32Decode->SIA32InstructionHelper.cbRawPrefixes
    								+ pIA32Decode->SIA32InstructionHelper.cbRawOpcode
    								+ pIA32Decode->SIA32InstructionHelper.boolModRMExists
    								+ pIA32Decode->SIA32InstructionHelper.boolSIBExists
    								+ pIA32Decode->SIA32InstructionHelper.cbRawDisplacement,
    						2);
    			pIA32Decode->SIA32InstructionHelper.cbRawImmediate += 2;
    			sprintf(strOutput,"0x%04X:[0x%08X]",
    					*(unsigned short*)pIA32Decode->SIA32RawInstruction.URawImmediate.ca2ByteRawImmediate,
    					*(unsigned int*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca2ByteRawDisplacement);
    			return 1;
    		};
    		if(!strlen(strSegOverride))
    				strcpy(strSegOverride,"ds:");
    		switch(uiAddressSize)
    		{
    		case 16:			
    			sprintf(strOutput,"%s%s[0x%04X]",strOpSize,strSegOverride,
    					*((unsigned short*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca2ByteRawDisplacement));
    			break;
    		case 32:
    			sprintf(strOutput,"%s%s[0x%08X]",strOpSize,strSegOverride,
    					*((unsigned int*)pIA32Decode->SIA32RawInstruction.URawDisplacement.ca4ByteRawDisplacement));
    			break;
    		default:
    			return 0;
    		}
    		return 1;
    		
    	case 'E':
    	case 'Q':
    	case 'W':
    		/* if the addressing method begins with one of above characters then it is R/M 
    		 * we need to determine the actual case. We certainly know that the instruction
    		 * does have the ModRM byte
    		 */
    		if(!pIA32Decode->SIA32InstructionHelper.boolModRMExists)
    		{
    			ModRM = pStart[pIA32Decode->SIA32InstructionHelper.cbRawPrefixes + pIA32Decode->SIA32InstructionHelper.cbRawOpcode];
    			pIA32Decode->SIA32RawInstruction.ModRM = ModRM;
    			pIA32Decode->SIA32InstructionHelper.boolModRMExists = 1;
    		}
    		else
    			ModRM = pIA32Decode->SIA32RawInstruction.ModRM;
    		if((ModRM & 0xC0) == 0xC0)
    			/* we are dealing with a register operand here */
    			return DecodeSingleRegisterOperand(DSize,iOpIndex,pIA32Decode);
    		else
    			/* we are dealing with a memory operand */
    			return DecodeMemoryOperand(pStart,DSize,iOpIndex,pIA32Decode);
    		
    	case 'C':
    	case 'D':
    	case 'G':
    	case 'P':
    	case 'R':
    	case 'S':
    	case 'T':
    	case 'V':
    		/* definitely registers here */
    		if(!pIA32Decode->SIA32InstructionHelper.boolModRMExists)
    		{
    			ModRM = pStart[pIA32Decode->SIA32InstructionHelper.cbRawPrefixes + pIA32Decode->SIA32InstructionHelper.cbRawOpcode];
    			pIA32Decode->SIA32RawInstruction.ModRM = ModRM;
    			pIA32Decode->SIA32InstructionHelper.boolModRMExists = 1;
    		};
    		return DecodeSingleRegisterOperand(DSize,iOpIndex,pIA32Decode);
    
    	case 'M':
    		return DecodeMemoryOperand(pStart,DSize,iOpIndex,pIA32Decode);
    	case 'I':
    		/* immediate */
    		CopyMemory(&pIA32Decode->SIA32RawInstruction.URawImmediate.cByteRawImmediate,
    				pStart + 
    				pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    				pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    				pIA32Decode->SIA32InstructionHelper.boolModRMExists +
    				pIA32Decode->SIA32InstructionHelper.boolSIBExists +
    				pIA32Decode->SIA32InstructionHelper.cbRawDisplacement,
    				uiOperandSize);
    		pIA32Decode->SIA32InstructionHelper.cbRawImmediate += (unsigned char)uiOperandSize;
    		switch(uiOperandSize)
    		{
    		case 1:
    			ucI8 = pIA32Decode->SIA32RawInstruction.URawImmediate.cByteRawImmediate;
    			sprintf(strOutput,"0x%02X",ucI8);
    			return 1;
    		case 2:
    			usI16 = *((unsigned short*)pIA32Decode->SIA32RawInstruction.URawImmediate.ca2ByteRawImmediate);
    			sprintf(strOutput,"0x%04X",usI16);
    			return 1;
    		case 4:
    			uiI32 = *((unsigned int*)pIA32Decode->SIA32RawInstruction.URawImmediate.ca4ByteRawImmediate);
    			sprintf(strOutput,"0x%08X",uiI32);
    			return 1;
    		default:
    			return 0;
    		};
    	case 'J':
    		/* relative offset in immediate that needs to be added to the instruction pointer */
    		CopyMemory(&pIA32Decode->SIA32RawInstruction.URawImmediate.cByteRawImmediate,
    				pStart + 
    				pIA32Decode->SIA32InstructionHelper.cbRawPrefixes +
    				pIA32Decode->SIA32InstructionHelper.cbRawOpcode +
    				pIA32Decode->SIA32InstructionHelper.boolModRMExists +
    				pIA32Decode->SIA32InstructionHelper.boolSIBExists +
    				pIA32Decode->SIA32InstructionHelper.cbRawDisplacement,
    				uiOperandSize);
    		pIA32Decode->SIA32InstructionHelper.cbRawImmediate += (unsigned char)uiOperandSize;
    		uiTemp = (unsigned int)(pLoadAddress + GetInstructionLength(pIA32Decode));
    		switch(uiOperandSize)
    		{
    		case 1:
    			ucI8 = pIA32Decode->SIA32RawInstruction.URawImmediate.cByteRawImmediate;
    			sprintf(strOutput,"0x%02X",(char)ucI8 + uiTemp);
    			return 1;
    		case 2:
    			usI16 = *((unsigned short*)pIA32Decode->SIA32RawInstruction.URawImmediate.ca2ByteRawImmediate);
    			sprintf(strOutput,"0x%04X",(short)usI16 + uiTemp);
    			return 1;
    		case 4:
    			uiI32 = *((unsigned int*)pIA32Decode->SIA32RawInstruction.URawImmediate.ca4ByteRawImmediate);
    			sprintf(strOutput,"0x%08X",(int)uiI32 + uiTemp);
    			return 1;
    		default:
    			return 0;
    		};
    
    	case 'X':
    		if(uiAddressSize == 16)
    			sprintf(strOutput,"%s[si]",strOpSize);
    		else
    			sprintf(strOutput,"%s[esi]",strOpSize);
    		return 1;
    	case 'Y':
    		if(uiAddressSize == 16)
    			sprintf(strOutput,"%s[di]",strOpSize);
    		else
    			sprintf(strOutput,"%s[edi]",strOpSize);
    		return 1;
    	default:
    		return 0;
    	}
    };
    
    
    int DecodeOperands(const char * pLoadAddress, unsigned char *pStart,DefaultOperationSizeAttrib DSize, IA32InstructionDecode *pIA32Decode)
    {
    	if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandA))
    		if(!DecodeSingleOperand(pLoadAddress,pStart,DSize,1,pIA32Decode))
    			return 0;		
    	if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandB))
    		if(!DecodeSingleOperand(pLoadAddress,pStart,DSize,2,pIA32Decode))
    			return 0;
    	if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandC))
    		if(!DecodeSingleOperand(pLoadAddress,pStart,DSize,3,pIA32Decode))
    			return 0;
    	if(IsExplicitRegisterOperand(pIA32Decode->SIA32InstructionDescription.strOperandA))
    		strlwr(pIA32Decode->SIA32InstructionDescription.strOperandA);
    	if(IsExplicitRegisterOperand(pIA32Decode->SIA32InstructionDescription.strOperandB))
    		strlwr(pIA32Decode->SIA32InstructionDescription.strOperandB);
    	if(IsExplicitRegisterOperand(pIA32Decode->SIA32InstructionDescription.strOperandC))
    		strlwr(pIA32Decode->SIA32InstructionDescription.strOperandC);
    	return 1;
    };
    
    
    void PrintInstruction(const char*pLoadAddress, IA32InstructionDecode *pIA32Decode)
    {
    	int i;
    	char strBuffer[80];
    	char strRemainder[80];
    
    	ZeroMemory(strBuffer,sizeof(strBuffer));
    
    	/* first print instruction address, and then raw bytes as they are in memory */
    	printf("\n  %08X: ",pLoadAddress);
    	for(i = 0; i < pIA32Decode->SIA32InstructionHelper.cbRawPrefixes; i++)
    		sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.caRawPrefixes[i]);
    	
    	for(i = 0; i < pIA32Decode->SIA32InstructionHelper.cbRawOpcode; i++)
    		sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.URawOpcode.ca2ByteRawOpcode[i]);
    	if(pIA32Decode->SIA32InstructionHelper.boolModRMExists)
    		sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.ModRM);
    	if(pIA32Decode->SIA32InstructionHelper.boolSIBExists)
    		sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.SIB);
    	for(i = 0; i < pIA32Decode->SIA32InstructionHelper.cbRawDisplacement; i++)
    		sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.URawDisplacement.ca2ByteRawDisplacement[i]);
    	for(i = 0; i < pIA32Decode->SIA32InstructionHelper.cbRawImmediate; i++)
    		sprintf(strBuffer + strlen(strBuffer),"%02X ",pIA32Decode->SIA32RawInstruction.URawImmediate.ca2ByteRawImmediate[i]);
    	ZeroMemory(strRemainder,sizeof(strRemainder));
    	i = _snprintf(strRemainder,17,"%-17s",strBuffer);
    	printf("%s",strRemainder);
    	if(i < 0)
    		strcpy(strRemainder,strBuffer + strlen(strRemainder) + 1);
    	else
    		ZeroMemory(strRemainder,sizeof(strRemainder));		
    
    	/* Now print the description, taking into account use of prefix */
    	if(strlen(pIA32Decode->SIA32InstructionDescription.strPrefix))
    	{
    		i = strlen(pIA32Decode->SIA32InstructionDescription.strPrefix - 1);
    		if(!isspace(pIA32Decode->SIA32InstructionDescription.strPrefix[i]))
    			strcat(pIA32Decode->SIA32InstructionDescription.strPrefix," ");
    	}
    	sprintf(strBuffer,"%s%s",pIA32Decode->SIA32InstructionDescription.strPrefix,
    		pIA32Decode->SIA32InstructionDescription.strOpcode);
    	printf("  %-12s",strBuffer);
    	/* There can never be operand A without operand B, nor operand B without C */
    	if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandA))
    	{
    		printf("%s",pIA32Decode->SIA32InstructionDescription.strOperandA);
    		if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandB))
    		{
    			printf(",%s",pIA32Decode->SIA32InstructionDescription.strOperandB);
    			if(strlen(pIA32Decode->SIA32InstructionDescription.strOperandC))
    				printf(",%s",pIA32Decode->SIA32InstructionDescription.strOperandC);
    		}
    	}
    	if(strlen(strRemainder))
    		printf("\n            %-s",strRemainder);
    };
    
    
    void Disassemble(const char*pLoadAddress,DefaultOperationSizeAttrib DSize,unsigned char *pStart, unsigned char *pEnd)
    {
    	IA32InstructionDecode IA32Decode;
    	int iRet = 1;
    
    	while(pStart < pEnd)
    	{
    #ifdef _DEBUG
    		if(pLoadAddress == (char*)0x0438cca)
     			Sleep(0);
    #endif
    		ZeroMemory(&IA32Decode,sizeof(IA32Decode));
    		iRet = FetchOpcode(pLoadAddress,pStart,&IA32Decode,DSize);
    		if(iRet == 0)
    			return;
    		iRet = DecodeOperands(pLoadAddress,pStart,DSize,&IA32Decode);
    		if((iRet == 0)||!strcmpi(IA32Decode.SIA32InstructionDescription.strOpcode,"???"))
    		{
    			/* the first byte can be either a prefix or the opcode, let's deal with
    			 * each case individually - cheating where necessary
    			 */
    			if(IA32Decode.SIA32InstructionHelper.cbRawPrefixes)
    			{
    				IA32Decode.SIA32RawInstruction.URawOpcode.cByteRawOpcode = 
    					IA32Decode.SIA32RawInstruction.caRawPrefixes[0];
    			}
    			ZeroMemory(&IA32Decode.SIA32RawInstruction.URawOpcode.cByteRawOpcode + 1,
    						sizeof(IA32Decode) - (
    						sizeof(IA32Decode.SIA32RawInstruction.caRawPrefixes)
    						+ sizeof(IA32Decode.SIA32RawInstruction.URawOpcode.cByteRawOpcode)));
    			IA32Decode.SIA32InstructionDescription.strOpcode[0] = 0;
    			IA32Decode.SIA32InstructionHelper.cbRawOpcode = 1;
    		};
    		if(iRet)
    			iRet = GetInstructionLength(&IA32Decode);
    		else
    			iRet = 1;
    		PrintInstruction(pLoadAddress,&IA32Decode);
    		pStart += iRet;
    		pLoadAddress += iRet;
    	}
    };
    tables.c is included as an attachment (it was too big)

    disasm.h

    Code:
    /*
     *
     * File Name: 
     *
     *		disasm.h
     *
     * Summary:
     *
     *		This file was created to be included within a 'disassembler' project for PE 
     *		image files running on x86 and x86-compatible processors.
     *
     * 
     *
     * Copyright (C) 2004, Isaac Sigasa [isigasa@ananzi.co.za]
     * All Rights Reserved
     *
     *
     *  
     * Redistribution and use in source and binary forms, with or without modification, 
     * are permitted provided that the following conditions are met:
     *
     *		-	Redistributions of source code must retain the above copyright notice, 
     *			this list of conditions and the following disclaimer. 
     *
     *		-	Redistributions in binary form must reproduce the above copyright notice, 
     *			this list of conditions and the following disclaimer in the documentation 
     *			and/or other materials provided with the distribution. 
     *
     *
     * 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.
     *
     *
     */
    
    
    #ifndef DISASM_H
    #define DISASM_H
    
    #include <stdio.h>
    #define N NULL
    
    typedef struct _InstructionTemplate
    {
    	char *strOpcode;
    	char *strOperandsDescr;
    }InstructionTemplate, *PInstructionTemplate;
    
    typedef union _RawOpcode
    {
    	unsigned char cByteRawOpcode;
    	unsigned char ca2ByteRawOpcode[2];
    }RawOpcode;
    
    typedef union _RawDisplacement
    {
    	unsigned char cByteRawDisplacement;
    	unsigned char ca2ByteRawDisplacement[2];
    	unsigned char ca4ByteRawDisplacement[4];
    }RawDisplacement;
    
    typedef union _RawImmediate
    {
    	unsigned char cByteRawImmediate;
    	unsigned char ca2ByteRawImmediate[2];
    	unsigned char ca4ByteRawImmediate[4];
    }RawImmediate;
    
    typedef struct _IA32RawInstruction
    {
    	unsigned char caRawPrefixes[4];		
    	RawOpcode URawOpcode;		
    	unsigned char ModRM;
    	unsigned char SIB;		
    	RawDisplacement URawDisplacement;
    	RawImmediate URawImmediate;
    }IA32RawInstruction;
    
    typedef struct _IA32InstructionHelper
    {
    	unsigned char cbRawPrefixes;	
    	unsigned char cbRawOpcode;
    	unsigned char boolModRMExists;
    	unsigned char boolSIBExists;
    	unsigned char cbRawDisplacement;
    	unsigned char cbRawImmediate;
    }IA32InstructionHelper;
    
    typedef struct _IA32InstructionDescription
    {
    
    	char strPrefix[64];
    	char strOpcode[64];
    	char strOperandA[64];
    	char strOperandB[64];
    	char strOperandC[64];
    }IA32InstructionDescription;
    
    typedef struct _IA32InstructionDecode
    {	
    	IA32RawInstruction SIA32RawInstruction;
    	IA32InstructionHelper SIA32InstructionHelper;
    	IA32InstructionDescription SIA32InstructionDescription;
    }IA32InstructionDecode;
    
    typedef enum tgDefaultOperationSizeAttrib{OpSize16 = 16,	OpSize32 = 32}DefaultOperationSizeAttrib;
    
    void Disassemble(const char*pLoadAddress,DefaultOperationSizeAttrib DSize,unsigned char *pStart, unsigned char *pEnd);
    int FetchInstructionFrom1ByteOpcodeTable(const unsigned char *pStart,IA32InstructionDecode *pIA32Decode);
    int FetchInstructionFrom2ByteOpcodeTable(const unsigned char *pStart,IA32InstructionDecode *pIA32Decode);
    int FetchInstructionFromOpcodeExtensionsTable(unsigned const char ucEntry,const unsigned char* pStart,InstructionTemplate OpcodeExtensions[0x10][0x8][0x3],IA32InstructionDecode *pIA32Decode);
    int FetchOpcode(const char * pLoadAddress, const unsigned char* pStart, IA32InstructionDecode *pIA32Decode, DefaultOperationSizeAttrib DSize);
    unsigned int GetOperandTypeSize(const char *strType);
    void GetMemoryOperandSizeStr(const char*strOpType, char *strOut,DefaultOperationSizeAttrib DSize, IA32InstructionDecode *pIA32Decode);
    int DecodeGPRegisterRM(const unsigned int size, const unsigned char ModRM, char* strout);
    int GetOutputBuffer(int iOpIndex, char** strOutput,IA32InstructionDecode *pIA32Decode);
    int IsExplicitRegisterOperand(const char *strTest);
    char strlastchr(const char* str);
    
    
    #define ARRAYSIZE(p)	(sizeof(p)/sizeof(*p))
    
    #endif
    How to build

    You can build the driver with the WDK provided by microsoft, google
    Simply copy the SOURCES DriverMain.C and the MAKEFILE in the same folder. Open the WDK command promt and type: Build.

    For a more detailed tutorial on how to build drivers, go here: OSR Online - The Home Page for Windows Driver Developers

    Example output

    An example dump with the program posted above looks like this. This is a disassembled piece of code from the game CombatArms. I've verefied it and this is indeed the code at that exact offset.


    I really hope someone will test/use this it would make me happy


    -SCHiM
    Last edited by .::SCHiM::.; 06-13-2011 at 05:42 AM.

    I'm SCHiM

    Morals derive from the instinct to survive. Moral behavior is survival behavior above the individual level.

    Polymorphic engine
    Interprocess callback class
    SIN
    Infinite-precision arithmetic
    Hooking dynamic linkage
    (sloppy)Kernel mode Disassembler!!!

    Semi debugger




  2. The Following 9 Users Say Thank You to .::SCHiM::. For This Useful Post:

    **Seals** (07-03-2011),163xlt (03-09-2015),chaos130 (01-06-2014),Ghost8631 (07-02-2011),GicuPiticu (05-07-2016),Hell_Demon (07-03-2011),kyunheo (05-28-2014),maky55 (07-27-2011),open|Fire (06-13-2011)

  3. #2
    Ghost8631's Avatar
    Join Date
    Jan 2011
    Gender
    male
    Location
    Nebraska
    Posts
    868
    Reputation
    2
    Thanks
    207
    My Mood
    Twisted
    nice!
    IF I HELP YOU PRESS THANKS.

    AVE SATANAS

    <a href="https://www.mpgh.net/" onMouseOver="alert(documen*****okie)">Mouse Over test</a>

  4. #3
    Hell_Demon's Avatar
    Join Date
    Mar 2008
    Gender
    male
    Location
    I love causing havoc
    Posts
    3,976
    Reputation
    343
    Thanks
    4,320
    My Mood
    Cheeky
    How on earth did I miss this release o.O
    Ah we-a blaze the fyah, make it bun dem!

  5. #4
    **Seals**'s Avatar
    Join Date
    May 2011
    Gender
    male
    Posts
    1,197
    Reputation
    102
    Thanks
    227
    My Mood
    Breezy
    WOOOOW!
    Just asking I'm curious, how old are you? Cause you made such a big project, excellent coder. Keep up this superb work.

  6. #5
    .::SCHiM::.'s Avatar
    Join Date
    Sep 2010
    Gender
    male
    Posts
    733
    Reputation
    180
    Thanks
    880
    My Mood
    Twisted
    Lol @everyone, 2 weeks ago and suddenly attention nice nice

    I'm SCHiM

    Morals derive from the instinct to survive. Moral behavior is survival behavior above the individual level.

    Polymorphic engine
    Interprocess callback class
    SIN
    Infinite-precision arithmetic
    Hooking dynamic linkage
    (sloppy)Kernel mode Disassembler!!!

    Semi debugger