我有一个手臂编译的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��

评论

您可以共享二进制文件以便我们为您提供更好的帮助吗?

@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数据库

#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