2022安洵杯
可能是因为看了一晚上球的原因,这天状态相当不好,赛后还是要好好反思和复现
reeee
这个题就是个rc4,没什么意思
RE1
首先主函数大概是一个加载驱动类的写法,但其实都不重要,重要的是不知道怎么调试,所以当时一直在搜索,其实找到逻辑直接分析就行。
1 | void __stdcall sub_4015C0(int a1, int a2) |
输入是12位,sub_4011D0是初始化,通过sub_401280函数进行对opcode的调用,sub_4012D0是进行对比
先看初始化函数
1 | int __thiscall sub_4011D0(_DWORD *this) |
再看调用方法,
1 | void __thiscall sub_401280(_DWORD *this) |
这个调用是通过调用this的数组进行的,判断的是op==this[4*i],然后进行执行this[2 * index + 5]的方法,最后下图比较
1 | void __noreturn sub_4012D0() |
接下来就是逆了
1 | opcode = [0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x30, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x31, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x32, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x22, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x03, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x33, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x23, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x34, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x24, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x35, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x25, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x36, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x26, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x37, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x27, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x38, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x09, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x39, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x29, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0A, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x3A, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0B, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x3B, 0x00, 0x00, 0x00, 0xF2, 0xF6, 0xF1, 0xE4, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x20, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x21, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0xA4, 0xF2, 0xF9, 0xE1, 0x05, 0xF1, 0xE4, 0x40, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x22, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0x70, 0xF2, 0xF9, 0xE1, 0x97, 0xF1, 0xE4, 0x41, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x22, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x23, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0x4F, 0xF2, 0xF9, 0xE1, 0x79, 0xF1, 0xE4, 0x42, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x23, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x24, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0xD3, 0xF2, 0xF9, 0xE1, 0x47, 0xF1, 0xE4, 0x43, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x24, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x25, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0x5F, 0xF2, 0xF9, 0xE1, 0x92, 0xF1, 0xE4, 0x44, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x25, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x26, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0x03, 0xF2, 0xF9, 0xE1, 0x4A, 0xF1, 0xE4, 0x45, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x26, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x27, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0x08, 0xF2, 0xF9, 0xE1, 0xBD, 0xF1, 0xE4, 0x46, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x27, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x28, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0x28, 0xF2, 0xF9, 0xE1, 0x39, 0xF1, 0xE4, 0x47, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x29, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0x7F, 0xF2, 0xF9, 0xE1, 0x29, 0xF1, 0xE4, 0x48, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x29, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x2A, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0x29, 0xF2, 0xF9, 0xE1, 0x3B, 0xF1, 0xE4, 0x49, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x2B, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0x37, 0xF2, 0xF9, 0xE1, 0xC1, 0xF1, 0xE4, 0x4A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x40, 0x00, 0x00, 0x00, 0xF8, 0xE2, 0xBA, 0xF2, 0xF9, 0xE1, 0xD1, 0xF1, 0xE4, 0x4B, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00] |
跑出来的用z3解密
1 | from z3 import * |
然后进行第一步的移位和异或
1 | for i in range(13): |
不过在分析过程中,并没有发现在什么地方执行了read,而且最后异或的时候也有一定蒙的成分,不知道字符串abcdefghijkl放在了什么位置。
RE2
连续三道题出题模式都一样,不好评价了有点。。。
这个题前面的逻辑全是假的,他又开了一个线程,真正逻辑在那个线程中,是一个经典的花指令,patch之后就能看到是个迷宫。
1 | int __cdecl sub_4027F0(int *a1) |
map:
1 | 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 |
不过怎么走都好像不能走75到终点,查看交叉引用
发现,起点被改了(2,2),终点位置也变了,但发现好像还是走不到75步,最后发现sleep好像被hook了,
1 | int __stdcall sub_402330(int a1) |
发现了原来这个东西是斜着走的,比如当输入为A,是向左下走的,输入为D,是向右上角走的,输入为S,是向右下角走的,输入为W,是向左上角走的,得到路线:dssaaasasssdsddddwddssasaaassdsssaasssddssasaassaaassdsdsssaaassddddsdssasa