【从零开始的新手之旅】:2023西工大计算机系统基础实验之Lab2

本文主要是介绍【从零开始的新手之旅】:2023西工大计算机系统基础实验之Lab2,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实验要求

        通过程序反汇编和逆向工程拆除所给的目标代码文中的二进制炸弹。⼀个“Binary Bombs”(二进制炸弹)是⼀个Linux可执行C程序,包含phase1~phase6共6个阶段,即6个炸弹。炸弹运⾏各阶段要求输⼊⼀个字符串,若输⼊符合程序预期,该阶段炸弹被“拆除”,否则“爆炸”。

        每个阶段考察机器级语言程序的不同方面,难度递增

*阶段1:字符串比较
*阶段2:循环
*阶段3:条件/分支:含switch语句
*阶段4:递归调用和栈
*阶段5:数组
*阶段6:链表/指针/结构
*秘密阶段(secret_phase)(选做)

实验所用

        *对程序机器级表示的基本理解(比如大端排序与小端排序;数组等数据在十六进制数表示的二进制文本中是如何存储的,还有栈的生长是从低地址开始还是从高地址开始的等等)   

        *出色的AI大模型(gdb调试器和objdump工具的指令不会用时可以问,类似高级语言的伪代码看不懂也可以问,用十六进制数表示的二进制文本看不懂还是可以问)

        *IDA(是一款业界领先的专业级静态反编译和逆向工程工具,以其卓越的功能和强大的分析能力闻名于网络安全、恶意软件分析、二进制逆向工程等领域)

        对于某些架构(如x86),IDA Pro包含了高度优化的反编译器,可以生成类似高级语言的伪代码,极大地简化了逆向工程的过程。这样实验某种程度上就变成了C语言程序阅读题。

        虽然实验目的是希望能够让学生熟悉汇编语言,并学会使用gdb调试器和objdump工具(偶尔还是会用一下的......)。但奈何本人水平有限,不得不出此下策。

        由于各种原因,在此本人就不放置下载链接了,各位自行上网搜索即可。

IDA超基础用法

我下载的IDA是运行在Windows系统上的。用IDA打开原本需要反汇编的Linux系统可执行文件(我

的文件名叫“bomb”),一路点击蓝色边框的选项就弹出了最下方的界面。

 

 

左边的“函数名称”那栏可以双击选择想要查看的函数 ,右键选择文本视图可以以文本形式而不是图表形式查看反汇编代码。

 

点击“Pseudocode-A”可以查看选定函数对应的类似高级语言的伪代码。标为黄色的函数名或变量名可以双击进入来查看所对应的函数的伪代码,或是全局变量的内容。

 

点击“Hex-Vew-1”可以查看用十六进制数表示的可执行文件的文本内容。

 退出时点击“确定”保存并退出,会生成一个IDB 文件 。需要时双击打开就可以继续查看了。

 

更为详尽且专业的应用方法,敬请参考互联网上的其他资源,例如CSDN博客平台上众多博主发布的相关文章。

实验思考与结果     

Phase1

IDA将汇编语言转为伪代码,可以看出它负责判断输入的字符串与“Houses will begat jobs, jobs will begat houses.”是否一致,若不一致则炸弹爆炸。因此“Houses will begat jobs, jobs will begat houses.”即为答案。

1.	int __cdecl phase_1(int a1)
2.	{
3.	  int result; // eax
4.	
5.	  result = strings_not_equal(a1, "Houses will begat jobs, jobs will begat houses.");
6.	  if ( result )
7.	    explode_bomb();
8.	  return result;
9.	}

Phase2

int __cdecl phase_2(int a1)
{int result; // eaxint v2[6]; // [esp+4h] [ebp-24h] BYREFint i; // [esp+1Ch] [ebp-Ch]read_six_numbers(a1, v2);result = v2[0];if ( v2[0] != 1 )explode_bomb();for ( i = 1; i <= 5; ++i ){result = v2[i];if ( result != 2 * v2[i - 1] )explode_bomb();}return result;
}

用IDA将汇编语言转为伪代码,可以看出这次需要输入六个数字存入数组V2[6]中,且根据read_six_number函数的伪代码可知,六个数字之间要使用空格分开。

根据“if ( v2[0] != 1 )explode_bomb();”可知第一个数字为1,又根据“if ( result != 2 * v2[i - 1] )explode_bomb();”可知从第二个数字开始每一个数字都是前一个数字的2倍,因此答案为“1 2 4 8 16 32”。

int __cdecl read_six_numbers(int a1, int a2)
{int result; // eaxresult = __isoc99_sscanf(a1, "%d %d %d %d %d %d", a2, a2 + 4, a2 + 8, a2 + 12, a2 + 16, a2 + 20);if ( result <= 5 )explode_bomb();return result;
}

Phase3

