第一次Android逆向初体验

不得不说,我的思维水平一直在低位徘徊,技术水平仍然停留在以前。

就像有家公司,你去面试,他说他对一个人说的话的根本就不感兴趣,他想看看你写的东西,比如博客。我后来才感觉,他是对的,从一个人的字里行间就可以知道他是什么人,他的思维模式,他经历的历史。

大约在2016年,我经历了第一次android逆向的完整过程,非常感谢当时老板的支持,因为我们那时候没人懂这个玩意儿,老板的奇思妙想,同事的信任,以及自己的任性,给了我很多的勇气和毅力来完成这个项目。我那时候一直坚信,我可以重构整个internet,只要我想的话。这种执着给我提供了源源不断的动力,就像在前线、在战场,意志力为一个战士的舞台提供了无与伦比的想象空间。

该程序是一个同步程序,用于备份同步本机和服务器上的通讯录、短信、通话记录等信息。其网络数据全部加密,其解密后的核心算法如下:

#include "stdafx.h"

unsigned char TeaKey[256] = {0};

unsigned char unk_19578[] = {
0x44,0x46,0x47,0x00,0x00,0x00,0x00,0x3C,0x3E,0x3C,0x00,0x00,0x00,0x00,0x26,0x2A,
0x4D,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x06,0x00,0x03,0x00,
0x05,0x00,0x04,0x00,0x00 };

unsigned char  * unk_1957F = unk_19578 + 7;
unsigned char * unk_19586 = unk_19578 + 14;
unsigned char  * unk_1958E = unk_19578 + 22;

unsigned char unk_1A43C[] = {
0x78,0xA4,0x6A,0xD7,0x56,0xB7,0xC7,0xE8,0xDB,0x70,0x20,0x24,0xEE,0xCE,0xBD,0xC1,
0xAF,0x0F,0x7C,0xF5,0x2A,0xC6,0x87,0x47,0x13,0x46,0x30,0xA8,0x01,0x95,0x46,0xFD,
0xD8,0x98,0x80,0x69,0xAF,0xF7,0x44,0x8B,0xB1,0x5B,0xFF,0xFF,0xBE,0xD7,0x5C,0x89,
0x22,0x11,0x90,0x6B,0x93,0x71,0x98,0xFD,0x8E,0x43,0x79,0xA6,0x21,0x08,0xB4,0x49,
//1a47c
0x62,0x25,0x1e,0xf6,0x40,0xB3,0x40,0xC0,0x51,0x5A,0x5E,0x26,0xAA,0xC7,0xB6,0xE9,
0x5D,0x10,0x2F,0xD6,0x53,0x14,0x44,0x02,0x81,0xE6,0xA1,0xD8,0xC8,0xFB,0xD3,0xE7,
0xE6,0xCD,0xE1,0x21,0xD6,0x07,0x37,0xC3,0x87,0x0D,0xD5,0xF4,0xED,0x14,0x5A,0x45,
0x05,0xE9,0xE3,0xA9,0xF8,0xA3,0xEF,0xFC,0xD9,0x02,0x6F,0x67,0x8A,0x4C,0x2A,0x8D,
0x42,0x39,0xFA,0xFF,0x81,0xF6,0x71,0x87,0x22,0x61,0x9D,0x6D,0x0C,0x38,0xE5,0xFD,
0x44,0xEA,0xBE,0xA4,0xA9,0xCF,0xDE,0x4B,0x60,0x4B,0xBB,0xF6,0x70,0xBC,0xBF,0xBE,
0xC6,0x7E,0x9B,0x28,0xFA,0x27,0xA1,0xEA,0x85,0x30,0xEF,0xD4,0x05,0x1D,0x88,0x04,
0x39,0xD0,0xD4,0xD9,0xE5,0x99,0xDB,0xE6,0xF8,0x7C,0xA2,0x1F,0x65,0x56,0xAC,0xC4,
0x44,0x22,0x29,0xF4,0x97,0xFF,0x2A,0x43,0xA7,0x23,0x94,0xAB,0x39,0xA0,0x93,0xFC,
0xC3,0x59,0x5B,0x65,0x92,0xCC,0x0C,0x8F,0x7D,0xF4,0xEF,0xFF,0xD1,0x5D,0x84,0x85,
0x4F,0x7E,0xA8,0x6F,0xE0,0xE6,0x2C,0xFE,0x14,0x43,0x01,0xA3,0xA1,0x11,0x08,0x4E,
0x82,0x7E,0x53,0xF7,0x35,0xF2,0x3A,0xBD,0xBB,0xD2,0xD7,0x2A,0x91,0xD3,0x86,0xEB,
//1a53c
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x01,0x06,0x0B,0x00,0x05,0x0A,0x0F,0x04,0x09,0x0E,0x03,0x08,0x0D,0x02,0x07,0x0C,
0x05,0x08,0x0B,0x0E,0x01,0x04,0x07,0x0A,0x0D,0x00,0x03,0x06,0x09,0x0C,0x0F,0x02,
0x00,0x07,0x0E,0x05,0x0C,0x03,0x0A,0x01,0x08,0x0F,0x06,0x0D,0x04,0x0B,0x02,0x09,
//1a57c
0x07,0x0C,0x11,0x16,0x05,0x09,0x0E,0x14,0x04,0x0B,0x10,0x17,0x06,0x0A,0x0F,0x15,
0x98,0x2F,0x8A,0x42,0x91,0x44,0x37,0x71,0xCF,0xFB,0xC0,0xB5,0xA5,0xDB,0xB5,0xE9,
0x5B,0xC2,0x56,0x39,0xF1,0x11,0xF1,0x59,0xA4,0x82,0x3F,0x92,0xD5,0x5E,0x1C,0xAB,
0x98,0xAA,0x07,0xD8,0x01,0x5B,0x83,0x12,0xBE,0x85,0x31,0x24,0xC3,0x7D,0x0C,0x55,
0x74,0x5D,0xBE,0x72,0xFE,0xB1,0xDE,0x80,0xA7,0x06,0xDC,0x9B,0x74,0xF1,0x9B,0xC1,
0xC1,0x69,0x9B,0xE4,0x86,0x47,0xBE,0xEF,0xC6,0x9D,0xC1,0x0F,0xCC,0xA1,0x0C,0x24,
0x6F,0x2C,0xE9,0x2D,0xAA,0x84,0x74,0x4A,0xDC,0xA9,0xB0,0x5C,0xDA,0x88,0xF9,0x76,
0x52,0x51,0x3E,0x98,0x6D,0xC6,0x31,0xA8,0xC8,0x27,0x03,0xB0,0xC7,0x7F,0x59,0xBF,
0xF3,0x0B,0xE0,0xC6,0x47,0x91,0xA7,0xD5,0x51,0x63,0xCA,0x06,0x67,0x29,0x29,0x14,
0x85,0x0A,0xB7,0x27,0x38,0x21,0x1B,0x2E,0xFC,0x6D,0x2C,0x4D,0x13,0x0D,0x38,0x53,
0x54,0x73,0x0A,0x65,0xBB,0x0A,0x6A,0x76,0x2E,0xC9,0xC2,0x81,0x85,0x2C,0x72,0x92,
0xA1,0xE8,0xBF,0xA2,0x4B,0x66,0x1A,0xA8,0x70,0x8B,0x4B,0xC2,0xA3,0x51,0x6C,0xC7,

0x19,0xE8,0x92,0xD1,0x24,0x06,0x99,0xD6,0x85,0x35,0x0E,0xF4,0x70,0xA0,0x6A,0x10,
0x16,0xC1,0xA4,0x19,0x08,0x6C,0x37,0x1E,0x4C,0x77,0x48,0x27,0xB5,0xBC,0xB0,0x34,
0xB3,0x0C,0x1C,0x39,0x4A,0xAA,0xD8,0x4E,0x4F,0xCA,0x9C,0x5B,0xF3,0x6F,0x2E,0x68,
0xEE,0x82,0x8F,0x74,0x6F,0x63,0xA5,0x78,0x14,0x78,0xC8,0x84,0x08,0x02,0xC7,0x8C,
0xFA,0xFF,0xBE,0x90,0xEB,0x6C,0x50,0xA4,0xF7,0xA3,0xF9,0xBE,0xF2,0x78,0x71,0xC6};

