2020moectf—flower
Posted mishixiaodai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020moectf—flower相关的知识,希望对你有一定的参考价值。
flower
题目:moectf Re flower
运行程序,看程序是如何运作的,发现给了一首诗,还抛出了一个经典的不能在经典的一个问题。然后输入任意字符串,emm竟然被教育了一顿。
但看它的报错是提示我们输入的字符串太长,因此输入一个短的,看来这阅卷老师是真厉害,直接把我高中的底给透出来了。
直接奖励它给他拖入ida中,查找程序出现的字符串,发现了一处让人一看就兴奋的字符串。
直接查看它在代码段中的位置,并使用F5插件得到主函数的伪代码,通过分析,前面一串伪代码是判断你输入的长度,如果不等于16的话程序就会退出,并输出一句话。
我们先查看off_4032A4函数,发现在它的地址上声明了两个函数,第一个函数就先命名为Swapposition,第二个函数就命名为encryption
我们先看第一个Swapposition函数,发现它并不能被ida转化为伪代码,但可以看到在红色位置出现明显错误,又因首字节是E8,猜测很有可能是为了防止反汇编而添加的一个字节,因此将其首字节E8patch为90(nop),并创建函数就可以转化成伪代码了。
分析汇编指令和伪代码,是先将Str2[result] xor(异或)16,然后将异或后的结果传给寄存器dl,然后将cl向左移动四位,再将dl向右移动四位,最后在进行or(或)运算相加。由于cl,dl寄存器只能存储两个16进制,因此在向左移动四位时相当于16进制数向左移动一位,并舍弃最左边的16进制,右边补0;向右移动时舍弃最右边的一位,左边补0。最后的结果就是将两个16进制位置互换了一下。
接着分析第二个函数,发现在代码段有一串数据,这是因为ida是递归分析的,当分析到jmp这个无条件跳转命令时,jmp所跳过的区域ida是不会进行反汇编的。但OD并不是递归分析,而是线性分析,它是逐条指令依次向下分析。
F5转化成伪代码,查看off_404018,发现有三个函数,分别命名为sub,xor,abs函数。for循环的作用就是依次调用这三个函数,并传递两个参数。
先看第一个函数sub,又是相同的问题,直接将E8patch成90,然后创建函数F5(后面两个函数也是如此)。发现他是将 我们的输入与参数a2相加。
第二个函数xor
第三个函数abs,这就有点意思了,abs()是取绝对值的意思,但通过X32debug动态分析后发现,并不是我们想象中的取法。
现在来动态调试看一下这个取绝对值的过程是咋样的。同意我们先通过字符串找到主函数在哪,并按 F2 设置断点,然后运行。输入长度为16的字符串,程序运行到断点处。步过函数,因为要分析第二个encryption函数,知道第二次到达call eax
处然后进入此函数。
在这里原本是要跳过两次call ecx
但在步过的时候直接跳到了其他地方,并且不能在调试了,猜测函数里有反调试的东西,于是在第一次就直接进入函数,发现这处与ida的所反汇编出来的代码不一样,在ida中是8b 45 0c
因此修改X32中的90为8b,这样第一个函数sub就修改完成了(后面两个函数也是如此)。
修改完后,查看第三个函数abs的取值过程,将数据段中的37给了寄存器eax,将77给了ecx,然后神奇的一步就来了,当sub eax,ecx
时,eax的值变为了0xFFFFFFc0。接着执行cdq
后edx值变为0xFFFFFFFF,然后xor eax,edx sub eax,edx
得到37-77后的绝对值。对于相减后结果大于0的情况cdq
后edx值变为0。弄清取绝对值的过程后,编写脚本就方便了。
回到ida中的encryption函数,在for循环结束后,又调用了递归函数,
因为传入的参数dword_404390是定值65,且与我们输入的字符串无关,且并不知道dword_404394的值,因此在这可以用动态调试查看这个函数是如何运行的。
继续之前的动态调试,进入函数,这时一定要一直点步进,并且每当执行到mov byte ptr ds:[ecx+54398],al
时,要记录一下al的值。
在执行到这一步时,在点步进没有反应,因为这时候*ds:[esi]*的地址调试器没有找到,所以就没有这个值,默认不存在,需要手动跳出。
继续点步进,直至跳出digui函数,发现记录了15个数据,并且Str的前15个数据分别与记录的15个数据进行xor(异或)操作。
最后用Str2与byte_4032AC比较,相同即原来输入的字符串套上moectf就为flag。程序的逻辑分析到这就结束了,接下来编写脚本。
由于本人能力不足(惭愧),在解密abs函数时,并不知道Str[a1] (key1[a1]) 和Str[a2] (key1[a2]) 谁大谁小,就采用了最笨的方法将Str[a1] 可能的两个值都解出来,再代入检验,才将flag解出来。
key='3EFE99768BDC0D1832786FBF43743373'#最后对比的值
key1=[int (a,16) for a in [key[i:i+2] for i in range(0,len(key),2)]]
key3='4d4c47504b46434a454e4948444241'#递归函数中需要异或的数
key4=[int(a,16) for a in [key3[i:i+2] for i in range(0,len(key3),2)]]
#三个函数
def sub(a1,a2):
key1[a1] -= a2
def abs1(a1,a2):
temp2 = key1[a1] + key1[a2] - 0xff - 1 #key1[a2]大
key1[a1] = temp2
def abs2(a1,a2):
temp1 = key1[a2] - key1[a1] + 0xff + 1 # key1[a2]小
key1[a1] = temp1
def xor(a1,a2):
key1[a1] ^= key1[a2]
#逆着来,先异或
for v4 in range(0, 15):
key1[v4] ^= key4[v4]
#调用七次函数,逆着来
d=[6, 5, 4, 3, 2, 1, 0]
for i in d :
if i==0 or i==5 or i==6:
sub(i,i+1)
if i==1 or i==3:
xor(i,i+1)
if i==4:
abs1(i,i+1)
if i==2:
abs2(i,i+1)
#将10进制变为16进制
for x in range(16):
key1[x]=hex(key1[x])
print(key1)
key1=[0x27,0x62,0x49,0x27,0x45,0x49,0x74,0x25,0x77,0x63,0x62,0x7f,0x70,0x63,0x27,0x37] #将数字颠倒
for x in range(0,16):
key1[x] ^= 0x16
key1[x] = (chr(key1[x]))
print(''.join(key1)) # 得到flag moectf1t_1S_b3autifu1!
以上是关于2020moectf—flower的主要内容,如果未能解决你的问题,请参考以下文章
ural 2020 Traffic Jam in Flower Town
Google 在 Android TV 应用上声称设备不兼容