2023-googleCTF-re-oldshool

2023-googleCTF-re-oldshool

本题叫用给出的用户名,逆向,写出注册机,来批量生成密码,50个用户名,50个密码。

刚刚拿到手,还打开不了,一直报错说窗口有问题,后来摸索了好久才知道,需要调整终端大小才能适应。而且这道题也是用Ncurses从零实现了GUI的图形解密,就造成了代码巨多,主函数的代码就接近5000行,还不算其他函数,要准确的找到我们想要的函数是十分的不容易的。这到题如果代码量少一些的话,难度就相对没那么大了。

对于终端大小,在ubuntu的命令行中输入resize命令和就可以查询目前的长宽大小,我们用Ctrl+鼠标滑轮就可以调节大小,大致这么多

在这里插入图片描述

我们打开oldshool,可以看到如下界面,输入用户名与密码。

在这里插入图片描述

对于本道题,我们使用动态调试来确定,我们的输入与验证函数。由于代码实在是太多。二分法最快,嘿嘿。

经过调试,我们可以在3856行的伪代码处,找到我们的加密函数。

在这里插入图片描述

这里我们可以知道每五位就会检测-号,也就是说我们的密码大致格式为22222-aaaaa-33333-bbbbb-44444

在这里插入图片描述

通过动态调试,追踪我们输入的密码,我们可以得知,这里的操作是移位查表,1→2,2→3,生成了一张表,我们可以归纳出其规律。

在这里插入图片描述

通过分析下面的的操作,我们可以知道,这些都是通过我们输入name生成一些固定的加密数据

在这里插入图片描述

这一部分就是将我们的password进行转置生成矩阵,第n列循环右移n字节,并且进行异或加密

在这里插入图片描述

最后这是运用了两矩阵相乘生成单位矩阵的性质来判断是否相等

其中后面的&0x1f是取其低 5 位,并将其他位设置为零。
在这里插入图片描述

到此我们算是分析完了,看到的加密。加密的逻辑就是:

对于密码,将我们输入的密码进行转位换表,然后转置生成矩阵,进行异或

对于用户名,将用户名进行一系列复杂的加密,生成一些固定的密文

最后,再通过逆矩阵知识,进行比较验证正确性。

我们逆向写脚本的话,就要通过动态调试,将用户名生成的对比密文提取出来,求其逆矩阵,然后,转置,异或,再进行查表,找到应该输入的对应用户名的密码。

按理说,我们写出脚本,就能将其解出的,我们使用z3进行爆破求其逆矩阵,但是我们会发现,求出的有些密码在动态调试时输入是正确的,能过验证,但是直接运行程序却不能过验证。甚至有些还不能爆破。但是我们无论如何看,我们的脚本都是没有问题的,这就很怪。

看了官方wp之后才知道,脚本确实没有写错,但是有反调试,检测到我们的调试器之后,就会悄悄的将我们加密使用的数据进行改变,由于我们的密文是经过动态调试出来的,所以直接中招。

通过几处的查看交叉引用

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我们可以发现都是这个if的这个函数下进行改变的,我们对这个函数查看交叉引用,我们可以找到所有的反调试,

在这里插入图片描述

四处地方,都是改变我们加密过程中的数据,藏得十分隐秘,因为不会有任何的报错与提示,而且代码量巨多,让其难以发现,写脚本没解出来,第一时间都怀疑脚本的正误与分析的正误,后面有所怀疑,最后也作罢。

按照官方的说法,这个就是ptrace函数。绕过这个反调试也很简单,在动态调试的时候,将ptrace返回的标志,从1改成0即可

一般的来说:

  • 如果 ptrace 执行成功,则返回 0 ,或者其他值
  • 如果 ptrace 执行失败,则返回 -1,或者其他值。

具体值的含义取决于请求的类型。

绕过反调试后,再用我们的脚本进行解密即可。

解密脚本

from z3 import *

matx = [[0x12, 0x1D, 0x10, 0x13, 0x1B],
[0x8, 0x1F, 0x8, 0x17, 0x1E],
[0x1D, 0x3, 0x1C, 0xA, 0x15],
[0x12, 0x1D, 0x08, 0x10, 0x1C],
[0x0B, 0x1E, 0x07, 0x14, 0x07],]  #动态调试username加密后的密文

 #爆破生成逆矩阵

rows = 5
cols = 5

arr = [[z3.BitVec(f'arr_{i}_{j}', 6) for j in range(cols)] for i in range(rows)]
s = Solver()

for k in range(5):
    for m in range(5):
        v28 = 0
        for i in range(5):
            v28 = ((arr[i][m]&0xff) * (matx[k][i]&0xff) + (v28&0xff)) & 0x1f
        if k == m:
            s.add(v28 == 1)
            if k != m:
                s.add(v28 == 0)

inv = []
if s.check() == sat:
    model = s.model()
    for i in range(rows):
        row = [model.evaluate(arr[i][j]).as_long() for j in range(cols)]
        inv.append(row)
else:
    print("err")

print("v18的逆矩阵为:")
print(inv)
#转置逆回去

for i in range(len(inv)):
    if i == 0:
        continue
    elif i == 4:
        inv[i][0], inv[i][1], inv[i][2], inv[i][3], inv[i][4] = inv[i][1], inv[i][2], inv[i][3], inv[i][4], inv[i][0]
    elif i == 3:
        inv[i][0], inv[i][1], inv[i][2], inv[i][3], inv[i][4] = inv[i][2], inv[i][3], inv[i][4], inv[i][0], inv[i][1]
    elif i == 2:
        inv[i][0], inv[i][1], inv[i][2], inv[i][3], inv[i][4] = inv[i][3], inv[i][4], inv[i][0], inv[i][1], inv[i][2]
    elif i == 1:
        inv[i][0], inv[i][1], inv[i][2], inv[i][3], inv[i][4] = inv[i][4], inv[i][0], inv[i][1], inv[i][2], inv[i][3]

print("调换位置后的逆矩阵:")
print(inv)
#矩阵进行异或
xor_arr = [[0x1B, 0x00, 0x0A, 0x0D, 0x08],
[0x18, 0x0F, 0x1C, 0x06, 0x07],
[0x12, 0x05, 0x0C, 0x02, 0x04],
[0x1D, 0x1F, 0x09, 0x13, 0x01],
[0x1E, 0x11, 0x0B, 0x16, 0x19]]

for k in range(5):
    for m in range(5):
        inv[k][m] ^= xor_arr[k][m]
print("异或后的矩阵:")
print(inv)

index_arr = [0x00000010, 0x0000000E, 0x0000000D, 0x00000002, 0x0000000B, 0x00000011, 0x00000015, 0x0000001E, 0x00000007, 0x00000018, 0x00000012, 0x0000001C, 0x0000001A, 0x00000001, 0x0000000C, 0x00000006, 0x0000001F, 0x00000019, 0x00000000, 0x00000017, 0x00000014, 0x00000016, 0x00000008, 0x0000001B, 0x00000004, 0x00000003, 0x00000013, 0x00000005, 0x00000009, 0x0000000A, 0x0000001D, 0x0000000F]

for k in range(5):
    for m in range(5):
        inv[k][m] = index_arr.index(inv[k][m])
print("索引:")
print(inv)
#查表得出flag
chr_arr = [0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A]
for i in range(5):
    for j in range(5):
        print(chr(chr_arr[inv[i][j]]), end='')
    print('-', end='')

参考文章

google-ctf/2023/rev-oldschool/solution at master · google/google-ctf · GitHub

(87条消息) oldschool_fi5hjump的博客-CSDN博客

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值