逆向-逻辑流控制
逻辑流控制
在我的抽象中执行逻辑有三种-顺序、选择、循环。默认汇编就是从上到下顺序执行,选择用if-else和switch,循环用while、for等。
分支语句
if-else
int main(int argc, char const *argv[])
{
int a=10;
if (a>10){
printf("a>10");
}else{
printf("a<=10");
}
return 0;
int main(int argc, char const *argv[])
{
int a=10;
if (a>10){
printf("a>10");
}else if(a<2){
printf("a<2");
}else{
printf("2<=a<=10");
}
return 0;
}
从上面两个二分支和三分支可以看出:
- 开始标志就是cmp,jcc 这两条标志语句,代表条件判断。
- 直接跳转的jmp代表执行的是它上面的分支。
- 每个分支内jmp跳的地址是一样的都是else{};这条语句之后的位置。
- 巧妙的运用了顺序结构
switch
int main(int argc, char const *argv[])
{
int a=11;
switch (a)
{
case 10:
printf("a=10");
break;
case 11:
printf("a=11");
break;
case 12:
printf("a=12");
break;
case 13:
printf("a=13");c
break;
case 14:
printf("a=14");
break;
default:
printf("!!");
}
return 0;
}
特征
- 当switch分支小的时候(视不同编译器实现,visual studio 为3个(包含)以下)返回百年结构和if-else结构相同,但是当分支测试的常量连续并且有一定数目,就会根据一个表保存要跳转的地址。
- 如果不是从0开始编译器会减去测试常量这个连续序列的最小值,直接得到偏移地址,加上基址即可到要跳转的分支。
总结
从分支语句中我们可以总结一些特征,测试条件用cmp、fcmp等指令,下面紧跟着jcc指令。jmp代表这个分支执行完了,一般跳出这个分支检测结构,而上面的cmp;jcc连着用的话一般指紧跟着的分支的否定,一般会跳到最后一个分支。switch在大量、连续的分支测试比if-else性能高。
循环
for (a=0;a<10;a++){
sum=sum+a;
}
80483ef: c7 45 f8 00 00 00 00 mov DWORD PTR [ebp-0x8],0x0
80483f6: eb 0a jmp 8048402 <main+0x27>
sum=sum+a;
80483f8: 8b 45 f8 mov eax,DWORD PTR [ebp-0x8]
80483fb: 01 45 fc add DWORD PTR [ebp-0x4],eax
for (a=0;a<10;a++){
80483fe: 83 45 f8 01 add DWORD PTR [ebp-0x8],0x1
8048402: 83 7d f8 09 cmp DWORD PTR [ebp-0x8],0x9
8048406: 7e f0 jle 80483f8 <main+0x1d>
初始化
a=0
mov DWORD PTR [ebp-0x8],0x0
条件判断,可以看到cmp;jcc;判断
cmp DWORD PTR [ebp-0x8],0x9
jle 80483f8 <main+0x1d>
控制变量变化
DWORD PTR [ebp-0x8],0x1
从上到下执行,首先初始化变量,接着直接jmp到cmp判断循环变量,向上跳到循环体
break和continue
for (a=0;a<10;a++){
if (a == 6){
continue;
}
if (a == 7){
break;
}
sum=sum+a;
}
80483ef: c7 45 f8 00 00 00 00 mov DWORD PTR [ebp-0x8],0x0
80483f6: eb 19 jmp 8048411 <main+0x36>
80483f8: 83 7d f8 06 cmp DWORD PTR [ebp-0x8],0x6
80483fc: 74 0e je 804840c <main+0x31>
80483fe: 83 7d f8 07 cmp DWORD PTR [ebp-0x8],0x7
8048402: 74 15 je 8048419 <main+0x3e>
8048404: 8b 45 f8 mov eax,DWORD PTR [ebp-0x8]
8048407: 01 45 fc add DWORD PTR [ebp-0x4],eax
804840a: eb 01 jmp 804840d <main+0x32>
804840c: 90 nop
804840d: 83 45 f8 01 add DWORD PTR [ebp-0x8],0x1
8048411: 83 7d f8 09 cmp DWORD PTR [ebp-0x8],0x9
8048415: 7e e1 jle 80483f8 <main+0x1d>
8048417: eb 01 jmp 804841a <main+0x3f>
8048419: 90 nop
804841a: b8 00 00 00 00 mov eax,0x0
804841f: c9 leave
8048420: c3 ret
break跳出循环jmp 804840d
continue跳到循环变量控制也就是a++;add DWORD PTR [ebp-0x8],0x1
总结
for循环典型特征jmp指令,循环体,条件控制和判断。jmp跳条件控制和判断,然后回调循环体。