2013-03-04 36 views
7

tôi có mã này trong C mà tôi cần phải cổng C#:Porting đang chứa unsigned con trỏ char trong C đến C#

void CryptoBuffer(unsigned char *Buffer, unsigned short length) 
{ 
    unsigned short i; 
    for(i=0; i < length; i++) 
    { 
     *Buffer ^= 0xAA; 
     *Buffer++ += 0xC9; 
    } 
} 

Tôi cố gắng này:

public void CryptoBuffer(byte[] buffer, int length) 
{ 
    for(int i = 0; i < length; i++) 
    { 
     buffer[i] ^= 0xAA; 
     buffer[i] += 0xC9; 
    } 
} 

Nhưng kết quả doesn' t phù hợp với dự kiến.

Theo ví dụ này, này:

A5 03 18 01... 

nên trở thành này:

A5 6F 93 8B... 

Nó cũng cho biết byte đầu tiên không được mã hóa, vì vậy đó là lý do tại sao A5 vẫn như cũ.

CHỈNH SỬA để làm rõ: Thông số chỉ cho biết bạn nên bỏ qua byte đầu tiên, nó không đi vào chi tiết, vì vậy tôi đoán bạn chỉ cần vượt qua chuỗi từ vị trí 1 cho đến vị trí cuối cùng để bỏ qua byte.

Nhưng kết quả của tôi với C# cảng gồm:

A5 72 7B 74... 

là cổng này đúng hay tôi thiếu cái gì?

EDIT 2: Để làm rõ thêm, đây là giao thức đóng, vì vậy tôi không thể đi vào chi tiết, đó là lý do tại sao tôi cung cấp đủ thông tin để giúp tôi chuyển mã, mã C đó là mã trao cho tôi, và đó là những gì đặc điểm kỹ thuật nói nó sẽ làm. Vấn đề thực sự là "0xAA" đã sai trong đặc điểm kỹ thuật, đó là lý do tại sao đầu ra không phải là dự kiến. Mã C# được cung cấp ở đây và bởi câu trả lời được chấp nhận là chính xác sau khi tất cả.

+7

Đó là một số mã C nghiêm trọng khó đọc. Ai nghĩ rằng nó là một ý tưởng tốt để trộn dereferencing, incrementing, bổ sung và phân công trong một biểu thức? –

+1

Với đầu vào ví dụ của bạn, tôi nhận được câu trả lời tương tự cho C và C#, ngoại trừ byte đầu tiên (vì bạn không đưa ra dấu hiệu nào trong mã là tại sao nó bị bỏ qua). – user7116

+1

@Eric: Kernighan và Ritchie dường như thích loại mã đó, nếu bộ nhớ của tôi đọc Ngôn ngữ lập trình C trong thập niên 80 phục vụ ...;) Ví dụ về strcpy của họ trông giống như trong khi ((* s ++) = * t ++)! = '\ 0'); '... Shudder –

Trả lời

9

Hãy phá vỡ nó xuống thì chúng tôi, một bước tại một thời điểm.

void CryptoBuffer(unsigned char *Buffer, unsigned short length) 
{ 
    unsigned short i; 
    for(i=0; i < length; i++) 
    { 
     *Buffer ^= 0xAA; 
     *Buffer++ += 0xC9; 
    } 
} 

Bất kể một số nhận xét khác, đây là cách bạn thường làm những việc này trong C/C++. Không có gì lạ mắt về mã này, và nó không quá phức tạp, nhưng tôi nghĩ tốt nhất là chia nhỏ nó ra để cho bạn thấy điều gì xảy ra.

Những điều cần lưu ý:

  1. unsigned char là cơ bản giống như byte trong C#
  2. dài unsigned có giá trị từ 0-65.536. Int nên làm các trick.
  3. Bộ đệm có tăng sau
  4. Việc gán byte (+ = 0xC9) sẽ tràn. Nếu nó tràn nó cắt ngắn đến 8 bit trong trường hợp này.
  5. Bộ đệm được chuyển bởi ptr, vì vậy con trỏ trong phương thức gọi sẽ giữ nguyên.
  6. Đây chỉ là mã C cơ bản, không có C++. Nó là khá an toàn để giả định mọi người không sử dụng quá tải nhà điều hành ở đây.

Điều "khó" duy nhất ở đây là bộ đệm ++. Chi tiết có thể được đọc trong cuốn sách "Exceptional C++" từ Sutter, nhưng một ví dụ nhỏ giải thích điều này là tốt. Và may mắn thay, chúng tôi có một ví dụ hoàn hảo theo ý của chúng tôi. Một đen dịch của mã trên là:

void CryptoBuffer(unsigned char *Buffer, unsigned short length) 
{ 
    unsigned short i; 
    for(i=0; i < length; i++) 
    { 
     *Buffer ^= 0xAA; 
     unsigned char *tmp = Buffer; 
     *tmp += 0xC9; 
     Buffer = tmp + 1; 
    } 
} 

Trong trường hợp này biến temp có thể được giải quyết trivially, dẫn chúng tôi:

void CryptoBuffer(unsigned char *Buffer, unsigned short length) 
{ 
    unsigned short i; 
    for(i=0; i < length; i++) 
    { 
     *Buffer ^= 0xAA; 
     *Buffer += 0xC9; 
     ++Buffer; 
    } 
} 

Thay đổi mã này vào C# tại là khá dễ dàng :

private void CryptoBuffer(byte[] Buffer, int length) 
{ 
    for (int i=0; i<length; ++i) 
    { 
     Buffer[i] = (byte)((Buffer[i]^0xAA) + 0xC9); 
    } 
} 

Điều này về cơ bản giống như mã được chuyển của bạn. Điều này có nghĩa là một nơi nào đó trên đường đi một cái gì đó khác đã đi sai ... Vì vậy, hãy hack cryptobuffer phải không? :-)

Nếu chúng ta giả định rằng byte đầu tiên không được sử dụng (như bạn nói) và rằng '0xAA' và/hoặc '0xC9' là sai, chúng ta chỉ có thể thử tất cả các kết hợp:

static void Main(string[] args) 
{ 
    byte[] orig = new byte[] { 0x03, 0x18, 0x01 }; 
    byte[] target = new byte[] { 0x6F, 0x93, 0x8b }; 

    for (int i = 0; i < 256; ++i) 
    { 
     for (int j = 0; j < 256; ++j) 
     { 
      bool okay = true; 
      for (int k = 0; okay && k < 3; ++k) 
      { 
       byte tmp = (byte)((orig[k]^i) + j); 
       if (tmp != target[k]) { okay = false; break; } 
      } 
      if (okay) 
      { 
       Console.WriteLine("Solution for i={0} and j={1}", i, j); 
      } 
     } 
    } 
    Console.ReadLine(); 
} 

Hiện tại, chúng tôi đi: oops không có giải pháp nào. Điều đó có nghĩa rằng các cryptobuffer không làm những gì bạn nghĩ rằng nó đang làm, hoặc một phần của mã C là mất tích ở đây. F.ex. họ có thực sự chuyển 'Buffer' sang phương thức CryptoBuffer hay họ đã thay đổi con trỏ trước đây?

Kết luận, tôi nghĩ câu trả lời duy nhất ở đây là thông tin quan trọng để giải quyết câu hỏi này bị thiếu.

+0

hứa hẹn với số tiền thưởng –

+0

Cảm ơn Ken Kin. Tuy nhiên, thông tin khác từ @Mahmoud sẽ rất hữu ích, vì vậy chúng tôi thực sự có thể giải quyết vấn đề này. – atlaste

+0

Vì nó chỉ ra vấn đề thực sự là mã C đã không làm những gì đặc điểm kỹ thuật đã nói, nên đó là lý do tại sao cổng không hoạt động, cả cổng của tôi và cổng của bạn đều hoạt động sau khi đặc tả chính xác được thông qua. Khóa "0xAA" không chính xác, nó thực sự là một chuỗi gồm 8 giá trị khác nhau. Tôi không thể đăng chúng ở đây vì nó là chìa khóa được cho là riêng tư, nhưng cảm ơn vì sự trợ giúp trả lời câu hỏi. – Mahmoud

1

Cổng trông.

Điều tôi sẽ làm trong trường hợp này là lấy ra một mẩu giấy và một cây bút, viết ra các byte theo dạng nhị phân, thực hiện XOR và sau đó thêm vào. Bây giờ so sánh điều này với mã C và C#.

1

Trong C#, bạn đang tràn byte để nó bị cắt bớt thành 0x72. Đây là phép tính để chuyển đổi 0x03 trong cả nhị phân và hex:

00000011 0x003 
^ 10101010 0x0AA 
= 10101001 0x0A9 
+ 11001001 0x0C9 
= 101110010 0x172 
+2

Nó sẽ tràn một cách giống hệt nhau trong C, tho. –

3

Porting trông đúng; bạn có thể giải thích tại sao 03 nên trở thành 6F? Thực tế là kết quả dường như được giảm giá trị "mong đợi" của 03 là một chút đáng ngờ với tôi.

+0

Đặc điểm kỹ thuật cho thấy đó là một ví dụ. Nó cũng nói rằng bạn nên luôn luôn bỏ qua byte đầu tiên. – Mahmoud

+1

@Mahmoud: bạn cần nói đặc điểm kỹ thuật bạn đang nói đến. – user7116

5

Ví dụ bạn đã cung cấp không phù hợp với mã trong mẫu C và mã C và C# tạo ra kết quả giống hệt nhau.

0

Với phương pháp ban đầu trong C, đầu tiên chúng ta giả sử chuỗi được giải mã/mã hóa trong một đối xứng cách với gọi CryptoBuffer

  • ban đầu gọi trên a5 03 18 01 ...

    a5 03 18 01 ... => d8 72 7b 74 ... 
    

    đó trở đi d8 72 7b 74 ...

    d8 72 7b 74 ... => 3b a1 9a a7 ... 
    
  • ban đầu gọi trên a5 6f 93 8b ...

    a5 6f 93 8b ... => d8 8e 02 ea ... 
    

    đó trở đi d8 8e 02 ea ...

    d8 8e 02 ea ... => 3b ed 71 09 ... 
    

và chúng tôi biết điều đó là không khả thi.

Tất nhiên, bạn có thể có phương thức giải mã bất đối xứng không đối xứng; nhưng trước hết, chúng tôi sẽ cần hoặc là a5 03 18 01 ... => a5 6f 93 8b ... hoặc ngược lại hướng được chứng minh với bất kỳ số ma thuật có thể. Mã phân tích với phương pháp tiếp cận vũ lực brute được đặt ở mặt sau của bài đăng.

Tôi đã tạo số ma thuật là biến để thử nghiệm. Với phân tích khả năng tái sản xuất, chúng tôi nhận thấy rằng trình tự ban đầu có thể được sao chép mọi lời gọi 256 trên số ma thuật liên tục thay đổi. Được rồi, với những gì chúng tôi đã trải qua, nó vẫn có thể ở đây.

Tuy nhiên, việc phân tích tính khả thi mà kiểm tra tất cả các trường hợp 256*256=65536 với cả hai hướng, từ original => expectedexpected => original, và không ai làm cho nó.

Và bây giờ chúng tôi biết không có cách nào để giải mã chuỗi được mã hóa thành kết quả mong đợi.

Do đó, chúng tôi chỉ có thể nói rằng các hành vi dự kiến ​​của cả hai ngôn ngữ hoặc mã của bạn là giống hệt nhau, nhưng đối với các kết quả mong đợi là không thể vì giả thuyết đã bị hỏng.


Mã để phân tích

public void CryptoBuffer(byte[] buffer, ushort magicShort) { 
    var magicBytes=BitConverter.GetBytes(magicShort); 
    var count=buffer.Length; 

    for(var i=0; i<count; i++) { 
     buffer[i]^=magicBytes[1]; 
     buffer[i]+=magicBytes[0]; 
    } 
} 

int Analyze(
    Action<byte[], ushort> subject, 
    byte[] expected, byte[] original, 
    ushort? magicShort=default(ushort?) 
    ) { 
    Func<byte[], String> LaHeX= // narrowing bytes to hex statement 
     arg => arg.Select(x => String.Format("{0:x2}\x20", x)).Aggregate(String.Concat); 

    var temporal=(byte[])original.Clone(); 
    var found=0; 

    for(var i=ushort.MaxValue; i>=0; --i) { 
     if(found>255) { 
      Console.WriteLine(": might found more than the number of square root; "); 
      Console.WriteLine(": analyze stopped "); 
      Console.WriteLine(); 
      break; 
     } 

     subject(temporal, magicShort??i); 

     if(expected.SequenceEqual(temporal)) { 
      ++found; 
      Console.WriteLine("i={0:x2}; temporal={1}", i, LaHeX(temporal)); 
     } 

     if(expected!=original) 
      temporal=(byte[])original.Clone(); 
    } 

    return found; 
} 

void PerformTest() { 
    var original=new byte[] { 0xa5, 0x03, 0x18, 0x01 }; 
    var expected=new byte[] { 0xa5, 0x6f, 0x93, 0x8b }; 

    Console.WriteLine("--- reproducibility analysis --- "); 
    Console.WriteLine("found: {0}", Analyze(CryptoBuffer, original, original, 0xaac9)); 
    Console.WriteLine(); 

    Console.WriteLine("--- feasibility analysis --- "); 
    Console.WriteLine("found: {0}", Analyze(CryptoBuffer, expected, original)); 
    Console.WriteLine(); 

    // swap original and expected 
    var temporal=original; 
    original=expected; 
    expected=temporal; 

    Console.WriteLine("--- reproducibility analysis --- "); 
    Console.WriteLine("found: {0}", Analyze(CryptoBuffer, original, original, 0xaac9)); 
    Console.WriteLine(); 

    Console.WriteLine("--- feasibility analysis --- "); 
    Console.WriteLine("found: {0}", Analyze(CryptoBuffer, expected, original)); 
    Console.WriteLine(); 
} 
0

Dưới đây là một cuộc biểu tình

http://codepad.org/UrX0okgu

cho thấy rằng mã gốc, do một đầu vào của sản xuất A5 03 18 01D8 72 7B 01; nên

  1. quy tắc đó byte đầu tiên không được giải mã có thể là đúng chỉ khi bộ đệm được gửi bắt đầu từ thứ 2 (chỉ cho chúng ta cuộc gọi)

  2. đầu ra không phù hợp (làm bạn bỏ lỡ các cuộc gọi khác ?)

Vì vậy, bản dịch của bạn là chính xác nhưng mong đợi của bạn về những gì mã ban đầu không.