首页 > 编程语言 >c++ 32位异常还原

c++ 32位异常还原

时间:2023-09-13 21:13:19浏览次数:48  
标签:case CAccessExcepction CExceptionBase 32 c++ 还原 printf catch throw

本文中的例子下载地址

https://wwmf.lanzout.com/ij4zq18au9yd
密码:2vts

确定try的位置

首先确定try的位置

image

上面明显是一个SEH结构,在c++异常中,state固定在var_4的位置上,这里state初始化位-1,我们将var_4改名为state

image

上图为ida的反编译图,当state赋值为0时,为try的开始,state赋值为-1时表示try块的结束

还原case1 - 4

下面我们分析每一个抛出的异常

image

_CxxThrowException的第一个参数为抛出异常的地址,那么这里的异常应该时一个常量3,我们可以跳转到第二个参数ThrowInfo

image

ThrowInfo的数据结构

image

上面是ThrowInfo的数据结构

可以看到这个异常时一个简单类型异常,并且为int

case 1 - 4 都是差不多的,它们可还原为下面的代码

		case 1:
    		throw 3;
   		case 2:
     		throw 3.0f;
    	case 3:
     		throw '3';
    	case 4:
     		throw 3.0;

还原case 5 - 6

image

image

下面看case 5,v7应该保存了这个异常对象的地址,sub_401310是该对象的构造函数,我们先分析这个类的类名,

image

在CatchTableTypeArray中,前面的类是抛出的类(这里是CDiv0Excepction),后面的类是该类的基类(这里为CExceptionBase),所以这里抛出的类为CDiv0Excepction

现在代码可还原为

case 5:
	throw CDiv0Excepction();

然后我们再分析CDiv0Excepction的构造函数

image

经过我们前面的分析,知道CDiv0Excepction有个基类CExceptionBase,所以sub_401360应为CExceptionBase的构造函数,现在将sub_401360重命名为CExceptionBase,看下图

image

这方面可异常关系不大,所以我简略过,下面查看CDiv0Excepction和CExceptionBase的虚表,最终可还原为

class CExceptionBase{
    public:
		virtual char * toString() = 0;
}

class CDiv0Excepction : public CExceptionBase{
    public:
    	CDiv0Excepction(){
        	printf("CExcepctionDiv0()\r\n");    
        }
    	virtual char * toString(){
            return "div zero excepction";
        }
}

case 6 和 case5是差不多的 ,最终可还原为


class CAccessExcepction : public CExceptionBase{
    public:
    	CAccessExcepction(){
        	printf("CAccessExcepction()\r\n");   
        }
    	virtual char * toString(){
            return "access excepction";
        }
}


case 6:
	throw CAccessExcepction();

还原case 7

下面看case 7

image

image

image

看上面我们可以看到case 7抛出的是一个指针CAccessExcepction *,(所有的对象指针都继承void *),所以下面可还原为

case 7:
	throw new CAccessExcepction();

最终try块可还原为

class CExceptionBase{
    public:
		virtual char * toString() = 0;
}

class CDiv0Excepction : public CExceptionBase{
    public:
    	CDiv0Excepction(){
        	printf("CExcepctionDiv0()\r\n");    
        }
    	virtual char * toString(){
            return "div zero excepction";
        }
}
class CAccessExcepction : public CExceptionBase{
    public:
    	CAccessExcepction(){
        	printf("CAccessExcepction()\r\n");   
        }
    	virtual char * toString(){
            return "access excepction";
        }
}

