攻防世界zorropub题解与subprocess模块

目录

题目分析:

subprocess模块:

subprocess.Popen()函数:

subprocess.run()函数:

题目脚本:


在攻防世界做到一个题目感觉还挺有意思,记录一下

这个放链接也只是攻防世界的页面,所以直接说题目地址是在攻防世界->Reverse模块->难度3->zorropub.

参考文章:zorropub 攻防世界_北风~的博客-CSDN博客

                    攻防世界 zorropub_路途之后是路途的博客-CSDN博客

题目分析:

下面进入正题:)

在IDA中打开附件,找到主函数

int sub_4009BD()
{__int64 v0; // raxint input_number; // [rsp+1Ch] [rbp-104h] BYREFint input; // [rsp+20h] [rbp-100h] BYREFint i; // [rsp+24h] [rbp-FCh]unsigned int seed; // [rsp+28h] [rbp-F8h]unsigned int v6; // [rsp+2Ch] [rbp-F4h]char v7[96]; // [rsp+30h] [rbp-F0h] BYREFchar v8[16]; // [rsp+90h] [rbp-90h] BYREFchar v9[32]; // [rsp+A0h] [rbp-80h] BYREFchar s[32]; // [rsp+C0h] [rbp-60h] BYREFchar s1[40]; // [rsp+E0h] [rbp-40h] BYREFunsigned __int64 v12; // [rsp+108h] [rbp-18h]v12 = __readfsqword(0x28u);seed = 0;puts("Welcome to Pub Zorro!!");printf("Straight to the point. How many drinks you want?");__isoc99_scanf("%d", &input_number);if ( input_number <= 0 ){printf("You are too drunk!! Get Out!!");exit(-1);}printf("OK. I need details of all the drinks. Give me %d drink ids:", input_number);// 输入数字for ( i = 0; i < input_number; ++i ){__isoc99_scanf("%d", &input);if ( input <= 16 || input > 0xFFFF ){puts("Invalid Drink Id.");printf("Get Out!!");exit(-1);}seed ^= input;                              // 根据输入的数字大小输入对应的drink_id,并且与seed异或}i = seed;v6 = 0;while ( i ){++v6;i &= i - 1;                                 // 判断一个数的二进制形式中含有多少个1}if ( v6 != 10 ){puts("Looks like its a dangerous combination of drinks right there.");puts("Get Out, you will get yourself killed");exit(-1);}srand(seed);MD5_Init(v7);for ( i = 0; i <= 29; ++i ){v6 = rand() % 1000;                         // 取随机数sprintf(s, "%d", v6);v0 = strlen(s);MD5_Update(v7, s, v0);                      // MD5加密v9[i] = v6 ^ LOBYTE(dword_6020C0[i]);}v9[i] = 0;MD5_Final(v8, v7);for ( i = 0; i <= 15; ++i )sprintf(&s1[2 * i], "%02x", v8[i]);if ( strcmp(s1, "5eba99aff105c9ff6a1a913e343fec67") )// 此处传的是加密结果的前16位{puts("Try different mix, This mix is too sloppy");exit(-1);}return printf("\nYou choose right mix and here is your reward: The flag is nullcon{%s}\n", v9);
}

函数先是要求输入一个数字a,再输入a个dring_id号,要求大小在16~0xffff之间,并且将这些id号与种子值seed异或,下面的一个while循环时判断seed值的,i&=i-1用来判断一个数的二进制形式中1的个数,也就是要求seed值的二进制形式里要有10个1 .

 接下来就是取30个随机数v6进行MD5加密,传MD5加密结果的前16位来进行判断是否相等,最后的flag就是v6异或数组dword_6020C0的值,这里%02x是以是十六进制形式表示,不足两位的补0

本来是想爆破v6的,还是没搞懂MD5加密,MD5加密,无论输入有多长,输出总是128位也就是32个16进制数,这里传的只是加密结果的前16位。不过也还是可以爆破的,不是从MD5爆破的就是了,看其他大佬的wp才知道可以使用subprocess模块,学到了

subprocess模块:

参考文章:python subprocess模块 - lincappu - 博客园 (cnblogs.com)

                 subprocess  (这个b站的视频也不错)

subprocess模块是Python中自带的一个模块,可以在父进程中创建一个子进程,允许在python中执行外部命令并与其进行交互。嗯我的理解是在一个程序中实现与另一个程序进行输入输出的交流,就类似于我们写一个自动脚本模拟我们与另一个程序进行交流的情况。(个人理解)

subprocess模块包含几个核心函数,这些函数方便启动和控制子进程

subprocess.Popen()函数:

这个函数是subprocess模块最核心,最底层的函数,用于创建一个子进程,可以在该对象上调用方法来与子进程进行交互

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, 
preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, 
startupinfo=None, creationflags=0,restore_signals=True, start_new_session=False, pass_fds=(),
*, encoding=None, errors=None)
  • args:shell命令,可以是字符串或者序列类型(如:list,元组)
  • bufsize:缓冲区大小。当创建标准流的管道对象时使用,默认-1。
    0:不使用缓冲区
    1:表示行缓冲,仅当universal_newlines=True时可用,也就是文本模式
    正数:表示缓冲区大小
    负数:表示使用系统默认的缓冲区大小。
  • stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
  • preexec_fn:只在 Unix 平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
  • shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令。
  • cwd:用于设置子进程的当前目录。
  • env:用于指定子进程的环境变量。如果 env = None,子进程的环境变量将从父进程中继承。

创建一个子进程,然后执行一个简单的命令:

subprocess.run()函数:

.run函数是python3.5之后出现的一个函数,其底层接口还是Popen,不过会更方便,用于运行一个外部命令,等待它完成并返回结果。

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)

  • args:表示要执行的命令。必须是一个字符串,字符串参数列表。
  • stdin、stdout 和 stderr:子进程的标准输入、输出和错误。其值可以是 subprocess.PIPE、subprocess.DEVNULL、一个已经存在的文件描述符、已经打开的文件对象或者 None。subprocess.PIPE 表示为子进程创建新的管道。subprocess.DEVNULL 表示使用 os.devnull。默认使用的是 None,表示什么都不做。另外,stderr 可以合并到 stdout 里一起输出。
  • timeout:设置命令超时时间。如果命令执行时间超时,子进程将被杀死,并弹出 TimeoutExpired 异常。
  • check:如果该参数设置为 True,并且进程退出状态码不是 0,则弹 出 CalledProcessError 异常。
  • encoding: 如果指定了该参数,则 stdin、stdout 和 stderr 可以接收字符串数据,并以该编码方式编码。否则只接收 bytes 类型的数据。
  • shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令。

 一般的话使用stdin,stdout比较多

补充:

Popen.communicate(): 用于与子进程进行输入输出交互,向子进程发送数据并获取输出结果。

  1. Popen.stdin, Popen.stdout, Popen.stderr: 分别代表子进程的标准输入、标准输出和标准错误输出。

  2. Popen.wait(): 等待子进程结束,并返回其返回码。

  3. 使用时要导入subpeocess ,比如import subprocess这样

import subprocess  #
import shlex  # 帮助分隔命令process = subprocess.run(shlex.split("python 解密脚本.py"))  # subprocess.run接口
print(process)
# returncode=0表示调用成功,不为0表示调用失败# subprocess.Popen不会阻断整个程序的运行
process = subprocess.Popen(['python', '解密脚本.py'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,stdin=subprocess.PIPE)
# shell表示终端,表示前面的Tree命令要在终端出运行,
# stdout=subprocess.PIPE,其中subprocess.PIPE表示创建一个管道,令stdout=subprocess.PIPE表示命令正常执行的结果丢到stdout这个管道里
# stderr表示命令执行出错的结果丢到这里,注意subprocess.PIPE每次都会创建一个新的管道,会得到一个对象obj接住这个对象
# stdin=subprocess.PIPE表示输入
res = process.stdout.read()  #读取管道信息
print(res.decode('utf-8'))  # 打印出正确执行的结果
process.stdin.write('yes\n'.encode())  # 向Py脚本输入数据使用此。encode表示转为byte类型,模拟与终端的交互
process.stdin.flush()  # 写入
print(process.stdout.read())

下面那这题作为例子具体介绍一下吧

题目脚本:

我们现在需要知道的就是随机数的值,因为没法利用MD5爆破所以只能利用程序自身了,我们知道只要得到符合要求的seed值,就可以进入下面随机数生成的部分,而固定的seed+固定的随机数算法=生成固定的随机数,所以我们只需要看哪一个符合要求的随机数种子得到的随机数是符合最后的加密结果就可以(感觉说的有点绕....就是找到所有符合要求的seed(编写脚本爆破找)->一个一个输入到程序中测试(这一块就可以使用subprocess来搞,手动输入当然是很麻烦)->看哪个seed是可以得到最后结果的)

注意:因为drink_id是在16~0xffff范围,而初始值位0的seed值和他们异或之后的最终结果也是在16~0xffff范围,这样的话,就方便爆破了。

#!/usr/bin/python
# -*- coding: utf-8 -*-
from subprocess import *# 这里是找出符合条件的数                           //这部分是先找到符合要求的数,即最后的seed,因为我们可以知道input在16到0xffff范围内,那么seed=0循环异或
# 原函数对种子的加密                               //的结果seed也是在这个范围内,那么当循环的次数最少的时候是不是就是找最后seed最简单的时候?,而且也是直接通过进程
a = []
for i in range(16, 65535):v9 = 0s = iwhile i:v9 += 1i &= i - 1if v9 == 10:a.append(s)                              //找出所有符合条件的值,可能不止一个,添加到a列表中
# 循环输入符合条件的数,爆破flag
for i in a:                                        //在符合第一个判断条件a列表中来和程序进行交互,看哪一个数的的输出结果包含flag,就打印这个数proc = Popen(['./87356aae634e4e0a9a081f30fc81fe16'], stdin=PIPE, stdout=PIPE)#PIPE表示新建输入输出管道,便于下面对管道的读取,若为none会直接在运行窗口输出,无法对其进行操作out = proc.communicate(('1\n%s\n' % i).encode('utf-8'))[0]#1\n%s\n表示喝一瓶饮料,id号为i,将i转为字符串加入其中,与'1\n%d\n' % i一样# 这里communicate与子进程进行输入输出交互,返回的是一个元组,但是元组只有一个元素,所以要加上偏移0,1为标准错误if "nullcon".encode('utf-8') in out:print(out)print(i)

这个脚本需要在linux中运行,但是在因为版本问题,在ubuntu里运行的时候会报错no such file or dictionary,后来问其他大佬,可能是libcrypto版本要求为1.0.0,所以我是运行不了....

最后的输出结果是

nullcon{nu11c0n_s4yz_x0r1n6_1s_4m4z1ng}

当然也可以直接爆破seed的值,然后手动运行程序输入input_number为1,再手动输入seed值拿到结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/18957.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI技术快讯:清华开源ChatGLM2双语对话语言模型

ChatGLM2-6B是一个开源项目&#xff0c;提供了ChatGLM2-6B模型的代码和资源。根据提供的搜索结果&#xff0c;以下是对该项目的介绍&#xff1a; 论文&#xff1a;https://arxiv.org/pdf/2103.10360.pdf ChatGLM2-6B是一个开源的双语对话语言模型&#xff0c;是ChatGLM-6B模…

0802|IO进程线程day5 作业(打印时钟在终端上,若终端输入quit,结束时钟)

作业1&#xff1a;守护进程 守护进程的创建&#xff08;5步&#xff09;&#xff1a; 创建孤儿进程&#xff1a;所有工作都在子进程中执行&#xff0c;从形式上脱离终端控制。 fork(), 退出父进程 创建新的会话组&#xff1a;使子进程完全独立出来&#xff0c;防止兄弟进程对其…

Python集成开发环境IDE:Spyder自动换行、函数列表outline、代码折叠

Spyder是一个用PythonQt编写的集成开发环境&#xff0c;包含许多有用的函数和工具。以下是一些常用功能&#xff1a; 变量浏览器&#xff1a;可以动态交互并修改变量&#xff0c;可以进行绘制直方图、时间序列&#xff0c;编辑日期框架或Numpy数组&#xff0c;对集合进行排序&…

【python】两数之和 python实现(详细讲解)

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

【Java可执行命令】(十三)策略工具policytool:界面化创建、编辑和管理策略文件中的权限和配置 ~

Java可执行命令之policytool 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 使用方式3.2 使用技巧3.3 注意事项 4️⃣ 应用场景&#x1f33e; 总结 1️⃣ 概念 在Java平台上&#xff0c;安全性是至关重要的。为了提供细粒度的安全管理机制&#xff0c;Java引入了policytool命令。p…

cmake使用笔记

vim CMakeLists.txt mkdir build cd build cmake ..创建 CMakeLists.txt&#xff0c;添加内容 cmake_minimum_required(VERSION 3.26) #工程名称 project(hello) #宏定义 add_definitions(-D宏名称) #头文件路径 include_directories(${PROJECT_SOURCE_DIR}/inc) #搜索源文件…

Python爬虫教程篇+图形化整理数据(数学建模可用)

一、首先我们先看要求 1.写一个爬虫程序 2、爬取目标网站数据&#xff0c;关键项不能少于5项。 3、存储数据到数据库&#xff0c;可以进行增删改查操作。 4、扩展&#xff1a;将库中数据进行可视化展示。 二、操作步骤&#xff1a; 首先我们根据要求找到一个适合自己的网…

Socket本质、实战演示两个进程建立TCP连接通信的过程

文章目录 Socket是什么引入面试题, 使你更深刻的理解四元组 Socket网络通信大体流程实战演示TCP连接建立过程需要用到的linux 查看网络的一些命令测试的程序一些准备工作启动服务端, 并没有调用accept启动客户端开启服务accept Socket是什么 通俗来说,Socket是套接字,是一种编…

InnoDB引擎底层逻辑讲解——架构之磁盘架构

1. System Tablespaces区域 系统表空间是change buffer&#xff08;更改缓冲区&#xff09;的存放区域&#xff0c;这是在8.0之后重新规划的&#xff0c;在5.x版本的时候&#xff0c;系统表空间还会存放innodb的数据字典undolog日志等信息&#xff0c;在8.0之后主要主要存放更…

Gitlab CI/CD笔记-第一天-GitOps和以前的和jenkins的集成的区别

一、GitOps-CI/CD的流程图 简单解释&#xff1a; 1.提交代码 2.编译构建 3.测试 4.部署 二、gitlab的实现 1、Runer 1.这个就是jenkins里的worker-slave的角色&#xff0c; 2.git-lab server 下发任务&#xff0c;Runner执行。 3.这个R…

关于样本方差为什么除以 n-1

今天上午集训摸鱼看到同学给我发的这个问题感觉挺有意思的 感性理解 这一部分的内容仅代表本蒟蒻没看严谨证明之前的个人见解&#xff0c;如果您想看严谨的证明&#xff0c;请翻到下一部分 还是先把图放上来罢省的有人不知道讲的什么东西 呃我知道这是生物竞赛的东西&#…

下载列表视频的具体操作

主要是介绍怎样获取上篇博客需要的HAR文件和请求域名

docker: Error response from daemon: No command specified.

执行 docker run -it -d -v /home/dell/workspace/workspace/test_192.168.1.202_pipeline:/home/workspace1 --name test_192.168.1.202_pipeline_10 qnx:7.1报错 问题定位&#xff1a;export导入的镜像需要带上command&#xff0c;以下命令查看command信息 docker ps --no…

十进制、八进制、二进制、十六进制

十进制 每一位都有 0~9 十个数码&#xff0c;逢十进一 二进制 每一位仅有 0 和 1 两个数码&#xff0c;逢二进一 八进制 每一位都有 0~7 八个数码&#xff0c;逢八进一 十六进制 每一位都有 0~9、A(10)、B(11)、C(12)、D(13)、E(14)、F(15)&#xff0c;十六个数码&#…

牛客网Verilog刷题——VL53

牛客网Verilog刷题——VL53 题目答案 题目 设计一个单端口RAM&#xff0c;它有&#xff1a; 写接口&#xff0c;读接口&#xff0c;地址接口&#xff0c;时钟接口和复位&#xff1b;存储宽度是4位&#xff0c;深度128。注意rst为低电平复位。模块的接口示意图如下。 输入输出描…

【A200】Ubuntu18.04 + ROS-Melodic + 比业电子VISIOSCAN雷达 评测

大家好&#xff0c;我是虎哥&#xff0c;朋友介绍&#xff0c;有一款单线激光雷达&#xff0c;25米的检测距离&#xff0c;有80HZ的扫描频率&#xff0c;而且角度分辨率最高可以到0.1&#xff0c;这个参数我确实没有见过&#xff0c;所以立刻着手从厂家那申请到了VISIOSCAN雷达…

JVM基础篇-虚拟机栈

JVM基础篇-虚拟机栈 定义 Java Virtual Machine Stacks &#xff08;Java 虚拟机栈&#xff09; 每个线程运行时所需要的内存&#xff0c;称为虚拟机栈每个栈由多个栈帧&#xff08;Frame&#xff09;组成&#xff0c;对应着每次方法调用时所占用的内存每个线程只能有一个活动…

机房断网断电监测网关支持远程告警

RTU5028E网络故障监测终端是一款功能强大且方便实用的设备&#xff0c;集合了断网、断电、网线故障报警功能。它支持同时监测多达7台网络设备&#xff0c;可以帮助用户快速定位远程网络设备离线的原因。此外&#xff0c;它还具备自动重启和远程重启网络设备的功能&#xff0c;为…

思科模拟器配置静态路由(下一跳使用IP)

Router0配置代码&#xff1a;##端口配置 Router(config)#int fastEthernet 0/0 Router(config-if)#ip address 192.168.10.254 255.255.255.0 Router(config-if)#no shutdown Router(config-if)#int fastEthernet 0/1 Router(config-if)#ip address 192.168.20.1 255.255.255.2…

深度剖析数据在内存中的存储

目录 数据类型介绍 类型的基本归类 整形家族: 浮点数家族: 构造类型: 指针类型 空类型: 整形在内存中的存储 原码、反码、补码 大小端介绍 什么大端小端: 为什么有大端和小端: 练习 浮点型在内存中的储存 一个例子 浮点数存储规则 数据类型介绍 前面我们…