unsigned char * unk_1A47C = unk_1A43C + 0x40;
unsigned char *  unk_1A53C = unk_1A43C + 0x100;
unsigned char *  unk_1A57C = unk_1A43C + 0x140;


int __fastcall sub_144C8(int result, unsigned int a2)		//52,packet size/4
{
  char v2  = 0; // nf@0
  int v3; // r12@1
  int v4; // r3@4
  char v5; // r0@8
  unsigned int v6; // r1@8
  unsigned int v7; // r2@8
  bool v8; // zf@17

  v3 = result ^ a2;

  if ( a2 <= 0 )
    a2 = -a2;

  if ( a2 == 1 )
  {
    if ( (v3 ^ result) < 0 )
      result = -result;
	return result;
  }
  else
  {
    v4 = result;
    if ( result < 0 )
      v4 = -result;

    if ( v4 <= a2 )
    {
      if ( v4 < a2 )
        result = 0;	

      if ( v4 == a2 )
        result = (v3 >> 31) | 1;
    }
    else if ( a2 & (a2 - 1) )
    {
      //v5 = __clz(a2) - __clz(v4);
	  __asm
	  {
		  pushad
		  mov eax,a2
		  bsr ecx,eax
		  mov edx,32
		  sub edx,ecx
		  sub edx,1
		  mov ebx,edx

		  mov eax,v4
		  bsr ecx,eax
		  mov edx,32
		  sub edx,ecx
		  sub edx,1
		  
		  sub ebx,edx
		  mov v5,bl
		  popad
	  }

      v6 = a2 << v5;
      v7 = 1 << v5;
      result = 0;
      while ( 1 )
      {
        if ( v4 >= v6 )
        {
          v4 -= v6;
          result |= v7;
        }
        if ( v4 >= v6 >> 1 )
        {
          v4 -= v6 >> 1;
          result |= v7 >> 1;
        }
        if ( v4 >= v6 >> 2 )
        {
          v4 -= v6 >> 2;
          result |= v7 >> 2;
        }
        if ( v4 >= v6 >> 3 )
        {
          v4 -= v6 >> 3;
          result |= v7 >> 3;
        }
        v8 = v4 == 0;
        if ( v4 )
        {
          v7 >>= 4;
          v8 = v7 == 0;
        }
        if ( v8 )
          break;
        v6 >>= 4;
      }
      if ( v3 < 0 )
        result = -result;
    }
    else
    {
		int Tmp = 0;
		__asm
		{
			pushad
			mov eax,a2
			bsr ecx,eax
			mov edx,32
			sub edx,ecx
			sub edx,1
			mov Tmp,edx
			popad
	  }
		result = (unsigned int)v4 >> (31 - Tmp);
      //result = (unsigned int)v4 >> (31 - __clz(a2));

      if ( result < 0 )
        result = -result;
    }
  }
  return result;
}






