• 【逆向知识】动态调试技巧-C++代码逆向


    1、C++类代码的特点

    寄存器ECX传参时一般用作this指针(对象地址)或是计数器。

    有ecx传参的call,是成员函数,构造函数,析构函数

    能访问成员变量的函数都会有ecx传参

    静态函数、全局函数无ecx(this指针)

    返回值

    寄存器eax一般用作返回值

    识别构造函数的OD反汇编代码

    特点:

    (1) 代码特点:没有返回值、用于初始化

    (2)反汇编特点:有返回值,而且是this指针

    根据反汇编可以看出成员变量的顺序,因为在内存数据中的排布顺序是由代码中成员变量定义顺序决定的。

    识别构造函数的办法:

    (1)构造函数调用时,会使用ECX用于this指针

    (2)构造函数在反汇编层有返回值,是eax存放this指针

    (3)构造函数用于初始化,一般内存如果是未初始化的比如CCCCCCC,经过构造函数会完成初始化。

    (4)如果一个函数有对前4字节初始化为一个指针地址,那么可能是在初始化虚函数表指针。

    如果一个类有虚函数,那么对象的内存数据里会有虚函数指针的定义。构造函数会初始化虚函数表指针,而类中定义多少个虚函数也只有一个虚函数表指针。

    识别成员函数的OD反汇编代码

    特点:

    (1)ECX传递this指针,调用成员函数

    (2)成员函数中会访问exc所指向的内存空间

    成员函数与虚函数本身没有什么区别,所以反汇编出来的代码都差不多。

    识别成员函数:

    (1)如果找到了构造函数,那么下面调用的应该都是成员函数

    (2)成员函数有this指针

    (3)成员函数会访问成员变量,即this指针指向的内存空间

    识别析构函数的OD反汇编代码

    特点与识别:

    (1)有ECX

    (2)用于释放资源,可能有delete,free等

    (3)一般是在函数返回时,编译器生成的调用。

    全局构造与析构函数

    初始化全局对象的构造函数,是在main函数之前,C运行库初始化的代码中_initterm函数

    操作:

    在return下断点,main函数执行完毕后F11继续执行,继续F11return会返回到上一个调用函数。

    exit(xxx) 调用析构函数

    有虚函数的派生类

    派生类对象的构造初始化

    大致流程:

    派生类的构造函数
    {
          基类的构造函数(函数中会初始化虚函数表指针)
    
          初始化虚函数表指针
    
          初始化数据
    }
    

    虚函数表创建

    虚函数表是在程序编译时就生成了,而且存储在程序的只读区段中

    程序中如果创建了多个对象,只会有一个虚函数表,共用一个虚函数表。

    C++中的多态实现

    	//多态的实现
    	A* pObj = &obj;
    	pObj->printfD();
    

    模拟反汇编的调用流程

    A* pObj = &obj;

    测试代码

    #include "stdafx.h"
    
    class A
    {
    public:
    	A::A() {
    		c = 3;
    		m = 1;
    		n = 2;
    
    
    	};
    
    	virtual void printA() { printf(" A::A
     "); };
    	virtual void printB() { printf(" A::B
     "); };
    	virtual void printC() { printf(" A::C
     "); };
    
    	void printfD() { 
    		
    		printf("(%d,%d)
    ",m,n);
    		printf("hahahahaah");
    	
    	};
    
    	A::~A() {
    	
    		printf(" A::~A
     ");
    	
    	};
    protected:
    private:
    	int n;
    	int c;
    	int m;
    };
    int main()
    {
    	A obj;
    	obj.printA();
    	obj.printfD();
    	printf(" %d
     ",sizeof(obj));
    	printf(" 3333333333333333333333333
     ");
        return 0;
    }
    
  • 相关阅读:
    CentOS /RHEL系统怎么更新安全补丁
    使用yum查询系统安装的软件及可以更新的软件并单独指定升级某一个软件
    惠普服务器通过ILO系统远程安装系统
    django进行数据库迁移的错误处理方法:You are trying to change the nullable field 'title' on book to non-nullable without a d
    Django数据库增删改查
    linux用户
    linux基础
    mysql小白系列_01 原理
    mysql运维入门6:MySQL读写分离
    mysql运维入门5:MySQL+kepalived高可用架构
  • 原文地址:https://www.cnblogs.com/17bdw/p/6674668.html
Copyright © 2020-2023  润新知