热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ODIDA应用分析C++常量字符串指针对象虚函数

OD一些常用的功能??设置软件断点:F2运行程序:F9单步步入:F7单步步过:F8运行到光标处&

 

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
#include

#include

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\r\n"); }~CObjA(){printf("CObjA::~CObjA\r\n"); };
void Print() {printf("Print %d %d\r\n", m_Num1, m_Num2); }
static void Print1() {printf("static Print1\r\n"); }
​friend
void Print2();

private:int m_Num1; int m_Num2;
};

void Print2() {printf("friend Print2\r\n"); }

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\r\n", mNum1, mNum2); }virtual void Print1() {printf("CObjA::Print1\r\n");}
private:int mNum1;int mNum2;
};

CObjA::CObjA()
{mNum1
= 1; mNum2 = 2;
}
CObjA::
~CObjA()
{
}

void hook() {printf("虚函数表 Hook\r\n"); }

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;
}

 

 

 

转:https://www.cnblogs.com/ltyandy/p/11251353.html



推荐阅读
author-avatar
亚瑟女皇韩版欧美风情女装旗舰店
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有