2011-01-27 64 views
1

我一直在努力將C++加密方法轉換爲C#。問題是,我不能以我想要的方式加密/解密。C#轉換XOR加密函數

這個想法很簡單,我捕獲一個數據包,並解密它。輸出將是: 數據包大小 - 命令/操作 - 空(完)

(解密器切斷第一和最後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; 
} 

- 但它不是,返回值是rubish的只是另一行,而不是的decryp特德值。給出的輸出是:OO &/OOOE。

那麼..至少'/'是在正確的地方出於某種原因。

一些更多信息:

  • 我使用的測試分組是這樣的:

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

純文本:... feGN ... e。

解密:XX/hereXX

x =未知值,我真的不能記得了,但沒關係。

  • 使用六角車間,您可以解密數據包是這樣的:
    1. 特殊粘貼十六進制值CF_TEXT,確保「當作十六進制值」複選框被選中。
    2. 然後,從剛剛粘貼的十六進制值中選擇一切,除了第一個和最後兩個字節。
    3. 轉到工具>操作>異或。
    4. 選擇'將數據視爲8位數據'並將值設置爲'61'。
    5. 按'確定',你就完成了。

這是我的時刻給予的所有信息,因爲我在寫這個了我的頭頂。

謝謝你的時間。

如果您沒有看到這個問題:

這將是巨大的,如果有人可以在代碼看看,看看有什麼不對的地方,或者,如果有另一種方式來做到這一點。我正在轉換此代碼,因爲我對C++非常不滿,並且希望使用該代碼創建一個C#應用程序。

Ps:代碼標籤等是一種痛苦,所以我很抱歉,如果間距等有點搞砸了。

+0

您只需按4個空格縮進所有內容,以指示markdown應將其格式化爲代碼。您也可以選擇整個代碼塊,然後單擊工具欄中的「代碼」按鈕(帶花括號的那個)。它不應該像它看起來那麼困難。 – 2011-01-27 12:00:41

+0

這不是一個非常複雜的加密(將每個字節與固定常量異或)。實際上,它與例如ROT13!使用ASCII圖表(例如http://www.asciitable.com/)作爲參考,應該非常簡單地瞭解它爲什麼不起作用。你已經用調試器和跟蹤語句學到了什麼? – 2011-01-27 12:02:29

+0

@Cody這就是我所做的,但標籤出現在不同的地方,所以我試圖剪切/粘貼標籤,但後來他們搞砸了一些線條。 *嘆了口氣* @Oli我知道它按照指示工作,但並非如預期的那樣。 – Nick 2011-01-27 12:04:45

回答

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方法(如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; 
} 
2

你的問題可能是因爲.NET的char是unicode,一些字符將會使用多個字節,而你的位掩碼只有一個字節長。所以最重要的字節將保持不變。

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