加密脚本分析—evil.py

1.题目

源文件

一共两个文件

enc_flag.txt

evil.py(原文件无注释)

 1 # coding: utf-8
2
3 import base64
4 import string
5 import random
6 import hashlib
7
8 #第二调用
9 def random_str(length=4, chars=string.ascii_lowercase):
10 words = ''
11 chars_len = len(chars) - 1
12 for i in range(length):
13 words += chars[random.randint(0, chars_len)]#随机获取小写英文字符
14 return words
15
16 #第三调用,使用key的md5值对加密过后的flag进行第二次异或加密
17 def key_crypt(data, key):
18 md5 = hashlib.md5()
19 md5.update(key.encode())
20 key_md5 = md5.hexdigest()
21 key_index = 0
22 cipher_data = ''
23 for i in range(len(data)):
24 key_index = 0 if key_index == 32 else key_index#无用,key_index第一次被赋值为0后就没有任何改变了
25 cipher_data += chr(ord(data[i]) ^ ord(key_md5[key_index]))
26 return cipher_data
27
28 #第一调用
29 def encrypt(plain_data, key):#('flag{fake_flag}', 'SK1llS_KeY')
30 rnd = random_str(32)#调用第二函数,获取随机的32位字符串
31 plain_data_len = len(plain_data)
32 rnd_index = 0
33 cipher_data = ''
34 for i in range(plain_data_len):#使用第二函数返回的32位字符串加密flag
35 rnd_index = 0 if rnd_index == 32 else rnd_index#无用,rnd_index第一次被赋值为0后就没有任何改变
36 cipher_data += rnd[rnd_index] + chr(ord(plain_data[i]) ^ ord(rnd[rnd_index]))
37 return base64.b64encode(key_crypt(cipher_data, key).encode()).decode()#调用第三函数二次加密flag并将二次加密后的flag转base64
38
39 #主函数
40 cipher = encrypt('flag{fake_flag}', 'SK1llS_KeY')
41 with open('enc_flag.txt', 'w') as f:
42 f.write(cipher)

2.解题过程

很明显encrypt的第一个参数就是要加密的flag,代码中的flag是假的但是我们可以使用ta来进行实验!

首先大体的观看代码并写下注释以便后续逆向

想要获得原来的flag需要知道三个必要条件“flag的长度”、“key”和“rnd”

key就直接写在代码上了“SK1llS_KeY”

直接cv key_crypt函数即可,因为key_crypt是使用key的md5值与第一次加密后的flag进行异或的,所以我们使用base64解码后的flag在次加密一次就可以获得第一次加密后的flag了

 1 import base64
2 import hashlib
3
4 flag = "HHoccBx9HHscZxwuHC0cKBwvHCwcKhwpHC4cLRwvHHgceRwuHHgcKhwvHCQcKhx5HCUcKBwrHC8cehwkHHoceBwlHH4cfhwpHHgcYQ=="
5 key = "SK1llS_KeY"
6
7 def key_crypt(data, key):
8   md5 = hashlib.md5()
9   md5.update(key.encode())
10   key_md5 = md5.hexdigest()
11   key_index = 0
12   cipher_data = ''
13   for i in range(len(data)):
14     key_index = 0 if key_index == 32 else key_index
15     cipher_data += chr(ord(data[i]) ^ ord(key_md5[key_index]))
16   return cipher_data
17 print(key_crypt(base64.b64decode(flag).decode(),key).encode())

输出

可以发现这串字符里有很多的y,在联想到第一函数的异或加密

1 def encrypt(plain_data, key):#('flag{fake_flag}', 'SK1llS_KeY')
2 rnd = random_str(32)#调用第二函数,获取随机的32位字符串
3 plain_data_len = len(plain_data)
4 rnd_index = 0
5 cipher_data = ''
6 for i in range(plain_data_len):#使用第二函数返回的32位字符串加密flag
7 rnd_index = 0 if rnd_index == 32 else rnd_index#无用,rnd_index第一次被赋值为0后就没有任何改变
8 cipher_data += rnd[rnd_index] + chr(ord(plain_data[i]) ^ ord(rnd[rnd_index]))
9 return base64.b64encode(key_crypt(cipher_data, key).encode()).decode()#调用第三函数二次加密flag并将二次加密后的flag转base64
  • cipher_data += rnd[rnd_index] + chr(ord(plain_data[i]) ^ ord(rnd[rnd_index]))

每次循环都在异或后的flag前面加上一个字符,所以确定当时加密这一段flag时随机生成的32位字符串的第0位为“y”

论证:

通过flag的头是“flag{”并稍微修改一下代码

 1 def encrypt(plain_data, key):
2   for o in string.ascii_lowercase:
3     rnd = [o]
4     plain_data_len = len(plain_data)
5     rnd_index = 0
6     cipher_data = ''
7     for i in range(plain_data_len):
8       rnd_index = 0 if rnd_index == 32 else rnd_index
9       cipher_data += rnd[rnd_index] + chr(ord(plain_data[i]) ^ ord(rnd[rnd_index]))
10     print(o+':'+base64.b64encode(key_crypt(cipher_data, key).encode()).decode())
11 cipher = encrypt('flag{fake_flag}', 'SK1llS_KeY')

可以发现rnd为“y”的加密flag头几个字符与最终的flag头几个字符一模一样,所以可以确定rnd就是“y”

将解密的flag按照y为头排成多列,有14列,所以确定循环异或了14遍

将分成的多列转成数组再用修改后的第一函数异或即可

 1 def encrypt():
2   rnd = ['y']
3   rnd_index = 0
4   cipher_data = ''
5   for i in list:
6     rnd_index = 0 if rnd_index == 32 else rnd_index
7     cipher_data += chr(ord(i) ^ ord(rnd[rnd_index]))
8   print(cipher_data)
9 list = ['\x1f','\x15','\x18','\x1e','\x02','K','H','M','J','I','O','L','K','H','J','\x1d','\x1c','K','\x1d','O','J','A','O','\x1c','@','M','N','J','\x1f','A','\x1f','\x1d','@','\x1b','\x1b','L','\x1d','\x04']
10 encrypt()

获得flag

加密脚本分析—evil.py的更多相关文章

  1. Selenium 2自动化测试实战33(带unittest的脚本分析)

    带unittest的脚本分析 #test.py #coding:utf-8 from selenium import webdriver from selenium.webdriver.common. ...

  2. 一段shell脚本分析

    工作中碰到这样的需求: 1.每天定时要执行python脚本生成excel 2.将生成的excel拷贝到特定目录下 3.通过python发送脚本发送给特定的接收者 因为之前没有接触过shell脚本,同事 ...

  3. Selenium(十七):unittest单元测试框架(三) 脚本分析、编写Web用例

    1. 带unittest的脚本分析 也许你现在心里还有疑问,unittest框架与我们前面所编写的Web自动化测试之间有什么必然联系吗?当然有,既然unittest可以组织.运行测试用例,那么为什么不 ...

  4. iredmail安装脚本分析(一)---iRedmail.sh

    iredmail是一套以postfix为核心的整合邮件系统的安装脚本,可以达到快速部署邮件服务器的目的.为了让自己不遗忘shell的语法,所以闲来无事,学习一下他的代码. 我从官网下载他的最新版,解压 ...

  5. busybox rootfs 启动脚本分析(一)

    imx6文件系统启动脚本分析.开机运行/sbin/init,读取/etc/inittab文件,进行初始化. 参考链接 http://blog.163.com/wghbeyond@126/blog/st ...

  6. Spark 个人实战系列(2)--Spark 服务脚本分析

    前言: spark最近非常的火热, 本文不讲spark原理, 而是研究spark集群搭建和服务的脚本是如何编写的, 管中窥豹, 希望从运行脚本的角度去理解spark集群. 研究的spark为1.0.1 ...

  7. 实用防火墙(Iptables)脚本分析

    实用防火墙(Iptables)脚本分析 --Redhat,CentOS,Ubuntu等常见Linux发行版中都会预装Iptables防火墙,大多数初学者设置起来由于对这款软件比较陌生,设置起来比较困难 ...

  8. Hadoop的shell脚本分析

    你会发现hadoop-daemon.sh用于启动单独的本机节点 而hadoop-daemons.sh 会批量的ssh到别的机器启动 前记: 这些天一直学习hadoop,学习中也遇到了许多的问题,主要是 ...

  9. uboot 连接脚本分析

    一.脚本分析 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm ...

  10. HBase配置&启动脚本分析

    本文档基于hbase-0.96.1.1-cdh5.0.2,对HBase配置&启动脚本进行分析 date:2016/8/4 author:wangxl HBase配置&启动脚本分析 剔除 ...

随机推荐

  1. spring session + redis实现共享session

    一.代码 1.pom.xml <!--spring session--> <dependency> <groupId>org.springframework.boo ...

  2. ssh连接不上、Xshell意外关闭Socket error Event: 32 Error: 10053.

    Xshell意外关闭可能会出现这种问题,如遇如下错误可解决: Connecting to 47.106.80.28:22- Connection established. To escape to l ...

  3. MarkDown初次见面——

    Markdown基础语法 分级标题 n级标题就在前面加n个#即可,但是仅支持到六级标题. 字体 柔骨兔 字体倾斜:左右两边加1个* 柔骨兔 字体加粗:左右两边各自添加2个* 柔骨兔 倾斜加粗:左右两边 ...

  4. TensorFlow架构

    Tensorflow基本信息 Tensorflow所需处理器 CPU,GPU,TPU(Google为AI研发的专用芯片) 平台 Windows,Linux,Android,iOS,Raspberry ...

  5. tomcat 重启脚本

    1 创建脚本后将脚本放到tomcat/bin目录下并授权,就可以通过此脚本一键重启拉! #!/bin/bash tomcat_path1="$( cd "$( dirname &q ...

  6. js小数相加精度不准确

    例: 0.1+0.1+0.1+0.7 != 1 0.1+0.2 != 0.3 解决办法: 相加 function addNum(num1, num2) {         let sq1, sq2; ...

  7. zxb2022习题班26

    (1) 购买日是2x21年12月31日, 理由:从该日起,甲公司能够控制乙公司的财务和经营决策:该项交易后续不存在实质性障碍. 商誉=10*10000-100000*80%=20000 相关会计分录: ...

  8. RKO组——冲刺随笔(1)

    这个作业属于哪个课程 至诚软工实践F班 这个作业要求在哪里 第五次团队作业:项目冲刺 这个作业的目标 记录冲刺计划.要求包括当天会议照片.会议内容以及项目燃尽图(项目进度) 1.昨日进展 小组成员讨论 ...

  9. cpu的调度

    什么是cpu的调度 所谓 CPU 调度,就是确定把哪个处于淮备就绪状态的进程移入运行状态.也就是说,CPU调度算法将决定把 CPU 给予哪个进程,以便它能够运行. 两种调度方式 CPU 调度可以是在一 ...

  10. hbase master 无法启动

    环境部署: hbase 采用azure的虚机,存储采用azure的blockblob. 问题: 生产碰到过几次,hbase master无法启动的问题,这种情况下是可以正常读写,但是如果这个时候,发生 ...