这两天攻防世界有个比赛,上面的题目还不错,参与了一下,至于为什么是两道re,因为正好赶上数模美赛,没怎么有时间做(实际上就是因为菜
cyclegraph
1 | void FUN_00401080(void) |
表面上看起来很复杂,仔细研究就会发现,开始的循环是在构造一个有向图,用到了一个结构体,而后面的部分是一个寻路的过程,正向的过程是根据输入的flag的值进行移动,最终走到最后一个位置,所以逆向的过程就是先寻找路径,然后通过找到的路径来计算flag的值
1 | #include <iostream> |
注释部分是对于程序的一个正向还原,寻路用到了dfs
算法,不是很难。
最后得到flag
1 | flag{d8b0bc97a6c0ba27} |
天津垓
题目里所有的内容都是假面骑士……
首先可以关注到一个函数名为f
的函数,这个函数很简单
1 | __int64 __fastcall f(__int64 a1, char **a2, char **a3) |
这里进行了简单的验证,中间得处理过程不是很好逆,因为涉及到与或非三种运算符,但是通过列真值表可以发现,这一串运算实际上和一个异或是一样的,所以这一部分就很好处理了
1 | target = 'Rising_Hopper!' |
输出Caucasus@s_ability
,尝试提交发现不对,这题应该没这么简单,在找找有没有遗漏的地方,然后通过Str
的交叉引用结果找到了遗漏的部分
1 | int sub_100401A6C() |
这个函数在输入并验证过Str
之后又调用了我们的输入,肯定还会有后续的处理
1 | BOOL __fastcall sub_100401506(void *a1, int a2, __int64 a3) |
这里是经过处理之后的内容,实际上是对一个地址上的数据进行了处理,显然是一个SMC
的过程,这个地址里存储的应该是有用的处理代码,我们输入的内容实际上也只是对数据解密的密钥而已,所以接下来写个IDC脚本来解密一下
1 | #include <idc.idc> |
不是很会用IDC,而且还没有数组类型,只能这样用很多分支去判断,然后得到了新的汇编代码,如果是汇编很好的话就可以直接做了,我还是习惯了无脑F5
,所以干脆patch
了一下后面的垃圾数据,写了一个retn
,然后创建函数,查看伪代码
1 | int sub_10040164D() |
关键的处理只有一句,但是有个很烦的取余,仔细观察可以发现,v62
这个数非常大,最后在计算的时候取不取这个余数都没关系,所以这一部分又变成了一个非常简单的除法,然后问题就很容易解决了
1 | v9 = [2007666, 2125764, 1909251, 2027349, 2421009, 1653372, 2047032, 2184813, 2302911, 2263545, 1909251, 2165130, |
输出flag
1 | flag{Thousandriver_is_1000%_stronger_than_zero-one} |
后记
然后这次比赛就没打算再做了,mobile
的题,研究了一下,应该不是特别难,但是没太有时间,又是作业又是网课又是美赛,让人很烦,如果后面有wp放出来的话再去研究研究,复现一下,做个补充。
Comments