暑期联合训练week 2 部分题解wp

Mobile

1.level 6

解压缩包文件apk,在/assets/bin/data/Managed/Metadata/global-metadata.dat文件,然后在lib里面找到libil2cpp.so文件,将两个文件放入同一个文件夹,用il2cpp dumper跑一下

打开里面的stringliteral.json文件

猜一下查找关键字unnty,直接找到flag

2.level 7

本题还是考查安卓逆向,老样子先把apk文件解压一下,找lib文件里面的arm文件里的.so文件,拖入ida反编译

找到Java_com_swdd_summertrain_MainActivity_Check函数,跟进

可以发现函数就是一个异或取反,主要是找密文

这个是假密文,跑出来是fakeflag

在此处跟进

就可以看到真密文,直接异或0xff逆一下就有flag了

flag{EasyInitArray}

Reverse

Ezsnake:

本题乍一看以为是一道贪吃蛇的题目,实际上比我想象的复杂得多,进到页面,是一个有关贪吃蛇界面

在uodateMap里面发现了花指令

去花过程:

跟进一个jmp到指令中间,即EB FF机器码使得下一条指令从FF开始解析,需要把EB给nop掉。

这样算正常

到下面还有一个基于call的花指令

该指令执行过程大概是:

1.push rbp 将rbp的值压栈

2.call $+5 说明是将call的下一条指令的地址压栈,$+5恰好跳转到下一条指令到pop rbp

3.pop rbp 将rip(下一条)的值弹出至rbp

4.add rbp, 8就是将rbp的值+8,此时rbp中的地址为地址结尾为175D的那个地方,为pop rbp

5.push rbp就是将rbp的值压入栈

6.retn 返回到栈顶的地址,也就是刚刚压栈的rbp的值,就是刚开始压栈的那个rip再+8的值

7.地址结尾为175D的那个地方反编译得到pop rbp,恢复rbp的值,至此花指令结束。

所以综上分析,最开始的push rbp到最后的pop rbp中间都是没用的花指令,都要nop掉

然后f5即可看到关键函数信息

乍一看有点像是魔改的xtea,再退到主函数部分分析一波

可以看到当贪吃蛇长度达到41的时候进入游戏

game.in为新分配的一块大小为地图大小的内存,而game.in前game.total字节被设置为’.’,应该是为储存地图strcpy(&game.in[game.total], a1)存储输入的flag。

scankey主要是只获取输入并按一定规则改变蛇的方向。printMap也没有关于flag输入输出的信息点。

moveSnake函数中位snake贪吃蛇吃*的有关信息点,并调用了updateMap这个关键的函数,所以要从该函数入手。

chakFlag里面是对密文的一个比较,密文数组是aetx,也就是flag加密后的结果

看到movesnake加密部分

  NextPos = getNextPos(*(qword_140008088 + dword_140008080), dword_140008078);
  if ( isDead(NextPos) )
    return 0xFFFFFFFFi64;
  ++dword_140008080;
  dword_140008080 %= dword_140008048;
  *(qword_140008088 + dword_140008080) = NextPos;
  if ( *(Block + NextPos) == 42 )
  {
    if ( dword_14000804C > 50 )
      dword_14000804C -= 10;
    *(Block + NextPos) = 64;
    v1 = genFoodPos();
    if ( v1 != -1 )
      *(Block + v1) = 42;
    ++dword_14000807C;
    updateMap();
    if ( dword_14000807C == dword_140008048 )
      return 1i64;
  }
  else
  {
    *(Block + NextPos) = 64;
    *(Block + *(qword_140008088 + dword_140008084++)) = 46;
    dword_140008084 %= dword_140008048;
  }
  return 0i64;
}

该加密函数每次吃到东西都会调用一次,结合胜利条件当蛇的长度达到总长度255可知总调用次数为255次(初始长度为1),同时dword_14000804C初始值为190,之后每一轮依次递减10至50便不会变化。(相当于密钥key的依次递减)

根据上述关系就可以写脚本来对flag逆向求值

exp

#include <stdio.h>
​
unsigned char aetx_[] =
{
   0xB7, 0x79, 0xDB, 0x62, 0xA6, 0xDA, 0xF0, 0x86, 0xE9, 0x44, 
    0x0A, 0xBD, 0x80, 0x0C, 0x0B, 0x66, 0x68, 0x1A, 0xE6, 0x7C, 
    0x27, 0x44, 0xFD, 0x63, 0xF9, 0x64, 0x15, 0x0A, 0x1D, 0x95, 
    0x73, 0x84, 0x2A, 0x8C, 0x63, 0xCA, 0xBD, 0x65, 0xA8, 0xC5, 
    0x46, 0xD2, 0xE2, 0x8C, 0x56, 0xBB, 0xC5, 0x07
};
​
unsigned int* aetx = (unsigned int*)aetx_;
​
int main() {
    for(int i=0;i<255;i++) {
        unsigned int* v5 = aetx + 12;
        unsigned int key = i<240?50:50+(i-240)*10;
        unsigned int sum = 256;
        for(int j=0;j<=5;j++) {
            v5-=2;
            unsigned int v4 = *v5;
            v5[1] -= ((v4 + ((v4 >> 5) ^ (16 * v4))) ^ (sum - 1640531527));
            unsigned int v3 = v5[1];
            *v5-=((v3 + ((v3 >> 5) ^ (16 * v3))) ^ key);
        }
    }
    puts((char*)aetx);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值