用IDA将汇编语言转为伪代码,根据“v5 = __isoc99_sscanf(a1, "%d %c %d", &v4, &v2, &v3);”可知这次需要输入一个数字,空格,一个字符,空格和又一个数字。根据“switch(V4)”可知程序会根据V4的值给V6赋上对应的值,并且V3的值也要等于该条件下某个特定值才不会让炸弹爆炸。又根据“if ( v6 != v2 ) explode_bomb();”可知我们输入的V2要等于对应的V4得到的V6。因为有多个出口,因此理论上答案不止一个,为了方便起见,取V4=0,则V6=111,V3=584,由ASCII码对照表可知,V2=‘o’,所以答案可以是“0 o 584”。

int __cdecl phase_3(int a1)
{int result; // eaxunsigned __int8 v2; // [esp+Fh] [ebp-19h] BYREFint v3; // [esp+10h] [ebp-18h] BYREFint v4; // [esp+14h] [ebp-14h] BYREFint v5; // [esp+18h] [ebp-10h]char v6; // [esp+1Fh] [ebp-9h]v5 = 0;v5 = __isoc99_sscanf(a1, "%d %c %d", &v4, &v2, &v3);if ( v5 <= 2 )explode_bomb();switch ( v4 ){case 0:v6 = 111;if ( v3 != 584 )explode_bomb();return result;case 1:v6 = 104;if ( v3 != 677 )explode_bomb();return result;case 2:v6 = 101;if ( v3 != 288 )explode_bomb();return result;case 3:v6 = 120;if ( v3 != 433 )explode_bomb();return result;case 4:v6 = 105;if ( v3 != 636 )explode_bomb();return result;case 5:v6 = 109;if ( v3 != 959 )explode_bomb();return result;case 6:v6 = 114;if ( v3 != 665 )explode_bomb();return result;case 7:v6 = 98;if ( v3 != 508 )explode_bomb();return result;default:v6 = 101;explode_bomb();}result = v2;if ( v6 != v2 )explode_bomb();return result;
}

Phase4

int __cdecl phase_5(int a1)
{int result; // eaxint v2; // [esp+8h] [ebp-20h] BYREFint v3; // [esp+Ch] [ebp-1Ch] BYREFint v4; // [esp+10h] [ebp-18h]int v5; // [esp+14h] [ebp-14h]int v6; // [esp+18h] [ebp-10h]int v7; // [esp+1Ch] [ebp-Ch]v5 = __isoc99_sscanf(a1, "%d %d", &v3, &v2);if ( v5 <= 1 )explode_bomb();v3 &= 0xFu;v4 = v3;v7 = 0;v6 = 0;while ( v3 != 15 ){++v7;v3 = array_2707[v3];v6 += v3;}if ( v7 != 15 || (result = v2, v6 != v2) )explode_bomb();return result;
}

用IDA将汇编语言转为伪代码,由“v6 = __isoc99_sscanf(a1, "%d %d", &v3, &v2);if ( v6 != 2 || v3 >= 0xF ) explode_bomb();”可知,要输入的是两个用空格隔开的数字,且前一个数字不大于15;又由“v5 = 6;v4 = func4(v3, 0, 14);if ( v4 != v5 || (result = v2, v2 != v5) ) explode_bomb();”可知调用func4函数后返回的结果等于6,且V2的值即输入的后一个数字是6 。

int __cdecl func4(int a1, int a2, int a3)
{int v4; // [esp+Ch] [ebp-Ch]v4 = (a3 - a2) / 2 + a2;if ( v4 > a1 )return 2 * func4(a1, a2, v4 - 1);if ( v4 >= a1 )return 0;return 2 * func4(a1, v4 + 1, a3) + 1;
}

现在研究func4函数来得到前一个数字的值。根据“v4 = func4(v3, 0, 14);”、“v4 = (a3 - a2) / 2 + a2;”、“  if ( v4 > a1 ) return 2 * func4(a1, a2, v4 - 1);”等可知,该函数的功能是取传入的后两个数据的平均值与第一个数据的值进行比较,再根据结果进行递归。由“if ( v4 >= a1 ) return 0;”可知,最后一次调用函数时一定得到了0的结果,否则无法结束递归;又因为结果为6,所以过程是“一共四层递归,最后一次调用得0,返回上一层进行2*0+1=1的运算,再返回上一层进行2*1+1=3的运算,最后返回最开始进行3*2=6的运算得到结果”。根据思路逆推可列出下表:

要求

a1

a2

a3

v4

v4>a1

v3

0

14

7

v4<a1

v3

0

6

3

v4<a1

v3

4

6

5

v4=a1

v3

6

6

6

则“v3<7&&v3>3&&v3>5&&v3=6”,故前一个数字的值也为6。因此答案为“6 6”。

Phase5

