本帖最后由 aw220 于 2022-2-17 15:22 编辑
脱壳
拖进DIE,有UPX壳
OD脱壳,ctrl+B搜索0000000000000,找到上面的jmp ,打断点。
运行,然后走一步,就到入口点了。
跟流程
拖入IDA,看到_main函数,可以发现流线比较清楚,输入UID后有两个走向,分别是UID合法和不合法
在UID合法的走向中,又分了两条,分别是Key正确和不正确,这个UID啊,刚开始压根不知道是账户UID,后来看别人回帖才知道的。
使用F5反编译,查看具体算法
看算法
可以看到,这个if-else就是关键了
进这个sub_401520 函数看看,里面又有一个if-else,只有进到else才能返回1
而控制的关键在于v8 这个变量
进到sub_403ED0 ,我们需要实现return的值为0,即result 为0,配合OD动态调试对比发现,memcmp 用于比较输入的内容和真正的Key是否相同(观察栈可以发现为flag{Happy_New_Year_52Pojie_2022 }),相同则返回0,至于这个if里面的东西,我也没搞懂。
回到上一层,看v50 是什么,分析后可以知道红框里面的两句分别是将输入的东西(a1 该函数的参数,传入的是被输入的东西)复制给v12 ,然后将v12 加密给v50
至于这个crypy 函数,核心是这一句,它在while循环里面,会加密输入的Key的每个大小写字母,通过跟踪函数调用时的相关参数,可以得出如下公式
X * (Y - (UID % 25) - 97) % 26 + 97 = 12 # 这个X与UID相关,但我没能力推出公式,可以在OD中运行时找到具体值
# Y是Key的每个字符的Ascii码
最后用python写了个脚本算Key,没有转换大写字母,因为我用这个转换出来的是错的,就索性用OD去转换每个大写字母,找到那几个关键字母再手动替换就可以了
def crypt():
t = ""
for y in "flag{Happy_New_Year_52Pojie_2022}":
if re.match("[a-z]", y):
for x in range(ord('A'),ord('Z')+1) and range(ord('a'),ord('z')+1):
if 9 * (x - 10 - 97) % 26 + 97 == ord(y): # 公式,替换关键部分为自己的
t += chr(x)
break
else:
t += y
return t
print(crypt())
|