zorropub
seed = 0;
puts("Welcome to Pub Zorro!!");
printf("Straight to the point. How many drinks you want?");
__isoc99_scanf("%d", &drinksNum); // 0
if ( drinksNum <= 0 )
{
printf("You are too drunk!! Get Out!!");
exit(-1);
}
printf("OK. I need details of all the drinks. Give me %d drink ids:", drinksNum);
for ( i = 0; i < drinksNum; ++i ) // drinksNum=1023
{
__isoc99_scanf("%d", &ids_num); // ids_num =1023
if ( ids_num <= 16 || ids_num > 0xFFFF )
{
puts("Invalid Drink Id.");
printf("Get Out!!");
exit(-1);
}
seed ^= ids_num; // seed =0
}
i = seed;
randd = 0;
while ( i ) // i=1023
{
++randd;
i &= i - 1;
}
if ( randd != 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((__int64)ctx);
for ( i = 0; i <= 29; ++i )
{
randd = rand() % 1000;
sprintf(randdd, "%d", randd);
len = strlen(randdd);
MD5_Update(ctx, randdd, len);
v12[i] = randd ^ LOBYTE(dword_6020C0[i]);
}
v12[i] = 0;
MD5_Final(v11, ctx);
for ( i = 0; i <= 15; ++i )
sprintf(&s1[2 * i], "%02x", (unsigned __int8)v11[i]);
if ( strcmp(s1, "5eba99aff105c9ff6a1a913e343fec67") )
{
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", v12);
}
程序使用srand(seed)生成伪随机数。我们可以便携python脚本先找到符合条件的seed。然后爆破进程,把seed一个一个尝试。
i &= i - 1 //清除整数二进制表示中最右侧的1
统计二进制中 1 的个数
int count = 0;
int i = 12; // 1100
while (i != 0) {
i &= i - 1;
count++; // 最终count=2(12的二进制有2个1)
}
subprocess --- 子进程管理
subprocess 模块允许你生成新的进程,连接它们的输入、输出、错误管道,并且获取它们的返回码。
subprocess.Popen
subprocess模块定义了一个类: Popen
class subprocess.Popen( args, #参数,可以是字符串,列表。
bufsize=0, #0表示不缓冲,1表示缓冲
executable=None,#指定要执行的程序
stdin=None, #子进程的标准输入
stdout=None, #子进程的标准输出
stderr=None, #子进程的标准错误
preexec_fn=None,
close_fds=False,
shell=False, #指定命令在shell中解析
cwd=None,
env=None,
universal_newlines=False,
startupinfo=None,
creationflags=0)
- 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 执行指定的命令。
communicate函数
communicate函数用于与子进程进行交互。它在子进程中执行一个命令,并返回两个元素的元组:标准输出和标准错误。
下面是communicate函数的基本用法示例:
import subprocess
# 执行命令
result = subprocess.Popen(["ls", "-l"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# 与子进程进行交互
output, error = result.communicate()
print(output.decode())
print(error.decode())
多个输入和输出
import subprocess
# 执行命令
p = subprocess.Popen(["grep", "hello"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
# 向子进程提供多个输入
input_data = "hello world\ngoodbye world\nhello cat\n"
output = p.communicate(input=input_data.encode('utf-8'))[0]#返回元组,0表示是标准输出,1表示是标准错误
# 从子进程获取多个输出
result = output.decode().strip().split("\n")
print(result)
解题脚本
import subprocess
seed=0
seedd=[]
for ids_num in range(17,0xffff):
seed ^=ids_num
i=seed
randd=0
if i<1023:
continue
while(i):
randd=randd+1
i &= i-1
if randd ==10:
print("ids_num=",ids_num)
seedd.append(ids_num)
for i in seedd:
proc = subprocess.Popen(['./87356aae634e4e0a9a081f30fc81fe16'],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
inputdata='1\n%s\n'%i
out=proc.communicate(input=inputdata.encode('utf-8'))[0]
if 'nullcon'.encode('utf-8') in out:
print(out)
print(i)

浙公网安备 33010602011771号