int __fastcall sub_144C0(int a1, int a2)			// 52, packet size
{
	if ( !a2 )
		return 0;
		//JUMPOUT(&loc_152A0);
	return sub_144C8(a1, a2);
}







int __fastcall sub_B764(unsigned int a1, unsigned int a2, int a3)			//a1 = key  a2 = 64, a3 = int [] return by c160
{
	int v3; // r4@1
	int v4; // r5@1
	int v5; // r3@1
	int v6; // r6@1
	int v7; // r3@1
	int v8; // r1@4
	unsigned int v9; // r2@4
	int v10; // r4@4
	int *v11; // r3@4
	int v12; // r2@5
	int v13; // r0@5
	int v14; // r1@5
	int v15; // r6@5
	int v16; // r3@5
	int v17; // r4@7
	int v18; // r4@8
	int v19; // r6@8
	int v20; // r3@8
	int v21; // r2@10
	char v22; // r6@10
	int v23; // r2@10
	int v24; // r2@10
  int v25; // r3@11
  int v26; // r5@11
  int v27; // r0@13
  int v28; // r5@13
  int v29; // r0@13
  int v30; // r3@14
  int v31; // r5@14
  int v32; // r1@16
  int v33; // r5@16
  int v34; // r1@16
  int result; // r0@18
  int v36; // r2@20
  int v37; // r1@20
  int v38; // r3@20
  int v39; // r4@20

  int v41; // [sp+4h] [bp+4h]@5
  int v42; // [sp+8h] [bp+8h]@3
  int v43; // [sp+Ch] [bp+Ch]@3
  int v44; // [sp+10h] [bp+10h]@1
  int v45; // [sp+14h] [bp+14h]@11
  int v46; // [sp+18h] [bp+18h]@3
  int v47; // [sp+1Ch] [bp+1Ch]@1
  int v48; // [sp+20h] [bp+20h]@1
  int v49; // [sp+24h] [bp+24h]@1
  int v50; // [sp+28h] [bp+28h]@1
  unsigned int v51; // [sp+2Ch] [bp+2Ch]@3
  int v52; // [sp+30h] [bp+30h]@7
  int v53; // [sp+34h] [bp+34h]@3
  int v54[17]; // [sp+38h] [bp+38h]@19			//


  v44 = a1 + 4 * (a2 >> 2);
  v3 = *(_DWORD *)(a3 + 4);
  v4 = *(_DWORD *)(a3 + 8);
  v50 = *(_DWORD *)a3;
  v5 = *(_DWORD *)(a3 + 16);
  v6 = *(_DWORD *)(a3 + 12);
  v49 = v3;
  v7 = a2 + v5;
  v48 = v4;
  v47 = v6;
  *(_DWORD *)(a3 + 16) = v7;
  if ( v7 < a2 )
    ++*(_DWORD *)(a3 + 20);
  v51 = a1;
  v46 = (int)unk_1A53C;		//
  v53 = (int)&v54[16];		//
  v43 = (int)unk_1A57C;		//
  v42 = a3;

  int  Tmp = (int)v54;

  while ( 1 )
  {
    result = v44;
    if ( v51 >= v44 )
      break;
    v9 = v51;
    v11 = v54;
    do
    {
      v8 = *(_DWORD *)v9;
      v9 += 4;
      v10 = v53;
      *v11 = v8;
      ++v11;			//将16字节数据和接下来的原始密钥拷贝到此处
    }
    while ( v11 != (int *)v10 );
    v12 = v47;
    v51 += 64;
    v13 = v48;
    v14 = v49;
    v15 = v50;
    v16 = 0;
    v41 = (int)unk_1A53C;
    while ( 1 )
    {
		
      v52 = (v12 ^ v13) & v14 ^ v12;			//顺序正确
      v52 += *((_DWORD *)unk_1A43C + v16) + v15 + *(DWORD*)((DWORD*)Tmp + *(_BYTE *)(v16 + v41) );			//
      v17 = __ROR4__(v52, 32 - *(_BYTE *)(v41 + 64 + (v16++ & 3)));
      if ( v16 == 16 )
        break;
      v15 = v12;
      v12 = v13;
      v13 = v14;
      v14 += v17;
    }
    v18 = v17 + v14;
    v19 = v12;
    v20 = 0;
    while ( 1 )
    {
      v21 = ((v14 ^ v18) & v13 ^ v14)
          + v19
          + *((_DWORD *)unk_1A43C + v20 + 16)
          + *(DWORD*)((DWORD*)Tmp + *(_BYTE *)(v46 + v20 + 16));
      v22 = *(_BYTE *)(v43 + (v20++ & 3) + 4);
      v23 = __ROR4__(v21, 32 - v22);
      v24 = v23 + v18;
      if ( v20 == 16 )
        break;
      v19 = v13;
      v13 = v14;
      v14 = v18;
      v18 = v24;
    }
    v45 = (int)unk_1A57C;
    v25 = 0;
    v26 = v13;
    while ( 1 )
    {
      v27 = (v18 ^ v24 ^ v14) + v26 + *((_DWORD *)unk_1A43C + v25 + 32);
      v52 = v27;
      v52 = v27 + *(DWORD*)((DWORD*)Tmp + *((_BYTE *)unk_1A53C + v25 + 32) );
      v27 = (v27 & 0xffffff00) + *(_BYTE *)(v45 + (v25++ & 3) + 8);
      v28 = __ROR4__(v52, 32 - v27);
      v29 = v28 + v24;
      if ( v25 == 16 )
        break;
      v26 = v14;
      v14 = v18;
      v18 = v24;
      v24 = v29;
    }
    v45 = (int)unk_1A57C;
    v30 = 0;
    v31 = v14;
    while ( 1 )
    {
      v32 = ((~v18 | v29) ^ v24) + v31 + *((_DWORD *)unk_1A43C + v30 + 48);
      v52 = v32;
      v52 = v32 + *(DWORD*)((DWORD*)Tmp + *((_BYTE *)unk_1A53C + v30 + 48) );
      v32 = (v32 & 0xffffff00) + *(_BYTE *)(v45 + (v30++ & 3) + 12);
      v33 = __ROR4__(v52, 32 - v32);
      v34 = v33 + v29;
      if ( v30 == 16 )
        break;
      v31 = v18;
      v18 = v24;
      v24 = v29;
      v29 = v34;
    }
    v50 += v18;
    v49 += v34;
    v48 += v29;
    v47 += v24;
  }

  //
  v36 = v42;
  v37 = v50;
  v38 = v49;
  v39 = v48;
  *(_DWORD *)(v42 + 12) = v47;
  *(_DWORD *)v36 = v37;
  *(_DWORD *)(v36 + 4) = v38;
  *(_DWORD *)(v36 + 8) = v39;
  return result;
}












int __fastcall sub_C160(int result)
{
  *(_DWORD *)result = 1732584193;
  *(_DWORD *)(result + 4) = -271733879;
  *(_DWORD *)(result + 8) = -1732584194;
  *(_DWORD *)(result + 12) = 271733878;
  *(_DWORD *)(result + 20) = 0;
  *(_DWORD *)(result + 16) = 0;
  *(_DWORD *)(result + 24) = 0;

  //C190拷贝原始密钥到后面的字节中
  return result;
}




//将原始密钥传入C160返回的数组中的第28开始的字节中
void *__fastcall sub_C190(void *result, int a2, unsigned int a3)	//int[] return by c160 ,key,keylen
{
  int v3; // r6@1
  int v4; // r5@3
  int v5; // r5@6
  unsigned int v6; // r4@7
  int v7; // r5@7
  unsigned int v8; // [sp+4h] [bp+4h]@1
  const void *src; // [sp+8h] [bp+8h]@1
  int n; // [sp+Ch] [bp+Ch]@1
  int na; // [sp+Ch] [bp+Ch]@4

  v3 = (int)result;
  src = (const void *)a2;
  v8 = a3;
  n = a3;
  if ( a3 << 26 )
  {
    v4 = *((_DWORD *)result + 6);
    if ( v4 )
    {
      na = a3;
      if ( a3 > 128 - v4 )
        na = 128 - v4;
      result = memcpy((char *)result + v4 + 28, (const void *)a2, na);
      v5 = na + v4;
      *(_DWORD *)(v3 + 24) += na;
      if ( (unsigned int)v5 > 0x40 )
      {
        v6 = v3 + (v5 & 0xFFFFFFC0);
        sub_B764(v3 + 28, v5 & 0xFFFFFFC0, v3);
        v7 = v5 & 0x3F;
        result = memcpy((void *)(v3 + 28), (const void *)(v6 + 28), v7);
        *(_DWORD *)(v3 + 24) = v7;
      }
      src = (char *)src + na;
      n = v8 - na;
    }
    if ( n > 64 )
    {
      result = (void *)sub_B764((unsigned int)src, n & 0xFFFFFFC0, v3);
      src = (char *)src + (n & 0xFFFFFFC0);
      n &= 0x3Fu;
    }
    if ( n > 0 )
    {
      result = memcpy((void *)(v3 + 28), src, n);
      *(_DWORD *)(v3 + 24) = n;
    }
  }
  else
  {
    result = (void *)sub_B764(a2, a3, (int)result);
  }
  return result;
}




//低位是C160 C190制造的密钥,高位指向一个整数 a2是一个整数
__int64 __fastcall sub_C250(__int64 a1, int a2)		//完成密钥的生成和复制,参数为两个地址
{
  int _8; // ST08_4@1
  unsigned int v3; // r5@1
  int v4; // r4@1
  int v5; // r3@1
  int v6; // r6@1
  signed int v7; // r3@3
  int v8; // r5@5
  int v9; // r3@5
  __int64 _0; // [sp+0h] [bp+0h]@1

  _0 = a1;
  _8 = a2;
  v3 = *(_DWORD *)(a1 + 24);		//原始密钥长度21//
  v4 = a1;
  v5 = v3 + *(_DWORD *)(a1 + 16);	//21
  v6 = HIDWORD(a1);					//数组
  *(_DWORD *)(a1 + 16) = v5;		//0
  if ( v5 < v3 )
    ++*(_DWORD *)(a1 + 20);
  v7 = 120;
  if ( v3 <= 0x37 )
    v7 = 56;
  HIDWORD(_0) = v7 - v3;				//35
  memset((void *)(a1 + v3 + 28), 0, v7 - v3);
  *(_BYTE *)(v4 + v3 + 28) = -128;
  v8 = HIDWORD(_0) + v3;
  v9 = v4 + v8;
  *(_DWORD *)(v9 + 28) = 8 * *(_DWORD *)(v4 + 16);
  *(_DWORD *)(v9 + 32) = *(_QWORD *)(v4 + 16) >> 29;
  sub_B764(v4 + 28, v8 + 8, v4);
  *(_DWORD *)v6 = *(_DWORD *)v4;							//返回真实的密钥 key, 64 ,16 bytes params
  *(_DWORD *)(v6 + 4) = *(_DWORD *)(v4 + 4);
  *(_DWORD *)(v6 + 8) = *(_DWORD *)(v4 + 8);
  *(_DWORD *)(v6 + 12) = *(_DWORD *)(v4 + 12);
  return _0;
}





int __fastcall sub_C2C4(const void *a1, unsigned int a2, void *a3)		//a1== key, a2 == keylen, a3 == int[] 
{
  void *v3; // r6@1
  unsigned int v4; // r5@1
  int result; // r0@1
  unsigned __int64 v6; // r2@1
  __int64 v7; // r0@3
  void * v8 = a3; // r2@3			//V8初始化为A3
  const void *src; // [sp+4h] [bp+4h]@1
  int v10[0x100]; // [sp+8h] [bp+8h]@3										//


  v3 = a3;
  src = a1;
  v4 = a2;
  //v11 = _stack_chk_guard;
  result = (int)memset(a3, 0, 0x10);
  v6 = __PAIR__((unsigned int)src, (unsigned int)src) - __PAIR__((unsigned int)((char *)src - 1), 1);	//此处编译有问题
  if ( (signed int)v4 > 16 && HIDWORD(v6) )
  {
    sub_C160((int)v10);				//
    sub_C190(v10, (int)src, v4);	//
    LODWORD(v7) = (unsigned int)v10;
    HIDWORD(v7) = (unsigned int)v3;
    result = sub_C250(v7, (int)v8);			//低位是C160 C190制造的密钥,根据汇编V8指向a3
  }
  else if ( (signed int)v4 > 0 && HIDWORD(v6) )
  {
    result = (int)memcpy(v3, src, v4);
  }
//   if ( v11 != _stack_chk_guard )
//     _stack_chk_fail(result);
  return result;
}
// 14FC: using guessed type int __fastcall _stack_chk_fail(_DWORD);











unsigned int __fastcall sub_C340(void *src, size_t n, int a3, int a4, void *dest, int a6)
{
  unsigned int v6; // r6@11
  int v7; // r4@8
  unsigned int v8; // r3@9
  unsigned int v9; // r12@9
  char *v10; // r2@10
  int v11; // r0@11
  int v12; // r4@11
  int v13; // r6@11
  int v14; // r1@12
  signed int v15; // r3@15
  int v16; // r4@16
  bool v17; // cf@16
  unsigned int v19; // [sp+0h] [bp+0h]@11
  int v20; // [sp+4h] [bp+4h]@9
  unsigned int v21; // [sp+8h] [bp+8h]@11
  char *v22; // [sp+Ch] [bp+Ch]@9
  unsigned int v23; // [sp+10h] [bp+10h]@10
  int v24; // [sp+14h] [bp+14h]@9
  int v25; // [sp+18h] [bp+18h]@1
  int v26; // [sp+1Ch] [bp+1Ch]@12
  
  int v27[0x100] = {0}; // [sp+20h] [bp+20h]@8			//此处应该是个数组

	//v19 = (int)(v27-8);
	//memmove((char*)v35,"\xf1\x5e\x78\xd2\x30\x33\xc2\xc4\xba\xc8\xa0\x25\x67\x7e\x86\x3a",16);
  v6 = n;
  v26 = a3;
  v25 = a4;
  if ( (signed int)n <= 0 || !src )
    return 0;
  if ( n << 30 )			//长度为4的倍数
    return -32227;
  if ( !dest )
    return v6;
  if ( a6 < (signed int)n )
    return -32227;
  if ( dest != src )							//这里肯定相等
    memcpy(dest, src, n);
  sub_C2C4((const void *)v26, v25, v27);		//v27 is int[]
  v26 = v6 >> 2;
  v25 = (v6 >> 2) - 1;
  v7 = *(_DWORD *)dest;
  if ( v25 <= 0 )
  {
    v15 = 3;
    do
    {
      v16 = __ROR4__(v7 - (*((int*)v27 + v15) ^ 0x9E3779B9), 16);
      v7 = v16 ^ 0x79B99E37;
      v17 = (unsigned int)v15-- >= 1;
    }
    while ( v17 );
    *(_DWORD *)dest = v7;
  }
  else
  {
    v24 = sub_144C0(52, v26);
    v8 = -1640531527 * (v24 + 6);
    v9 = v6;
    v22 = (char *)dest + 4 * v25;
    v20 = 4 * (v26 + 0x3FFFFFFF);
    while ( v24 != -6 )
    {
      v23 = (v8 >> 2) & 3;
      v10 = (char *)dest + v20;
      v26 = v25;
      do
      {
        v21 = (*(v27 + (v26 & 3 ^ v23) ) ^ *((_DWORD *)v10 - 1)) + (v7 ^ v8);
        v19 = ((unsigned int)v7 >> 3) ^ 16 * *((_DWORD *)v10 - 1);
        v11 = (v19 + (4 * v7 ^ (*((_DWORD *)v10 - 1) >> 5))) ^ v21;
        v12 = *(_DWORD *)v10;
        --v26;
        v13 = v26;
        v7 = v12 - v11;
        *(_DWORD *)v10 = v7;
        v10 -= 4;
      }
      while ( v13 );
      v7 = *(_DWORD *)dest
         - (((16 * *(_DWORD *)v22 ^ ((unsigned int)v7 >> 3)) + ((*(_DWORD *)v22 >> 5) ^ 4 * v7)) ^ ((v7 ^ v8)
                                                                                                  + (*(_DWORD *)v22 ^ *(v27 + v23))));
      v14 = v24 - 1;
      *(_DWORD *)dest = v7;
      v8 += 1640531527;
      v24 = v14;
    }
    v6 = v9;
  }

  return v6;
}




unsigned int __fastcall sub_C49C(void *a1, int a2, int a3, int a4, void *a5, int a6)		
{
  unsigned int result; // r0@1
  int v7; // r3@3

  result = sub_C340(a1, a2, a3, a4, a5, a6);
  if ( (signed int)result > 0 && a5 )
  {
    v7 = *(_DWORD *)((char *)a5 + result - 4);
    if ( v7 < 0 || (signed int)(result - 3) <= v7 )
    {
      result = -32227;
    }
    else
    {
      *((_BYTE *)a5 + v7) = 0;
      result = v7;
    }
  }
  return result;
}











	
//src == dest == packet, a2== a6 == pack len, a3 = key, a4 = keylen
int __fastcall sub_C4D8(void *src, int a2, int a3, int a4, void *dest, int a6)	
{
  int v6; // r5@3
  size_t i; // r2@8
  unsigned int v8; // r3@11
  char *v9; // r6@11
  unsigned int v10; // r5@11
  unsigned int v11; // r3@12
  void *v12; // r1@13
  unsigned int v13; // r3@13
  int v14; // r2@13
  unsigned int v15; // r12@13
  int v16; // r0@14
  int v17; // r3@14
  int v18; // r3@14
  unsigned int v19; // r0@14
  int v20; // r0@14
  unsigned int v21; // r2@15
  int v22; // r1@15
  int *v23; // r2@18
  int v24; // r6@19
  int v25; // r3@19

  unsigned int v28; // [sp+4h] [bp+4h]@14
  size_t v29; // [sp+8h] [bp+8h]@12
  unsigned int v30; // [sp+Ch] [bp+Ch]@14
  unsigned int v31; // [sp+10h] [bp+10h]@13
  int v32; // [sp+14h] [bp+14h]@1
  size_t v33; // [sp+18h] [bp+18h]@1
  size_t n; // [sp+1Ch] [bp+1Ch]@1
  int v35[0x10] = {0}; // [sp+20h] [bp+20h]@11



  //memmove((char*)v35,"\xf1\x5e\x78\xd2\x30\x33\xc2\xc4\xba\xc8\xa0\x25\x67\x7e\x86\x3a",16);
  n = a2;
  v33 = a3;
  v32 = a4;
  if ( a2 > 0 && src )
  {
    v6 = (a2 + 3) & 0xFFFFFFFC;
    if ( dest )
    {
      if ( a6 >= v6 )
      {
        if ( dest != src )
          memcpy(dest, src, n);
        for ( i = n; (signed int)i < v6; ++i )
          *((_BYTE *)dest + i) = 0;
        n = i;
        sub_C2C4((const void *)v33, v32, v35);
        v8 = *(_DWORD *)dest;
        v9 = (char *)dest + 4 * ((n >> 2) - 1);
        v33 = (n >> 2) - 1;
        v10 = *(_DWORD *)v9;
        if ( (signed int)v33 <= 0 )
        {
          v23 = v35;
          do
          {
            v24 = *v23;
            ++v23;
            v25 = __ROR4__(v8, 16);
            v8 = (v24 ^ 0x9E3779B9) + (v25 ^ 0x9E3779B9);
          }
          while ( v23 != &v35[4] );
          *(_DWORD *)dest = v8;
        }
        else
        {
          v32 = sub_144C0(52, n >> 2);
          v11 = 0;
          v29 = v33 & 3;
          while ( v32 != -6 )
          {
            v12 = dest;
            v13 = v11 - 1640531527;		//0xffffffff9E3779B9
            v31 = (v13 >> 2) & 3;
            v14 = 0;
            v15 = v13;
            do
            {
				//v27 = 0;
              v16 = *(DWORD*)(v35 + (v14 & 3 ^ v31) );
              v17 = *(_DWORD *)((_DWORD *)v12 + 1);
              ++v14;
              v30 = v16 ^ v10;
              v18 = (v16 ^ v10) + (v17 ^ v15);
              v19 = *((_DWORD *)v12 + 1);
              v30 = v18;
              v28 = 16 * v10 ^ (v19 >> 3);
              v10 = ((v28 + ((v10 >> 5) ^ 4 * v19)) ^ v18) + *(_DWORD *)v12;
              v20 = v33;
              *(_DWORD *)v12 = v10;
              v12 = (char *)v12 + 4;
            }
            while ( v14 < v20 );
            v21 = *(_DWORD *)dest;
            v11 = v15;
            v30 = (*(_DWORD *)dest >> 3) ^ 16 * v10;
            v10 = ((v30 + (4 * v21 ^ (v10 >> 5))) ^ ((v10 ^ *(v35 + (v31 ^ v29) )) + (v21 ^ v15))) + *(_DWORD *)v9;
            v22 = v32;
            *(_DWORD *)v9 = v10;
            v32 = v22 - 1;
          }
        }
		
        v6 = n;
      }
      else
      {
        v6 = -32226;
      }
//	  Utf8ToGB2312((char*)dest,v6);
    }
  }
  else
  {
    v6 = 0;
  }
  return v6;
}




