⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disasm.c

📁 反汇编intel32位指令的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        fread( (void*)(ins.code_data), 16, 1, CodeTable) ;

        return;
}

void ModifyOpCode(void)		//根据段前缀修改反汇编的操作码字串
{
        switch (ins.prefix[2])	//处理前缀f0,f2,f3
        {
                case 0:
                        break;
                case 0xf0:
                        strcat(ins.asm_code,"LOCK ");
                        break;
                case 0xf2:
                        strcat (ins.asm_code,"REPNE ");
                        break;
                case 0xf3:
                        switch (ins.ins_buf[ins.processing])
                        {
                                case 0xa6:
                                case 0xa7:
                                case 0xae:
                                case 0xaf:
                                        strcat (ins.asm_code,"REPE ");
                                        break;
                                default:
                                        strcat (ins.asm_code,"REP ");
                        }

        }


        if (ins.prefix[1])        //处理前缀67
        {
                switch (ins.ins_buf[ins.processing])     //看看有没有必要修改操作码
                {
                        case 0x6d:
                                ins.code_data[3] = 'W'; //如果当前指令是INSD,改为INSW
                                break;
                        case 0x9c:
                                ins.code_data[5] = '\0';//如果是PUSHFD,改为PUSHF
                                break;
                        case 0x9d:
                                ins.code_data[4] = '\0';//POPFD改为POPF
                                break;
                        case 0xa5:              //MOVSD
                        case 0xa7:              //CMPSD
                        case 0xab:              //STOSD
                        case 0xad:              //LODSD
                        case 0x6f:              //OUTSD
                        case 0xaf:              //SCASD
                                ins.code_data[4] = 'W';
                                break;

                }
        }
        return;
}

void Process2ByteIns(void)      //处理双字节操作码
{
        ins.processing ++;

        fseek(CodeTable2, ins.ins_buf[ins.processing]<<4, SEEK_SET);     //从CodeTable2中读入双字节指令信息,这里没考虑非法指令的情况,也没必要
        fread( (void*)(ins.code_data), 16, 1, CodeTable2);

        return;
}

void Process3BitGroup(void)     //处理需要MODRM的5,4,3位确定的操作码
{
        ins.modrm.reg = (ins.ins_buf[ins.processing+1]>>3)&7;            //计算modrm的reg字段

        fseek(CodeGrpTable, ((ins.code_data[2]<<3) + ins.modrm.reg)<<4, SEEK_SET);         //从opcode_grp_table中读取操作码信息
        fread( (void*)(ins.code_data), 16, 1, CodeGrpTable);

        return;
}

void GetModrm(void)             //从ins.ins_buf[ins.insprocessing]取得MODRM
{
        ins.modrm.mod = (ins.ins_buf[ins.processing]>>6)&3;
        ins.modrm.reg = (ins.ins_buf[ins.processing]>>3)&7;
        ins.modrm.rm =  (ins.ins_buf[ins.processing])&7;

        if (ins.prefix[1])         //先判断下前缀67,如果是67先写进16位偏移(不管有没有偏移),如果是8位偏移再进行转换
        {
                ins.num = *((long *)(ins.ins_buf+ins.processing+1)) & 0xffff;
		
                if (ins.modrm.mod == 1)	//8位偏移
		{
                        ins.num &= 0xff;
			if ( ins.num & 0x80 )	//如果是负的
				ins.num |= ( (~0)<<8 );	//符号扩展
		}
		else if ( ins.num & 0x8000 )	//如果是负的
			ins.num |= ( (~0)<<16 );//符号扩展

                return;
        }
        if (ins.modrm.rm==4 && ins.modrm.mod!=3)        //如果需要读出SIB字段,读SIB
        {
                ins.sib.s = 1 << ( (ins.ins_buf[ins.processing+1]>>6)&3 );	//s值等于2^s
                ins.sib.index = (ins.ins_buf[ins.processing+1]>>3)&7;
                ins.sib.base = (ins.ins_buf[ins.processing+1])&7;

                ins.num = *((long *)(ins.ins_buf+ins.processing+2)) ;	//不管有没有disp,读一下,省着判断
		if (ins.modrm.mod == 1)                 //如果8位disp
		{
                        ins.num &= 0xff;
			if ( ins.num & 0x80)		//如果是负的
				ins.num |= ( (~0)<<8 );	//符号扩展
		}
		else if ( ins.num & 0x80000000 )	//如果是负的
			ins.num |= ( (~0)<<32 );	//符号扩展

        }
        else if ( (ins.modrm.mod==0&&ins.modrm.rm==5) || (ins.modrm.mod==2) )     //如果modrm后为32位disp字段,读32位disp
        {
                ins.num = *((long *)(ins.ins_buf+ins.processing+1)) & 0xffffffff;
		if ( ins.num & 0x80000000 )	//如果是负的
			ins.num |= ( (~0)<<32 );//符号扩展
        }
        else if ( ins.modrm.mod == 1 )		//如果modrm后为8位disp字段,读8位disp
	{
                ins.num = *((long *)(ins.ins_buf+ins.processing+1)) & 0xff;
		if ( ins.num & 0x80 )		//如果是负的
			ins.num |= ( (~0)<<8 );	//符号扩展
	}
        return;
}