int __cdecl phase_5(int a1)
{int result; // eaxint v2; // [esp+8h] [ebp-20h] BYREFint v3; // [esp+Ch] [ebp-1Ch] BYREFint v4; // [esp+10h] [ebp-18h]int v5; // [esp+14h] [ebp-14h]int v6; // [esp+18h] [ebp-10h]int v7; // [esp+1Ch] [ebp-Ch]v5 = __isoc99_sscanf(a1, "%d %d", &v3, &v2);if ( v5 <= 1 )explode_bomb();v3 &= 0xFu;v4 = v3;v7 = 0;v6 = 0;while ( v3 != 15 ){++v7;v3 = array_2707[v3];v6 += v3;}if ( v7 != 15 || (result = v2, v6 != v2) )explode_bomb();return result;
}

用IDA将汇编语言转为伪代码,根据“v5 = __isoc99_sscanf(a1, "%d %d", &v3, &v2);”可知字符串的格式为“数字 数字”。“v3&=0XFu”的意思是只保留v3二进制格式的后四位,因为“0XFu”等价于“00001111”且只有1&1=1。故将v3视作一个不大于15的自然数。汇编代码中出现了“array_2707”,而根据“int array_2707[16]”可知这是一个有16个int类型元素的全局数组。

又由“while ( v3 != 15 ){++v7;v3=array_2707[v3]; v6 += v3; }”和“if ( v7 != 15 || (result = v2, v6 != v2) ) explode_bomb();”可知,执行完while循环语句后v3和v7的值都变为15且v2要等于v6。我们还能知道v7相当于计数器,则循环总共执行了15次;在循环中v3每次会取数组array_2707[16]的一个元素,则循环结束后v6表示v3取到的所有元素之和。因此为了得到答案,我们需要知道数组array _2707[16]的结构。

因为一个地址对应一个字节,汇编代码是以十六进制的形式来表示字节的,int类型整数是四个字节长的,且字节的排列方式为小端序,数组元素是按下标从小到大从低地址向高地址排序的,所以array_2707[16]的结构为:

array_2707[0]=10

array_2707[1]=2

array_2707[2]=14

array_2707[3]=7

array_2707[4]=8

array_2707[5]=12

array_2707[6]=15

array_2707[7]=11

array_2707[8]=0

array_2707[9]=4

array_2707[10]=1

array_2707[11]=13

array_2707[12]=3

array_2707[13]=9

array_2707[14]=6

array_2707[15]=5

.data:0804D5E0                               ; int array_2707[16]
.data:0804D5E0 0A 00 00 00                   array_2707 dd 0Ah                       ; DATA XREF: phase_5+52↑r
.data:0804D5E4 02                            db    2
.data:0804D5E5 00                            db    0
.data:0804D5E6 00                            db    0
.data:0804D5E7 00                            db    0
.data:0804D5E8 0E                            db  0Eh
.data:0804D5E9 00                            db    0
.data:0804D5EA 00                            db    0
.data:0804D5EB 00                            db    0
.data:0804D5EC 07                            db    7
.data:0804D5ED 00                            db    0
.data:0804D5EE 00                            db    0
.data:0804D5EF 00                            db    0
.data:0804D5F0 08                            db    8
.data:0804D5F1 00                            db    0
.data:0804D5F2 00                            db    0
.data:0804D5F3 00                            db    0
.data:0804D5F4 0C                            db  0Ch
.data:0804D5F5 00                            db    0
.data:0804D5F6 00                            db    0
.data:0804D5F7 00                            db    0
.data:0804D5F8 0F                            db  0Fh
.data:0804D5F9 00                            db    0
.data:0804D5FA 00                            db    0
.data:0804D5FB 00                            db    0
.data:0804D5FC 0B                            db  0Bh
.data:0804D5FD 00                            db    0
.data:0804D5FE 00                            db    0
.data:0804D5FF 00                            db    0
.data:0804D600 00                            db    0
.data:0804D601 00                            db    0
.data:0804D602 00                            db    0
.data:0804D603 00                            db    0
.data:0804D604 04                            db    4
.data:0804D605 00                            db    0
.data:0804D606 00                            db    0
.data:0804D607 00                            db    0
.data:0804D608 01                            db    1
.data:0804D609 00                            db    0
.data:0804D60A 00                            db    0
.data:0804D60B 00                            db    0
.data:0804D60C 0D                            db  0Dh
.data:0804D60D 00                            db    0
.data:0804D60E 00                            db    0
.data:0804D60F 00                            db    0
.data:0804D610 03                            db    3
.data:0804D611 00                            db    0
.data:0804D612 00                            db    0
.data:0804D613 00                            db    0
.data:0804D614 09                            db    9
.data:0804D615 00                            db    0
.data:0804D616 00                            db    0
.data:0804D617 00                            db    0
.data:0804D618 06                            db    6
.data:0804D619 00                            db    0
.data:0804D61A 00                            db    0
.data:0804D61B 00                            db    0
.data:0804D61C 05                            db    5
.data:0804D61D 00                            db    0
.data:0804D61E 00                            db    0
.data:0804D61F 00                            db    0

 那么由结果逆推可列出下表表示循环过程:

