翻译

本文另有 英文版本。

  • Reverse Script In Script
  • Reverse Where is my 13th count?
  • Reverse simple
  • Misc Welcome to SCTF 2018
  • Misc 神秘的交易
  • Misc 肥宅快乐题
  • Misc 侧信道初探
  • Web easiest web - phpmyadmin

Script In Script

JavaScript 代码全部压缩,不忍直视。在 Chrome 的 Console 中输入函数的名称可以直接看到函数代码,找出 r 以及相关的函数。r 的内容很简单,检查 flag 长度是否为 24,再分别对其中的字符进行检查。J 是相等,L 是字符转为 ASCII 码,Q 是字符串比较,后经 dydxh 提醒,D、E、F、G 分别是加减乘除。有了这些就很容易能推出 flag 的各字符了(其实根据题目的名字也能猜出来一部分 flag)。

Flag:sctf{5cr1Pt_In_ScrIpT!!}

Where is my 13th count?

这道题的思路和前几周 SUCTF 中的“RoughLike 与期末大作业”一题思路如出一辙。看题目的名字应该是要吃到 13 个方块。用 .NET Reflector 打开 Cheat Engine_Data\Managed\Assembly-CSharp.dll,找到 PlayerController::OnTriggerEnter(Collider other),这就是球碰到方块时的事件处理函数了:

1
2
3
4
5
6
7
8
9
private void OnTriggerEnter(Collider other)
{
    if (other.gameObject.CompareTag("Pick Up"))
    {
        other.gameObject.SetActive(false);
        this.count++;
        this.SetCountText();
    }
}

打开 Reflexil 插件,找到 other.gameObject.SetActive(false); 一行对应的 IL:

OffsetOpCodeOperand
21ldarg.1
22callvirtUnityEngine.GameObject UnityEngine.Component::get_gameObject()
27ldc.i4.0
28callvirtSystem.Void UnityEngine.GameObject::SetActive(System.Boolean)

将 Offset 为 27 的那行指令改成 ldc.i4.1,相当于将原来的 other.gameObject.SetActive(false); 改成了 other.gameObject.SetActive(true);,保存并退出。用修改后的 DLL 换掉原来的,再启动游戏。这回吃到方块之后方块不会消失了,绕场一周,多吃几个方块就能看到 flag。

Where is my 13th count 的 flag

Flag:SCTF{ThEFLAGGGGGGG}

simple

对安卓逆向懂得不是很多,实际上是什么逆向都不懂,老实说这题是连蒙带猜做出来的。打开源代码之后居然连 MainActivity.java 都没有。看了看 ProxyApplication.java,里面有一行 FindAssetfile.getAssetsFile(this, "test.zip", paramContext, null);,像是打开了 test.zip。然而直接解压 APK 找到的 test.zip 虽然开头是 PK,后面的内容显然不是 ZIP,可能有猫腻。再看 FindAssetfile.java,这段代码比较诡异:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
catch (IOException paramContext)
{
  paramContext.printStackTrace();
  while (true)
  {
    return null;
    if (paramMethod == null)
      break;
    paramContext = (byte[])paramMethod.invoke(null, new Object[] { localByteArrayOutputStream.toByteArray() });
    paramString1.close();
    localByteArrayOutputStream.close();
    paramString1 = new FileOutputStream(new File(paramString2));
    paramContext[0] = 113;
    paramContext[1] = 114;
    paramContext[2] = 10;
    paramContext[3] = 8;
    paramString1.write(crypt(paramContext, "E82038F4B30E810375C8365D7D2C1A3F"));
    paramString1.close();
  }
}

crypt 是 RC4 加密算法,猜测这段代码是把 test.zip 的内容用 RC4 加密了一遍,于是试着解密了一下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def rc4(plain,key):
    s=[i for i in range(256)]
    i=0
    j=0
    while i<256:
        j=(s[i]+j+ord(key[i%len(key)]))%256
        s[j],s[i]=s[i],s[j]
        i+=1
    k=0
    cipher=list(plain)
    n=len(cipher)
    i=0
    j=0
    while i<n:
        j=(j+1)%256
        k=(s[j]+k)%256
        s[k],s[j]=s[j],s[k]
        cipher[i]=chr(ord(cipher[i])^s[(s[j]+s[k])%256])
        i+=1
    return ''.join(cipher)


