案例来自于 《二进制安全基础》(ISBN:9787302651277)

对可执行文件进行反汇编,得到汇编代码

               4-1.c:2 (25)
    080484bb 8d 4c 24 04              LEA   ECX=>argc,[ESP + 0x4]
    080484bf 83 e4 f0                 AND   ESP,0xfffffff0
    080484c2 ff 71 fc                 PUSH  dword ptr [ECX + local_res0]
    080484c5 55                       PUSH  EBP
    080484c6 89 e5                    MOV   EBP,ESP
    080484c8 51                       PUSH  ECX
    080484c9 83 ec 34                 SUB   ESP,0x34
    080484cc 89 c8                    MOV   EAX,ECX
    080484ce 8b 40 04                 MOV   EAX,dword ptr [EAX + argv]
    080484d1 89 45 d4                 MOV   dword ptr [EBP + local_34],EAX

	... ....

	               LAB_08048668                   XREF[1]:   08048661(j)  
    08048668 8b 4d fc                 MOV   ECX,dword ptr [EBP + local_c]
    0804866b c9                       LEAVE
    0804866c 8d 61 fc                 LEA   ESP=>local_res0,[ECX + -0x4]
    0804866f c3                       RET

先写出 C 语言代码大致框架

void main(int argc, char* argv[])
{
	....
}

               4-1.c:3 (7)
    080484df c7 45 e0 00 00 00 00     MOV   dword ptr [EBP + local_28],0x0
               4-1.c:4 (7)
    080484e6 c7 45 e4 00 00 00 00     MOV   dword ptr [EBP + local_24],0x0
               4-1.c:5 (7)
    080484ed c7 45 e8 00 00 00 00     MOV   dword ptr [EBP + local_20],0x0

C 语言中的局部变量一般存在栈上

void main(int argc, char* argv[])
{
	int a1 = 0;		// [EBP + local_28]
	int a2 = 0;		// [EBP + local_24]
	int a3 = 0;		// [EBP + local_20]
}

               4-1.c:6 (16)
    080484f4 83 ec 0c                 SUB   ESP,0xc
    080484f7 68 f0 86 04 08           PUSH  DAT_080486f0                                                        = E8h
    080484fc e8 7f fe ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    08048501 83 c4 10                 ADD   ESP,0x10
               4-1.c:7 (16)
    08048504 83 ec 0c                 SUB   ESP,0xc
    08048507 68 39 87 04 08           PUSH  DAT_08048739                                                        = E8h
    0804850c e8 6f fe ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    08048511 83 c4 10                 ADD   ESP,0x10

这里可以看出调用了 puts() 函数,PUSH DAT_XXX 是将 DAT_XXX 地址值保存到栈上,说白点就是传参,puts() 函数会输出 DAT_XXX 地址所在的数据,以 DAT_08048739 为例,其它太多了,就不一一贴出来了

               DAT_08048739                   XREF[1]:   main:08048507(*)  
    08048739 e8                       ??    E8h
    0804873a af                       ??    AFh
    0804873b b7                       ??    B7h
    0804873c e8                       ??    E8h
    0804873d be                       ??    BEh
    0804873e 93                       ??    93h
    0804873f e5                       ??    E5h
    08048740 85                       ??    85h
    08048741 a5                       ??    A5h
    08048742 61                       ??    61h    a
    08048743 e7                       ??    E7h
    08048744 9a                       ??    9Ah
    08048745 84                       ??    84h
    08048746 e5                       ??    E5h
    08048747 80                       ??    80h
    08048748 bc                       ??    BCh
    08048749 3a                       ??    3Ah    :
    0804874a 00                       ??    00h

这个是编码后的内容,我找 AI 写了一个 Python 脚本写了一个将它转为字符,可以参考我的这篇博客,转出来的字符是 “请输入a的值:”

#include <stdio.h>