v7

v3

v6

0

5

0

1

12

12

2

3

15

3

7

22

4

11

33

5

13

46

6

9

55

7

4

59

8

8

67

9

0

67

10

10

77

11

1

78

12

2

80

13

14

94

14

6

100

15

15

115

所以“v3&=0XFu=5,v2=v6=115”,则答案为“5 115”。

Phase6

_DWORD *__cdecl phase_6(int a1)
{_DWORD *result; // eaxint v2[6]; // [esp+0h] [ebp-48h]int v3[6]; // [esp+18h] [ebp-30h] BYREF_DWORD *v4; // [esp+30h] [ebp-18h]int j; // [esp+34h] [ebp-14h]int i; // [esp+38h] [ebp-10h]_DWORD *v7; // [esp+3Ch] [ebp-Ch]v4 = &node1;read_six_numbers(a1, v3);for ( i = 0; i <= 5; ++i ){if ( v3[i] <= 0 || v3[i] > 6 )explode_bomb();for ( j = i + 1; j <= 5; ++j ){if ( v3[i] == v3[j] )explode_bomb();}}for ( i = 0; i <= 5; ++i ){v7 = v4;for ( j = 1; v3[i] > j; ++j )v7 = (_DWORD *)v7[2];v2[i] = (int)v7;}v4 = (_DWORD *)v2[0];v7 = (_DWORD *)v2[0];for ( i = 1; i <= 5; ++i ){v7[2] = v2[i];v7 = (_DWORD *)v7[2];}v7[2] = 0;result = v4;v7 = v4;for ( i = 0; i <= 4; ++i ){if ( *v7 > *(_DWORD *)v7[2] )explode_bomb();result = (_DWORD *)v7[2];v7 = result;}return result;
}

用IDA将汇编语言转为伪代码。由“read_six_numbers(a1, (int)v3); for ( i = 0; i <= 5; ++i ) { if ( v3[i] <= 0 ||v3[i] > 6 )explode_bomb();for ( j = i +1;j<=5;++j ){if( v3[i]==v3[j] )explode_bomb();}}”可知,输入的字符串一定“1 2 3 4 5 6”这六个数字的某种排列组合,因为“read_six_numbers(a1, (int)v3);”说明输入的字符串的格式是六个以空格间隔的整数;“if( v3[i]<=0||v3[i] >6 )explode_bomb();”说明这六个数字都是不大于六的自然数;“for ( j = i +1;j<=5;++j ){if( v3[i]==v3[j] )explode_bomb();}}”说明这六个数字互不相等。

.data:0804D4E0                               public node6
.data:0804D4E0 37                            node6 db  37h ; 7
.data:0804D4E1 02                            db    2
.data:0804D4E2 00                            db    0
.data:0804D4E3 00                            db    0
.data:0804D4E4 06                            db    6
.data:0804D4E5 00                            db    0
.data:0804D4E6 00                            db    0
.data:0804D4E7 00                            db    0
.data:0804D4E8 00                            db    0
.data:0804D4E9 00                            db    0
.data:0804D4EA 00                            db    0
.data:0804D4EB 00                            db    0
.data:0804D4EC                               public node5
.data:0804D4EC 81                            node5 db  81h
.data:0804D4ED 01                            db    1
.data:0804D4EE 00                            db    0
.data:0804D4EF 00                            db    0
.data:0804D4F0 05                            db    5
.data:0804D4F1 00                            db    0
.data:0804D4F2 00                            db    0
.data:0804D4F3 00                            db    0
.data:0804D4F4 E0                            db 0E0h
.data:0804D4F5 D4                            db 0D4h
.data:0804D4F6 04                            db    4
.data:0804D4F7 08                            db    8
.data:0804D4F8                               public node4
.data:0804D4F8 D2                            node4 db 0D2h
.data:0804D4F9 02                            db    2
.data:0804D4FA 00                            db    0
.data:0804D4FB 00                            db    0
.data:0804D4FC 04                            db    4
.data:0804D4FD 00                            db    0
.data:0804D4FE 00                            db    0
.data:0804D4FF 00                            db    0
.data:0804D500 EC                            db 0ECh
.data:0804D501 D4                            db 0D4h
.data:0804D502 04                            db    4
.data:0804D503 08                            db    8
.data:0804D504                               public node3
.data:0804D504 0D                            node3 db  0Dh
.data:0804D505 03                            db    3
.data:0804D506 00                            db    0
.data:0804D507 00                            db    0
.data:0804D508 03                            db    3
.data:0804D509 00                            db    0
.data:0804D50A 00                            db    0
.data:0804D50B 00                            db    0
.data:0804D50C F8                            db 0F8h
.data:0804D50D D4                            db 0D4h
.data:0804D50E 04                            db    4
.data:0804D50F 08                            db    8
.data:0804D510                               public node2
.data:0804D510 13                            node2 db  13h
.data:0804D511 03                            db    3
.data:0804D512 00                            db    0
.data:0804D513 00                            db    0
.data:0804D514 02                            db    2
.data:0804D515 00                            db    0
.data:0804D516 00                            db    0
.data:0804D517 00                            db    0
.data:0804D518 04                            db    4
.data:0804D519 D5                            db 0D5h
.data:0804D51A 04                            db    4
.data:0804D51B 08                            db    8
.data:0804D51C                               public node1
.data:0804D51C 8C                            node1 db  8Ch                           ; DATA XREF: phase_6+6↑o
.data:0804D51D 02                            db    2
.data:0804D51E 00                            db    0
.data:0804D51F 00                            db    0
.data:0804D520 01                            db    1
.data:0804D521 00                            db    0
.data:0804D522 00                            db    0
.data:0804D523 00                            db    0
.data:0804D524 10                            db  10h
.data:0804D525 D5                            db 0D5h
.data:0804D526 04                            db    4
.data:0804D527 08                            db    8

