(xxxx)八:加密图片的解密

时间:2024-02-20 12:05:27

      1、 xxxx接收到图片后,不会明文存储在磁盘,因为不安全,都是加密后存储在特定目录的,截图如下(请忽略两个jpg的文件,这是我为了做测试人为添加的,xxxx原始是不会存这些图片的):

       

        可以看到图片都是以dat格式存储的。用010editor打开:全是没意义的数据,图片的头信息完全找不到!

         

         既然都是加密存储的,在xxxx软件中是怎么看到图片的了? 换句话说,xxxx软件都是怎么解密这些图片的了?

        2、正式介绍解密之前,先做个位运算知识的铺垫:异或 XOR

       (1)两个bit做XOR,如果不同那么结果为1;如果相同结果为0; 打个比方:男女在一起才能生娃,同性在一起是不行的!也就是:1^1=0, 0^0=0,  但是1^0=1;

       (2)XOR最大的作用: 对称加密!   比如明文是0xA=1010, 密钥是0xB=1011,那么密文=A^B=0x1;  解密时,用密钥^密文即可,这里便是0x1^B=A,成功得到明文;

       (3)XOR最大的特性:明文、密钥、密文三个的关系像个三角形,其中任意两个异或,都能得到第三个!比如上面用加密的算法是A^B=0x1;解密的算法是B^0x1=A; 但是用明文A^密文0x1也能得到密钥B; 这个特性有啥用了:

  •     明文、密钥、密文只能对外公布一个,一般公开密文(这不废话么?)
  •     曾经有人利用该特性找到了windwos PG保护的密钥(用IDA静态分析找到明文,windbg动态分析找到密文,两个异或就找到了密钥
  •     也有人利用这个特性做PE文件保护(原理和PG保护类似),PE文件的代码和数据都加密存储,直到执行前才在内存解密得到真正的代码
  •     密文和明文大小是一样的(后面会根据这个猜图片的加密方式)

      (4)XOR对称加密的另一大特点:计算方式简单! XOR本质是位运算,CPU内部的硬件电路是可以直接实现的,一条XOR的汇编指令就能完成计算,理论上只需要1ns的时间(这里扩展一下:其实CPU内部的加减乘除都是通过XOR实现的);只要key的长度足够,短时间内想要通过暴力穷举是不可能的。比如key的长度是1024bit,那么key就有2的1024次方个。和同为对称加密的AES算法比,效率高太多了!所以用XOR加密是非常广泛的!

 (5)XOR最后一个优点:因为是按照位计算的,所以计算的时间和复杂度只和位数相关,和数据实际数值无关!这么做的好处是啥了? 防止侧信道攻击!比如只要密码位数一定,不论是数字,还是字母,还是特殊符号,解密的时间都一样,不会因为字符不同而导致时间不同!

        3、 之前找过xxxx接受消息的call,这里继续下断点,然后再手机上通过文件助手发条消息,断下来了:

          

         这里已经能看到消息的部分内容了,但OD显示的长度有限,看不全,所以这里需要CE辅助:注意地址的配置,这里就要选Unicode了

         

          下面就是图片的数据格式:是xml的;从字段的名称看,有AES密钥、cdn的密钥、cdn的url、md5等信息;图片还有大图和midimg(从字面猜测应该是中等大小的图片,大概率是在聊天窗展示的那种);可惜的是没有找到图片保存的名字和位置;

<?xml version="1.0"?>
<msg>
    <img aeskey="7a40664635a1aac64816c8deff4a39b0" encryver="0" cdnthumbaeskey="7a40664635a1aac64816c8deff4a39b0" cdnthumburl="304f020100044830460201000204513ea50e02033d14ba02047851fb3a020460376bb60421777875706c6f61645f66696c6568656c7065723730375f31363134323434373838020401090a020201000400" cdnthumblength="3967" cdnthumbheight="90" cdnthumbwidth="120" cdnmidheight="0" cdnmidwidth="0" cdnhdheight="0" cdnhdwidth="0" cdnmidimgurl="304f020100044830460201000204513ea50e02033d14ba02047851fb3a020460376bb60421777875706c6f61645f66696c6568656c7065723730375f31363134323434373838020401090a020201000400" length="1" md5="5733041f60a14ce9f4d75be1bb49a213" hevc_mid_size="176859" />
</msg>

       继续往下,终于找到了图片存放的位置和名字,如下:

         

        用同样的方法再CE里面能看到图片加密后bat文件的全称和存放路径(就是刚才说的那个目录):

       

         根据bat文件的名字和路径,把加密前后的图片都放进010editor中对比:加密后的文件已经面目全非,连图片头信息都没了,不过加密后文件有个最大的特征:大小和加密前完全一样!

        

       那么有没有可能用XOR来加密的了? 怎么验证了?

      4、这里就要用到刚才提到的XOR特点:密文、密钥、明文三者像三角形的关系其中任意两个异或,都能得到第三个!明文图片的第一个字节是FF,密文第一个字节是B3,FF^B3=4C,那么4C是不是key了? 为了逻辑严密,需要交叉验证:第二个明文是D8,这时已经知道key=4C了,D8^4C=0x94,居然刚好等于第二个密文,4C就是key看来没错了!为了谨慎,我们再用密文交叉验证试试:第三个密文是B3,那么解密算法就是B3^4C=0xFF,刚好等于第三个明文!此时,通过三次明文、密文、密钥的交叉验证,实锤了加密算法是XOR、密钥是4C

       最后解密的POC如下:

#include <stdio.h>
#include <string.h>  
#include <fstream>
#include <iostream>
using namespace std;

const char* filename = "decryptPic\\07a00a9454f983ca808cd1a6028d581c.dat";

int main(int argc, char** argv) {
    std::ifstream streamReader(filename, std::ios::binary); //以二进制的形式读取文件
    streamReader.seekg(0, std::ios::end);//跳转到尾部
    unsigned filesize = streamReader.tellg();//得到文件大小
    char* _data = new char[filesize];
    char* _decrypt = new char[filesize];
    printf("length is:%d\n", filesize);
    streamReader.seekg(0, std::ios::beg);//跳转到开始
    streamReader.read(_data, filesize);
    streamReader.close();
    for (int i=0;i< filesize;i++)
    {
        //std::cout << _data[i];
        /*
        //https://www.coder.work/article/2223646  参考这里,打印的时候必须转成(unsigned char),否则默认会以4字节、也就是unsinged int打印
        */
        //printf("%1x",(unsigned char)_data[i]);
        _decrypt[i] = _data[i] ^ 0x4c;//解密
        //printf("%1x", (unsigned char)_decrypt[i]);//从010editor看是对的
    }

    std::ofstream  ofs;
    ofs.open("decryptPic\\decript.jpg", ios::out | ios::app | ios::binary, _SH_DENYNO);
    ofs.write(_decrypt, filesize);
    ofs.close();
    return 0;

      效果:成功解密,生成decrypt.jpg图片!

   

     以后写勒索病毒,完全可以复用这段代码对文件加密,然后让对方用比特币支持,想想都刺激.......