zoukankan      html  css  js  c++  java
  • OD-IDA应用-分析C++常量-字符串-指针-对象-虚函数

     

    OD一些常用的功能??

    设置软件断点:F2

    运行程序:F9

    单步步入:F7

    单步步过:F8

    运行到光标处:F4

    如果说我们分析的时候,在反汇编窗口中看到一个地址,想查看这个位置的内存:

    右键­­­­­­­­­­》数据窗口中跟随

    如果说想在反汇编窗口查看一个代码:

    右键­­­­­­­》反汇编窗口中跟随

    如果说我们想搜索指令:

    右键-查找-命令

    搜索所有字符串:

     

    可以使用OD的中文搜索引擎插件,是一个快速便捷的查看字符串的方式。 需要处于所在的模块当中,再去搜索

    断点: 软件断点:F2 在B窗口中可以看到所有的软件断点,方便的禁用和启用断点

    硬件断点

    在代码段上右键,可以设置硬件执行

    在数据段上右键,可以设置硬件访问和硬件写入。

    我们可以在:调试­­­­­》硬件断点中看到我们设置过的硬件断点。

    内存断点:

    用的时候并不太多

    可以设置:读 写 执行

    条件断点:

    消息断点:

    必须将目标位置事先指定为回调函数的原型:

     

    之后在此位置点击右键,就可以设置消息断点: 使得程序可以在触发某一种消息的时候中断下来。

    查看堆栈:

    [ebp­-8] 局部变量的区域

    [ebp­-4] 局部变量的区域

    [ebp] 上一个函数的

    ebp [ebp+4] 返回地址

    [ebp+8] 第一个参数

    有两个重要的用处:

    • 1 分析 参数与局部变量

    • 2 能够查看到调用关系,回溯出整个的调用链。

    通常分析程序的一般步骤:

    1 运行一下程序,找到我们感兴趣的功能,然后搜集信息

    • a. 编译环境 是否加壳了

    • b. 有哪些关键字符串

    • c. 可能调用的什么函数

    • d. 使用了哪些DLL

    • e. 如果有关键dll,可以分析关键dll中的字符串 函数名 等等信息

    2 猜测了关键函数,关键字符串,使用了什么库之后,有对应的一些方法

    • 1 搜索关键字符串

    • 2 在关键函数上下断点 运行程序 栈回溯

    IDA的一些常见功能:

    切换代码视图和图形视图:空格

    想要重命名:n 将常量设置

    enum: m

    识别一个位置为结构体:atl+q

    分析VC++程序:

    #define SIZE  100                   
    const int g_nCount = 1000; 
    enum eData { 
        enum_TYPE_1 = 1,  
        enum_TYPE_2 = 2,   
        enum_TYPE_3 = 3 };
    struct sData {  
        int n;   
        float fNum; 
        char chA; };
    int main() 
    {    
        bool bRet = true;  // 布尔常量
        const int nCount = SIZE;             // 宏常量 
        const char* szHello = "Hello 15PB";  // 字符串常量 
        const eData data = enum_TYPE_1;      // 枚举常量 
        const float  fNum = 1.5;                 // 浮点
        常量     
            const sData stc = { 
            1,
            2.0,
            '1' 
        };   // 结构体常量    
        return 0; 
    }

    这是一个结构体,要把这3个合成一个结构体的操作如下:

     

     

    1.Structurs 视图

    2.按下Ins按钮跳出

     

    3.按d添加成员及更改db类型,只能更改最后一个成员

     

     

    4.选择结构体首成员位置ALT+Q选择自己定义的结构体。

    5.成功之后显示

     

    如何将一个数组显示为浮点数:

    分析字符串:

    #include <iostream>
    #include <iostream>
    #include <afx.h> 
    int main()
    {
        char szStr[100] = { "szStr[100] Hello 15PB" };     wchar_t szWchar[100] = L"szWchar Hello 15PB";     char szHello[] = "szHello[] Hello 15PB";
        std::string strHello = "string Hello 15PB";
        CString csString = "CString Hello 15PB";
        return 0;
    }

     

    char*是4个字节4个字节分开传到栈里,再用memcopy

    总结:字符串都是放在rdata段中,指令是使用字符串的地址。 分析 STL中的string对象

    我们应该能够识别出可能是thiscall的函数。

    在调用函数的时候,传递ecx是传递对象的地址。

     

     

    分析CString的信息

     

    CString只有一个字段。

     

    指针和引用:

    int main()
    {
        int n = 15;
        int* pData = &n;     int &m = n;
        return 0;
    }

    指针和引用在汇编层面来看,没有任何区别:

     

    关于全局对象和局部对象调用:

    成员函数

    静态函数

    友元函数的行为

    class CObjA
    { 
    public:
        CObjA() {
            m_Num1 = 1;
            m_Num2 = 2;
            printf("CObjA::CObjA
    ");     }
        ~CObjA(){
            printf("CObjA::~CObjA
    ");     };
    ​
        void Print() {
            printf("Print %d %d
    ", m_Num1, m_Num2);     }
    ​
        static void Print1() {
            printf("static Print1
    ");     }
    ​
        friend void Print2();
    ​
    private:
        int m_Num1;     int m_Num2; 
    };
    ​
    void Print2() {
        printf("friend Print2
    "); }
    ​
    CObjA g_obj; //本身会生成一个函数,用于调用构造函数
    int main()
    {
        CObjA obj;
        g_obj.Print();
        obj.Print();
        obj.Print1();
        Print2();
        // 函数末尾 调用析构函数     return 0;
    }

    总结:

     

    全局对象调用成员函数,ecx是通过mov指令得到的对象地址 局部对象调用成员函数,ecx是通过lea指令得到的对象地址 静态函数和友元函数 都和普通函数的调用是一致的。

     

    虚函数的调用:

     

    class CObjA
    { 
    public:
        CObjA();
        ~CObjA();
        virtual void Print() {
            printf("CObjA::Print %d %d
    ", mNum1, mNum2);     }
        virtual void Print1() {
            printf("CObjA::Print1
    ");
        } 
    private:
        int mNum1;
        int mNum2;
    };
    ​
    CObjA::CObjA()
    {
        mNum1 = 1;     mNum2 = 2; 
    }
    CObjA::~CObjA()
    {
    }
    ​
    void hook() {
        printf("虚函数表 Hook
    "); }
    ​
    int main()
    {
        CObjA objA;
        CObjA* pObj = &objA;     pObj‐>Print();
    ​
        // 修改虚表中的函数地址
        // 1. 获取虚函数表地址
        PDWORD dwVTableAddr = *(DWORD**)pObj;
        // 2. 修改内存属性
        DWORD dwOldProtect;
        VirtualProtect(dwVTableAddr, 4, PAGE_READWRITE,&dwOldProtect);     // 3. 修改函数地址
        *dwVTableAddr = (DWORD)hook;
        // 4. 恢复内存属性
        VirtualProtect(dwVTableAddr, 4, dwOldProtect, &dwOldProtect);     // 
        pObj‐>Print();
        return 0;
    }

     

  • 相关阅读:
    第二次作业
    《自动化技术中的进给电气传动》读书笔记1.1-1.2
    证券投资分析
    微信官方文档概述
    联想拯救者Y7000电池无法充电问题
    Ubuntu用户权限管理
    证券市场基础知识
    Markdown All in One使用教程
    Markdown学习笔记
    第九周
  • 原文地址:https://www.cnblogs.com/ltyandy/p/11251353.html
Copyright © 2011-2022 走看看