因为“v4 = &node1;”且“v7 = v4;”,所以我们必须弄明白“public”类型变量node1的结构。又因为v4,v7全都是“_DWORD *”类型的指针,长度为四个字节,而“public”类型的变量是一个长度为十二个字节的结构体,因此我们可以将变量node1按每四个字节为一组划分为三段,这样“_DWORD *”类型的指针每次只指向其中的一段。又因为之后的代码中出现了“v7 = (_DWORD *)v7[2];”这样的语句,它的意思是记v7中存储的地址对应的“四个字节”为第一段“四个字节”(即v[0])。然后开始向高地址移动两次,取第三段的“四个字节”存入v7之中。值得注意的是,node1的第三段恰好是“public”类型变量node2的地址,且它们的名字惊人地相似,而这样的变量还有四个。这绝对不是巧合,因此我们可以先将变量node(1~6)从低地址到高地址排序备用:

node6

0237h

0

0

node5

0181h

5

& node6

node4

02D2h

4

& node5

node3

030Dh

3

& node4

node2

0313h

2

& node3

node1

028Ch

1

& node2

只有进行了前面分析,我们才有能力来解读“for ( i = 0; i <= 5; ++i ){ v7 = v4;for ( j = 1; v3[i] > j; ++j )v7 = (_DWORD *)v7[2];v2[i] = (int)v7;}”这段代码。外层for循环的“i = 0; i <= 5; ++i”以及内部出现的“v3[i] > j”和“v2[i] = (int)v7;”表明内部的操作与数组v2[6]和v3[6]的所有元素都相关,且两个数组中相同下标的元素间存在某种关联;而内层for循环的“j = 1; v3[i] > j; ++j”表明v3[i]比1大多少,该循环就进行多少次。据此我们列出表格,来记录v3[i]与v7的关系:

v3[i]

v7

1

&node1

2

&node2

3

&node3

4

&node4

5

&node5

6

&node6

所以v3[i]与v2[i]之间的关系具体为v3[i]=k,则v2[i]=&node(k)(k=1~6)。

接着分析“v7 = (_DWORD *)v2[0];for ( i = 1; i <= 5; ++i ) { v7[2] = v2[i];v7 = (_DWORD *)v7[2] ;}v7[2] = 0;”这段代码。该循环执行5次,第一遍循环时“v7[2] = v2[i];”的意思是将变量v2[0]对应的node(x)的第三段的“四个字节”换为v2[1]中存储的&node(y);“v7 = (_DWORD *)v7[2];”的意思则是将v7中存储的值更改为&node(y)。也就是说如果:

v2[0]

&node(x)

v2[1]

&node(y)

v2[2]

&node(z)

v2[3]

&node(u)

v2[4]

&node(v)

v2[5]

&node(w)

那么(该表不表示node变量之间的顺序,且变量的前两段没有改动):

node(x)

X

& node(y)

node(y)

Y

& node(z)

node(z)

Z

& node(u)

node(u)

U

& node(v)

node(v)

V

& node(w)

node(w)

W

0

当然,仅仅是这样的话,得到的信息必然是不足以让我们得出答案的,我们还需要分析剩下的最后那段代码。

现在我们来分析结尾的“v7=v4;for ( i = 0; i<=4;++i ){if( *v7 >*(_DWORD*)v7[2] ) explode_bomb(); result = (_DWORD *)v7[2];  v7 = result; }”。根据上文的“v4 = (_DWORD *)v2[0];”,那么“v7=v4;”是令指针v7重新指向node(x)。接下来是一个执行次数为五的循环,第一遍循环时“*v7 >*(_DWORD*) v7[2] )”的意思是要求node(x)的前四个字节代表的整数一定不大于node(y) 的前四个字节代表的整数;而“result = (_DWORD *)v7[2]; v7 = result;”等价于“v7 = (_DWORD *)v7[2];” 意思是令指针v7指向node(y)。这样的话就要求:“X≤Y≤Z≤U≤V≤W”,又因为“0181h<0237h<028Ch<02D2h <030Dh <0313h”,根据之前的表格可知:

