so
文件,找到了IDA Pro生成的伪代码如下所示的解密函数:char __cdecl EncodeUtil::getDecryptStr()
{
int *v0; // r0
int *v1; // r7
unsigned int i; // r5
char v3; // r6
int v5; // [sp+4h] [bp-1Ch]
v1 = v0;
HttpUtility::URLDecode(&v5);
for ( i = 0; i < *(_DWORD *)(v5 - 12); ++i )
{
sub_3B25D0(&v5);
v3 = byte_41A7DD[i & 7]; //byte_41A7DD DCB 0xC, 0x17, 0xDE, 0x22, 0x2C, 0xC9, 0x37, 0x43
*(_BYTE *)(v5 + i) ^= v3;
sub_3B25D0(&v5);
if ( !*(_BYTE *)(v5 + i) )
{
sub_3B25D0(&v5);
*(_BYTE *)(v5 + i) ^= v3;
}
}
sub_3B2E20(v1, &v5);
sub_3B1CCC(&v5);
return (char)v1;
}
,而
sub_3B25D0
函数是:int *__fastcall sub_3B25D0(int *result)
{
if ( *(_DWORD *)(*result - 4) >= 0 )
result = sub_3B2580(result);
return result;
}
和
sub_3B2580
函数是:int *__fastcall sub_3B2580(int *result)
{
int v1; // r3
int *v2; // r4
v1 = *result;
v2 = result;
if ( (int *)(*result - 12) != &dword_4C60C0 )
{
if ( *(_DWORD *)(v1 - 4) > 0 )
{
result = sub_3B1D0C(result, 0, 0, 0);
v1 = *v2;
}
*(_DWORD *)(v1 - 4) = -1;
}
return result;
}
,然后是
sub_3B1D0C
int *__fastcall sub_3B1D0C(int *result, size_t a2, int a3, int a4)
{
int v4; // r12
int v5; // r10
int v6; // r8
int v7; // r7
unsigned int v8; // r3
unsigned int v9; // r8
int *v10; // r5
int v11; // r4
size_t v12; // r6
size_t v13; // r10
int v14; // r0
int v15; // r9
bool v16; // zf
int v17; // r7
int v18; // r4
const void *v19; // r1
int v20; // r7
int v21; // r4
_BYTE *v22; // r1
char v23; // [sp+4h] [bp-24h]
v4 = *result;
v5 = *(_DWORD *)(*result - 12);
v6 = a4 - a3;
v7 = a4;
v8 = *(_DWORD *)(*result - 8);
v9 = v6 + v5;
v10 = result;
v11 = a3;
v12 = a2;
v13 = v5 - a2 - a3;
if ( v9 > v8 || *(_DWORD *)(v4 - 4) > 0 )
{
v14 = sub_3B1B30(v9, v8, &v23);
if ( v12 )
{
v22 = (_BYTE *)*v10;
if ( v12 == 1 )
{
*(_BYTE *)(v14 + 12) = *v22;
v15 = v14 + 12;
}
else
{
v15 = v14 + 12;
memcpy((void *)(v14 + 12), v22, v12);
}
}
else
{
v15 = v14 + 12;
}
if ( v13 )
{
v20 = v7 + v12;
v21 = v11 + v12;
if ( v13 == 1 )
*(_BYTE *)(v15 + v20) = *(_BYTE *)(*v10 + v21);
else
memcpy((void *)(v15 + v20), (const void *)(*v10 + v21), v13);
}
result = (int *)(*v10 - 12);
if ( result != &dword_4C60C0 )
result = (int *)sub_3B1C84();
v4 = v15;
*v10 = v15;
}
else
{
v16 = a3 == v7;
if ( a3 != v7 )
v16 = v13 == 0;
if ( !v16 )
{
v17 = v7 + a2;
v18 = a3 + a2;
result = (int *)(v4 + v17);
v19 = (const void *)(v4 + a3 + a2);
if ( v13 == 1 )
*(_BYTE *)(v4 + v17) = *(_BYTE *)(v4 + v18);
else
result = (int *)memmove(result, v19, v13);
v4 = *v10;
}
}
if ( (int *)(v4 - 12) != &dword_4C60C0 )
{
*(_DWORD *)(v4 - 4) = 0;
*(_DWORD *)(v4 - 12) = v9;
*(_BYTE *)(v4 + v9) = 0;
}
return result;
}
谁能最好地猜测
HttpUtility::URLDecode
之后的功能是什么?编辑
NirIzr在下面的答案和一些评论中,我编写了一段Java代码来尝试XOR,如下所示:
public static void main(String args[])
{
byte[] _bytes = null;
byte[] key = {(byte) 0xC,(byte)0x17,(byte)0xDE,(byte)0x22,(byte)0x2C,(byte)0xC9,(byte)0x37,(byte)0x43};
String s = "%EB%9Ff%C5%A4q%D0%D9%88%F2M%87%C9Z%92%A6%83%BC%3B%86%8B%2D%8B%EC";
try {
String decoded = URLDecoder.decode(s,"UTF-8");
_bytes = decoded.getBytes();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
for(int i=0;i<_bytes.length;i++){
_bytes[i] = (byte)(_bytes[i] ^ key[i%key.length]);
}
System.out.println(new String(_bytes));
}
但是输出结果似乎不好:
�cD�mF�����v��c͓tm���1��&���c�v�����͓t��
#1 楼
这个答案的全部功劳应该归功于@NirIzr和@ Avery3R。这是一个Python脚本,实现了这些善良的人提到的异或运算:
import urllib
import binascii
data = "%EB%9Ff%C5%A4q%D0%D9%88%F2M%87%C9Z%92%A6%83%BC%3B%86%8B%2D%8B%EC" #quoted data as is
unquoted = urllib.unquote(data)
key = binascii.unhexlify("0C17DE222CC93743") # the key
idx = 0
res = ""
for c in unquoted:
res += chr(ord(c) ^ ord(key[idx % len(key)]))
idx += 1
print res
运行结果:
╭─wireshrink@[cenzored] ~/test
╰─$ python ./test.py
爸爸的哥哥叫大伯
我认为您要么忘记在打印之前将其编码回UTF8,要么存在其他问题与编码相关的代码或默认环境。
评论
谢谢,我将弄清楚我的java代码是什么问题:D
–armnotstrong
18年1月30日在13:38
有趣的内容(通过Google翻译):“爸爸的哥哥叫大伯”->“爸爸的哥哥叫叔叔”;)
–PawełŁukasik
18年1月30日在13:56
@PawełŁukasik哈哈
–armnotstrong
18年1月30日在14:29
#2 楼
首先,我不得不说反汇编中有几件事并没有加起来,而且我经常发现比反汇编更容易理解反汇编。让我们从执行大部分工作的功能开始-
sub_3B25D0
。 由于该函数有点长,并且其中包含一些引号-引号的令人恐惧的数学运算,因此我们的第一印象可能是该函数完成了全部或大部分加密工作。但是,经过进一步研究(在这里我将不做详细介绍),您可以清楚地看到压缩算法的迹象。有多个关键要素揭示了这一点,您可以在此答案中找到有关如何区分压缩和加密的完整说明。您提供的代码段。
字符串中的所有字符都没有按顺序整齐的迭代。几乎所有的加密算法(块或流)都会迭代输入字符串的所有字符。块将遍历字符串的块大小的块。
对输入消息或流/状态的替换不足。 -输入字符串的序列。
因此,将
memcpy
重命名为memmove
。您可以使用自己的缩写。我假设这是一种解压缩,而不是一种压缩函数,仅仅是因为您将流称为“解密”,意味着输入是无形的。看到那些功能只是对输入运行了几个简单的健全性检查,但基本上没有做任何有趣的事情。短暂浏览之后,似乎可以防止在同一字符串上多次运行sub_3B1D0C
函数,但是不确定。让我们跳过它们,转到第二个有趣的功能-NI_BlockDecompression
。我发现多次致电
sub_3B2580
很奇怪,建议您进一步研究一下发生的情况。 sub_3B25D0
函数似乎只是在NI_BlockDecompression
处使用硬编码的“ XOR加密”密钥对字节进行了异或运算。评论
嗨,@ Nirlzr谢谢您的回答,似乎很有希望,我将深入探讨
–armnotstrong
18年1月30日在3:03
嗨,@Nirlzr检查编辑:-(您能提供一些伪代码,所以我可以试着理解吗?
–armnotstrong
18年1月30日在3:38
@armnotstrong您正在执行异或运算(尽管同样,这里的代码不仅是异或运算。多次调用sub_3B25D0等有一些特殊性),但不执行解压缩。
– NirIzr
18年1月30日,下午3:39
评论
您可以共享二进制文件以便我们为您提供更好的帮助吗?@sudhackar当然,可以在这里找到.so文件,您可以搜索EncodeUtil.getDecryptStr以找到函数
您是否尝试过将其与您评论的字节数组进行异或运算?如果那不起作用,我尝试使用调试器逐步完成它。
最好是有一些示例来运行它们,但是看起来xoring可以完成cryptoStr所做的工作。
@PawełŁukasik@ Avery3R我想您可以使用%EB%9Ff%C5%A4q%D0%D9%88%F2M%87%C9Z%92%A6%83%BC%3B%86%8B%2D%8B%EC这样字符串(根据代码首先使用httpUrlEncode进行编码)进行测试,此外,我在此处上传了包含加密字符串的SQLite数据库