首页
社区
课程
招聘
[抛砖引玉]NAGA & PIOWIND 2014 APP应用攻防竞赛第二阶段题目解析
发表于: 2014-11-5 17:19 22007

[抛砖引玉]NAGA & PIOWIND 2014 APP应用攻防竞赛第二阶段题目解析

2014-11-5 17:19
22007

简单说一下个人的想法
第一题 (http://bbs.pediy.com/showthread.php?t=193755)
基本就是纯粹考察ARM的逆向能力,IDA F5 + 部分ARM汇编,很容易就可以将算法部分分析出来。最后得出的结论就是,其实就是base64加了三条'-'
值得一提的是,通过第一题,对加密部分代码有了比较深入的了解之后,对后面两道题解答有很大帮助

第二题(http://bbs.pediy.com/showthread.php?t=193824)
so加了壳,静态分析会发现dynamic字段是空。
当时偷懒,没细看,直接通过gDvm->loadedClasses找到 "Lcom/crackme/MainActivity"类的ClassObject,然后枚举Method获取了crackme函数的地址。
然后静态分析,发现就是倒序之后base64加密
补充一下"静态分析会发现dynamic字段是空"的问题,其实就是利用了文件和内存中使用的偏移不同的方法,如下图,文件中会读0x3C000,而内存中会读0x3D000,实际上(此SO)内存中布局是完全按照文件中的布局映射的,只要读取0x3D000处,就可以得到正常的dynamic了


第三题(http://bbs.pediy.com/showthread.php?t=193877)
貌似是添加了AntiDebug,由于是周末,家里啥环境都没有,也就没有细搞。按照第二题的思路,写了一个程序,进程注入,把crackme的函数地址读出来了,然后就没有然后了~~
希望大神来给分析一下AntiDebug怎么实现的,又是怎么绕过的。
好吧,我承认我懒得分析了,目测单步测试so加载部分代码应该能有所收获。
结论就是前面 n-2个字符两两交换,然后算base64

第四题(http://bbs.pediy.com/showthread.php?t=193953)
真正考逆向水平的题目。方法就是单步~读ARM指令~对照IDA F5~单步~读ARM指令~对照IDA F5~~~~多尝试几遍就行了。还好so里面保留了部分des的符号,让那些不熟悉des加密的娃(例如me)可以猜到是用了des加密。
不知道是不是我找的源码的问题。测试的时候,发现自己程序的加密结果和crackme的不同,经过反复反复反复反复地测试,发现是S_BOX和另外一个初始化的数组值有差异,测试的方法就是逐过程对照结果,看看哪一步得到的结果不一样,然后对照参数。最后找到不同点。
然后就很简单了。必须吐槽一下,这道题测试好麻烦,手工输入32个字符还算好的。
哦~忘了一点,秘钥生成,是使用了用户名的前8个字节,然后依次异或了0x100个字符 =.= ,话说,异或不是有交换结合律么,结果就是直接异或0x93就行了。

以上就是个人的一些方法,欢迎来讨论或者提供更好的解题思路啊

================== YD的分割线===============
我x~~竟然总顶了,受宠若惊啊,所以决定还是把整个解题流程写一下,方便各位查阅

持续更新中~~~~~~
===================低调的分割线=================

前言
这次比赛,前三道题目的算法都是base64,最后一题是des。
由于dex部分十分简单,就是调用libcrackme.so中的crackme函数,所以这里就不赘述了。

Crackme1
目的是分析libcrackme.so,不过这个so如果用IDA打开的话,会卡一段时间,然后报错,同时生成6G+的数据文件。这种情况明显是文件格式有猫腻 ,处理这种问题,推荐010Editor的模板。
用010Editor打开libcrackme.so,然后执行ELF模板,会提示解析出错。然后就能找到出错的内容了

可以看到,是一个程序节内容错误,本着简(懒)单(惰)的原则,直接将此节内容清零,保存文件后,IDA就可以正常打开文件了。此问题在后续的so里面都会出现,就不再赘述了。
之后就是找到Java_com_crackme_MainActivity_crackme函数,F5分析代码。
然后发现。。。。。。原来是加密的。
处理加密,考虑到运行时必定已经解密,所以运行crackme1,然后再吧so文件dump出来,过程不多说了,这里提一下用IDA下面python插件dump内存的方法:

import idaapi

base = 0x74E71000
size = 266252

data = idaapi.dbg_read_memory(base,size)
if data != None:
    f = open("e:\\crackme1.so","wb")
    f.write(data)
    f.close()
int __fastcall Java_com_crackme_MainActivity_crackme(int a1, int a2, int a3, int a4)
{
  v4 = a4;
  v5 = a1;
  v6 = (*(int (**)(void))(*(_DWORD *)a1 + 676))();
  v7 = (*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)v5 + 676))(v5, v4, 0);
  sub_536C(&dword_15220[1], v6, v7);
  sub_597C(&dword_15220[1]);
  return (*(int (__fastcall **)(int, int *))(*(_DWORD *)v5 + 668))(v5, &dword_15220[1]);
}
int __fastcall sub_536C(int a1, const char *a2, const char *a3)
{
  v3 = a3;
  v4 = a1;
  v5 = a2;
  result = sub_5328();
  if ( v3 )
  {
    if ( v5 )
    {
      v7 = strlen(v5);
      v13 = v7;
      v8 = v7;
      v9 = strlen(v3);
      v10 = v8 + 1;
      v14 = v9;
      n = v9 + 1;
      *(_DWORD *)(v4 + 52) = operator new[](v10);
      result = operator new[](n);
      v11 = *(void **)(v4 + 52);
      *(_DWORD *)(v4 + 56) = result;
      if ( v11 )
      {
        if ( result )
        {
          memset(v11, 0, v10);
          memset(*(void **)(v4 + 56), 0, n);
          memcpy(*(void **)(v4 + 52), v5, v13);
          result = (int)memcpy(*(void **)(v4 + 56), v3, v14);
        }
      }
    }
  }
  return result;
}
signed int __fastcall sub_597C(int a1)
{
   v1 = a1;
  sub_53E4();
  v2 = *(_DWORD *)(v1 + 56);
  if ( *(_BYTE *)(v2 + 3) != 45 || *(_BYTE *)(v2 + 7) != 45 || *(_BYTE *)(v2 + 11) != 45 )
  {
    *(_BYTE *)_cxa_allocate_exception(1) = 1;
    _cxa_throw();
  }
  sub_5430(v1);
  v3 = *(const char **)(v1 + 56);
  v4 = (unsigned __int8)byte_15120;
  if ( !byte_15120 )
  {
    do
      byte_15121[v4++] = -128;
    while ( v4 != 256 );
    v5 = 0;
    do
    {
      byte_15121[v5 + 65] = v5;
      ++v5;
    }
    while ( v5 != 26 );
    v6 = &byte_15182;
    do
    {
      *v6 = v5;
      v5 = (v5 + 1) & 0xFF;
      ++v6;
    }
    while ( v5 != 52 );
    v7 = &byte_15151;
    do
    {
      *v7 = v5;
      v5 = (v5 + 1) & 0xFF;
      ++v7;
    }
    while ( v5 != 62 );
    byte_1514C = 62;
    byte_15150 = 63;
    byte_1515E = 0;
    byte_15120 = 1;
  }
  if ( v3 )
  {
    v8 = strlen(v3);
    v9 = (const void *)operator new[](v8 + 1);
  }
  else
  {
    v9 = 0;
  }
  v10 = strlen(v3);
  v11 = 0;
  v12 = v9;
  v13 = 0;
  v14 = v3;
  while ( v11 < (signed int)(v10 - 3) )
  {
    v15 = 0;
    do
    {
      v16 = byte_15121[*(&v14[v11] + v15)];
      *(&v21 + v15) = v16;
      if ( v16 & 0x80 )
        *(&v21 + v15) = 0;
      ++v15;
    }
    while ( v15 != 4 );
    v13 += 3;
    v11 += 4;
    v17 = v22;
    *(_BYTE *)v12 = ((signed int)v22 >> 4) | 4 * v21;
    v18 = v23;
    *((_BYTE *)v12 + 1) = 16 * v17 | ((signed int)v23 >> 2);
    *((_BYTE *)v12 + 2) = (v18 << 6) | v24;
    v12 = (char *)v12 + 3;
  }
  v19 = (void *)operator new[](v13);
  memmove(v19, v9, v13);
  if ( v9 )
    operator delete[]((void *)v9);
  memcpy((void *)(v1 + 60), v19, v13);
  if ( v19 )
    operator delete[](v19);
  sub_548C(v1);
  return 1;
}
signed int __fastcall sub_53E4(int a1)
{
  if ( !*(_DWORD *)(a1 + 52)
    || (v1 = *(const char **)(a1 + 56)) == 0
    || (v2 = strlen(*(const char **)(a1 + 52)) - 6, v3 = strlen(v1), v2 > 0xE)
    || v3 - 12 > 0x12 )
  {
    *(_BYTE *)_cxa_allocate_exception(1) = 1;
    _cxa_throw();
  }
  return 1;
}
v2 = *(_DWORD *)(v1 + 56);
  if ( *(_BYTE *)(v2 + 3) != 45 || *(_BYTE *)(v2 + 7) != 45 || *(_BYTE *)(v2 + 11) != 45 )
  {
    *(_BYTE *)_cxa_allocate_exception(1) = 1;
    _cxa_throw();
  }
sub_5430(v1);

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 3
支持
分享
最新回复 (18)
雪    币: 21
活跃值: (494)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
2
醉了。我居然没发现是base64.....................
2014-11-5 17:22
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
醉了
2014-11-5 18:00
0
雪    币: 4522
活跃值: (2146)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
醉了 有详细的分析没哦
2014-11-5 19:28
0
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
5
没有做题的话,估计是看不懂的。这个帖子是为了讨论思路。详细的分析等公布提交的解题报告吧。
2014-11-5 21:41
0
雪    币: 367
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
没看过第一题
第二题只要dump出so,用ida就可以看到完整的函数名,dump出的文件是没有加密代码的,
第三题加了anti,对xpose/android_server/debug_server有检测,对Traceid是否是0有检测,对/proc/pid/stat的task_state状态有检测
第四题anti和第三题一样,dump出so后发现,crackme函数有一部分代码是动态加密的0xf0字节,跑完解密部分就可以得到完整的代码,用ida就可以看了
算法就看了第二题,其他没看
2014-11-5 21:57
0
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
7
我第三题IDA一Attach上去,程序就退出,第四题却没有这个问题啊,可以正常单步调试。
2014-11-6 09:37
0
雪    币: 47147
活跃值: (20460)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
8
http://bbs.pediy.com/forumdisplay.php?f=122

答案提交区权限开放
各题的成绩出来了,各位参赛者,若有异议,请在今天提出,明天将公布名次。
2014-11-6 14:38
0
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
9
还是没看明白分数是怎么算的,怎么只有零点几分?

我算出来了~~~是算的8次方?不是1/8次方??
2014-11-6 15:09
0
雪    币: 47147
活跃值: (20460)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
10
公式以这帖为准:http://bbs.pediy.com/showthread.php?t=193953

s=[(2880-t)/2880][sup]1/8[/sup]×100

你那个我联系玩命重新看看。
2014-11-6 15:30
0
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
11
[QUOTE=kanxue;1328898]公式以这帖为准:http://bbs.pediy.com/showthread.php?t=193953

s=[(2880-t)/2880][sup]1/8[/sup]×100

你那个我联系玩命重新看看。[/QUOTE]

我看了一下别人的,好像都是按照8次方算的。
2014-11-6 15:45
0
雪    币: 47147
活跃值: (20460)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
12
稍等,会重新算一遍。
目前公式目的:提交的时间不是最重要的权重系数,正确性是最重要的,即在都答对的情况下,参考一下时间。
2014-11-6 16:00
0
雪    币: 47147
活跃值: (20460)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
13
用excel表格重新计算了一遍,将有误的修正过了。
2014-11-6 16:32
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
前段时间没时间做 看看大牛的思路
2014-11-8 12:10
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
没看明白怎么绕过 反调试的...
2014-11-19 13:51
0
雪    币: 236
活跃值: (60)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
顶,大牛做事就是能直达要点。一招一式都那么干练直接,弱弱的问下 010Editor 工具哪里有的下载,论坛里有人分享了,http://bbs.pediy.com/showthread.php?t=194253,不知道跟LZ大牛的相同么?不好意思,自己不仔细 http://bbs.pediy.com/showthread.php?t=177160&highlight=010Editor这个帖子已经破解了,穷人,先用着,此问就不劳烦LZ大牛了。
2014-11-19 14:25
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
Crackme3 图 所用工具是啥?
2014-11-19 14:58
0
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
18
我没有调试啊,注入了一个so,把内容dump出来的。
2014-11-19 16:23
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
v6 v7虽然知道是调用的java里的string,但是怎么来确定使用的是什么还输,完成的是什么操作呢?
2015-10-12 14:51
0
游客
登录 | 注册 方可回帖
返回
//