?? disasm.c
字號:
/*
*
* 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;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -