2

単純なC++関数をJavascriptに移植していますが、Javascriptがビット演算子を処理する方法に問題が発生しているようです。

C ++の場合:

AnsiString MyClass::Obfuscate(AnsiString source)
{
    int sourcelength=source.Length();
    for(int i=1;i<=sourcelength;i++)
    {
        source[i] = source[i] ^ 0xFFF;
    }
    return source;
}

Obfuscate( "test")は一時的なintvaluesを生成します

-117, -102, -116, -117

Obfuscate( "test")はstringvalueを生成します

‹šŒ‹

Javascriptの場合:

function obfuscate(str) 
{
    var obfuscated= "";
    for (i=0; i<str.length;i++) {

        var a = str.charCodeAt(i);                 
        var b = a ^ 0xFFF;
        obfuscated= obfuscated+String.fromCharCode(b);
    }
    return obfuscated;
}       

obfuscate( "test")は一時的なintvaluesを生成します

3979 , 3994 , 3980 , 3979

obfuscate( "test")はstringvalueを生成します

ྋྚྌྋ

今、私は、Javascriptがすべての数値をfloatとして扱い、ビット単位の操作には32ビットintへの一時的なキャストが含まれることを指摘するスレッドがたくさんあることに気付きました。

私がJavascriptで難読化し、C ++で反転していることと、異なる結果が実際には一致しないことを除いて、実際には問題にはなりません。

Javascriptの結果をC++の結果に変換するにはどうすればよいですか?簡単なシフトはありますか?

4

5 に答える 5

4

作業デモ

xoring 116withが-117を0xFFF与えるという結果から判断すると、JavaScriptで2の補数の8ビット整数をエミュレートする必要があります。

function obfuscate(str) 
{
    var bytes = [];
    for (var i=0; i<str.length;i++) {
        bytes.push( ( ( ( str.charCodeAt(i) ^ 0xFFF ) & 0xFF ) ^ 0x80 ) -0x80 );
    }
    return bytes;
}   

これらのバイトはWindowscp1252で解釈され、負の場合はおそらく256から減算されます。

var ascii = [
    0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F
    ,0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F
    ,0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F
    ,0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F
    ,0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F
    ,0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F
    ,0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F
    ,0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F
];

var cp1252 = ascii.concat([
    0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021,0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD
    ,0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,0x02DC,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
    ,0x00A0,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7,0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF
    ,0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7,0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF
    ,0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7,0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF
    ,0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF
    ,0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7,0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF
    ,0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7,0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x00FF
]);

function toStringCp1252(bytes){
    var byte, codePoint, codePoints = [];
    for( var i = 0; i < bytes.length; ++i ) {
        byte = bytes[i];
        if( byte < 0 ) {
            byte = 256 + byte;
        }
        codePoint = cp1252[byte];
        codePoints.push( codePoint );

    }

    return String.fromCharCode.apply( String, codePoints );
}

結果

toStringCp1252(obfuscate("test"))
//"‹šŒ‹"
于 2012-07-19T14:57:16.197 に答える
1

これには8ビット文字が含まれていると思いAnsiStringます(ANSI文字セットは8ビットであるため)。XORの結果を文字列に戻すと、8ビットに切り捨てられるため、結果の値は[-128...127]の範囲になります。

(一部のプラットフォームでは、[0..255]になる可能性があり、他のプラットフォームでは、char符号付きか符号なしか、または8ビット以上かどうかが指定されていないため、範囲が広くなる可能性があります)。

Javascript文字列には、はるかに広い範囲の値を保持できるUnicode文字が含まれているため、結果は8ビットに切り捨てられません。XORの結果は、少なくとも12ビットの範囲[0 ... 4095]になるため、そこに大きな数値が表示されます。

元の文字列に8ビット文字しか含まれていないと仮定すると、操作を変更するa ^ 0xffと、両方の言語で同じ結果が得られるはずです。

于 2012-07-19T14:50:31.973 に答える
1

AnsiString私はそれが何らかの形で、sの配列であると仮定しcharます。そしてこれが問題です。では、通常char8ビットしか保持できません。したがって、とXORを実行し0xfff、結果をに格納すると、。とXORを実行charするのと同じになり0xffます。

これはには当てはまりません。Unicodeを使用したJavaScript。これは、整数値を調べることで示されます。

-117 == 0x8b3979 == 0xf8b

0xffこれは両方の言語で機能するため、XORを使用することをお勧めします。または、 Unicodeを使用するようにコードを切り替えることができます。

于 2012-07-19T14:49:13.380 に答える
0

まず、をに変換しAnsiStringますwchar_t*。その後、個々の文字を難読化します。

AnsiString MyClass::Obfuscate(AnsiString source)
{
   /// allocate string
   int num_wchars = source.WideCharBufSize();
   wchar_t* UnicodeString = new wchar_t[num_wchars];
   source.WideChar(UnicodeString, source.WideCharBufSize());

   /// obfuscate individual characters
   int sourcelength=source.Length();
   for(int i = 0 ; i < num_wchars ; i++)
   {
       UnicodeString[i] = UnicodeString[i] ^ 0xFFF;
   }

   /// create obfuscated AnsiString
   AnsiString result = AnsiString(UnicodeString);

   /// delete tmp string
   delete [] UnicodeString;

   return result;
}

申し訳ありませんが、私はC ++ Builderの専門家ではありませんが、私の要点は単純です。JavaScriptにはWCS2記号(またはUTF-16)があるため、AnsiString最初にワイド文字に変換する必要があります。

WideString代わりに使用してみてくださいAnsiString

于 2012-07-19T14:49:02.173 に答える
0

まったくわかりませんAnsiStringが、これはキャラクターの幅に関係していると思います。具体的には、32ビット幅未満であると思われます。もちろん、ビット単位の演算では、特に2の補数を処理する場合に、操作対象の幅が重要になります。

JavaScriptでは、"t"in"test"は文字コード116で、b00000000000000000000000001110100です。0xFFF(4095)はb00000000000000000000111111111111であり、取得する結果(3979)はb00000000000000000000111110001011です。XORに対して正しい結果が得られていることがすぐにわかります。

116 = 00000000000000000000000001110100
4095 = 00000000000000000000111111111111
3979 = 00000000000000000000111110001011

したがって、C ++コードで切り捨てなどが発生していると思います。特に、-117は8ビット2の補数のb10001011であるためです。これは、上記の3979の最後の8ビットとまったく同じです。

于 2012-07-19T14:52:23.047 に答える