2024鹏城杯minire
0x00 前言
VM题,有点小难度
0x01 解
法一
查壳,发现是UPX
可以判断是改了的
手工脱了,参考这个:https://blog.csdn.net/m0_49936845/article/details/119976496
注意脱的时候注意一下idc脚本的导出路径,要不然导不出来
直接进start,发现有个判断
根据分析可以知道,会先对调用参数进行一个判断,参数长度为4,且内容是root则进入sub_403193
,否则走else
else里面就是接受一个输入,然后判断其hash值是否为
1 | 3c2d515f04e71ba58cb1247461981337 |
sub_4010C0
为获取长度的函数,v26
为输入的内容,根据sub_4018D5
可以知道这是MD5,直接爆破可以知道原来的输入内容为
1 | fksdde7039 |
然而这并不是flag
真正的flag藏在了sub_403193
里面
这里最重要的是这个sub_402A9B
,它的参数看上去就像opcode
而sub_402A9B
这个函数无法解析,因为太大了
没办法,手动跟了
直接跑,然后暂停,一步步回到这个函数,发现是这个地方调用了read的syscall
通过跟踪可以发现是不断读取一个字符然后放入了[rax+rdx]
里面,下个硬件断点在第一个,一直运行直到断下
之后可以在开始调用输入的时候通过查看数组大小判断输入的内容长度
这边通过判断发现长为37
之后通过观察,发现调用这个数组的地方集中于这一块
在运算的地方都下个断点(可以通过观察发现进行运算的地方前面都调用了sub_405C10
,然后会接一个运算的指令),然后一个个来看
需要注意的是lea
这条指令是能当add
用的
之后会发现不停来回调用上面这些东西,在各个断点写个脚本输出断点位置内容
1 | import idc |
注意unk_5175A0
是分配空间的首地址,而cs:dword_768090
是偏移,分配空间的首地址加偏移才是存储输入内容的数组首地址,所以在输出的时候要减去偏移(0x46)
根据不同地方的断点改变中间的符号就好
最后可以得到如下的运算过程
1 | x[0]^=4 |
得到运算过程不够,还要知道密文
在xor的最后跳转下断点,一路运行到加密流程全部执行完毕
之后给加密结果下硬断,发现断在这
通过硬断位置和下面的movzx
指令可以知道,rax+rdx
就是对加密结果的索引(0x5175A0+0x46=0x5175E6)
由此可以推断是在这里获取数据的,取消硬件断点,在此处下个软件断点,执行后发现此处变为0x96
根据上面的计算方法,可以得到0x96的偏移(0x5175A0+0x96=0x517636)为一个数组
结合已知的flag头加密结果,可以推断这个应该是密文,dump下来写脚本
1 | from z3 import * |
法二
brute.py:
1 | import subprocess |
hook.js:
1 | var number = 0 |
但是速度真的很慢(爆了近2h),而且有出错的风险(flag中的7变成了z)