最近在研究逆向工程,做了一些ctf题,今天遇到的这个问题卡了我很长时间才拿到flag。事后分析这道题暴露出我的一个思维短板:形象思维总是盖过逻辑思维,太相信直觉,于是总也拿不到正确结果。

核心算法如下:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

TextList = [?,?,?,?,?,?,?]#列表长度是7,元素内容未知

dw=0x02
v38 = [0x62,0x39,0x62,0x37,0x64,0x64,0x31]
v39 = [0x79,0x65,0x6e,0x6f,0x6d,0x6f,0x6e]

for i in range(7):
    TextList[6-i] ^= v38[i] ^ dw ^ v39[i]
    dw = TextList[6-i]
    
print "CipherList is:",

------------------------------------------------------
已知密文是:
CipherList = [0x51,0x3c,0x0f,0x67,0x5c,0x2c,0x41]#密文

已知密文CipherList,让反推出明文,属于很常见的逆向题目。

这个算法有几方面增加了过程的复杂度和迷惑性,1)对列表元素的处理是逆序处理的;2)^=操作;3)dw的值每个循环都在变化。这些处理过程成功迷惑了我,使得我认为逆运算就是这个算法本身!因为我把关注点都放在了TextList[6-i] ^= v38[i] ^ dw ^ v39[i]这行代码,我认为名文就是"密文 xor v38 xor v39 xor dw",而忽略了dw值是否正确。

实际上,为了得到正确的明文,你必须获取到正向运算中的dw值,但是按照我最开始的想法“逆运算就是它本身”,得到的dw值根本就不是正向运算中的值。因为忽略了这一点,所以永远也不会得到正确答案。

其实现在看来我最开始的想法是很低级错误的,根本原因是对逆运算的分析错误,再根本的原因是对逆向的理解不正确。我原来更多将逆向的关注点放在算术操作上,也就是那些异或操作。实际上,为了得到正确的逆向结果,不仅操作要正确,过程中的数据也要正确

而且,为了降低代码的迷惑性,也可以把那一行异或操作展开,改为"TextList[6-i] = v38[i] ^ dw ^ v39[i] ^ TextList[6-i]"。

下面附上正确的逆运算代码:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import random

dwlist = [0x02,0x41,0x2c,0x5c,0x67,0x0f,0x3c]

PlainTextList = [0,0,0,0,0,0,0]
CipherText = [0x51,0x3c,0x0f,0x67,0x5c,0x2c,0x41]#密文
v38 = [0x62,0x39,0x62,0x37,0x64,0x64,0x31]
v39 = [0x79,0x65,0x6e,0x6f,0x6d,0x6f,0x6e]

l1 = []
l2 = []

for i in range(7):
    PlainTextList[6-i] = v38[i] ^ dwlist[i] ^ v39[i] ^ CipherText[6-i]

resStr = ""
for j in PlainTextList:
    resStr += chr(j)

print resStr#key is:28ac|1X

#username is:nsfocus

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