1

私はC++の暗号化メソッドをC#に変換する作業をしています。問題は、希望どおりに暗号化/復号化できないことです。

アイデアは単純です。パケットをキャプチャして復号化します。出力は次のようになります。パケットサイズ-コマンド/アクション-ヌル(終了)

(復号化機能は最初と最後の2バイトを切り取ります)

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;
}

-しかし、そうではありません。返される値は、復号化された値ではなく、単なる別の行です。与えられる出力は次のとおりです:.. O♦&amp;/OOOe。

ええと..少なくとも「/」は何らかの理由で正しい場所にあります。

いくつかの詳細情報:

  • 私が使用しているテストパケットは次のとおりです。

16進値:0C 00 E2 66 65 47 4E 09 04 13 65 00

プレーンテキスト:... feGN...e。

復号化:XX / hereXX

X =不明な値、私は本当に思い出せませんが、それは問題ではありません。

  • Hex Workshopを使用すると、次の方法でパケットを復号化できます。
    1. 特殊16進値をCF_TEXTとして貼り付け、[16進値として扱う]チェックボックスがオンになっていることを確認します。
    2. その後、最初と最後の2バイトを除いて、貼り付けた16進値からすべてを選択します。
    3. [ツール]>[操作]>[Xor]に移動します。
    4. 「データを8ビットデータとして扱う」を選択し、値を「61」に設定します。
    5. 「OK」を押すと完了です。

これを頭のてっぺんから書いているので、現時点で提供できる情報はこれだけです。

お時間をいただきありがとうございます。

これに質問が表示されない場合:

誰かがコードを見て何が悪いのかを知ることができれば、あるいはそれを行う別の方法があるとしたら、それは素晴らしいことです。私はC++にひどいので、このコードを変換しています。そのコードを使用してC#アプリケーションを作成したいと思います。

追伸:コードタグなどが面倒だったので、少し間隔などがめちゃくちゃになってすみません。

4

3 に答える 3

2

問題は、.NETのcharがユニコードであるため、一部の文字が複数のバイトを使用し、ビットマスクの長さが1バイトしかないことです。したがって、最上位バイトは変更されません。

于 2011-01-27T12:01:43.427 に答える
1

私はちょうどあなたの関数を試しました、そしてそれは大丈夫のようです:

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メソッド(このような方法)を使用することも検討できます。このようにして、次のようなものではなく、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;
}
于 2011-01-27T12:23:34.640 に答える
1

これは、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;
    }
}
于 2011-01-27T12:29:23.003 に答える