180626 逆向-SUCTF(Python大法好)

时隔许久详细的复现一下~

这个题目也挺有意思的,刺激学了一遍pyc233

题目提供了一份opcode.txt、elf二进制程序a和一个密文cipher.txt

opcode打开来可以发现是pyc的解析

虽然有code,但是试着用python解析了一下发现有点复杂

读opcode是不可能的,这辈子都不可能的
本来读起来就麻烦,缺少符号信息就更恐怖了,更别说还有lambda和join等等骚方法了

思路转为根据一些关键词来搜索,试图找到该文件的生成方法和逆转换方法。毕竟只要能得到pyc就能通过uncompyle的工具还原出源码

搜了一下找到了几乎完全一样的脚本

然后拿一个正常的pyc打了一份解析出来,对照发现除了code的disassembly以外什么都不缺,这也就意味着根据上述信息是可以还原出pyc的

根据pyc的解析和解析来反填写pyc

比赛的时候是手动搞的,懒得写脚本操作了,本来都不熟悉再出什么bug调起来更慢2333

pyc整体是4字节版本标识+4字节时间戳+一个PyCodeObject。PyCodeObject的内部由若干成员组成。
每个成员的第一个字节是类型标识,然后四个字节表示长度,接着依次列举内部的各个成员

类型标识如下

#define TYPE_NULL               '0'  
#define TYPE_NONE               'N'  
#define TYPE_FALSE              'F'  
#define TYPE_TRUE               'T'  
#define TYPE_STOPITER           'S'  
#define TYPE_ELLIPSIS           '.'  
#define TYPE_INT                'i'  
#define TYPE_INT64              'I'  
#define TYPE_FLOAT              'f'  
#define TYPE_BINARY_FLOAT       'g'  
#define TYPE_COMPLEX            'x'  
#define TYPE_BINARY_COMPLEX     'y'  
#define TYPE_LONG               'l'  
#define TYPE_STRING             's'  
#define TYPE_INTERNED           't'  
#define TYPE_STRINGREF          'R'  
#define TYPE_TUPLE              '('  
#define TYPE_LIST               '['  
#define TYPE_DICT               '{'  
#define TYPE_CODE               'c'  
#define TYPE_UNICODE            'u'  
#define TYPE_UNKNOWN            '?'  
#define TYPE_SET                '<'  
#define TYPE_FROZENSET          '>'

PyCodeObject的类型标识符是’c’,即0x63

接下来依次是4个参数,argcount, nlocals, stacksize, flags,每个参数4字节小端序表示

然后是co_code,即opcode的字节流,作为一个string保存。类型标识符为’s’,即0x73
string显然需要len来标识接下来的读取范围,因此4字节表示len,后面len个字节就是bytes啦

再往后是consts常量,它是一个tuple。类型标识符为’(‘,0x28。后面4字节表示tuple的len,即元素个数。然后是依次放置各个元素,通常情况下最大PyCodeObject的consts里还会有PyCodeObject,是一个递归的过程。依次向内解析即可。除此以外还会有None(只需要类型标识符’N’即可,无长度无内容)、Int(类型标识符‘I’+4字节值)、String(如前所述,类型标识符’s’+len+content)等等

consts之后是names、varnames、freevars、cellvars四个tuple,空的tuple长度为0即可,否则字符串照样展开就行

然后是filename和name两个string、firstlineno这个四字节表示的常量(不需要类型标识和长度)以及最后一个string,lnotab

全部输入以后通过marshal即可装载,uncompyle系工具就可以成功将其反编译了

明天写个自动化的工具来递归还原~

得到py后发现其将key转为hex后直接通过cdll.LoadLibrary调用函数……所以我折腾这么半天就是为了得到它是把key转hex的结论?!

逆向二进制程序,发现其中的加密方法比较眼熟,其实就是RC4

流密码没什么攻击方法,只能爆破密钥了

根据*号长度猜测key是8位,从最简单的纯数字入手
多线程爆破,启动!

单线程爆了很久都没反应,多线程倒是秒出(:з」∠)运气真好

你可能感兴趣的:(CTF,CrackMe)