做算法题,得认真观看源码
hflag = flag.encode('hex')
iflag = int(hflag[2:], 16)
这是把flag每个字符变成十六进制后,再转换为十进制

i = 0
r = ''
while i < len(str(iflag)):
d = str(iflag)[i:i+2]
nf = FAN(int(d), 3)
r += str(nf)+"."
i += 2
这段代码就是遍历这个十进制的字符串,每次取2个字符(最后一次可能是1个字符,代码中会说明),经过FAN()后得到一个字符串,把所有字符串串起来就是enc.txt的内容。
FAN()里面的操作看起来不是很麻烦,但头疼的点在于长度,我们不知道每次操作后的长度到底有多长,enc.txt的密文也只是一长串数字(没有分隔符),没有长度这个概念后很多操作举步维艰,在这种情况下再写个deFAN()来逆推多半是吃力不讨好。

从另一个角度去想,由于是转换为十进制再每次取2个字符,所以FAN()的n的取值范围就是00~99,通过FAN()后得到100个key(幸好不重复,构建成一个字典以便查询),密文就是由这些key任意组成,然后最大的问题还是长度问题,这些key长度从1位到4位,我这里采用的匹配方法是每4位字符匹配,如果匹配不到,就匹配3位字符,以此类推到1位字符。最后把所有值组合起来,转换为十六进制即可。(如果有更好的方法请告诉我,谢谢)

# -*- coding: utf8 -*-

#原代码中的FAN()
def FAN(n, m):
    i = 0
    z = []
    s = 0
    while n > 0:
    	if n % 2 != 0:
    		z.append(2 - (n % 4))
    	else:
    		z.append(0)
    	n = (n - z[i])/2
    	i = i + 1
    z = z[::-1]
    l = len(z)
    for i in range(0, l):
        s += z[i] * m ** (l - 1 - i)
    return s

def foo():
	#读取密文
	s=open("enc.txt").read().strip()

	#构造0~99对应的FAN()的值的字典
	dct={}
	for n in xrange(0,100):
		#key为FAN()的结果,value为n(位数补足到2位)
		dct[str((FAN(n,m=3)))]="%02d"%n

	lst=[]
	offset=0
	while offset<len(s):
		#先从4个字符匹配直至1个字符
		for i in xrange(4,0,-1):
			tmp=s[offset:offset+i]
			if tmp in dct:
				lst.append(dct[tmp])
				offset+=i
				break
	flag="".join(lst)

	#python中s[i:i+2]不一定取到2个字符,
	#如s="pcat",s[3:4]和s[3:5],甚至s[3:100]都是"t"
	#此题中最后得到"09",但也可能是"9",故做下面的判断
	if len(hex(long(flag))[2:-1])%2!=0:
		flag=flag[:-2]+flag[-1]
	
	flag=hex(long(flag))[2:-1].decode('hex')
	print flag
	pass

if __name__ == '__main__':
	foo()
	print 'ok'

Flag:

温馨提示: 此处内容需要评论本文后刷新才能查看,支付2元即可直接查看所有Flag。

小广告:关于获取西普实验吧所有Flag请点击这里查看索引

查看所有Flag文章需要输入密码,需要获取文章密码的童鞋请扫描下面微信或支付宝二维码捐助至少2元(老哥,捐多捐少是个缘分)之后发送支付凭证号联系我获取,Flag大全地址:Flag大全

新功能:捐款的小伙伴请联系我把自己的注册邮箱加入网站白名单,可以免回复看到本站所有Flag

PS:本站不是实验吧的官方站点,纯粹是个人博客,收取Flag费用仅是维持服务器费用,做站不易,且行窃珍惜!

微信二维码:
支付宝二维码: