C语言代码逆向基础--循环结构

C语言代码逆向基础–循环结构

C语言循环结构有for循环、while循环、do循环和goto。

for循环

编写个简单的1-100累加和代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>

int main()

{
int nNum = 0,nSum = 0;
for(nNum=1;nNum<=100;nNum++)
{
nSum += nNum;
}

printf("nSum = %d \r\n",nSum);

return 0;
}

其反汇编代码如下,可以分为三个部分,第一部分为初始化部分,第二部分为修改循环变量的部分,第三部分为比较循环条件和循环体的部分。

第一部分反汇编代码如下

1
2
3
4
.text:00401028                 mov     [ebp+nNum], 0
.text:0040102F mov [ebp+nSum], 0
.text:00401036 mov [ebp+nNum], 1
.text:0040103D jmp short loc_401048

对nNum和nSum变量进行初始化,然后跳转到401048地址,其为循环部分判断条件,如下

1
2
3
4
5
6
7
.text:00401048 loc_401048:                             ; CODE XREF: _main_0+2D↑j
.text:00401048 cmp [ebp+nNum], 64h ; 'd'
.text:0040104C jg short loc_401059
.text:0040104E mov ecx, [ebp+nSum]
.text:00401051 add ecx, [ebp+nNum]
.text:00401054 mov [ebp+nSum], ecx
.text:00401057 jmp short loc_40103F

将nNum与100进行比较,jg指令(大于则跳转)不跳转,执行下面一系列指令,执行nSum+=nNum得到nSum值,然后跳转到40103F地址执行相关指令,如下

1
2
3
4
.text:0040103F loc_40103F:                             ; CODE XREF: _main_0+47↓j
.text:0040103F mov eax, [ebp+nNum]
.text:00401042 add eax, 1
.text:00401045 mov [ebp+nNum], eax

将nNum变量加1操作,然后再执行上面的比较代码,直到jg跳转到401059地址处的指令,输出nSum的值,结束程序。

结构

1
2
3
4
5
6
7
8
9
10
11
;初始化变量
mov xxx,xxx

LOC_STEP:
;修改循环变量
LOC_CMP:
;循环变量的判断
jxx LOC_ENDFO(符合则跳转到LOC_ENDFOR,否则执行循环体)
;循环体
jmp LOC_STEP
LOC_ENDFOR:

Do…while循环

do…while循环体总是会被多执行一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>

int main()
{
int nNum=1,nSum=0;
do
{
nSum+=nNum;
nNum++;
}while(nNum<=100);

printf("nSum=%d \r\n",nSum);

return 0;
}

其反汇编代码如下

观察下IDA生成的流程图

反汇编关键代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
.text:00401028                 mov     [ebp+nNum], 1
.text:0040102F mov [ebp+nSum], 0
.text:00401036
.text:00401036 loc_401036: ; CODE XREF: _main_0+3C↓j
.text:00401036 mov eax, [ebp+nSum]
.text:00401039 add eax, [ebp+nNum]
.text:0040103C mov [ebp+nSum], eax
.text:0040103F mov ecx, [ebp+nNum]
.text:00401042 add ecx, 1
.text:00401045 mov [ebp+nNum], ecx
.text:00401048 cmp [ebp+nNum], 64h ; 'd'
.text:0040104C jle short loc_401036
.text:0040104E mov edx, [ebp+nSum]

先对变量nNum和nSum进行初始化,然后执行nSum+=nNum得到nSum的值,并且将nNum的值加1,然后jle指令(小于等于)与100进行比较,符合则跳转到401036地址处执行循环体,否则就输出nSum的值并退出程序。

结构

1
2
3
4
5
6
;初始化变量
LOC_DO:
;执行循环体
;修改循环变量
cmp xxx,xxx ;循环变量的比较
jxx LOC_DO(符合即再次执行循环体,否则跳出循环)

While结构

while循环和do循环之间的区别是再进入循环体之前要先进行一次条件判断;而do循环是先执行循环体再进行判断,会导致多执行一次循环体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>

int main()
{
int nNum=1,nSum=0;
while(nNum<=100)
{
nSum+=nNum;
nNum++;
}

printf("nSum=%d \r\n",nSum);

return 0;
}

其反汇编关键代码如下

生成流程图如下

反汇编关键代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.text:00401028                 mov     [ebp+nNum], 1
.text:0040102F mov [ebp+nSum], 0
.text:00401036
.text:00401036 loc_401036: ; CODE XREF: _main_0+3E↓j
.text:00401036 cmp [ebp+nNum], 64h ; 'd'
.text:0040103A jg short loc_401050
.text:0040103C mov eax, [ebp+nSum]
.text:0040103F add eax, [ebp+nNum]
.text:00401042 mov [ebp+nSum], eax
.text:00401045 mov ecx, [ebp+nNum]
.text:00401048 add ecx, 1
.text:0040104B mov [ebp+nNum], ecx
.text:0040104E jmp short loc_401036
.text:00401050 ; ---------------------------------------------------------------------------
.text:00401050
.text:00401050 loc_401050: ; CODE XREF: _main_0+2A↑j
.text:00401050 mov edx, [ebp+nSum]

前面对两个变量进行初始化,与do循环的区别是先进行判断比较,使用cmp指令将nNum和100进行比较,jg(大于)指令符合的话就跳转到401050地址的输出nSum值,否则就执行循环体。

结构

1
2
3
4
5
6
7
8
;初始化变量

LOC_WHILE:
cmp xxx,xxx;比较循环变量
jxx LOC_WHILEEND
;循环体
jmp LOC_WHILE
LOC_SHILEEND:

在这三种循环结构中,循环效率从高到低排序:DO>while>for

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2024 John Doe
  • 访问人数: | 浏览次数:

让我给大家分享喜悦吧!

微信