int sub_401000(int n){
    
    try{
        switch(n){
            case 1:
                throw 3;
            case 2:
                throw 3.0f;
            case 3:
                throw '3';
            case 4:
                throw 3.0;
        	case 5:
				throw CDiv0Excepction();
        	case 6:
				throw CAccessExcepction();
        	case 7:
				throw new CAccessExcepction();
    }
    catch...
}

还原前面4个catch

下面还原catch

image

我们可以看到再函数开头有明显的SEH增加节点的行为转到SEH_401000

image

看到这里是FuncInfo的地址,下面转到FuncInfo

image

FuncInfo的结构

image

上面为FuncInfo的结构

上面只有一个TryBlockMapEntry,代表这里只有一个try块,catch的数量为TryBlockMapEntry的第四个成员dwCatchCount,这里有7个catch块,在ida中msRttiDscr表示为HandlerType

msRttiDscr 有几个成员需要关注,pType表明了catch的类型,CatchProc表示catch后执行的函数,dispCatchObjOffset表示catch后异常对象在栈中的偏移(以EBP为基准线)

前面四个可还原为

    catch(int a){
    	printf("catch int %d\r\n",a);
    }
     catch(float a){
    	printf("catch float %f\r\n",a);
    }
     catch(char a){
    	printf("catch char %c\r\n",a);
    }
    catch(double a){
    	printf("catch double %f\r\n",a);
    }

还原剩下的catch异常

现在还原剩下的catch异常

image

大家看上面圈出的catch异常,可能会认为这个异常类型为CExceptionBase,但是注意看msRttiDscr 的第一个成员nFlag的值为8,这代表这是一个引用类型的异常,所以这个catch异常可还原为

 catch(CExceptionBase& a){
    	printf("catch error %s\r\n",a.toString());
    }

第6个catch异常可还原为

 catch(CAccessExcepction* a){
    	printf("catch error %s\r\n",a->toString());
    }

最后一个异常的类型为0,这个的意思是任何异常都匹配,这个catch异常可还原为

 catch(...){
    	printf("catch ...\r\n");
    }

还原程序的结尾

最后我们这个程序的结尾

我们找最后一个catch异常的catch函数(其实随便一个就可以),

image

image

我们可以看到在catch函数中,最后会返回一个地址,这个地址就是catch函数执行完,要跳转的那个地址,我们跟过去

image

看到上面将state设置为-1,代表try ... catch结束了,再接着跳转到loc_40122E

image

这就是这个函数的结尾,可还原为

printf("Test end!\r\n")

整个函数的还原

最后整理一下整个函数的还原情况

#include <iostream>

class CExceptionBase{
    public:
        virtual char * toString() = 0;
};

class CDiv0Excepction : public CExceptionBase{
    public:
        CDiv0Excepction(){
            printf("CExcepctionDiv0()\r\n");    
        }
        virtual char * toString(){
            return "div zero excepction";
        }
};
class CAccessExcepction : public CExceptionBase{
    public:
        CAccessExcepction(){
            printf("CAccessExcepction()\r\n");   
        }
        virtual char * toString(){
            return "access excepction";
        }
};

int sub_401000(int n){
    
    try{
        switch(n){
            case 1:
                throw 3;
            case 2:
                throw 3.0f;
            case 3:
                throw '3';
            case 4:
                throw 3.0;
            case 5:
                throw CDiv0Excepction();
            case 6:
                throw CAccessExcepction();
            case 7:
                throw new CAccessExcepction();
            }
    }
    catch(int a){
    printf("catch int %d\r\n",a);
    }
    catch(float a){
    printf("catch float %f\r\n",a);
    }
    catch(char a){
    printf("catch char %c\r\n",a);
    }
    catch(double a){
    printf("catch double %f\r\n",a);
    }
     catch(CExceptionBase& a){
        printf("catch error %s\r\n",a.toString());
    }
     catch(CAccessExcepction* a){
        printf("catch error %s\r\n",a->toString());
    }
     catch(...){
        printf("catch ...\r\n");
    }
    printf("Test end!\r\n");
}

int main(){

    sub_401000(1);
}

标签:case,CAccessExcepction,CExceptionBase,32,c++,还原,printf,catch,throw
From: https://www.cnblogs.com/czlnb/p/17700753.html

相关文章

  • CF1332E Height All the Same
    原题翻译首先看到这题首先可以想到应该和奇偶性相关……然后就没有一点思路了,遂看题解首先,可以观察到结果和实际的高度无关,之和高度的奇偶性有关。这个很好理解,因为我们可以用操作\(2\)使得在同奇偶性的数域内变化。因此我们只考虑操作\(1\)这里要知道一个结论:如果\(a_{i,j......
  • 对标金九银十,分享32个模块的Android面试题,分分钟拿捏面试官
    前言2023年初伴随着疫情结束,迎来了“金三银四”。以为终于迎来胜利的“曙光”,不成想,现实却是当头一棒!!!从“金三银四”的“战绩”来看,程序员跳槽或者找工作并不理想,大批人迟迟找不到工作,大厂仍旧在进行几轮裁员,整个就业市场都不是太好!出现这种情况是因为中美贸易战,导致大环境不好、大......
  • c/c++ 混合编译makefile
    CC=gccC++=g++LINK=g++INCLUDES=-L.-IsconvLIBS=-lz-lmCCFLAGS=$(COMPILER_FLAGS)--std=c99-c-g-MMD-MP$(DEFINES)C++FLAGS=$(COMPILER_FLAGS)-std=c++11-c-g-O2-W-WallTARGET=222CFILES=sconv/sconv.cC++FILES=2.cppOBJ......
  • 复习c++
    一些偏门的点endl可以用\n代替cout<<"Helloworld"<<"\n"intmain()括号里加void才能表示不可传参//这样是正确的intmain(){if(0)main(42);}//这样会出错intmain(void){if(0)main(42);}默认编译产生的文件名就是cpp的名且不带后面的参数。如果......
  • C++算法进阶系列之倍增算法解决求幂运算
    1.引言学习倍增算法,先了解什么是倍增以及倍增算法的优势。如果面前有一堆石子,要求计算出石子的总数量。这是一个简单的数数问题,可以:一颗石子一颗石子的数。两颗石子两颗石子的数。三颗石子三颗石子的数。或者更多颗石子更多颗石子的数……在石子很多的情况下,每一次选择更......
  • 32笔记
    重新定义fputcintfputc(intch,FILE*f){uint8_ttemp[1]={ch};HAL_UART_Transmit(&huart1,temp,1,2);}printf("%c",a);输出单个字符。printf("%d",a);输出十进制整数。printf("%f",a);输出十进制浮点数.printf("%o",a);输出八进制数。......
  • C++11之智能指针(万字长文详解)
    C++11之智能指针为什么需要智能指针#include<iostream>usingnamespacestd;intdiv(){inta,b;cin>>a>>b;if(b==0)throwinvalid_argument("除0错误");returna/b;}voidFunc(){//1、如果p1这......
  • stm32f103移植lvgl
    这篇需做前期工作:https://www.cnblogs.com/njit-sam/p/17699205.htmlLVGL官方主页:https://lvgl.io/当你想快速上手时,点击这个:https://docs.lvgl.io/master/get-started/quick-overview.html这里,官方建议可以先在电脑上模拟,按照步骤一步步来就可以了,笔者选择的是CodeBlocks,配合......
  • SI3262 低功耗 SOC +13.56mhz刷卡+触摸三合一芯片,适用于智能锁方案
    Si3262是一款高度集成的低功耗SOC芯片,其集成了基于RISC-V核的低功耗MCU和工作在13.56MHz的非接触式读写器模块。MCU模块具有低功耗、LowPinCount、宽电压工作范围,集成了13/14/15/16位精度的ADC、LVD、UART、SPI、I2C、TIMER、WUP、IWDG、RTC、TSC等丰富的外设。内核......
  • 【Docker】# MySQL从安装到备份还原
    Writer:夏明亮Date:2022/03/28Docker安装略MySQL安装部署https://hub.docker.com/_/mysql/#:~:text=Run%20docker%20stack%20deploy%20-c%20stack.yml%20mysql%20%28or,you%20to%20run%20commands%20inside%20a%20Docker%20container.搜索合适的镜像[root@docker-master~]#dockers......