《C++反汇编与逆向分析技术揭秘》--钱林松,赵海旭 著
作者:互联网
1 熟悉工作环境和相关工具
1.1 调试工具Microsoft Visual C++6.0和OllyDBG
1.2 反汇编静态分析工具IDA
1.3 反汇编引擎的工作原理
2 基本数据类型的表现形式
2.1 整数类型
2.2 浮点数类型
2.3 字符和字符串
2.4 布尔类型
2.5 地址、指针和引用
2.6 常量
3 认识启动函数,找到用户入口
3.1 程序的真正入口
3.2 了解VC++6.0的启动函数
3.3 main函数的识别
4 观察各种表达式的求值过程
4.1 算术运算和赋值
4.2 关系运算和逻辑运算
4.3 位运算
4.4 编译器使用的优化技巧
4.5 一次算法逆向之旅
5 流程控制语句的识别
5.1 if语句
-
if语句只能判断两种情况,0和非0
-
5-1 if语句构成
#include<stdio.h>
int main()
{
int a=2;
if (a==2)//注意与汇编位置对比
{
printf("%d",a);
}
return 0;
}
-
使用相反的条件跳转指令
-
表达式短路和if语句的反汇编一样,不容易区分
总结: ;先执行各类影响标志位的指令 ;其后各种条件跳转指令 JCC xxxx
-
循环结构中也会出现类似代码,分析过程还需要结合上下文
5.2 if...else...语句
- 取相反的条件跳转指令
- if语句条件成立执行后有个jmp指令,跳过else的代码块
- 条件表达式与if-else的判断比较难
- 5-3 if-else组合
#include<stdio.h>
int main()
{
int a=2;
if (a==2)
{
printf("a等于2");
}
else{
printf("a不等于2");
}
return 0;
}
- 利用两个跳转(jne,jmp)来区别if块和else块的边界
总结:
;先执行影响标志位的指令
jcc ELSE_BEGIN ;重点
IF_BEGIN:
...
IF_END:
jmp ELSE_END ;重点
ELSE_BEGIN:
...
ELSE_END:
- 在没有高级源码的情况下,分析者需要先定位语句块的边界,然后根据跳转目标和逻辑依赖慢慢推出高级代码
5.3 用if构成的多分支流程
#include<stdio.h>
int main()
{
int a=2;
if (a<0)
{
printf("a小于2");
}
else if(a==2)
{
printf("a等于2");
}
else
{
printf("a为其他");
}
return 0;
}
- 每一个if语句由cmp与jcc组成,而else代码之前没有cmp判断,直接跳到最后
总结:
;会影响标志位的指令
JCC ELSE_IF_BEGIN //if条件不成立,跳转到下一条if_else首地址
IF_BEGIN:
... //if条件成立执行代码块
IF_END:
jmp END //执行if后跳出到结束地址
ELSE_IF_BEGIN: //else_if条件不成立,跳转到else首地址
;会影响标志位的指令
JCC ELSE_BEGIN
... //else_if条件成立,执行代码块
ELSE_IF_END:
jmp END //执行else_if后跳出到结束地址
ELSE_BEGIN: //if和else_if条件都不成立,执行else代码
...
ELSE_END //执行完就结束了,不用再跳转了
...
END:
...
- 编译器自动优化问题,空间与效率的问题
5.4 switch的真相
- switch是常用的多分支结构,效率上高于if else_if语句
#include<stdio.h>
int main()
{
int nIndex = 1;
scanf_s("%d", &nIndex);
switch (nIndex)
{
case 1:
printf("nIndex==1");
case 2:
printf("nIndex==2");
case 100:
printf("nIndex==100");
}
return 0;
}
int main()
{
000C18B0 push ebp
000C18B1 mov ebp,esp
000C18B3 sub esp,0D4h
000C18B9 push ebx
000C18BA push esi
000C18BB push edi
000C18BC lea edi,[ebp-14h]
000C18BF mov ecx,5
000C18C4 mov eax,0CCCCCCCCh
000C18C9 rep stos dword ptr es:[edi]
000C18CB mov eax,dword ptr [__security_cookie (0CA024h)]
000C18D0 xor eax,ebp
000C18D2 mov dword ptr [ebp-4],eax
000C18D5 mov ecx,offset _A43DB3BE_源@cpp (0CC003h)
000C18DA call @__CheckForDebuggerJustMyCode@4 (0C1316h)
int nIndex = 1;
000C18DF mov dword ptr [nIndex],1
scanf_s("%d", &nIndex);
000C18E6 lea eax,[nIndex]
000C18E9 push eax
000C18EA push offset string "%s" (0C7B30h)
000C18EF call _scanf_s (0C13C0h)
000C18F4 add esp,8
switch (nIndex)
000C18F7 mov eax,dword ptr [nIndex]
000C18FA mov dword ptr [ebp-0D4h],eax
000C1900 cmp dword ptr [ebp-0D4h],1
000C1907 je __$EncStackInitStart+61h (0C191Dh)
000C1909 cmp dword ptr [ebp-0D4h],2
000C1910 je _printf+0Ah (0C192Ah)
000C1912 cmp dword ptr [ebp-0D4h],64h
000C1919 je _printf+17h (0C1937h)
000C191B jmp _printf+24h (0C1944h)
{
case 1:
printf("nIndex==1");
000C191D push offset string "two" (0C7B34h)
000C1922 call _printf (0C10CDh)
000C1927 add esp,4
case 2:
printf("nIndex==2");
000C192A push offset string "nIndex==2" (0C7BE4h)
000C192F call _printf (0C10CDh)
000C1934 add esp,4
case 100:
printf("nIndex==100");
000C1937 push offset string "nIndex==100" (0C7BF0h)
000C193C call _printf (0C10CDh)
000C1941 add esp,4
}
return 0;
000C1944 xor eax,eax
}
- if...else_if会在条件跳转后紧跟语句块,switch case则将所有的条件跳转放到一起,把case语句块也放到了一起
5.5 难以构成跳转表的switch
5.6 降低判定树的高度
5.7 do/while/for的比较
5.8 编译器对循环结构的优化
6 函数的工作原理
6.1 栈帧的形参和关闭
6.2 各种调用方式的考察
6.3 使用ebp或esp寻址
6.4 函数的参数
6.5 函数的返回值
6.6 回顾
7 变量在内存中的位置和访问方式
7.1 全局变量和局部变量的区别
7.2 局部静态变量的工作方式
7.3 堆变量
8 数组和指针的寻址
8.1 数组在函数内
8.2 数组作为参数
8.3 数组作为返回值
8.4 下标寻址和指针寻址
8.5 多维数组
8.6 存放指针类型数据的数组
8.7 指向数组的指针变量
8.8 函数指针
9 结构体和类
9.1 对象的内存布局
9.2 this指针
9.3 静态数据成员
9.4 对象作为函数参数
9.5 对象作为返回值
10 关于构造函数和析构函数
10.1 构造函数的出现时机
10.2 每个对象都有默认的构造函数吗
10.3 析构函数的出现时机
11 关于虚函数
11.1 虚函数的机制
11.2 虚函数的识别
12 从内存角度看继承和多重继承
- 父类指针指向子类对象
12.1 识别类和类之间的关系
-
子类具备父类所有成员数据,成员函数
-
父类声明为私有的成员,子类对象无法直接访问,但在子类对象的内存结构中,父类私有的成员数据依然存在
-
C++访问权限仅限于编译层面,不会影响对象的内存结构
-
12-1 定义派生类和继承类
12.2 多重继承
12.3 抽象类
12.4 菱形继承
13 异常处理
13.1 异常处理的相关知识
13.2 异常类型为基本数据类型的处理流程
13.3 异常类型为对象的处理流程
13.4 识别异常处理
14 PEiD的工作原理分析
14.1 开发环境的识别
14.2 开发环境的伪造
15 “熊猫烧香”病毒逆向分析
15.1 调试环境配置
15.2 病毒程序初步分析
15.3 “熊猫烧香”启动过程分析
15.4 “熊猫烧香”的自我保护分析
15.5 “熊猫烧香”的感染过程分析
16 调试器OllyDBG的工作原理分析
16.1 INT3断点
16.2内存断点
16.3 硬件断点
16.4 异常处理机制
16.5 加载调试程序
17 反汇编代码的重建与编译
17.1 重建反汇编代码
17.2 编译重建后的反汇编代码
标签:--,跳转,C++,else,钱林松,ebp,printf,ELSE,nIndex 来源: https://www.cnblogs.com/ruler3389/p/15363773.html