v2[0]

&node5

v2[1]

&node6

v2[2]

&node1

v2[3]

&node4

v2[4]

&node3

v2[5]

&node2

所以

v3[0]

5

v3[1]

6

v3[2]

1

v3[3]

4

v3[4]

3

v3[5]

2

输入的字符串为“5 6 1 4 3 2”。

Secret Phase

int secret_phase()
{int v1; // [esp+8h] [ebp-10h]char *nptr; // [esp+Ch] [ebp-Ch]nptr = (char *)read_line();v1 = atoi(nptr);if ( v1 <= 0 || v1 > 1001 )explode_bomb();if ( fun7(&n1, v1) != 2 )explode_bomb();puts("Wow! You've defused the secret stage!");return phase_defused();
}

先用IDA将汇编语言转为伪代码。对于“nptr = (char *)read_line(); v1 = atoi(nptr);”这段代码,我的理解是从终端中读入输入的字符串并用atoi函数将其转换为int类型再赋给v1。而“if ( v1 <= 0 || v1 > 1001 )explode_bomb();”要求 v1是一个不大于1001的自然数。“if ( fun7(n1, v1) != 2 )explode_bomb();”则要求调用fun7函数并且返回的值要为2,因此接下来我们需要来分析fun7函数。

int __cdecl fun7(_DWORD *a1, int a2)
{if ( !a1 )return -1;if ( *a1 > a2 )return 2 * fun7(a1[1], a2);if ( *a1 == a2 )return 0;return 2 * fun7(a1[2], a2) + 1;
}

fun7函数与func4函数在名称和结构上都非常相似,且“fun7(n1, v1)”中涉及到了全局变量n1。依据“_DWORD n1[4]”,我们可以知道n1是一个有四个元素的数组,每个元素都是一个长度为四个字节的“_DWORD *”类型的指针。我们还可以发现在比n1的地址更低的地方,还有“n21、n22、n31……n48”这些与n1只是下标不同的“public”类型的变量,我们可以称其为“n族变量”。某些n族变量也像变量node(1~6)一样储存了同族其他变量的地址。基于这些现象,我们可以断定这道题目启示我们要参考解决Phase4和Phase6的经验,这可以为我们打开解题的思路。

