.PNG和.JPG文件的解密

3
我正在尝试修改我使用的软件的图形资产(出于美学目的,我猜这很难对图形资产造成伤害),但开发者对其进行了加密。我不确定他为什么决定这样做,因为我使用和修改了许多类似的软件,那些软件的开发人员并没有费心(我看不到加密这些资产必要的原因)。
所以这里是这些加密图形资产的示例:

http://www.mediafire.com/view/sx2yc0w5wkr9m2h/avatars_50-alpha.jpg http://www.mediafire.com/download/i4fc52438hkp55l/avatars_80.png

有没有解密的方法?如果有,我该怎么做?


1
https://dev59.com/OEXRa4cB1Zd3GeqPqECW - Ignacio Vazquez-Abrams
你第一个例子中的字符重复次数太高,无法加密。也许你无法读取它,但这更多是关于图像编码/解码的问题。 - Maarten Bodewes
2个回答

9

头部的"CF10"似乎是一个私自添加的标记,用于表示文件的其余部分被"编码"了。这是一种非常简单的异或编码:xor 8Dh 是我尝试的第一个值,而且我第一次就成功了。之所以首先尝试该值的原因是,该值8D 在前100个字节左右经常出现,在那里通常会有很多零。

"解密"非常简单:如果文件以四个字节CF10开头,删除它们并对文件的其余部分应用xor 8Dh。解码文件显示,第一个"JPG"实际上是一个微小的PNG图像(而且也不是很有趣),第二个确实是一个PNG文件:

decoded image

文件扩展名可能是原始的,也可能不是;一个样本称为".jpg"的文件实际上也是一个PNG文件,可以从其头部签名看出来。

以下快速和肮脏的C源代码将解码图像。同样的程序也可以调整为编码它们,因为xor操作完全相同。唯一需要的是添加一些逻辑流程:

  1. 读取输入文件的前4个字节(最多)并测试是否形成字符串CF10
  2. 如果不是,则文件未被编码:
    a. 将CF10写入输出文件
    b. 对每个字节应用xor 8Dh来编码图像
  3. 如果是这样,
    b. 对每个字节应用xor 8Dh进行解码。

如您所见,没有"3a",而且两个"b"步骤是相同的。

#include <stdio.h>
#include <string.h>

#ifndef MAX_PATH
    #define MAX_PATH    256
#endif

#define INPUTPATH "c:\\documents"
#define OUTPUTPATH ""

int main (int argc, char **argv)
{
    FILE *inp, *outp;
    int i, encode_flag = 0;
    char filename_buffer[MAX_PATH];
    char sig[] = "CF10", *ptr;

    if (argc != 3)
    {
        printf ("usage: decode [input] [output]\n");
        return -1;
    }

    filename_buffer[0] = 0;
    if (!strchr(argv[1], '/') && !strchr(argv[1], 92) && !strchr(argv[1], ':'))
        strcpy (filename_buffer, INPUTPATH);
    strcat (filename_buffer, argv[1]);

    inp = fopen (filename_buffer, "rb");
    if (inp == NULL)
    {
        printf ("bad input file '%s'\n", filename_buffer);
        return -2;
    }
    ptr = sig;
    while (*ptr)
    {
        i = fgetc (inp);
        if (*ptr != i)
        {
            encode_flag = 1;
            break;
        }
        ptr++;
    }
    if (encode_flag)
    {
        /* rewind file because we already read some bytes */
        fseek (inp, 0, SEEK_SET);
        printf ("encoding input file: '%s'\n", filename_buffer);
    } else
        printf ("decoding input file: '%s'\n", filename_buffer);

    filename_buffer[0] = 0;
    if (!strchr(argv[2], '/') && !strchr(argv[2], 92) && !strchr(argv[2], ':'))
        strcpy (filename_buffer, OUTPUTPATH);
    strcat (filename_buffer, argv[2]);

    outp = fopen (filename_buffer, "wb");
    if (outp == NULL)
    {
        printf ("bad output file '%s'\n", filename_buffer);
        return -2;
    }
    printf ("output file: '%s'\n", filename_buffer);

    if (encode_flag)
        fwrite (sig, 1, 4, outp);
    do
    {
        i = fgetc(inp);
        if (i != EOF)
            fputc (i ^ 0x8d, outp);
    } while (i != EOF);
    fclose (inp);
    fclose (outp);
    printf ("all done. bye bye\n");
    return 0;
}

还没有尝试过,但从我上面看到的,显然它会起作用。你太厉害了,非常感谢。我将把您的帖子标记为解决方案,但如果您能在以后回答我的后续问题,我可能会有跟进的问题。再一次,您太棒了。 - Forc3ofWill
好的,我本以为我能够自己完成这个任务,但不幸的是我的编程知识非常有限(我只知道一些C#和JavaScript的基础知识,我主要使用我的平面设计技能来修改其他类似的软件,我提到过的那些软件没有被编码),甚至不确定如何编译C程序...您能解释一下应该如何使用您提供的代码吗?(如何编译它,如何“显示”我想要解密的程序文件等)。我将非常感激。 - Forc3ofWill
抱歉,这个问题对于 Stack Overflow 的回答来说太过宽泛了。请使用 Google 进行搜索。在编译后,如果没有给出参数,则会显示其用法。 - Jongware
好的,我已经做了研究。现在我知道如何在Visual Studio中编译和构建C代码了。但是我仍然不理解C语法,以至于无法理解你的代码。但由于我上次的问题太宽泛了,所以现在我要问一个具体的问题:如何修改你上面发布的代码,以预定义我想要解密的文件路径(例如c:\documents\fileIWantToDecrypt.png)。这应该比让程序要求用户输入路径更容易。 - Forc3ofWill
最后一个问题。你能告诉我如何修改这段代码以对文件进行编码而不是解码吗?我知道你之前提到过,但我仍然不太理解C语法,无法弄清楚它的含义。 - Forc3ofWill
显示剩余2条评论

1

好的,当涉及到由@Jongware提供的代码的实际使用时,对我来说不是很清楚 - 我在一些帮助下弄明白了:)

  1. 我使用Visual Studio编译了代码(您可以找到如何执行此操作的指南,基本上创建新的Visual C ++项目,并在Project-> Project Propeties中选择C / C ++-> All options和Compile as C Code (/ TC))。
  2. 然后使用参数“program encrypted_file decrypted_file”在命令提示符中打开程序。

非常感谢Jongware的帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接