一道Py杂项题 bitwise


PW给的一道CTF题,由于实验吧把这一道题目归类于逆向,实际上感觉还是考察Python基础的,现在感觉以前的题目好简单呀。

题目

You see the doors to the loading bay of the hangar, but they are locked. However, you are able to extract the password verification program from the control panel… Can you find the password to gain access to the loading bay?
翻译

你可以看到机库的装货门,但是它们被锁上了。但是,您可以从控制面板中提取密码验证程序…你能找到进入装货港的密码吗?

附件

bitwise.py

#!/usr/bin/env python
user_submitted = raw_input("Enter Password: ")

if len(user_submitted) != 10:
  print "Wrong"
  exit()


verify_arr = [193, 35, 9, 33, 1, 9, 3, 33, 9, 225]
user_arr = []
for char in user_submitted:
  # '<<' is left bit shift
  # '>>' is right bit shift
  # '|' is bit-wise or
  # '^' is bit-wise xor
  # '&' is bit-wise and
  user_arr.append( (((ord(char) << 5) | (ord(char) >> 3)) ^ 111) & 255 )

if (user_arr == verify_arr):
  print "Success"
else:
  print "Wrong"

bitwise.java

import java.util.*;

public class Main {
    public static void main(String[] args) {
        System.out.print("Enter Password: ");
        Scanner s = new Scanner(System.in);
        String user_key = s.next();
        if (user_key.length() == 10) {
            System.out.println("Wrong");
            return;
        }

        char[] verify_arr = {193, 35, 9, 33, 1, 9, 3, 33, 9, 225};

        ArrayList<Character> user_arr = new ArrayList<Character>();
        char[] user_submitted_arr = user_key.toCharArray();
        System.out.println(user_submitted_arr.length);

        for (char ch : user_submitted_arr) {
            user_arr.add((char)((((ch << 5) | (ch >> 3)) ^ 111) & 255));
            System.out.println(user_arr);
        }

        int i;
        for(i = 0; i < 10; i++) {
            if (!user_arr.get(i).equals((char)verify_arr[i])) {
                System.out.println("Wrong");
                return;
            }
        }
        System.out.println("Success");
    }
}

思路

由于本人Java水平一般般这里就不去解读Java代码了,所以来直接阅读Python代码。

简单分析代码

这里我在源代码基础上 直接加上注释吧,方便阅读

#!/usr/bin/env python
user_submitted = raw_input("Enter Password: ")
# 提示输入密码并记录此刻用户的输入值  用户输入的密码值 存入 user_submitted 变量中

if len(user_submitted) != 10:
  print "Wrong"
  exit()
# 如果用户输入的密码长度不是10位 输出 Wrong 并结束程序

verify_arr = [193, 35, 9, 33, 1, 9, 3, 33, 9, 225]
# 定义一个数组 verify_arr 用来验证作用
user_arr = []
# 定义并初始化一个 user_arr 数组变量

for char in user_submitted:
# 循环提取user_submitted变量中的字符
  # '<<' is left bit shift
  # '>>' is right bit shift
  # '|' is bit-wise or
  # '^' is bit-wise xor
  # '&' is bit-wise and
  user_arr.append( (((ord(char) << 5) | (ord(char) >> 3)) ^ 111) & 255 )
# 对这个字符进行 加密处理 这里是核心加密代码,加密后的代码放入user_arr这个变量里面
if (user_arr == verify_arr):
# 拿user_arr与验证数组verify_arr 来做判断 输入正确或者错误
  print "Success"
else:
  print "Wrong"

突破

这一题目的代码很容易理解,从代码中可以看出这一题想让我们写出正确的密码,flag 就是密码值。
一次性还原出10位数密码有点难度,这里我的思路是11位的去还原。

POC代码第一版

第一版代码比较繁琐,手工输入字典,然后手工一位一位的来破解,效率不是很高,虽然最后也可以解出密码来。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
zidian =['{','}','[',']','\'','|',';',':','"',',','<','>','.','/','?','0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','!','!','@','#','$','^','&','*','(',')','-','+']
jiami = (int)(input("请输入被加密后的密文:"))
for i in range(0,(len(zidian)-1)):
  g = ( (((ord(zidian[i]) << 5) | (ord(zidian[i]) >> 3)) ^ 111) & 255 )
  if (g == jiami):
      print("密码原文是")
      print (zidian[i])

效果演示

POC代码第二版

我们每次破解还原1位密码还得重新来运行这个脚本,现在思考能不能一直循环的来运行呢?

#!/usr/bin/env python
# -*- coding:utf-8 -*-
zidian =['{','}','[',']','\'','|',';',':','"',',','<','>','.','/','?','0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','!','!','@','#','$','^','&','*','(',')','-','+']
while(1):
    jiami = (int)(input("请输入被加密后的密文:"))
    for i in range(0,(len(zidian)-1)):
        g = ( (((ord(zidian[i]) << 5) | (ord(zidian[i]) >> 3)) ^ 111) & 255 )
        if (g == jiami):
            print("密码原文是")
            print(zidian[i])
            panduan = raw_input("是否继续输入?[Y/N]")
            if(panduan == 'N' or panduan =='n'):
                print("Bye Bye~")
                exit()

效果演示

可以看到效率提高了很多,尤其是在密码位数比较多的情况下就会显示出差距了。

POC代码第三版

这个脚本用起来还不够方便,因为是一位一位去破解的,而且最后为了拿到密码值,我们还得一位一位的拼接起来,现在思考能不能最后把密码值完全拼接好再print出来呢?

#!/usr/bin/env python
# -*- coding:utf-8 -*-
zidian =['{','}','[',']','\'','|',';',':','"',',','<','>','.','/','?','0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','!','!','@','#','$','^','&','*','(',')','-','+']
jieguo = []
while(1):
    jiami = (int)(input("请输入被加密后的密文:"))
    for i in range(0,(len(zidian)-1)):
        g = ( (((ord(zidian[i]) << 5) | (ord(zidian[i]) >> 3)) ^ 111) & 255 )
        if (g == jiami):
            print("密码原文是")
            print(zidian[i])
            jieguo.append(zidian[i])
            panduan = raw_input("是否继续输入?[Y/N]")
            if(panduan == 'N' or panduan =='n'):
                print("Bye Bye~")
                print("最后的密码是:")
                print(jieguo)
                exit()  

效果演示

关于第N个版本

当然目前来看这个POC验证代码在用户体验上还不是那么友好而且代码中zidian这个在代码中显得过于臃肿。后期肯定还是可以再完善这个代码的。后期的改进方向:

  • 从文件中加载字典
  • 1次性输入全部密码 然后解密
  • 图形化界面
  • WEB界面
  • 添加修改算法规则,灵活破解‘

当然真正要全部实现这些功能的话,在Python代码上面还得多多的下功夫才可以。↖(^ω^)↗加油


文章作者: 国光
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 国光 !
 上一篇
一次对南师大的校园网认证系统的逻辑漏洞测试 一次对南师大的校园网认证系统的逻辑漏洞测试
记录了最近在南师大对其校园网逻辑漏洞测试中的一些有趣曲折的点 前言最近常来南京师范大学(随园校区)这边玩,来感受一下研究生们的学霸学习氛围~ 作为一名职业网民,打开电脑的第一件事当然就是来连接周围的WiFi啦。南师大的WiFi是校园网全校
2017-11-18
下一篇 
用户密码重置找回10种常见姿势 用户密码重置找回10种常见姿势
本篇文章是参考大神carry_your讲师(360补天排名第一)的任意用户密码重置的10种常见姿势总结的笔记。原视频地址:https://www.ichunqiu.com/course/59045 介绍本次课程主要针对挖掘逻辑漏洞中的
2017-10-26
  目录