.data:0804D528                               public n48
.data:0804D528 E9                            n48 db 0E9h
.data:0804D529 03                            db    3
.data:0804D52A 00                            db    0
.data:0804D52B 00                            db    0
.data:0804D52C 00                            db    0
.data:0804D52D 00                            db    0
.data:0804D52E 00                            db    0
.data:0804D52F 00                            db    0
.data:0804D530 00                            db    0
.data:0804D531 00                            db    0
.data:0804D532 00                            db    0
.data:0804D533 00                            db    0
.data:0804D534                               public n46
.data:0804D534 2F                            n46 db  2Fh ; /
.data:0804D535 00                            db    0
.data:0804D536 00                            db    0
.data:0804D537 00                            db    0
.data:0804D538 00                            db    0
.data:0804D539 00                            db    0
.data:0804D53A 00                            db    0
.data:0804D53B 00                            db    0
.data:0804D53C 00                            db    0
.data:0804D53D 00                            db    0
.data:0804D53E 00                            db    0
.data:0804D53F 00                            db    0
.data:0804D540                               public n43
.data:0804D540 14                            n43 db  14h
.data:0804D541 00                            db    0
.data:0804D542 00                            db    0
.data:0804D543 00                            db    0
.data:0804D544 00                            db    0
.data:0804D545 00                            db    0
.data:0804D546 00                            db    0
.data:0804D547 00                            db    0
.data:0804D548 00                            db    0
.data:0804D549 00                            db    0
.data:0804D54A 00                            db    0
.data:0804D54B 00                            db    0
.data:0804D54C                               public n42
.data:0804D54C 07                            n42 db    7
.data:0804D54D 00                            db    0
.data:0804D54E 00                            db    0
.data:0804D54F 00                            db    0
.data:0804D550 00                            db    0
.data:0804D551 00                            db    0
.data:0804D552 00                            db    0
.data:0804D553 00                            db    0
.data:0804D554 00                            db    0
.data:0804D555 00                            db    0
.data:0804D556 00                            db    0
.data:0804D557 00                            db    0
.data:0804D558                               public n44
.data:0804D558 23                            n44 db  23h ; #
.data:0804D559 00                            db    0
.data:0804D55A 00                            db    0
.data:0804D55B 00                            db    0
.data:0804D55C 00                            db    0
.data:0804D55D 00                            db    0
.data:0804D55E 00                            db    0
.data:0804D55F 00                            db    0
.data:0804D560 00                            db    0
.data:0804D561 00                            db    0
.data:0804D562 00                            db    0
.data:0804D563 00                            db    0
.data:0804D564                               public n47
.data:0804D564 63                            n47 db  63h ; c
.data:0804D565 00                            db    0
.data:0804D566 00                            db    0
.data:0804D567 00                            db    0
.data:0804D568 00                            db    0
.data:0804D569 00                            db    0
.data:0804D56A 00                            db    0
.data:0804D56B 00                            db    0
.data:0804D56C 00                            db    0
.data:0804D56D 00                            db    0
.data:0804D56E 00                            db    0
.data:0804D56F 00                            db    0
.data:0804D570                               public n41
.data:0804D570 01                            n41 db    1
.data:0804D571 00                            db    0
.data:0804D572 00                            db    0
.data:0804D573 00                            db    0
.data:0804D574 00                            db    0
.data:0804D575 00                            db    0
.data:0804D576 00                            db    0
.data:0804D577 00                            db    0
.data:0804D578 00                            db    0
.data:0804D579 00                            db    0
.data:0804D57A 00                            db    0
.data:0804D57B 00                            db    0
.data:0804D57C                               public n45
.data:0804D57C 28                            n45 db  28h ; (
.data:0804D57D 00                            db    0
.data:0804D57E 00                            db    0
.data:0804D57F 00                            db    0
.data:0804D580 00                            db    0
.data:0804D581 00                            db    0
.data:0804D582 00                            db    0
.data:0804D583 00                            db    0
.data:0804D584 00                            db    0
.data:0804D585 00                            db    0
.data:0804D586 00                            db    0
.data:0804D587 00                            db    0
.data:0804D588                               public n34
.data:0804D588 6B                            n34 db  6Bh ; k
.data:0804D589 00                            db    0
.data:0804D58A 00                            db    0
.data:0804D58B 00                            db    0
.data:0804D58C 64                            db  64h ; d
.data:0804D58D D5                            db 0D5h
.data:0804D58E 04                            db    4
.data:0804D58F 08                            db    8
.data:0804D590 28                            db  28h ; (
.data:0804D591 D5                            db 0D5h
.data:0804D592 04                            db    4
.data:0804D593 08                            db    8
.data:0804D594                               public n31
.data:0804D594 06                            n31 db    6
.data:0804D595 00                            db    0
.data:0804D596 00                            db    0
.data:0804D597 00                            db    0
.data:0804D598 70                            db  70h ; p
.data:0804D599 D5                            db 0D5h
.data:0804D59A 04                            db    4
.data:0804D59B 08                            db    8
.data:0804D59C 4C                            db  4Ch ; L
.data:0804D59D D5                            db 0D5h
.data:0804D59E 04                            db    4
.data:0804D59F 08                            db    8
.data:0804D5A0                               public n33
.data:0804D5A0 2D                            n33 db  2Dh ; -
.data:0804D5A1 00                            db    0
.data:0804D5A2 00                            db    0
.data:0804D5A3 00                            db    0
.data:0804D5A4 7C                            db  7Ch ; |
.data:0804D5A5 D5                            db 0D5h
.data:0804D5A6 04                            db    4
.data:0804D5A7 08                            db    8
.data:0804D5A8 34                            db  34h ; 4
.data:0804D5A9 D5                            db 0D5h
.data:0804D5AA 04                            db    4
.data:0804D5AB 08                            db    8
.data:0804D5AC                               public n32
.data:0804D5AC 16                            n32 db  16h
.data:0804D5AD 00                            db    0
.data:0804D5AE 00                            db    0
.data:0804D5AF 00                            db    0
.data:0804D5B0 40                            db  40h ; @
.data:0804D5B1 D5                            db 0D5h
.data:0804D5B2 04                            db    4
.data:0804D5B3 08                            db    8
.data:0804D5B4 58                            db  58h ; X
.data:0804D5B5 D5                            db 0D5h
.data:0804D5B6 04                            db    4
.data:0804D5B7 08                            db    8
.data:0804D5B8                               public n22
.data:0804D5B8 32                            n22 db  32h ; 2
.data:0804D5B9 00                            db    0
.data:0804D5BA 00                            db    0
.data:0804D5BB 00                            db    0
.data:0804D5BC A0                            db 0A0h
.data:0804D5BD D5                            db 0D5h
.data:0804D5BE 04                            db    4
.data:0804D5BF 08                            db    8
.data:0804D5C0 88                            db  88h
.data:0804D5C1 D5                            db 0D5h
.data:0804D5C2 04                            db    4
.data:0804D5C3 08                            db    8
.data:0804D5C4                               public n21
.data:0804D5C4 08                            n21 db    8
.data:0804D5C5 00                            db    0
.data:0804D5C6 00                            db    0
.data:0804D5C7 00                            db    0
.data:0804D5C8 94                            db  94h
.data:0804D5C9 D5                            db 0D5h
.data:0804D5CA 04                            db    4
.data:0804D5CB 08                            db    8
.data:0804D5CC AC                            db 0ACh
.data:0804D5CD D5                            db 0D5h
.data:0804D5CE 04                            db    4
.data:0804D5CF 08                            db    8
.data:0804D5D0                               public n1
.data:0804D5D0 24                            n1 db  24h ; $                          ; DATA XREF: secret_phase+39↑o
.data:0804D5D1 00                            db    0
.data:0804D5D2 00                            db    0
.data:0804D5D3 00                            db    0
.data:0804D5D4 C4                            db 0C4h
.data:0804D5D5 D5                            db 0D5h
.data:0804D5D6 04                            db    4
.data:0804D5D7 08                            db    8
.data:0804D5D8 B8                            db 0B8h
.data:0804D5D9 D5                            db 0D5h
.data:0804D5DA 04                            db    4
.data:0804D5DB 08                            db    8
.data:0804D5DC 00                            db    0
.data:0804D5DD 00                            db    0
.data:0804D5DE 00                            db    0
.data:0804D5DF 00                            db    0

先将n族变量整理备用(n族变量是按地址从高到低排序,但各变量内部是按地址从低到高排序):

*n1[4]

n1[0]=36

n1[1]=&n21

n1[2]=&n22

n1[3]=0

n21

8

&n31

&n32

n22

50

&n33

&n34

n31

6

&n41

&n42

n32

22

&n43

&n44

n33

45

&n45

&n46

n34

107

&n47

&n48

n41

1

0

0

n42

7

0

0

n43

20

0

0

n44

35

0

0

n45

40

0

0

n46

47

0

0

n47

99

0

0

n48

1001

0

0

fun7函数中“if ( !a1 )return -1;”是检查第一个传入的变量的值是否为零,如果为零返回-1;如果不为零,则根据a1中的值解引用后得到的值与a2的大小关系进行递归。根据之前的经验,如果能跳出递归,那么最后要么执行“if ( !a1 )return -1;”要么执行“if ( *a1 == a2 )return 0;”。因为我们想要的返回值为2,那不妨设计如下的步骤:“一共三层递归,最后一次调用得0,返回上一层进行2*0+1=1的运算,最后进行1*2=2的运算得到返回值”。

将思路用表格的形式呈现:

a1

*a1

a2

*a1 > a2

n1

36

v1

*a1 < a2

&n21

8

v1

*a1 = a2

&n32

22

v1

所以“36>v1&&v1>8&&v1=22”解得v1=22,则答案为“22”。

温馨提示

         *善于运用人工智能技术,遇到不解之处可随时向AI寻求解答。

         *尽管题目整体框架是一致的,但具体细节却存在差异性,因此本人的答案可能并不通用,仅供参考。

        *本人的论述极度缺乏专业性,对此,建议各位参阅其他博主撰写的深度文章以获取更为准确的知识。同时,建议各位最好理解并掌握相关原理,因为难度较高的理论课考试可能会涉及到。

        *完全依赖个人的独立摸索并非总是最优策略,如果你能得到来自同学伙伴或学长学姐的指导与帮助,那么恭喜你。

这篇关于【从零开始的新手之旅】:2023西工大计算机系统基础实验之Lab2的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/701658

相关文章

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

软件设计师备考——计算机系统

学习内容源自「软件设计师」 上午题 #1 计算机系统_哔哩哔哩_bilibili 目录 1.1.1 计算机系统硬件基本组成 1.1.2 中央处理单元 1.CPU 的功能 1)运算器 2)控制器 RISC && CISC 流水线控制 存储器  Cache 中断 输入输出IO控制方式 程序查询方式 中断驱动方式 直接存储器方式(DMA)  ​编辑 总线 ​编辑

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

c++基础版

c++基础版 Windows环境搭建第一个C++程序c++程序运行原理注释常亮字面常亮符号常亮 变量数据类型整型实型常量类型确定char类型字符串布尔类型 控制台输入随机数产生枚举定义数组数组便利 指针基础野指针空指针指针运算动态内存分配 结构体结构体默认值结构体数组结构体指针结构体指针数组函数无返回值函数和void类型地址传递函数传递数组 引用函数引用传参返回指针的正确写法函数返回数组

【QT】基础入门学习

文章目录 浅析Qt应用程序的主函数使用qDebug()函数常用快捷键Qt 编码风格信号槽连接模型实现方案 信号和槽的工作机制Qt对象树机制 浅析Qt应用程序的主函数 #include "mywindow.h"#include <QApplication>// 程序的入口int main(int argc, char *argv[]){// argc是命令行参数个数,argv是