void main(int argc, char* argv[])
{
	int a1 = 0;		// [EBP + local_28]
	int a2 = 0;		// [EBP + local_24]
	int a3 = 0;		// [EBP + local_20]
	
	puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
	puts("请输入a的值:");
}

               4-1.c:8 (20)
    08048514 83 ec 08                 SUB   ESP,0x8
    08048517 8d 45 e0                 LEA   EAX=>local_28,[EBP + -0x20]
    0804851a 50                       PUSH  EAX
    0804851b 68 4b 87 04 08           PUSH  DAT_0804874b                                                        = 25h    %
    08048520 e8 7b fe ff ff           CALL  libc.so.6::__isoc99_scanf                                           undefined __isoc99_scanf()
    08048525 83 c4 10                 ADD   ESP,0x10
               4-1.c:9 (16)
    08048528 83 ec 0c                 SUB   ESP,0xc
    0804852b 68 4e 87 04 08           PUSH  DAT_0804874e                                                        = E8h
    08048530 e8 4b fe ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    08048535 83 c4 10                 ADD   ESP,0x10
               4-1.c:10 (20)
    08048538 83 ec 08                 SUB   ESP,0x8
    0804853b 8d 45 e4                 LEA   EAX=>local_24,[EBP + -0x1c]
    0804853e 50                       PUSH  EAX
    0804853f 68 4b 87 04 08           PUSH  DAT_0804874b                                                        = 25h    %
    08048544 e8 57 fe ff ff           CALL  libc.so.6::__isoc99_scanf                                           undefined __isoc99_scanf()
    08048549 83 c4 10                 ADD   ESP,0x10
               4-1.c:11 (16)
    0804854c 83 ec 0c                 SUB   ESP,0xc
    0804854f 68 60 87 04 08           PUSH  DAT_08048760                                                        = E8h
    08048554 e8 27 fe ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    08048559 83 c4 10                 ADD   ESP,0x10
               4-1.c:12 (20)
    0804855c 83 ec 08                 SUB   ESP,0x8
    0804855f 8d 45 e8                 LEA   EAX=>local_20,[EBP + -0x18]
    08048562 50                       PUSH  EAX
    08048563 68 4b 87 04 08           PUSH  DAT_0804874b                                                        = 25h    %
    08048568 e8 33 fe ff ff           CALL  libc.so.6::__isoc99_scanf                                           undefined __isoc99_scanf()
    0804856d 83 c4 10                 ADD   ESP,0x10

这里写了分别输入 a、b、c 的值,估计原来的变量命名也是如此

#include <stdio.h>

void main(int argc, char* argv[])
{
	// [EBP + local_28] [EBP + local_24] [EBP + local_20]
	int a = 0, b = 0, c = 0;
	
	puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
	puts("请输入a的值:");
	scanf("%d",&a);
	puts("请输入b的值:");
	scanf("%d",&b);
	puts("请输入c的值:");
	scanf("%d",&c);

}

               4-1.c:13 (9)
    08048570 8b 45 e0                 MOV   EAX,dword ptr [EBP + local_28]
    08048573 c1 e0 03                 SHL   EAX,0x3
    08048576 89 45 e0                 MOV   dword ptr [EBP + local_28],EAX

这里 shl 是逻辑左移

#include <stdio.h>

void main(int argc, char* argv[])
{
	// [EBP + local_28] [EBP + local_24] [EBP + local_20]
	int a = 0, b = 0, c = 0;
	
	puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
	puts("请输入a的值:");
	scanf("%d",&a);
	puts("请输入b的值:");
	scanf("%d",&b);
	puts("请输入c的值:");
	scanf("%d",&c);

	a = a << 3;
}

               4-1.c:14 (12)
    08048579 8b 45 e0                 MOV   EAX,dword ptr [EBP + local_28]
    0804857c 83 f8 0f                 CMP   EAX,0xf
    0804857f 0f 8e be 00 00 00        JLE   LAB_08048643
               4-1.c:14 (12)
    08048585 8b 45 e0                 MOV   EAX,dword ptr [EBP + local_28]
    08048588 83 f8 10                 CMP   EAX,0x10
    0804858b 0f 8f b2 00 00 00        JG    LAB_08048643

