Python 2.7中的Unicode字符串的XOR

时间:2017-01-09 11:45:40

标签: python python-2.7 unicode

我正在尝试解码混淆的Android应用。反编译后,我可以看到几个字符串以这种方式被混淆:

static char[] java_decode(char[] cArr, char[] cArr2) {
        int i = 0;
        for (int i2 = 0; i2 < cArr.length; i2++) {
            cArr[i2] = (char) (cArr2[i] ^ cArr[i2]);
            i++;
            if (i >= cArr2.length) {
                i = 0;
            }
        }
        return cArr;
    }
str2 = new String(epgwmgrwgrdvzck("浶㫻ᒍ夓䌎箜湛泰Ⳮ䯣倝".toCharArray(), new char[]{'浌', '㫛', 'ᓮ', '奼', '䍻', '篲', '港', '沂', 'Ⲕ', '䯃', '倧'})).intern();
# java.lang.String str2 = ": country :"

为了更好地理解和快速审查,我希望将所有这些字符串改为普通字符串;我选择了Python,因为它只是一种快速而快速的脚本语言 可悲的是,我对那些多字节字符有些困难。这是我试图写的功能:

# coding=utf-8

def decode(string1, string2):
    string1 = list(string1)

    i = 0
    i2 = 0

    while i2 < len(string1):
        string1[i2] = chr(ord(string2[i]) ^ ord(string1[i2]))

        i += 1

        if i >= len(string2):
            i = 0

        i2 += 1

    string1 = str("".join(string1))    
    print string1

    return string1

decode("浶㫻ᒍ夓䌎箜湛泰Ⳮ䯣倝", ['浌', '㫛', 'ᓮ', '奼', '䍻', '篲', '港', '沂', 'Ⲕ', '䯃', '倧'])
# TypeError: ord() expected a character, but string of length 3 found

这里的主要问题是ord()只接受一个字符,而这些字符串由多字节字符组成。
关于如何解决这个问题的任何建议?

我使用的是Python 2.7.11 | Anaconda 4.0.0(x86_64)。我知道Python 3比Python 2有更好的Unicode支持;如果解决方案仅适用于Python 3,我可以毫无问题地使用它,因为它只是一次性脚本。

1 个答案:

答案 0 :(得分:2)

您的代码按原样运行(除非您需要在Python 3中将print string1更改为print(string1);输出和返回值为字符串: country :

但是,这在Python 2中不起作用,因为在Python 2中,字符串不是 unicode ;你需要在所有unicode字符串文字前加u前缀,即u'浌' /或者你需要使用from __future__ import unicode_literals来''在Python 2中创建unicode文字;并且chr还将值转换为8位字符串值(即字节),而不是unicode字符。

FWIW,代码可以更容易用 Python 3 编写为

from itertools import cycle

def decode(s1, s2):
    return ''.join([
        chr(ord(c1) ^ ord(c2))
        for c1, c2 in
        zip(s1, cycle(s2))
    ])

result = decode("浶㫻ᒍ夓䌎箜湛泰Ⳮ䯣倝",
                ['浌', '㫛', 'ᓮ', '奼', '䍻', '篲', '港', '沂', 'Ⲕ', '䯃', '倧'])

print(result)  # prints ": country :"

首先,似乎java代码允许第二个数组比第一个数组短,并且在这种情况下,它的值重复;在Python中,我们可以使用itertools.cycle来更有效地实现此效果。我们使用zip来配对输入数组中的相应值,并使用列表推导来构建将提供给''.join的列表。

此代码可以在 Python 2 中进行一些小修改,方法是添加from __future__ import unicode_literals并将chr更改为unichr

from __future__ import unicode_literals, print_function
from itertools import cycle

def decode(s1, s2):
    return ''.join([
        unichr(ord(c1) ^ ord(c2))
        for c1, c2 in
        zip(s1, cycle(s2))
    ])

result = decode("浶㫻ᒍ夓䌎箜湛泰Ⳮ䯣倝",
                ['浌', '㫛', 'ᓮ', '奼', '䍻', '篲', '港', '沂', 'Ⲕ', '䯃', '倧'])

print(result)  # prints ": country :"