湖湘杯 pyc分析 BY Assassin

这个题目还是很厉害的,比赛的时候没有做出来,在赛后参考和学习之后勉勉强强能够明白题目的意思,这个题目是XDCTF2015的re300,看网上湖湘杯的题解和播报的代码都一样,做出来的估计是找到了原题吧,毕竟这题在当时的比赛中都很少有人做出来。。。
言归正传,首先我们得到一个pyc文件,很明显我们要反编译的,但是代码就一行,所以一定要用美化工具美化一下,否则看的蛋疼的要死。美化后的反编译代码如下

bbbb = (lambda __g, __y: [
    [
        [
            [
                [
                    [
                        [(fin.close(), [
                                [(lambda __items, __after, __sentinel: __y(lambda __this: lambda: (lambda __i: ([(ss.append(c), (sss.append(0), __this())[1])[1]
                                        for __g['c'] in [__i]
                                    ][0]
                                    if __i is not __sentinel
                                    else __after()))(next(__items, __sentinel)))())(iter(s), lambda: [
                                    [(lambda __items, __after, __sentinel: __y(lambda __this: lambda: (lambda __i: ([(lambda __value: [__this() for __g['sssss'] in [(lambda __ret: (__g['sssss'] + __value
                                            if __ret is NotImplemented
                                            else __ret))(getattr(__g['sssss'], '__iadd__', lambda other: NotImplemented)(__value))]][0])(chr(c)) for __g['c'] in [__i]][0]
                                        if __i is not __sentinel
                                        else __after()))(next(__items, __sentinel)))())(iter(ssss), lambda: [(fout.write(sssss), (fout.close(), None)[1])[1]
                                        for __g['fout'] in [open('key.enc', 'wb+')]
                                    ][0], []) for __g['sssss'] in ['']][0]
                                    for __g['ssss'] in [encode(ss, sss)]
                                ][0], []) for __g['sss'] in [
                                    []
                                ]][0]
                                for __g['ss'] in [
                                    []
                                ]
                            ][0])[1]
                            for __g['s'] in [fin.read().strip()]
                        ][0]
                        for __g['fin'] in [open('key.txt', 'r')]
                    ][0]
                    for __g['encode'], encode.__name__ in [(lambda data, buf: (lambda __l: [
                        [(lambda __items, __after, __sentinel: __y(lambda __this: lambda: (lambda __i: ([
                                [__this() for __l['data'][__l['i']] in [table.index(__l['data'][__l['i']]) + 1]][0]
                                for __l['i'] in [__i]
                            ][0]
                            if __i is not __sentinel
                            else __after()))(next(__items, __sentinel)))())(iter(xrange(__l['_len'])), lambda: (lambda __items, __after, __sentinel: __y(lambda __this: lambda: (lambda __i: ([
                                [
                                    [__this() for __l['buf'] in [setbit(__l['buf'], __l['i'], getbit(__l['data'], __l['j']))]][0]
                                    for __l['j'] in [__l['i'] / 6 * 8 + __l['i'] % 6]
                                ][0]
                                for __l['i'] in [__i]
                            ][0]
                            if __i is not __sentinel
                            else __after()))(next(__items, __sentinel)))())(iter(xrange(__l['_len'] * 6)), lambda: __l['buf'], []), []) for __l['_len'] in [len(__l['data'])]][0]
                        for __l['data'], __l['buf'] in [(data, buf)]
                    ][0])({}), 'encode')]
                ][0]
                for __g['getbit'], getbit.__name__ in [(lambda p, pos: (lambda __l: [
                    [
                        [__l['p'][__l['cpos']] >> __l['bpos'] & 1
                            for __l['bpos'] in [__l['pos'] % 8]
                        ][0]
                        for __l['cpos'] in [__l['pos'] / 8]
                    ][0]
                    for __l['p'], __l['pos'] in [(p, pos)]
                ][0])({}), 'getbit')]
            ][0]
            for __g['setbit'], setbit.__name__ in [(lambda p, pos, value: (lambda __l: [
                [
                    [(lambda __target, __slice, __value: [(lambda __target, __slice, __value: [__l['p']
                        for __target[__slice] in [(lambda __old: (lambda __ret: (__old | __value
                            if __ret is NotImplemented
                            else __ret))(getattr(__old, '__ior__', lambda other: NotImplemented)(__value)))(__target[__slice])]
                    ][0])(__l['p'], __l['cpos'], __l['value'] << __l['bpos']) for __target[__slice] in [(lambda __old: (lambda __ret: (__old & __value
                        if __ret is NotImplemented
                        else __ret))(getattr(__old, '__iand__', lambda other: NotImplemented)(__value)))(__target[__slice])]][0])(__l['p'], __l['cpos'], ~(1 << __l['bpos'])) for __l['bpos'] in [__l['pos'] % 8]][0]
                    for __l['cpos'] in [__l['pos'] / 8]
                ][0]
                for __l['p'], __l['pos'], __l['value'] in [(p, pos, value)]
            ][0])({}), 'setbit')]
        ][0]
        for __g['table'] in [string.printable.strip()]
    ][0]
    for __g['string'] in [__import__('string', __g, __g)]
][0])(globals(), lambda f: (lambda x: x(x))(lambda y: f(lambda: y(y)())))

