首先,用IDA打开程序,看到一大堆while(1)又套着while(1)的结构,肯定是控制流平坦化了,我们可以使用IDA插件d810去掉。
现在程序就好看多了。如果IDA没有显示这堆中文字符串,可以考虑使用IDA8.3,就可以显示了。
首先,反汇编第12行那个函数sub_7FF783BFCB20,里面一大堆奇奇怪怪的语句,不知道是干嘛的。我们可以在第十六行下断点,然后随便输入一堆字符串,就可以知道,这个函数其实就是对v6字符串赋值。
可以点进去v6看看,往下拉一拉,就能看到了,就是赋值到比较后面的位置而已。
sub_7FF783BE1000这个函数比较简单,就是输入的字符串不能有数字。
sub_7FF783BE11E0,这个函数就是对你输入的字符串,重复的字母会压缩成一个,并且后面跟着一个重复次数。例如,CC会变成C2,BBB会变成B3,也可以动调玩玩看。
下面的sub_7FF783BE1E30这个函数就比较重要了,其中,sub_7FF783BE1A50这个函数:
里面有个sub_7FF783BE2030(&v6[3 * i], “%%%02X”, (unsigned __int8)a1[i]);
这个语句其实就是sprintf。这个函数就是把字符串的ascii码转16进制字符串。
sub_7FF783BE1840这个函数,就是把字符的数字转成数字,如果是字母,也做一些转换,具体的转换可以自己看看,非常简单。
sub_7FF783BE15D0这个函数应该是最重要的了。sub_7FF783BFC480这个函数就是一个赋值,动调可以知道。下面的语句,就是在Str中,找对应位置的两个汉字赋值到v3,最后返回v3。(一个汉字是对应两个字节的,这个是汉字的编码方式)
对应的位置指的是,sub_7FF783BE1840这个函数不是会得到一些数字吗?我们会从输入的字符串转变过来的数字,然后根据这些数字找到Str对应的位置,找到相应的汉字赋值。
思路清晰了,脚本非常好写:
key="冻笔新诗懒写寒炉美酒时温醉看墨花月白恍疑雪满前村"
ciphertext="美酒恍疑时温寒炉美酒寒炉寒炉懒写墨花前村时温时温前村恍疑墨花懒写墨花月白墨花懒写醉看墨花醉看恍疑醉看美酒墨花醉看醉看前村恍疑醉看时温醉看前村月白醉看新诗醉看月白醉看美酒墨花冻笔醉看恍疑墨花冻笔醉看恍疑墨花懒写墨花前村墨花"
table=[]
for i in range(0,len(ciphertext),2):
table.append(key.find(ciphertext[i:i+2]))
#print(table)
for i in range(0,len(table)):
table[i]=int(table[i]/2)
def get_char(pos):
cnt=0
new_pos=pos
string=""
c=0
while cnt<2:
if table[new_pos]!=11:
string+=str(table[new_pos])
new_pos+=1
cnt+=1
else:
new_pos+=1
string+=str(chr(61+table[new_pos]))
new_pos+=1
cnt += 1
return new_pos,chr(int(string,16))
i=0
ans=""
while i<len(table):
i, c = get_char(i)
ans += c
print(ans)
#ISC2{_rxrgidvoenahdpipir}