void AnalyzeOperand(void)               //根据code_data后八字节中前二到四个字节翻译操作数字段,code_data从数据文件中获得
{
        switch (ins.code_data[8])       //分析寻址方式
        {
                case 'B':               //寻址方式B,操作数的反汇编字串已知,根据前缀确定
                        if ( ins.code_data[9]=='$')	//串指令和PUSHAD,POPAD,这一段if可能不好理解,弄懂前缀66和段前缀对串指令和PUSHAD,POPAD的影响就好理解了
                        {
				//如果是串指令且有段更改前缀(ins.prefix[3]),就要写操作数,比如MODSD要写上[EDI],XX:[ESI],真麻烦,这种特殊的情况要这么多行来处理
				//如果是PUSHAD或POPAD且有前缀66就要去掉D
				if ( ins.ins_buf[ins.processing-1]==0x60 || ins.ins_buf[ins.processing-1]==0x61 )	//PUSHAD/POPAD
				{
					ins.asm_code_writing --;

					if ( !ins.prefix[0] )
						break;
					ins.asm_code_writing --;
					break;
				}
                                if ( !ins.prefix[3])
                                {
					ins.asm_code_writing --;
                                        break;
                                }
                                ins.prefix[2] = ins.prefix[3];          //ins.prefix[2]是存放REP之类的地方,在分析操作码的时候才会用到,这以下不会用到,因此借用一下保存段前缀,因为AnalyzeOperModrm()是要处理段前缀的,而串指令的目的操作数不受段前缀影响
                                ins.prefix[3] = 0;
                                ins.ins_buf[ins.processing] = 7;         //设置缓冲区当前的操作数为"[EDI]"然后交给AnalyzeOperModrm()处理
                                AnalyzeOperModrm();
				* ins.asm_code_writing++ = ',';

                                ins.prefix[3] = ins.prefix[2];          //写上段前缀给AnalyzeOperModrm()处理
                                ins.ins_buf[ins.processing] = 6;         //设置缓冲区当前的操作数为"[ESI]"然后交给AnalyzeOperModrm()处理
                                AnalyzeOperModrm();                                                                  
                                break;
                        }

                        strncpy(ins.asm_code_writing, ins.code_data+9, 3);	//拷贝ins.code_data[9]处的三字节
                        if (ins.prefix[0] && ins.code_data[9]=='E')	//如果有前缀66,且是寄存器Exx,则寄存器Exx变成xx
				* ins.asm_code_writing = ' ';
			ins.asm_code_writing += 3;
                        break;

                case 'C':
                case 'D':
                case 'T':
                case 'G':
                case 'S':
                        AnalyzeOperReg();       //这5类寻址方式是到MODRM的reg字段分析
                        break;

                case 'I':
                case 'J':
                        AnalyzeOperImm();       //这2类是立即数寻址
                        break;
                case 'O':
                case 'E':
                case 'M':
                case 'R':
                        AnalyzeOperModrm();     //O类操作数在内存中,指令直接给出了偏移,其它三类操作数根据MODRM的mod字段判断
                        break;
        }

	*ins.asm_code_writing = '\0';

        return;
}

void AnalyzeOperReg(void)               //分析寻址方式为C,D,T,G,S的情况,操作数在MODRM的reg字段
{
        ins.modrm.reg = (ins.ins_buf[ins.processing]>>3)&7;      //计算ins.modrm.reg

        switch (ins.code_data[8])       //分析寻址方式
        {
                case 'C':               //寻址方式C,D,T,分别根据MODRM的reg字段确定CRx,DRx,TRx寄存器
                case 'D':
                case 'T':
			* ins.asm_code_writing++ = ins.code_data[8];	//C,D还是T?
			* ins.asm_code_writing++ = 'R';
			* ins.asm_code_writing++ = ( (ins.modrm.reg>>3)&7 ) + 0x30;	//从modrm的reg字段获得寄存器号
                        break;
                case 'G':               //寻址方式G根据操作数大小和MODRM的reg字段从reg_table中找到表示相应寄存器的字串
                        if (ins.code_data[9] == 'B')     //如果操作数大小是B,即字节型
                        {
                                fseek(RegTable, (ins.modrm.reg<<3)+0x80, SEEK_SET);	////从reg_table表读8位寄存器字串
                                fread( ins.asm_code_writing, 8, 1, RegTable);
				ins.asm_code_writing += 2;
                        }
                        else            //否则就应该是V,即32/16位,根据有无指令前缀66判断
                        {
                                if (ins.prefix[0])      //如果有前缀66,取16位寄存器
                                {
                                        fseek(RegTable, (ins.modrm.reg<<3)+0x40, SEEK_SET);	//从reg_table表读16位寄存器字串
                                        fread( ins.asm_code_writing, 8, 1, RegTable);
					ins.asm_code_writing += 2;
                                }
                                else                    //否则取32位寄存器
                                {
                                        fseek(RegTable, ins.modrm.reg<<3, SEEK_SET);	//从reg_table表读32位寄存器字串
                                        fread( ins.asm_code_writing, 8, 1, RegTable);
					ins.asm_code_writing += 3;
                                }
                        }
                        break;
                case 'S':               //寻址方式S是段寄存器
                        fseek(RegTable, (ins.modrm.reg<<3)+0xc0, SEEK_SET);	//从reg_table表读段寄存器字串
                        fread( ins.asm_code_writing, 8, 1, RegTable);
			ins.asm_code_writing += 2;
                        break;
        }

        return;
}

void AnalyzeOperImm(void)               //分析寻址方式是I,J的情况,操作数为立即数
{
        ins.processing += ins.operand_len;      //如果操作数是立即数,则操作数在指令中的位移必定在已经处理过的操作数之后

        switch (ins.code_data[9] )      //根据操作数大小判断
        {
                case 'P':               //操作数大小P在这个函数里只与J搭配,表示48位或32位远指针
			strcpy(ins.asm_code_writing,"FAR PTR ");
			ins.asm_code_writing += 8;

                        if (ins.prefix[0])      //如果有前缀66,取seg:disp16格式
                        {
                                ins.operand_len += 4;
                                ins.num = *((long *)(ins.ins_buf+ins.processing+2));	//取long型就可以,NumToText()会根据正确的字节数截断
				NumToText(2);
				* ins.asm_code_writing++ = ':';
                                ins.num = *((long *)(ins.ins_buf+ins.processing));
				NumToText(2);
                        }
                        else                    //否则取seg:disp32格式
                        {
                                ins.operand_len += 6;
                                ins.num = *((long *)(ins.ins_buf+ins.processing+4));
                                NumToText(2);
				* ins.asm_code_writing++ = ':';
                                ins.num = *((long *)(ins.ins_buf+ins.processing));
				NumToText(4);
                        }
                        break;
                case 'B':               //操作数大小是BYTE
                        ins.operand_len += 1;
                        ins.num = *( (long *)(ins.ins_buf+ins.processing) ) & 0xff;	//这里ins.num保存的必须是正确的8位数,因为下边寻址方式J要加上下一指令的偏移

			if (ins.code_data[8] == 'J')            //如果是跳转指令
			{
				if ( ins.num & 0x80 )		//如果是负的
					ins.num |= (~(long)0) << 8;	//做符号扩展				
				ins.num += (ins.current_code+2);//加上下一条指令的偏移
                                NumToText(4);
			}else
				NumToText(1);
                        break;
                case 'W':               //操作数大小是WORD
                        ins.operand_len += 2;
                        ins.num = *((long *)(ins.ins_buf+ins.processing));
			NumToText(2);
                        break;
                case 'D':               //操作数大小是DWORD
                        ins.operand_len += 4;
                        ins.num = *((long *)(ins.ins_buf+ins.processing));
			NumToText(4);
                        break;
                case 'V':               //操作数大小是WORD或DWORD,根据前缀66判断
                        if (ins.prefix[0])      //判断前缀66
                        {
                                ins.operand_len += 2;
                                ins.num = *((long *)(ins.ins_buf+ins.processing)) & 0xffff;	//这里ins.num保存的必须是正确的16位数,因为下边寻址方式J要加上下一指令的偏移

				if (ins.code_data[8] == 'J')            //如果是跳转指令
                                {
                                        if ( ins.num & 0x8000 )		//如果是负的
                                                ins.num |= (~(long)0) << 16;	//做符号扩展
                                        ins.num += (ins.current_code+3);//加上下一条指令的偏移
					NumToText(4);
                                }
				else
					NumToText(2);
                        }
                        else
                        {
                                ins.operand_len += 4;
                                ins.num = *((long *)(ins.ins_buf+ins.processing)) & 0xffffffff;	//这里ins.num保存的必须是正确的32位数,因为下边寻址方式J要加上下一指令的偏移

                                if (ins.code_data[8] == 'J')            //如果是跳转指令
                                {
                                        if ( ins.num & 0x80000000 )		//如果是负的
                                                ins.num |= (~(long)0) << 32;	//做符号扩展
                                        ins.num += (ins.current_code+5);	//加上下一条指令的偏移
                                }
				NumToText(4);
                        }
                        break;
        }

        return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -