首页
社区
课程
招聘
[原创]第六题 追凶者也_pw
2018-12-12 00:05 2262

[原创]第六题 追凶者也_pw

2018-12-12 00:05
2262

运行效果。

IDA加载

快速定位错误位置。

int __cdecl W_CHECKsub_401040(HWND hDlg)
{
  void *v1; // ST08_4
  signed int i; // [esp+Ch] [ebp-24h]
  signed int v4; // [esp+10h] [ebp-20h]
  CHAR String; // [esp+18h] [ebp-18h]
  int v6; // [esp+19h] [ebp-17h]
  int v7; // [esp+1Dh] [ebp-13h]
  int v8; // [esp+21h] [ebp-Fh]
  int v9; // [esp+25h] [ebp-Bh]
  __int16 v10; // [esp+29h] [ebp-7h]
  char v11; // [esp+2Bh] [ebp-5h]

  strcpy(aTryAgain_0, "try again!");
  strcpy(aFail_0, "fail");
  String = 0;
  v6 = 0;
  v7 = 0;
  v8 = 0;
  v9 = 0;
  v10 = 0;
  v11 = 0;
  GetDlgItemTextA(hDlg, 1001, &String, 20);
  v4 = 0;
  for ( i = 0; i < 20; ++i )
    v4 += *(&String + i);
  if ( v4 > 0 && v4 < 4132 )
  {
    v1 = malloc(v4);
    sub_401020();
    j___free_base(v1);
  }
  return MessageBoxA(0, aTryAgain_0, aFail_0, 0);
}

初步分析,发现对字符串和计算,然后进入401020。分析401020并没有什么作用。猜测过溢出跳转真正代码。

无奈之际发现存在另外的线程。

void __stdcall StartAddress(LPVOID lpThreadParameter)
{
  while ( 1 )
  {
    EnterCriticalSection(&CriticalSection);
    if ( dword_4147FC == 1 )
    {
      sub_401C10();
      dword_4147FC = 0;
    }
    LeaveCriticalSection(&CriticalSection);
  }
}

是不是很熟悉,修改内存,跳转到指定位置401A10。
int __cdecl sub_401C10()
{
  void *v0; // edx
  signed int j; // [esp+0h] [ebp-Ch]
  signed int i; // [esp+8h] [ebp-4h]

  sub_4018D0(0xCCCCCCCC, 0xCCCCCCCC, 0xCCCCCCCC);
  lpAddress = v0;                               // // getdlgitemtexta
                                                // 
  sub_4019B0(v0);                               // protect
  for ( i = 0; i < 5; ++i )
    byte_4147DC[i] = *((_BYTE *)lpAddress + i + 32);
  *(_DWORD *)&byte_414028[1] = (char *)W_chek___sub_401A10 - (char *)((_BYTE *)lpAddress + 32) - 5;
  for ( j = 0; j < 5; ++j )
    *((_BYTE *)lpAddress + j + 32) = byte_414028[j];
  return sub_4019E0(lpAddress);
}

进入跳转的函数,发现别有洞天。4147F0 开始计算是否正确。计算成功后对对话框的提示字符串进行异或计算,生成正确的字符串。

Int __usercall W_chek___sub_401A10@<eax>(int a1@<ecx>, int a2@<ebp>, int a3@<esi>)
{
  unsigned int v3; // et0
  int v4; // eax
  _BYTE *v5; // ecx
  unsigned int v7; // [esp-24h] [ebp-24h]
  int v8; // [esp-18h] [ebp-18h]

  v8 = a1;
  v3 = __readeflags();
  v7 = v3;
  dword_414800 = a3;
  len_20_dword_4147EC = *(_DWORD *)(a2 + 20);
  pIn_dword_4147F0 = malloc(len_20_dword_4147EC);
  dword_4147F4 = a2 + 16;
  memmove(pIn_dword_4147F0, *(const void **)(a2 + 16), len_20_dword_4147EC);
  *(_DWORD *)(a2 - 0x10) = pIn_dword_4147F0;
  *(_DWORD *)(a2 - 0x14) = *(_DWORD *)(a2 - 0x10) + 1;
  do
    *(_BYTE *)(a2 - 0x15) = *(_BYTE *)(*(_DWORD *)(a2 - 0x10))++;
  while ( *(_BYTE *)(a2 - 0x15) );
  *(_DWORD *)(a2 - 28) = *(_DWORD *)(a2 - 16) - *(_DWORD *)(a2 - 20);//  求长度
  if ( sub_401290((int)pIn_dword_4147F0, *(_DWORD *)(a2 - 28)) )// 检测开始
  {
    v4 = sub_401870(pIn_dword_4147F0);
    if ( sub_4017B0((int)pIn_dword_4147F0, v4) == 0x5634D252 )
    {
      v5 = off_414030;
      *(_WORD *)off_414030 = 0;
      v5[2] = 0;
      for ( *(_WORD *)(a2 - 4) = 0; *(signed __int16 *)(a2 - 4) < 8; ++*(_WORD *)(a2 - 4) )
        *((char *)off_414030 - *(signed __int16 *)(a2 - 4)) = (0x27 - *(unsigned __int16 *)(a2 - 4)) ^ byte_41401C[7 - *(signed __int16 *)(a2 - 4)];
      *(_WORD *)off_414034 = 0;
      for ( *(_WORD *)(a2 - 8) = 0; *(signed __int16 *)(a2 - 8) < 3; ++*(_WORD *)(a2 - 8) )
        *((char *)off_414034 - *(signed __int16 *)(a2 - 8)) = (34 - *(unsigned __int16 *)(a2 - 8)) ^ byte_414024[2 - *(signed __int16 *)(a2 - 8)];
    }
  }
  j___free_base(pIn_dword_4147F0);
  dword_4147F8 = (int (__thiscall *)(_DWORD))((char *)lpAddress + 32);
  sub_4019B0(lpAddress);
  for ( *(_DWORD *)(a2 - 12) = 0; *(_DWORD *)(a2 - 12) < 5; ++*(_DWORD *)(a2 - 12) )
    *((_BYTE *)lpAddress + *(_DWORD *)(a2 - 12) + 32) = byte_4147DC[*(_DWORD *)(a2 - 12)];
  sub_4019E0(lpAddress);
  dword_4147FC = 1;
  __writeeflags(v7);
  return dword_4147F8(v8);
}