def main():
    key='E82038F4B30E810375C8365D7D2C1A3F'
    plain=open('test.zip','r').read()
    plain='\x71\x72\x0A\x08'+plain[4:]
    open('1.dex','w').write(rc4(plain,key))


if __name__=='__main__':
    main()

根据文件开头的 dex 推测是 Dalvik 字节码,再次使用 dex2jar 和 jd-gui 查看源码,这回出现了 MainActivity.java。有的代码有微小的错误,但是整体上影响不大,剩下的就是逆向了。因为实在不想写 Java,就用 Python 把 Square 和 Point 重新实现了一遍:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class point:
    ...

class square:
    ...


def main():
    good=[]
    j=0
    while j<24:
        i=49
        while i<112:
            if square((i<<8)+828309504+255,j/2+4).check():
                good.append(i)
            i+=1
        j+=8
    print(''.join(map(lambda x:chr(x),good)))


if __name__=='__main__':
    main()

运行出来结果是 57=?UW]_QSUWY[]_9;=?Y[]_。要说这一堆乱七八糟的东西是 flag,我是打死也不会信的,然而放到安卓模拟器里试了一下,还真出来个 Success。行吧,被安排得明明白白,我也不说什么了。

Flag:SCTF{57=?UW]_QSUWY[]_9;=?Y[]_}

Welcome to SCTF 2018

打开题目,找到 sctf 开头的那一行,选中,按 Ctrl+C,点击输入 flag 的文本框,按 Ctrl+V,点击提交。重点是手速要快。

神秘的交易

在淘宝上搜索逻辑分析仪,看详情页可以知道 .logicdata 文件是 Saleae Logic 产生的。打开它,参照看雪上的帖子《用逻辑嗅探破解接触式 IC 卡口令》,寻找 0x33。教程上的数据貌似是反着的,也就是 0x33 是 11001100,在 6.900 秒附近可以找到这段数据。

逻辑分析仪中的 IC 卡命令

可以看到第一段指令是 0x33 0x01 0x40,所以密码第一字节是 0x40。后两段命令与此类似,分别是 0x33 0x02 0x31 和 0x33 0x03 0x10,所以密码是 0x40 0x31 0x10,然而我并没有看出来这是哪门子的门牌号。

Flag:SCTF{403110}

肥宅快乐题

试着玩了两局,不出三关就挂了。用 SWF Decompiler 逆向到一半就死机了,于是简单粗暴一点,把播放器的进度条直接向后拖,拖到第 57 帧就能看过场动画了。

肥宅快乐题过场动画

1
2
$ echo -ne 'U1lDe0YzaVpoYWlfa3U0aWxlX1QxMTF9' | base64 -d -
SYC{F3iZhai_ku4ile_T111}

别说,做完这道题还真的想买一瓶肥宅快乐水了 23333。

Flag:SYC{F3iZhai_ku4ile_T111}

侧信道初探

最开始的思路出现了偏差,后来想通了:不管 key 是 0 还是 1,都会执行 R <- [2]R 这条指令;但如果 key 是 1,还会额外执行 R <- R + P。所以在能量图上,只有密集的一条的是 0,一条密集、一条稀疏的是 1。

侧信道能量图

这里必须吐槽一下 flag 的格式了:首页上写的是 sctf{},然而用小写字母提交是错的,甚是无奈。

Flag:SCTF{0110111010}

easiest web - phpmyadmin

我这种一点 Web 都不会的人就只会做这道题了:利用 phpMyAdmin 产生一个 Web shell。密码是 root:root。登录进去之后,把 general log 变量设置成 ON,在 phpMyAdmin 入口网址后加上 index.php?lang[]=1 让 PHP 报错,爆出绝对地址;把 general log file 变量设成想生成的 Web shell 地址,例如 C:\phpStudy\WWW\xx.php,然后执行查询语句 select '<?php @eval(...);?>' from mysql.user where 1=1,这样 Web shell 就被写到 xx.php 里面了。

实际做题的时候战斗太激烈,general log file 被改来改去,索性不改了,直接把自己的 Web shell 写到别的队的 Web shell 里。祭出黑站神器——中国菜刀,连接上 Web shell,大肆搜刮一番,找到 flag。

Flag:sctf{31cf2213cc49605a30f07395d6e5b9c4}