int __fastcall sub_C62C(void *src, int a2, int a3, int a4, void *dest, int a6)
{
  int v6; // r6@1
  int v7; // r5@1
  int i; // r1@5
  int v10; // [sp+8h] [bp+0h]@1
  int v11; // [sp+Ch] [bp+4h]@1

  v10 = a4;
  v6 = a2;
  v11 = a3;
  v7 = ((a2 + 3) & 0xFFFFFFFC) + 4;
  if ( dest )
  {
    if ( a6 < v7 )
    {
      v7 = -1;
    }
    else
    {
      if ( dest != src )
        memcpy(dest, src, a2);
      for ( i = v6; i < v7; ++i )
        *((_BYTE *)dest + i) = 0;
      *((_DWORD *)dest + (i >> 2) - 1) = v6;
      v7 = sub_C4D8(dest, i, v11, v10, dest, i);
    }
  }
  return v7;
}




int  __fastcall sub_183C(char * str,int strlen,char * key, int keylen, char * decbuf, int decbuflen,int Flag)
{

	int Cnt = 0;
	if ( Flag )
		Cnt = sub_C62C(str, strlen, (int)key, keylen, decbuf, decbuflen);
	else
		Cnt = sub_C49C(str, strlen, (int)key, keylen, decbuf, decbuflen);

	if (Cnt <= 0)
	{
		return 0;
	}

	return Cnt;
}








// void __cdecl New_sub_16f4()
// {
// 	__asm
// 	{
// 		//push edi
// 		//push esi
// 		//push ebx
// 		push ebp
// 		mov ebp,esp
// 		sub esp,0x7c
// 		
// 		push 64
// 		push 0
// 		push offset TeaKey
// 		call memset
// 		add esp ,12
// 
// 		push dword ptr 0x7c
// 		push dword ptr 0
// 		push esp
// 		call memset
// 		add esp,12
// 		add esp,0x20
// 
// 		mov ebx, esp
// 		add ebx ,8
// 		
// 		push 4
// 		push offset unk_19578
// 		mov eax, ebx
// 		add eax,0x1f
// 		push eax
// 		call memcpy
// 		add esp,12
// 
// 
// 		mov eax,0x252423
// 		mov [ebx + 0x54 - 0x3c], eax			
// 		mov eax, offset unk_19578
// 		mov [ebx + 0x54 - 0x50],eax		
// 		mov ax,0x235e
// 		mov [ebx + 0x54 - 0x2e],ax			
// 		mov ax,0x25
// 		mov [ebx + 0x54 - 0x2c],ax		
// 
// 		push 4
// 		mov eax,offset unk_19578
// 		add eax, 7
// 		push eax
// 		mov eax,ebx
// 		add eax,0x2d
// 		push eax
// 		call memcpy
// 		add esp,12
// 
// 		mov eax,0x475224
// 		mov [ebx + 0x54 - 0x20],eax
// 
// 		push 4
// 		mov eax,offset unk_19578
// 		add eax,0x0e
// 		push eax
// 		mov eax,ebx
// 		add eax,0x3b
// 		push eax
// 		call memcpy
// 		add esp,12
// 
// 
// 		mov ax,0x5248
// 		mov [ebx + 0x42],ax
// 		mov ax,0x28
// 		mov [ebx + 0x42 + 2],ax
// 
// 		push 0x0e
// 		mov eax,offset unk_19578
// 		add eax, 0x16
// 		push eax
// 		mov eax,ebx
// 		add eax,8
// 		push eax
// 		call memcpy
// 		add esp,12
// 
// 		sub esp,0x20
// 		//push 0x20
// 		//push 0
// 		//push esp
// 		//call memset
// 		//add esp,12
// 
// 		mov esi,esp
// 		add esi,8
// 
// 		lea esi,TeaKey
// 		
// 		push esi
// 
// 		mov [ebx + 0x54 - 0x50],esi
// 		mov edi,ebx
// 		add edi,0x18
// 
// 
// 		//r0 =esp - 0x20 + 8 == esi
// 		mov edx,0
// 		SetKey:
// 		push esi
// 
// 		mov ecx,8
// 		add ecx,edx
// 		movzx eax,word ptr [ebx + ecx]
// 		add edx,2
// 
// 		mov ecx,eax
// 		shl eax,1
// 		add eax,ecx
// 		add esi,eax
// 
// 		mov cl,[edi]
// 		mov [esi ],cl
// 		mov cl,[edi+1]
// 		mov [esi + 1],cl
// 		mov cl, [edi + 2]
// 		mov [esi + 2],cl
// 		add edi,7
// 
// 		pop esi
// 		cmp edx, 0x0e
// 		jnz SetKey
// 
// 		pop eax
// 		mov esp,ebp
// 		pop ebp
// 	
// 		//pop ebx
// 		//pop esi
// 		//pop edi	
// 		//retn 0
// 	}
// 
// 	return ;
// }






int AscToHex(unsigned char * Asc,int AscLen, unsigned char * Hex)
{
	unsigned char Table[] = "0123456789abcdef";
	unsigned int Index = 0;
	unsigned int Cnt = 0;
	unsigned int Counter = 0;
	unsigned char Tmp = 0;
	
	for (Cnt = 0; Cnt < AscLen; )
	{
		for (Index = 0; Index < 16; Index ++)
		{
			if ( Asc[Cnt] == Table[Index] )
			{
				Tmp = Index << 4;
			}
		}
		
		Cnt ++;
		
		for (Index = 0; Index < 16; Index ++)
		{
			if ( Asc[Cnt] == Table[Index] )
			{
				Tmp = Tmp | Index;
			}
		}
		
		Cnt ++;
		
		Hex[Counter] = Tmp;
		Counter ++ ;
	}
	
	return Counter;
}




上面的接口很简单,入口是sub_183C,最后的Flag字段代表要不要做md5验证,如果要的话,执行sub_C49C,否则执行sub_C62C函数。其中的sub_C2C4调用sub_C160和sub_C160,几个函数的作用是计算md5值。sub_C340是主要加解密函数。有些细节我也是模棱两可,知识照抄ida的反汇编伪C代码。

这个项目是我经历过难度最大最复杂的工程。
逆向过程持续了差不多一个月的时间,从java层smali插桩输入日志、观察参数,推导数据执行流程,到so层ARM反汇编过程。刚开始做的最频繁的,还是smali插桩分析。因为android程序用的arm汇编,解密程序是x86机器,需要将有些Arm汇编翻译为x86指令。
而在so层面,除了少量arm指令代码,将ida的伪代码直接拷贝到vs工程里编译是ok的,但在运行时解密结果是错的,因为这个原因,自己卡在这里好多天,后来偶然的机会纠正了这个错误,以至于到后来,到底是伪c代码和arm转x86汇编部分,哪里错了我都不记得了。

因为整个通信基本上都是加密数据通信,java层封装的各种加解密接口非常之多,我只能挑选某些地方插桩,最后找到从java的native接口到进入so的入口:
第一次Android逆向初体验_第1张图片

该程序的so库文件罗列如下:
第一次Android逆向初体验_第2张图片
本程序第一个数据包的解密密钥:“DFG# %^#% RGHR(&*M<><”,解密算法sub_183C。第一个pos或者get数据包中去掉http包头后,数据部分用这个密钥解密后,可以得到客户端登录信息,比如IMEI,IMSI,手机号等。同时,该数据包中还有一个密钥,该密钥用于解密服务器返回的数据包,结构的名称是“GetUserIdentity”,前缀一般是"\x0b\x8c\x98\x0c\xa8\x0c",是一个tlv数据结构,具体含义不明。

服务器端返回的数据包中包含另一个16(或许是21)字节的密钥,他所在的格式名称是“GetUserIdentityResp”,解密算法也是sub_183C。该密钥是字符串格式化的,需要转化为二进制后用到上的密钥解密,解密之后的16个字节就是通信过程中通讯录的密钥datakey。

当客户端和服务器通讯录同步时,先用密钥"DFG# %^#% RGHR(&*M<><"调用sub_183C函数解密,然后利用上面的密钥datakey再次调用sub_183C函数,对第一次解密后的数据再次解密,即可得到明文数据。

解密后的数据如下:
第一次Android逆向初体验_第3张图片
该程序所有的文本数据都是先转化为utf8和base64,然后先加密后压缩传输的。

其中的base64编码:
44CQ6YKu5YKo6ZO26KGM44CR5oKo5bC+5Y+3OTc4OeeahOmTtuihjOWNoeato+WcqOeUs+ivt+W8gOmAmumCruWCqOmTtuihjOaUr+S7mOWuneW/q+aNt+aUr+S7mO+8jOmqjOivgeegge+8mjQ2NzA5NO+8jOW/q+aNt+aUr+S7mOWPr+iDveS8muW4puadpei+g+mrmOeahOi1hOmHkeaNn+WksemjjumZqe+8jOivt+iwqOaFjuaTjeS9nOOAglvlt6XkvZzkurrlkZjkuI3kvJrntKLlj5bvvIzor7fli7/ms4TpnLJd

解码后是:【邮储银行】您尾号9789的银行卡正在申请开通邮储银行支付宝快捷支付,验证码:467094,快捷支付可能会带来较高的资金损失风险,请谨慎操作。[工作人员不会索取,请勿泄露]

自此,整个程序逆向的框架基本完毕。其中有个java层smali插桩的问题,那会刚接触android,但并不知道有个叫做xposed的神器,因此都是手动编写java,反汇编为smali后,将之插入到apk反汇编后的smali中,再次对apk的smali打包并签名,安装运行。

该程序还有一个孪生兄弟程序,叫做xxx电话本。该程序还有一个大名鼎鼎的大哥程序,叫做xxx信。他们初始化密钥相同:@#%^SEF#$Sddhfvh,而且解密过程更简单,数据解压缩后直接调用sub_183C函数即可。

但是不到一年之后,程序进行了更新,改为了RSA非对称方式加解密,因此此算法早已彻底失效。

你可能感兴趣的:(arm,网络安全,汇编,android)