输入参数为字符串指针和长度。下列函数中初始化9字节的内存(3*3)

Bool __cdecl sub_401290(int a1, int a2)
{
  byte_4147D0[0] = 4;
  byte_4147D0[1] = 1;
  byte_4147D0[2] = 3;
  byte_4147D0[3] = 7;
  byte_4147D0[4] = 2;
  byte_4147D0[5] = 5;
  byte_4147D0[6] = 8;
  byte_4147D0[7] = 6;
  byte_4147D0[8] = 0;
  return sub_4015B0(a1, a2);
}


检查输入个数是否为偶数,按照2个字节一组对4147D0进行操作。操作函数401380。

输入: 413725860

输出: 123456780

Bool __cdecl sub_4015B0(int a1, int a2)
{
  int I; // [esp+0h] [ebp-Ch]
  int v4; // [esp+8h] [ebp-4h]

  v4 = 0xCCCCCCCC;
  if ( a2 % 2 )
    return 0;
  for ( I = 0; I < a2; I += 2 )
  {
    if ( *(_BYTE *)(I + a1) == ‘w’ )
      v4 = 0;
    if ( *(_BYTE *)(I + a1) == ‘d’ )
      v4 = 1;
    if ( *(_BYTE *)(I + a1) == ‘s’ )
      v4 = 2;
    if ( *(_BYTE *)(I + a1) == ‘a’ )
      v4 = 3;
    if ( !sub_401380(v4, *(char *)(I + a1 + 1) – ‘0’) )
      return 0;
  }
  return byte_4147D0[0] == 1
      && byte_4147D0[1] == 2
      && byte_4147D0[2] == 3
      && byte_4147D0[3] == 4
      && byte_4147D0[4] == 5
      && byte_4147D0[5] == 6
      && byte_4147D0[6] == 7
      && byte_4147D0[7] == 8
      && !byte_4147D0[8];
}


进一步分析401380.  A1 取值 wdsa. A2取值1234567890. A1想不想打游戏的前后左右操作。A2的值在4147D0中计算索引位置。该位置分解为横纵俩个坐标(3*3)。分析法发现 w 将当前 位置值向上移动, s 是向下移动,d向右移动, a向左移动。

Char __cdecl sub_401380(int a1, int a2)
{
  char result; // al
  signed int i; // [esp+8h] [ebp-8h]
  signed int v4; // [esp+Ch] [ebp-4h]

  if ( !a2 )
    return 0;
  v4 = 0;
LABEL_4:
  if ( v4 >= 3 )
    return 0;
  for ( i = 0; ; ++i )
  {
    if ( i >= 3 )
    {
      ++v4;
      goto LABEL_4;
    }
    if ( byte_4147D0[3 * v4 + i] == a2 )
      break;
LABEL_6:
    ;
  }
  switch ( a1 )
  {
    case 0:
      if ( v4 )
      {
        if ( byte_4147D0[3 * (v4 - 1) + i] )
        {
          result = 0;
        }
        else
        {
          byte_4147D0[3 * (v4 - 1) + i] = byte_4147D0[3 * v4 + i];
          byte_4147D0[3 * v4 + i] = 0;
          result = 1;
        }
      }
      else
      {
        result = 0;
      }
      break;
    case 1:
      if ( i == 2 )
      {
        result = 0;
      }
      else if ( byte_4147D1[3 * v4 + i] )
      {
        result = 0;
      }
      else
      {
        byte_4147D1[3 * v4 + i] = byte_4147D0[3 * v4 + i];
        byte_4147D0[3 * v4 + i] = 0;
        result = 1;
      }
      break;
    case 2:
      if ( v4 == 2 )
      {
        result = 0;
      }
      else if ( byte_4147D0[3 * (v4 + 1) + i] )
      {
        result = 0;
      }
      else
      {
        byte_4147D0[3 * (v4 + 1) + i] = byte_4147D0[3 * v4 + i];
        byte_4147D0[3 * v4 + i] = 0;
        result = 1;
      }
      break;
    case 3:
      if ( i )
      {
        if ( byte_4147CF[3 * v4 + i] )
        {
          result = 0;
        }
        else
        {
          byte_4147CF[3 * v4 + i] = byte_4147D0[3 * v4 + i];
          byte_4147D0[3 * v4 + i] = 0;
          result = 1;
        }
      }
      else
      {
        result = 0;
      }
      break;
    default:
      goto LABEL_6;
  }
  return result;
}


结果就是完成七巧板控制。0可以与周围任意交换。

41 3
7
2
5
86
0


1
2
3
4
5
6
7
8
0


所以结论是:d6d8s7s4a1w2a5w6


七巧板应该还有其他的解,程序中已经限定20个字符,10个操作。这可能也就是唯一解了。当然应该也可以爆破。


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2018-12-12 00:06 被scpczc编辑 ,原因:
收藏
点赞3
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回