2020网鼎杯 青龙组reverse:joker

main函数不能F5,原因堆栈不平衡

 打开ida的general设置

 

 勾选栈指针选项

 

 修改出错的地方的栈指针偏移,快捷键alt+k,值改为0

 

 看绿色部分,栈偏移都是0AC了

 

这下,main函数 F5成功

 但是,在main函数的伪代码里还有一个encrypt函数不能F5,出现以下提示,“不能转换成代码”

-cannot convert to microcode
无法转换成伪代码
成因,部分指令无法被反编译
有未设置成指令的数据字节按c将其设置成指令
或者这里我选择启动动态调试,程序运行到代码段这里会自动问你要不把数据换成代码,选择yes

原来的data数据变为汇编代码

 

(.text代码段的数据)

 

(上一张图的数据自动变为汇编代码)

右键原来的encrypt函数,选择创建函数

 然后F5就可以成功出现伪代码了

从main函数到encrypt函数,我们已经将所有不能F5的地方修复了。

main函数逻辑,输入24个字符,对输入的内容进行wrong函数加密

wrong函数,对输入的前23个进行加密

比较wrong加密结果和unk_4030C0地址的值是否相同

把unk_4030C0地址的值考出来,反手写个解密,步骤如下

1.快捷键d,把数据类型从db转为dd

 2.然后用ida导出,啊..我晕,怎么还是db数据类型,没办法只有自己处理了

3.很可惜,运行出来是个假flag

'''
s=[102,   0,   0,   0, 107,   0,   0,   0,  99,   0, 
    0,   0, 100,   0,   0,   0, 127,   0,   0,   0, 
   97,   0,   0,   0, 103,   0,   0,   0, 100,   0, 
    0,   0,  59,   0,   0,   0,  86,   0,   0,   0, 
  107,   0,   0,   0,  97,   0,   0,   0, 123,   0, 
    0,   0,  38,   0,   0,   0,  59,   0,   0,   0, 
   80,   0,   0,   0,  99,   0,   0,   0,  95,   0, 
    0,   0,  77,   0,   0,   0,  90,   0,   0,   0, 
  113,   0,   0,   0,  12,   0,   0,   0,  55,   0, 
    0,   0, 102,   0,   0,   0]

out =[]
for i in s:
          if i !=0:
                    out.append(i)
'''

s=[102, 107, 99, 100, 127, 97, 103, 100, 59, 86, 107, 97, 123, 38, 59, 80, 99, 95, 77, 90, 113, 12, 55, 102]

out =[]
for i in range(0,24):
          if i&1:
                    s[i] += i
                    out.append(s[i])
                    
          else:
                    s[i] ^=i
                    out.append(s[i])

flag=''                 
for i in out:
          flag += chr(i)
print(flag)

wrong函数,不行不是真flag往后看吧,encrpt和wrong函数差不多

一样的,找到unk_403040地址的值,把值考出来,用以写解密

 出了flag的前19位

'''
s=[   14,   0,   0,   0,  13,   0,   0,   0,   9,   0, 
    0,   0,   6,   0,   0,   0,  19,   0,   0,   0, 
    5,   0,   0,   0,  88,   0,   0,   0,  86,   0, 
    0,   0,  62,   0,   0,   0,   6,   0,   0,   0, 
   12,   0,   0,   0,  60,   0,   0,   0,  31,   0, 
    0,   0,  87,   0,   0,   0,  20,   0,   0,   0, 
  107,   0,   0,   0,  87,   0,   0,   0,  89,   0, 
    0,   0,  13,]

out =[]
for i in s:
          if i !=0:
                    out.append(i)
'''

s=[14, 13, 9, 6, 19, 5, 88, 86, 62, 6, 12, 60, 31, 87, 20, 107, 87, 89, 13]
haha='hahahaha_do_you_find_me?'

out =[]
for i in range(0,len(s)):
          out.append(s[i]^ord(haha[i]))

flag=''                 
for i in out:
          flag += chr(i)
print(flag)

剩下的5位在finall函数里,但是....代码逻辑很迷惑,不懂

 来到汇编处,看出是因为把汇编代码存成了data数据,所以伪代码才那么迷惑

动态调试到finally

 

 create function查看伪代码

伪代码(37 != *a1) == v9这里很迷看不出来什么意思,转到汇编可以看出比较的al、dl是数组元素,var_15是0x25

比较完了,al的值清空保存到eax里

 随着var_10的增加dl和al取的数组值也在相应发生变化,当var_10增加到4时,退出finally函数

逻辑很明显了,就是以下五个数字和传入的参数al相比,刚才算出了flag的前19位,传入的参数自然是flag的后五位。

.text:004015A0 mov     [ebp+var_15], 25h
.text:004015A4 mov     [ebp+var_14], 74h
.text:004015A8 mov     [ebp+var_13], 70h
.text:004015AC mov     [ebp+var_12], 26h
.text:004015B0 mov     [ebp+var_11], 3Ah

最后eax和前面的rand()随机生成的数字做比较,如果不等则退出

 

 不知是我汇编水平太差没看出来,还是里面压根没有写输入和flag有何关系,只讲明了输入和那五个数字应该相等

25h,74h,70h,26h,3Ah

通过猜测,最后一位应该是},再猜0x3A和}之间是异或关系,得到的值为71,再将之前的四个值都和71异或

 s=[0x25,0x74,0x70,0x26,0x3a]
 for i in s:
    print(chr(i^71),end='')

 加起来便是,flag{d07abccf8a410cb37a}

什么脑洞啊......服了

原文地址:https://www.cnblogs.com/blackicelisa/p/12961832.html