这里可以看出是分支语句。CMP EAX,0xf 就是比较变量 a 与 15 比大小,JLE LAB_08048643 表示变量 a 小于或等于 15 的话,就跳转到 LAB_08048643,JG 表示如果大于则跳转。写成表达式就是 a <= 15 || a > 16。

               LAB_08048643                   XREF[2]:   0804857f(j), 0804858b(j)  
               4-1.c:42 (16)
    08048643 83 ec 0c                 SUB   ESP,0xc
    08048646 68 72 87 04 08           PUSH  s_failed!_08048772                                                  = "failed! "
    0804864b e8 30 fd ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    08048650 83 c4 10                 ADD   ESP,0x10
               4-1.c:44 (2)
    08048653 eb 01                    JMP   LAB_08048656
               LAB_08048655                   XREF[2]:   080485a8(j), 08048641(j)  
               4-1.c:14 (1)
    08048655 90                       NOP
               LAB_08048656                   XREF[1]:   08048653(j)  
               4-1.c:44 (13)
    08048656 90                       NOP
               switchD_080485b5::default
    08048657 8b 45 f4                 MOV   EAX,dword ptr [EBP + local_14]
    0804865a 65 33 05 14 00 00 00     XOR   EAX,dword ptr GS:[0x14]
    08048661 74 05                    JZ    LAB_08048668
               4-1.c:44 (13)
    08048663 e8 08 fd ff ff           CALL  libc.so.6::__stack_chk_fail                                         undefined __stack_chk_fail()
               -- Flow Override: CALL_RETURN (C
               LAB_08048668                   XREF[1]:   08048661(j)  
    08048668 8b 4d fc                 MOV   ECX,dword ptr [EBP + local_c]
    0804866b c9                       LEAVE
    0804866c 8d 61 fc                 LEA   ESP=>local_res0,[ECX + -0x4]
    0804866f c3                       RET

分支语句执行完后 main() 函数就结束了

#include <stdio.h>

void main(int argc, char* argv[])
{
	// [EBP + local_28] [EBP + local_24] [EBP + local_20]
	int a = 0, b = 0, c = 0;
	
	puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
	puts("请输入a的值:");
	scanf("%d",&a);
	puts("请输入b的值:");
	scanf("%d",&b);
	puts("请输入c的值:");
	scanf("%d",&c);

	a = a << 3;

	if (a <= 15 || a > 16)
	{
		puts("failed! ");
	}
}

回到 0x0804858b 处的指令,接着往下看

               4-1.c:15 (7)
    08048591 c7 45 ec 00 00 00 00     MOV   dword ptr [EBP + local_1c],0x0
               4-1.c:16 (7)
    08048598 c7 45 f0 00 00 00 00     MOV   dword ptr [EBP + local_18],0x0
               4-1.c:17 (24)
    0804859f 8b 45 e4                 MOV   EAX,dword ptr [EBP + local_24]
    080485a2 83 e8 05                 SUB   EAX,0x5
    080485a5 83 f8 04                 CMP   EAX,0x4
    080485a8 0f 87 a7 00 00 00        JA    LAB_08048655
    080485ae 8b 04 85 88 87 04 08     MOV   EAX,dword ptr [EAX*0x4 + switchD_080485b5::switchdataD_08048788]    = 080485b7
               switchD_080485b5::switchD
    080485b5 ff e0                    JMP   EAX

发现还有一部分,可以估计刚才的分支语句是 if ... else ... 结构,而且 else 的部分嵌套了 switch 分支

#include <stdio.h>

void main(int argc, char* argv[])
{
	// [EBP + local_28] [EBP + local_24] [EBP + local_20]
	int a = 0, b = 0, c = 0;
	
	puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
	puts("请输入a的值:");
	scanf("%d",&a);
	puts("请输入b的值:");
	scanf("%d",&b);
	puts("请输入c的值:");
	scanf("%d",&c);

	a = a << 3;

	if (a <= 15 || a > 16)
	{
		puts("failed! ");
	}
	else
	{
		// [EBP + local_1c] [EBP + local_18]
		int a1 = 0, a2 = 0;
		switch (b)
		{
			....
		}
	}
}

接下来看分支语句内部

               switchD_080485b5::switchdataD_ XREF[1]:   main:080485ae(*)  
    08048788 b7 85 04 08              addr  switchD_080485b5::caseD_5
    0804878c c9 85 04 08              addr  switchD_080485b5::caseD_6
    08048790 db 85 04 08              addr  switchD_080485b5::caseD_7
    08048794 ed 85 04 08              addr  switchD_080485b5::caseD_8
    08048798 30 86 04 08              addr  switchD_080485b5::caseD_9

后面的数字提示了我们 case 后的值,如果没有,也是可以推出来

    0804859f 8b 45 e4                 MOV   EAX,dword ptr [EBP + local_24]
    080485a2 83 e8 05                 SUB   EAX,0x5
    080485a5 83 f8 04                 CMP   EAX,0x4
    080485a8 0f 87 a7 00 00 00        JA    LAB_08048655
    080485ae 8b 04 85 88 87 04 08     MOV   EAX,dword ptr [EAX*0x4 + switchD_080485b5::switchdataD_08048788]    = 080485b7

可以看到这里 b - 5,如果值大于 4 就结束了,不会进入后面的跳转语句,这是 switch 语句的一个优化,当 b 的值大于 9 的时候就不进入 switch 分支。EAX 的值乘以 4 加上 switchD_080485b5::switchdataD_08048788 的地址 0x08048788 就是 b - 5 小于或等于 4 时会跳转的地址。如果 b - 5 的值为 0,那就跳转到 0 × 0 x 4 + 0 x 08048788 0\times0\mathrm{x}4+0\mathrm{x}08048788 0×0x4+0x08048788 也就是 0x08048788;如果为 1,跳转到 0x0804878c

switch (b)
{
	case 5: ...;
	case 6: ...;
	case 7: ...;
	case 8: ...;
	case 9: ...;
}

刚才似乎看到了一个 default

               switchD_080485b5::default
    08048657 8b 45 f4                 MOV   EAX,dword ptr [EBP + local_14]
    0804865a 65 33 05 14 00 00 00     XOR   EAX,dword ptr GS:[0x14]
    08048661 74 05                    JZ    LAB_08048668

为什么 switch 分支代码里没写 default 呢?这里的 default 在 main() 函数结束前做了检查栈的工作,有可能是反汇编的时候,反汇编软件标记出错了。

#include <stdio.h>

void main(int argc, char* argv[])
{
	// [EBP + local_28] [EBP + local_24] [EBP + local_20]
	int a = 0, b = 0, c = 0;
	
	puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
	puts("请输入a的值:");
	scanf("%d",&a);
	puts("请输入b的值:");
	scanf("%d",&b);
	puts("请输入c的值:");
	scanf("%d",&c);

	a = a << 3;

	if (a <= 15 || a > 16)
	{
		puts("failed! ");
	}
	else
	{
		// [EBP + local_1c] [EBP + local_18]
		int a1 = 0, a2 = 0;
		switch (b)
		{
			case 5: ...;
			case 6: ...;
			case 7: ...;
			case 8: ...;
			case 9: ...;
		}
	}
}

看看 switch 语句的前 3 个分支

               switchD_080485b5::caseD_5      XREF[2]:   080485b5(j), 08048788(*)  
               4-1.c:19 (16)
    080485b7 83 ec 0c                 SUB   ESP,0xc
    080485ba 68 72 87 04 08           PUSH  s_failed!_08048772                                                  = "failed! "
    080485bf e8 bc fd ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    080485c4 83 c4 10                 ADD   ESP,0x10
               4-1.c:20 (2)
    080485c7 eb 78                    JMP   LAB_08048641
               switchD_080485b5::caseD_6      XREF[2]:   080485b5(j), 0804878c(*)  
               4-1.c:22 (16)
    080485c9 83 ec 0c                 SUB   ESP,0xc
    080485cc 68 72 87 04 08           PUSH  s_failed!_08048772                                                  = "failed! "
    080485d1 e8 aa fd ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    080485d6 83 c4 10                 ADD   ESP,0x10
               4-1.c:23 (2)
    080485d9 eb 66                    JMP   LAB_08048641
               switchD_080485b5::caseD_7      XREF[2]:   080485b5(j), 08048790(*)  
               4-1.c:25 (16)
    080485db 83 ec 0c                 SUB   ESP,0xc
    080485de 68 72 87 04 08           PUSH  s_failed!_08048772                                                  = "failed! "
    080485e3 e8 98 fd ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    080485e8 83 c4 10                 ADD   ESP,0x10
               4-1.c:26 (2)
    080485eb eb 54                    JMP   LAB_08048641
               LAB_08048641                   XREF[5]:   080485c7(j), 080485d9(j), 
                                                          080485eb(j), 0804861c(j), 
                                                          0804862e(j)  
               4-1.c:14 (2)
    08048641 eb 12                    JMP   LAB_08048655

可以看出都是打印,打印完就 switch 分支就结束了

#include <stdio.h>

void main(int argc, char* argv[])
{
	// [EBP + local_28] [EBP + local_24] [EBP + local_20]
	int a = 0, b = 0, c = 0;
	
	puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
	puts("请输入a的值:");
	scanf("%d",&a);
	puts("请输入b的值:");
	scanf("%d",&b);
	puts("请输入c的值:");
	scanf("%d",&c);

	a = a << 3;

	if (a <= 15 || a > 16)
	{
		puts("failed! ");
	}
	else
	{
		// [EBP + local_1c] [EBP + local_18]
		int a1 = 0, a2 = 0;
		switch (b)
		{
			case 5:
				puts("failed! ");
				break;
			case 6:
				puts("failed! ");
				break;
			case 7:
				puts("failed! ");
				break;
			case 8: ...;
			case 9: ...;
		}
	}
}

switch 分支第四个语句

               switchD_080485b5::caseD_8      XREF[2]:   080485b5(j), 08048794(*)  
               4-1.c:28 (9)
    080485ed c7 45 f0 00 00 00 00     MOV   dword ptr [EBP + local_18],0x0
    080485f4 eb 08                    JMP   LAB_080485fe
               LAB_080485f6                   XREF[1]:   08048604(j)  
               4-1.c:29 (4)
    080485f6 83 45 ec 01              ADD   dword ptr [EBP + local_1c],0x1
               4-1.c:28 (4)
    080485fa 83 45 f0 01              ADD   dword ptr [EBP + local_18],0x1
               LAB_080485fe                   XREF[1]:   080485f4(j)  
               4-1.c:28 (8)
    080485fe 8b 45 e8                 MOV   EAX,dword ptr [EBP + local_20]
    08048601 39 45 f0                 CMP   dword ptr [EBP + local_18],EAX
    08048604 7e f0                    JLE   LAB_080485f6
               4-1.c:31 (6)
    08048606 83 7d ec 09              CMP   dword ptr [EBP + local_1c],0x9
    0804860a 75 12                    JNZ   LAB_0804861e
               4-1.c:32 (16)
    0804860c 83 ec 0c                 SUB   ESP,0xc
    0804860f 68 7b 87 04 08           PUSH  s_success!_0804877b                                                 = "success! "
    08048614 e8 67 fd ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    08048619 83 c4 10                 ADD   ESP,0x10
               4-1.c:36 (2)
    0804861c eb 23                    JMP   LAB_08048641
               LAB_0804861e                   XREF[1]:   0804860a(j)  
               4-1.c:34 (16)
    0804861e 83 ec 0c                 SUB   ESP,0xc
    08048621 68 72 87 04 08           PUSH  s_failed!_08048772                                                  = "failed! "
    08048626 e8 55 fd ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    0804862b 83 c4 10                 ADD   ESP,0x10
               4-1.c:36 (2)
    0804862e eb 11                    JMP   LAB_08048641

可以看到有一个 for 循环

	080485ed c7 45 f0 00 00 00 00     MOV   dword ptr [EBP + local_18],0x0
    080485f4 eb 08                    JMP   LAB_080485fe
               LAB_080485f6                   XREF[1]:   08048604(j)  
               4-1.c:29 (4)
    080485f6 83 45 ec 01              ADD   dword ptr [EBP + local_1c],0x1
               4-1.c:28 (4)
    080485fa 83 45 f0 01              ADD   dword ptr [EBP + local_18],0x1
               LAB_080485fe                   XREF[1]:   080485f4(j)  
               4-1.c:28 (8)
    080485fe 8b 45 e8                 MOV   EAX,dword ptr [EBP + local_20]
    08048601 39 45 f0                 CMP   dword ptr [EBP + local_18],EAX
    08048604 7e f0                    JLE   LAB_080485f6

流程是先给循环控制变量 a2 赋初值 0,判断是否小于等于变量 c,满足的话变量 a1 就自增,然后变量 a2 自增

for (a2 = 0; a2 <= c; a2++)
{
	a1++;
}

循环结束后就是一个分支语句

               4-1.c:31 (6)
    08048606 83 7d ec 09              CMP   dword ptr [EBP + local_1c],0x9
    0804860a 75 12                    JNZ   LAB_0804861e
               4-1.c:32 (16)
    0804860c 83 ec 0c                 SUB   ESP,0xc
    0804860f 68 7b 87 04 08           PUSH  s_success!_0804877b                                                 = "success! "
    08048614 e8 67 fd ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    08048619 83 c4 10                 ADD   ESP,0x10
               4-1.c:36 (2)
    0804861c eb 23                    JMP   LAB_08048641
               LAB_0804861e                   XREF[1]:   0804860a(j)  
               4-1.c:34 (16)
    0804861e 83 ec 0c                 SUB   ESP,0xc
    08048621 68 72 87 04 08           PUSH  s_failed!_08048772                                                  = "failed! "
    08048626 e8 55 fd ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    0804862b 83 c4 10                 ADD   ESP,0x10
               4-1.c:36 (2)
    0804862e eb 11                    JMP   LAB_08048641

把变量 a1 与 9 比较,如果不相等,就输出 failed! , switch 分支结束;如果相等,就输出 success! ,switch 分支结束

if (a1 != 9)
{
	puts("failed! ");
}
else
{
	puts("success! ");
}
break;

switch 语句第四个分支

#include <stdio.h>

void main(int argc, char* argv[])
{
	// [EBP + local_28] [EBP + local_24] [EBP + local_20]
	int a = 0, b = 0, c = 0;
	
	puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
	puts("请输入a的值:");
	scanf("%d",&a);
	puts("请输入b的值:");
	scanf("%d",&b);
	puts("请输入c的值:");
	scanf("%d",&c);

	a = a << 3;

	if (a <= 15 || a > 16)
	{
		puts("failed! ");
	}
	else
	{
		// [EBP + local_1c] [EBP + local_18]
		int a1 = 0, a2 = 0;
		switch (b)
		{
			case 5:
				puts("failed! ");
				break;
			case 6:
				puts("failed! ");
				break;
			case 7:
				puts("failed! ");
				break;
			case 8:
				for (a2 = 0; a2 <= c; a2++)
				{
					a1++;
				}

				if (a1 != 9)
				{
					puts("failed! ");
				}
				else
				{
					puts("success! ");
				}
				break;
			case 9: ...;
		}
	}
}

switch 语句最后一个分支

               switchD_080485b5::caseD_9      XREF[2]:   080485b5(j), 08048798(*)  
               4-1.c:38 (16)
    08048630 83 ec 0c                 SUB   ESP,0xc
    08048633 68 72 87 04 08           PUSH  s_failed!_08048772                                                  = "failed! "
    08048638 e8 43 fd ff ff           CALL  libc.so.6::puts                                                     int puts(char * __s)
    0804863d 83 c4 10                 ADD   ESP,0x10
               4-1.c:39 (1)
    08048640 90                       NOP
               LAB_08048641                   XREF[5]:   080485c7(j), 080485d9(j), 
                                                          080485eb(j), 0804861c(j), 
                                                          0804862e(j)  
               4-1.c:14 (2)
    08048641 eb 12                    JMP   LAB_08048655

也是一个打印

#include <stdio.h>

void main(int argc, char* argv[])
{
	// [EBP + local_28] [EBP + local_24] [EBP + local_20]
	int a = 0, b = 0, c = 0;
	
	puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
	puts("请输入a的值:");
	scanf("%d",&a);
	puts("请输入b的值:");
	scanf("%d",&b);
	puts("请输入c的值:");
	scanf("%d",&c);

	a = a << 3;

	if (a <= 15 || a > 16)
	{
		puts("failed! ");
	}
	else
	{
		// [EBP + local_1c] [EBP + local_18]
		int a1 = 0, a2 = 0;
		switch (b)
		{
			case 5:
				puts("failed! ");
				break;
			case 6:
				puts("failed! ");
				break;
			case 7:
				puts("failed! ");
				break;
			case 8:
				for (a2 = 0; a2 <= c; a2++)
				{
					a1++;
				}

				if (a1 != 9)
				{
					puts("failed! ");
				}
				else
				{
					puts("success! ");
				}
				break;
			case 9: 
				puts("failed! ");
				break;
		}
	}
}

函数返回前并未看到将某个值移到寄存器内,只检查了栈,估计没有返回值,最终的代码:

#include <stdio.h>

void main(int argc, char* argv[])
{
	// [EBP + local_28] [EBP + local_24] [EBP + local_20]
	int a = 0, b = 0, c = 0;
	
	puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
	puts("请输入a的值:");
	scanf("%d",&a);
	puts("请输入b的值:");
	scanf("%d",&b);
	puts("请输入c的值:");
	scanf("%d",&c);

	a = a << 3;

	if (a <= 15 || a > 16)
	{
		puts("failed! ");
	}
	else
	{
		// [EBP + local_1c] [EBP + local_18]
		int a1 = 0, a2 = 0;
		switch (b)
		{
			case 5:
				puts("failed! ");
				break;
			case 6:
				puts("failed! ");
				break;
			case 7:
				puts("failed! ");
				break;
			case 8:
				for (a2 = 0; a2 <= c; a2++)
				{
					a1++;
				}

				if (a1 != 9)
				{
					puts("failed! ");
				}
				else
				{
					puts("success! ");
				}
				break;
			case 9: 
				puts("failed! ");
				break;
		}
	}
}

最后附上源代码

#include <stdio.h>
void main(int argc, char* argv[]){
	int a=0;
	int b=0;
	int c=0;
	printf("请依次输入a、b、c的值(正整数),使程序输出 success!\n");
	printf("请输入a的值:\n");
	scanf("%d",&a);
	printf("请输入b的值:\n");
	scanf("%d",&b);
	printf("请输入c的值:\n");
	scanf("%d",&c);
	a=a<<3;
	if(a>15 && a<17){
		int tmp=0;
		int i=0;
		switch(b){
		case 5:
			printf("failed! \n");
			break;
		case 6:
			printf("failed! \n");
			break;
		case 7:
			printf("failed! \n");
			break;
		case 8:
			for(i=0;i<=c;i++){
				tmp++;
			}
			if(tmp==9){
				printf("success! \n");
			}else{
				printf("failed! \n");
			}
			break;
		case 9:
			printf("failed! \n");
			break;
		}
	}else{
		printf("failed! \n");
	}
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