首页
社区
课程
招聘
[原创]第十八题分析
发表于: 2016-12-6 20:20 3398

[原创]第十八题分析

2016-12-6 20:20
3398
od载入后查找字符串看到success!,双击后看代码应该是一个比较干净的VM,先不管
下断GetDlgItemTextA,可以到关键地址:


进IDA对这个函数f5发现不行,原因是函数中间做了个断开,干扰了IDA静态分析:







以上分析总结如下:
1)注册码长度要大于13位
2)长于13位的部份必须是数字‘0’-‘9’
3)用注册码前9位跟'3!"!5|ben'每一位xor,再减去0x41,第一个结果必须大于1并且9个结果是从小到大顺序的
4)第3步的9个结果相乘减去0xD4C2086,然后用100去除

会发现并没有到达success那个CALL的操作就直接jmp返回了,上面去除了防IDA静态分析的干扰后用IDA F5这个函数就能发现:
int __cdecl sub_401120(HWND hWnd, char *sn)
{
  int result; // eax@1
  char v3; // [sp+Ch] [bp-A4h]@1
  int v4; // [sp+4Ch] [bp-64h]@1
  int v5; // [sp+50h] [bp-60h]@1
  __int16 v6; // [sp+54h] [bp-5Ch]@1
  int v7; // [sp+58h] [bp-58h]@1
  int v8; // [sp+5Ch] [bp-54h]@1
  int i; // [sp+60h] [bp-50h]@2
  int sn_len; // [sp+64h] [bp-4Ch]@1
  int v11; // [sp+68h] [bp-48h]@1
  int v12[8]; // [sp+6Ch] [bp-44h]@1
  LPVOID lpMem; // [sp+8Ch] [bp-24h]@1
  int *v14; // [sp+90h] [bp-20h]@1
  int *v15; // [sp+94h] [bp-1Ch]@1
  CPPEH_RECORD v16; // [sp+98h] [bp-18h]@1

  memset(&v3, 0xCCu, 0x8Cu);
  lpMem = malloc(0xCu);
  v11 = 0;
  memset(v12, 0, sizeof(v12));
  sn_len = 0;
  v8 = 0;
  v7 = 1;
  v4 = 555884851;
  v5 = 1700953141;
  v6 = 110;
  v16.registration.TryLevel = 0;
  v15 = &v16.registration.ScopeTable->EnclosingLevel;
  v14 = &v16.registration.ScopeTable->EnclosingLevel;
  *(_DWORD *)lpMem = v16.registration.ScopeTable->EnclosingLevel;
  *((_DWORD *)lpMem + 1) = v14[1];
  *((_DWORD *)lpMem + 2) = v14[2] + 6;      // 这里指向的是success处的VM函数
  v16.registration.ScopeTable = (PSCOPETABLE_ENTRY)lpMem;
  result = strlen(sn);
  sn_len = result;
  if ( result >= 13 )
  {
    v8 = 0;
    for ( i = 13; ; ++i )
    {
      result = i;
      if ( i >= sn_len )
        break;
      if ( sn[i] >= 0x30 )
      {
        result = (int)&sn[i];
        if ( sn[i] <= 0x39 )
          continue;
      }
      v8 = 1;
      break;
    }
    if ( !v8 )
    {
      for ( i = 0; i <= 8; ++i )
      {
        result = *((_BYTE *)&v4 + i);
        *(&v11 + i) = (result ^ sn[i]) - 65;
      }
      if ( v11 <= 1 )
        v8 = 1;
      for ( i = 0; i < 8; ++i )
      {
        result = *(&v11 + i);
        if ( result >= v12[i] )
        {
          v8 = 1;
          break;
        }
        result = i + 1;
      }
      if ( !v8 )
      {
        v7 = 1;
        for ( i = 0; i < 9; ++i )
          v7 *= *(&v11 + i);
        result = 100 / (223092870 - v7);
        v7 = 100 / (223092870 - v7);
      }
    }
  }
  v16.registration.TryLevel = -1;
  if ( lpMem )
    result = sub_404284(lpMem);
  return result;
}


看到其实是一个异常处理,通过以上分析能出现异常的地方只有第4步的除法,可以让他抛出一个除0异常就可以到达关键函数
也就是说注册码前9位的运算结果必须是0xD4C2086
分解质因数如下:
23*19*17*13*11*7*5*3*2

正好顺序9个,再依次+0x41后xor '3!"!5|ben',得到前9位注册码'pediy2016'

把输入注册码改为pediy20161234就可以进入到4013b0函数中,
是一个VM,而且函数太长我就不贴代码了,说一下跟踪的方法
这个vm比较干净,handler和vm_code很容易找到,
对注册码下访问断点直接跟关键的handler就行了

找到退出的VM_CODE为0x00
对注册码最后一位下访问断点,会发现很容易失败然后退出虚拟机,猜测注册码长度不对,所以手动增加注册码位数后用以上方法测试出总的注册码长度必须为20

输入注册码改为pediy2016abcd1234567
注册码应该是分成3部份的
第一部份9位,用来到达关键函数
第二部分4位,上面的长度判断有提到小于13位就退出,so...
第三部份7位,必须全部都是数字

已知第三部份7位全是数字,这部份可以枚举,现在只要得到第二部份就可以了
对第10-13位注册码下访问断点,过了几个vm_handler之后发现他跟'cool'对比

至此,剩下的第三部份用枚举就好了,毕竟跟vm太累

typedef void (__cdecl *_test)( char* u, char* sn );
void __cdecl my_test( DWORD dwRetAddr, _test RealTest,
	char* u, char* sn )
{
	for( int i = 0; i < 9999999; ++ i )
	{
		char buffer[100];
		sprintf( buffer, "pediy2016cool%07d", i );
		RealTest( u, buffer );
	}
}

...
InstallHookStub( (PVOID)0x401120, my_test, e_cdecl );
...


写dll注入后点击确定,直到弹出'success'提示框
得到完整注册码为'pediy2016cool1531223'

以上,谢谢观看

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//