【问题标题】:C# Converting a XOR crypt functionC# 转换 XOR crypt 函数
【发布时间】:2011-01-27 20:34:31
【问题描述】:

我一直致力于将 C++ 加密方法转换为 C#。问题是,我无法让它按照我想要的方式加密/解密。

这个想法很简单,我捕获一个数据包,然后解密它。输出将是: 数据包大小 - 命令/操作 - 空(结束)

(解密器将前两个字节截掉)

C++ 代码是这样的:

// Crypt the packet with Xor operator
void cryptPacket(char *packet)
{
    unsigned short paksize=(*((unsigned short*)&packet[0])) - 2;

    for(int i=2; i<paksize; i++)
    {
         packet[i] = 0x61 ^ packet[i];
    }
}

所以我认为如果我不想使用指针,这将在 C# 中工作:

public static char[] CryptPacket(char[] packet)
{
    ushort paksize = (ushort) (packet.Length - 2);

    for(int i=2; i<paksize; i++)
    {
        packet[i] = (char) (0x61 ^ packet[i]);
    }

    return packet;
}

-但它不是,返回的值只是另一行 rubish 而不是解密的值。给出的输出是:..O♦&/OOOe。

嗯.. 至少 '/' 出于某种原因在正确的位置。

更多信息:

  • 我使用的测试包是这样的:

十六进制值:0C 00 E2 66 65 47 4E 09 04 13 65 00

纯文本:...feGN...e.

解密:XX/hereXX

X = 未知值,我不记得了,但没关系。

  • 使用 Hex Workshop,您可以通过以下方式解密数据包:
    1. Special 将十六进制值粘贴为 CF_TEXT,确保选中“视为十六进制值”框。
    2. 然后,从您刚刚粘贴的十六进制值中选择所有内容,除了第一个和最后 2 个字节。
    3. 转到工具>操作>异或。
    4. 选择“将数据视为 8 位数据”并将值设置为“61”。
    5. 按“确定”,您就完成了。

这就是我目前所能提供的所有信息,因为我是在脑海中写下这些。

感谢您的宝贵时间。

如果您在此没有看到问题:

如果有人可以查看代码以了解其中有什么问题,或者是否有其他方法可以做到这一点,那就太好了。我正在转换这段代码,因为我不喜欢 C++,并且想用该代码创建一个 C# 应用程序。

Ps:代码标签之类的东西很痛苦,所以如果间距等有点混乱,我很抱歉。

【问题讨论】:

  • 您只需将所有内容缩进 4 个空格,以指示 markdown 将其格式化为代码。您还可以选择整个代码块,然后单击工具栏中的“代码”按钮(带有花括号的那个)。它不应该像看起来那么困难。
  • 这不是一个非常复杂的加密(XORing 每个字节与一个固定的常数)。事实上,它基本上与例如没有什么不同。烂13!使用 ASCII 图表(例如asciitable.com)作为参考,单步执行并查看它为什么不起作用应该非常简单。您已经从调试器和跟踪语句中学到了什么?
  • @Cody 这就是我所做的,但是标签出现在不同的地方,所以我尝试剪切/粘贴标签,但后来它们弄乱了一些行。 sigh @Oli 我了解到它按指示工作,但未按预期工作..
  • @Nick:当您逐步完成循环时,packet[i] 的每个值是您所期望的吗?每次异或运算的结果是否符合您的预期?
  • 正如 Massif 下面所说,使用byte 而不是char。此外,使用ushort 代替int 来代替paksize 并没有太大的好处。

标签: c# c++ encryption xor


【解决方案1】:

您的问题可能是由于 .NET 的 char 是 unicode,因此某些字符将使用超过一个字节,而您的位掩码只有一个字节长。所以最高有效字节将保持不变。

【讨论】:

  • +1 没错,将char 替换为byte 应该可以解决问题。
  • 试过了,结果是:'..O♦&/OOOe.'但是,我确实看到 / 和“e”在正确的位置,所以我们越来越近了。 =P 谢谢你的回复,希望你能想到点别的。
【解决方案2】:

我刚试了你的功能,感觉还可以:

class Program
{
    // OP's method: http://stackoverflow.com/questions/4815959
    public static byte[] CryptPacket(byte[] packet)
    {
        int paksize = packet.Length - 2;
        for (int i = 2; i < paksize; i++)
        {
            packet[i] = (byte)(0x61 ^ packet[i]);
        }
        return packet;
    }

    // http://stackoverflow.com/questions/321370 :)
    public static byte[] StringToByteArray(string hex)
    {
        return Enumerable.Range(0, hex.Length).
               Where(x => 0 == x % 2).
               Select(x => Convert.ToByte(hex.Substring(x, 2), 16)).
               ToArray();
    }

    static void Main(string[] args)
    {
        string hex = "0C 00 E2 66 65 47 4E 09 04 13 65 00".Replace(" ", "");
        byte[] input = StringToByteArray(hex);
        Console.WriteLine("Input: " + ASCIIEncoding.ASCII.GetString(input));
        byte[] output = CryptPacket(input);
        Console.WriteLine("Output: " + ASCIIEncoding.ASCII.GetString(output));
        Console.ReadLine();
    }
}

控制台输出:

Input: ...feGN.....
Output: ...../here..
(where '.' represents funny ascii characters)

您的CryptPacket 方法正在用输出值覆盖初始数组,这似乎有点臭。并且不会修剪不相关的字符。但是如果你想移植一些东西,我想你应该知道你在做什么。

您还可以考虑修剪输入数组,首先删除不需要的字符,然后使用通用 ROT13 方法(如 this one)。这样,您就拥有自己的“专用”版本,其中 crypt 函数本身具有 2 字节偏移量,而不是类似:

public static byte[] CryptPacket(byte[] packet)
{
    // create a new instance
    byte[] output = new byte[packet.Length];

    // process ALL array items
    for (int i = 0; i < packet.Length; i++)
    {
        output[i] = (byte)(0x61 ^ packet[i]);
    }

    return output;
}

【讨论】:

  • 从unicode字符串转换为字节数组的更正确方法:System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); byte[] byteArray = encoding.GetBytes("sample string");
  • 感谢您的代码,它就像一个魅力!不相关的数据也可以正确解密,但我无需付出额外的努力,因为我只需要提取以“/”开头的字符串,直到该字符串的结尾。再次感谢!
【解决方案3】:

这是从 C++ 到 C# 的几乎字面翻译,它似乎有效:

var packet = new byte[] {
                            0x0C, 0x00, 0xE2, 0x66, 0x65, 0x47,
                            0x4E, 0x09, 0x04, 0x13, 0x65, 0x00
                        };

CryptPacket(packet);

// displays "....../here." where "." represents an unprintable character
Console.WriteLine(Encoding.ASCII.GetString(packet));

// ...

void CryptPacket(byte[] packet)
{
    int paksize = (packet[0] | (packet[1] << 8)) - 2;

    for (int i = 2; i < paksize; i++)
    {
        packet[i] ^= 0x61;
    }
}

【讨论】:

  • 感谢您的宝贵时间,我已经收到了一个工作代码,但这个版本将在我正在从事的另一个项目中帮助我很多!
猜你喜欢
  • 1970-01-01
  • 2011-10-09
  • 1970-01-01
  • 2020-01-17
  • 2016-02-17
  • 2014-09-15
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多