循环
do…while
do…while 代码定式,debug和release差不多
while_begin:
...
... ;中间部分为循环体
...
JXX while_begin ;注意这里为上跳
示例
int main(int argc, char* argv[])
{
int nSum = 0;
int i = 0;
do
{
nSum = nSum + i;
i++;
printf("HelloWorld");
} while (i <= argc);
printf("HelloWorld");
printf("HelloWorld");
printf("HelloWorld");
return argc;
}
while
release while 代码定式
//优化成 if条件里面嵌套一个do...while
IF 判断条件 ;if
jxx while_end ;判断为相反的条件下跳
while_begin: ;do
...
... ;中间部分为循环体
...
JXX while_begin ;while 注意这里为上跳循环
while_end
示例
int main(int argc, char* argv[])
{
int nSum = 0;
while (argc <= 100)
{
printf("%d", nSum);
argc--;
}
return argc;
}
debug版 while
for
DEBUG版 for循环 代码定式
FOR_INIT:
int i=0;
jmp FOR_CMP
FOR_SETP:
++i;
FOR_CMP
i>argc
jxx FOR_END
FOR_BODY:
nSum=nSum+i;
jmp FOR_SETP
FOR_END
示例
int main(int argc, char* argv[])
{
int nSum = 0;
int i = 0;
for (i = 0; i < argc; i++)
{
nSum = nSum + i;
i++;
printf("%d\n", i);
}
return argc;
}
release版 for循环 代码定式
//优化成if do...while 形式
//如果判断条件简单可能会出现代码外提( i < argc / 7 ),把 argc / 7的结果提到外面
//判断条件如果是与函数返回值比较则不会外提( i < strlen("hello") ),函数返回值优化不了,因为返回值是未知的
//强度削弱,如果循环体内代码简单,可能会将除法优化成加法执行
int main(int argc, char* argv[])
{
int i = 0;
int nSum = 0;
for (i = 0; i <= argc; ++i)
{
nSum = i*100;
printf("%d\n", nSum);
};
}
release版 for循环 累加优化
- 出现场景:在循环中出现累加
- 优化形式:编译器可能会视情况将其分为不大于4部分累加
- 优势:可以减少循环的次数
代码案例
int main(int argc)
{
int nSum = 0;
for (int i = 0; i < 50; i++)
{
nSum += i;
}
printf("%d", nSum);
return 0;
}
变量
全局变量和静态全局
- 全局变量和静态全局特征 :函数内会通过立即数间接寻址操作变量
初始化位置定位
- 下断点查找
main函数下断点找函数调用堆栈,找第二个_initterm(第一个用于初始化std库,第二个保存了初始化全局变量的函数指针)针对不同编译器可以自己写程序调试,观察具体赋值的API - 利用od查找
全局位置下硬件写入断点
断点来的时候就是初始化的位置
代码示例
/*
_initterm的两个参数存的是函数指针的范围,如这个程序的RetInt函数指针就放在这个范围中
通过遍历这个范围来调用函数指针来在main函数之前初始化
*/
int RetInt()
{
int n = 0;
scanf("%d", &n);
return n;
}
int g_nNumber = RetInt();
int main(int argc)
{
g_nNumber = 3;
scanf("%d", &g_nNumber);
return 0;
}
可以通过IDA找到这个函数,然后找到参数,通过参数获取函数指针数组,依次查找到对应的函数指针,去查看这个函数功能
局部变量和块变量
局部变量和块变量特征
1.EBP定位
- EBP + val(>4) 访问的就是参数
- EBP - val 访问的就是局部变量
2.IDA定位
- r(返回地址) 上面的是变量
静态局部变量
静态局部变量特征
1。进函数后,初始化过程会有一个条件判断
- 取标志位判断是否初始化过
- 未初始化过则进行初始化
- 已初始化过会直接跳转至初始化结束位置
2.如果是高版本IDA,则会存放在TLS段内,每个线程内独享
代码示例
int main(int argc, char* argv[])
{
static int nNumber = argc;
scanf("%d",&nNumber);
return nNumber;
}
vc6.0