-
-
[原创] KCTF2020 秋季赛 第三题 重返地球
-
2020-12-15 00:14 4744
-
程序比较长,翻着看看操作,感觉像是一个指令是链表的虚拟机。先建个结构体。
1 2 3 4 5 6 | struct Node { int opcode; int arg0; int arg1; int arg2; }; |
程序流程感觉大概是
1.设置数据节点(相当于设置内存)(set_val..)
2.设置寄存器的值(一些输入) (Regxxx = )
3.设置指令入口 (Code_entry = ...)
4.进入虚拟机 (flow_dispatcher)
5.把算出来的vm_output拿出来看一看,比一比
嗯,看看程序。
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 32 33 34 35 | int __cdecl main( int argc, const char * * argv, const char * * envp) { sub_3E1080(aInputYourFlag); / / 提示 Input_Node = sub_3E11D0(); / / 输入 Input_Node2 = Input_Node; / / 当前节点 Code_entry = strlen_func; / / 一个关键的跳转变量 flow_dispatcher(); / / 每次dispatcher一次就可以得到一个vm_output if ( sub_3E11A0(vm_output, 37 ) ) / / 验证长度 { / / ... 省略非常长的设置节点的操作 v1408 = set_one(); v1409 = set_zero_arg0_arg1( 17163 , v1408); / / .. 省略一堆节点设置 Reg7 = set_zero_arg0_arg1_(v1445, v1407); Reg8 = Input_Node; Code_entry = transform_input_func; flow_dispatcher_2(); / / 这个VM来对输入进行变换 v1446 = set_one(); / / 这是最终要比较相等的值 v1447 = set_zero_arg0_arg1( 7821 , v1446); / / ... 省略一堆节点设置 v1483 = set_zero_arg0_arg1( 0x312A , v1482); if ( sub_3E12C0(vm_output, v1483) ) / / 比较变换后的输出 sub_3E1080(aFlagCorrect); else sub_3E1080(aFlagWrong); } else { sub_3E1080(aFlagWrong_0); } return 0 ; } |
前面strlen_func不分析了,后面的transform_input_func 分析一下,因为指令比较少,就直接边调试边看看。
发现先是几轮加法操作
output1 = inp[0] * 8868
output2 = inp[1] * 27507
.....
然后得到一个链表新的 [output1,output2...]
然后就是上演了操作 output = output1 % 29527 + output2 % 29527 + ....
所以看到这里,就知道是
flag 乘上 已知矩阵 = 一个已知的值,然后是取模意义下的。
拿神仙工具sage解一下,百度个脚本改改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # d0, d1, d2...是提取出来的数据,就不往wp上抄了。 res = [ 7821 , 8110 , 28701 , 2882 , 4374 , 11830 , 22009 , 376 , 7691 , 2176 , 662 , 13481 , 16812 , 7204 , 10762 , 6282 , 6660 , 2410 , 21411 , 28102 , 22854 , 5466 , 24919 , 22382 , 875 , 25566 , 8859 , 9908 , 11941 , 1555 , 22145 , 23914 , 4893 , 12668 , 13603 , 18694 , 0x312A ] d = [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31, d32, d33, d34, d35, d36] A = [k[:: - 1 ] for k in d] # mod 29527 F = GF( 29527 ) # 构造矩阵 A = matrix(F, A) # 构造向量 b = matrix(F, res).transpose() # 解方程 x = A.solve_right(b) flag = bytes(vector(x)).decode() print (flag) # KCTF{r4Ck3t_M4tr|X_W1tH_CP5_YqBHxjWX} # https://sagecell.sagemath.org/ |
恭喜ID[飞翔的猫咪]获看雪安卓应用安全能力认证高级安全工程师!!
赞赏
他的文章