是不是猛一下看不懂?这里需要将一些python很好玩的东西

如何在[]中赋值,如何用lambda

>>> [x for x in [range(3)]]
[[0, 1, 2]]

题目为啥复杂,因为赋值可以有层级关系

>>> [[ [i for i in [77+kkk+aaa]] for kkk in range(3)] for aaa in [233]]
[[[310], [311], [312]]]
>>> [[ [i for i in [77+kkk+aaa]] for kkk in range(3)] for aaa in [233]][0][0]
[310]

这种就用到了大量的嵌套,看上去就是一大堆中括号…要死…

之后我们来简单分析一下代码吧,首先需要明确的

__g=globals()  全局变量
__l 不知道是啥,但是看在函数中才有,而且用的方法很像__g,貌似是一个局部变量

用到lambda函数构造了几个函数分别是setbit、getbit和encode几个函数。貌似像是构造了一个类啥的,但是没看太懂。
setbit和geibit没什么好讲的,确实就是设置和得到比特位。
其中encode

这里写图片描述

我们注意到,首先是对所有字符串的对应有个table表对应的index全部加了一
那么table是个啥!!!因为前面讲过的python语法,赋值语句可能很靠后,最终在最后找到了table
这里写图片描述

转换出来就是

table ='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

总共有96个字符

encode函数貌似只是取了每个字符的低6位比特位,但是我们需要注意上面还有什么s ss sss什么的变量,分析不太清楚,只好print输出一下啦,然后找一下规律,我输入字符串AAAAA
得到的ss和sss输出分别是

[37, 37, 37, 37, 37]
[101, 89, 150, 37, 0]

ss无疑就是我们输入串AAAAA的index+1后的结果(A在table中的index是36)
sss是啥,我们转变成比特看一下

[101, 89, 150, 37, 0]
#01100101
#01011001
#10010110
#00100101
#00000000

首先我们明确5位输入对应5位输出,不够的补充后缀0。看看规律37对应的后6位比特是100101,然后我们就能大概猜测字节序被改变了!
输入ABCDABCD得到的是[165, 121, 162,165, 121, 162, 0,0]
猜测是4位一个组成3*8==4*6的加密方法
然后字节序比较特别。
还有需要注意的是table表是96长的,但是我们后6位只能到63,所以比特的第七位可0可1,需要特判
下面就可以写程序了

# _*_ coding:utf-8 _*_
import binascii
table ='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
def handle(target):
    global table 
    tmp = bin(int(target,16))[2:]
    b = '0'*(24-len(tmp))+tmp
    #print b
    return table[(int(b[2:8],2)+63)%64]+table[(int(b[12:16]+b[0:2],2)+63)%64]+table[(int(b[22:24]+b[8:12],2)+63)%64]+table[(int(b[16:22],2)+63)%64]
path = r'key1.enc'
content = file(path).read()
flag = ''
flag1 = ''
for i in range(0,len(content),3):
    flag+=handle(content[i:i+3].encode('hex'))
print flag

然后得到结果是

hhhhhqqqqKeyd9733c070b2138e5fsssfffffff"""""""""""""

肯定不对劲,然后看看

h -> >
q -> {
s -> }
f -> >
" -> 空字符

最终结果

>>>>>{{{{Keyd9733c070b2138e5f}}}<<<<<<<

这个题目水平还是挺高的(对于我这种垃圾来说)





























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值