1024_密码系统

admin 2022年1月5日22:55:56CTF专场评论15 views3890字阅读12分58秒阅读模式

>

>

1024_密码系统

emmmm

1024_密码系统

附件1024sys.py

# -*- coding:utf-8 -*-
# Author:airrudder

from Crypto.Cipher import DES
from binascii import b2a_hex, a2b_hex
from secret import FLAG,KEY,HINT
from itertools import *
import random

def Encode_1024sys(data,key):
	data_list = [data[i:i+8] for i in range(0,len(data),8)]
	k1 = DES.new(key.encode(), DES.MODE_ECB)
	k2 = DES.new(key[::-1].encode(), DES.MODE_ECB)
	data_res = ''
	for i in range(0,len(data_list)):
		k = random.choice([k1,k2])
		c = k.encrypt(data_list[i].encode())
		data_res += b2a_hex(c).decode()
	return data_res

def Encode_1024(data,key):
	len_data=len(data)
	choices = cycle('1024')
	while len_data%8!=0:
		data += next(choices)
		len_data=len(data)
	data_res = Encode_1024sys(data,key)
	data_out = hex(int(data_res,16)**12 + random.randint(10**1023,10**1024))[2:]
	return data_out

def main():
	menu = '''
1. Encode
2. Verify your FLAG
3. Exit
'''
	try:
		while True:
			print(menu)
			choice = input("> ")
			if choice == "1":
				msg=input("Please input your msg: ")
				data_out = Encode_1024(msg+FLAG,KEY)
				print("hex(Encode_1024(msg+flag)) is :",data_out)
			elif choice == "2":
				yourFLAG = input('Please input your FLAG: ')
				if yourFLAG == FLAG:
					print(HINT)
				else:
					print('1024, nonono..., come on!!!')
			elif choice == "3":
				print("Bye!")
				return
			else:
				print("Invalid choice!")
				continue
	except:
		print('error')
		
if __name__ == "__main__":
	main()

这里解释主要参考Lazzaro师傅的wp:https://lazzzaro.github.io/2020/10/25/match-CTFshow-1024%E6%9D%AF/
输出值是密文$c$经过$c{12}+rand(10{1023},10{1024})$处理的,
假设$c{12}+rand(10{1023},10{1024}) \lt(c+1){12}$,那么对输出值直接开12次方取整即为 $c$。

明文由输入值m+flag+padding组成,$m$ 为空时,$c$ 可分 $k$ 块,不断调整 $m$ 的长度,直到 $m$ 长度为 $l+1$ 时 $c$ 可分 $k+1$ 块,那么说明 $m$ 长度为 $l$ 时 $c$ 刚好可分 $k$ 块,即无padding情况下,$m+flag$ 可分 $k$ 块,则flag长度即为 $8k−l$。
利用上面的思想,在 $m$ 长度为 $l$ 的基础上,长度不断加1,则可以把flag从后开始的每一位推到下一个块中,得到下一个块的密文 $ci$;
已爆破出的flag位+padding已知,则下一个块的构成为未知字符1位+已爆破出的flag位(+padding)
根据DES-ECB的性质,相同明文块对应的密文块相同。爆破第一位未知字符,将上面的块构成作为输入值输入,得到对应的密文的第一块,分别与实际密文 ci 比较,匹配的即为正确的明文字符。
此题padding是按照1024顺次填充。

举个例子:

假设flag为		flag{12345678}						#共14位
填充后			flag{12345678}10					#16位,明文分组为“flag{123”、“45678}10”
#flag前面的数据可控,假如填入的msg为“111”
flag会被填充到	111flag{12345678}1024102			#共24位,明文分组为“111flag{”、“12345678”、“}1024102”
#也就是说flag的最后一位“}”就被挤出了原来的分组,总长度增加。而且最后一个明文分组为“}1024102”。
#那么假如我在一开始填入的msg为“}1024102111”
flag会被填充到	}1024102111flag{12345678}1024102	#共32位,明文分组为“}1024102”、“111flag{”、“12345678”、“}1024102”
#这也就是说第一个明文分组和最后一个明文分组是一样的,所以ECB模式下,所对应的密文分组也一样。
#所以对输入的msg逐位添加爆破即可
爆破8位后,得到	2345678}1024102111flag{12345678}	#共32位
#到第9位时,就需要比较第一个明文分组和倒数第二个明文分组所对应的密文分组是否一样了
12345678}1024102111flag{12345678}1024102	#共40位,明文分组“12345678”、“}1024102”、“111flag{”、“12345678”、“}1024102”
#同样的,到(8k+1)位是,需要比较第一个明文分组和倒数第(k+1)位的明文分组

exp

from pwn import *
import gmpy2
import string
import sys
import random

def main():
	try:
		sh = remote(sys.argv[1],sys.argv[2])
		print('\n[+] 开始爆破FLAG')
		FLAG = get_FLAG(sh)
		print('\n[+] 开始解密得到flag')
		flag = yunying(FLAG)
		print('flag{'+flag.lower()+'}')
	except:
		print_msg()
		exit(0)

def print_msg():
	print('='*50)
	print('Usage: python exp.py <ip> <port>')
	print('   Eg: python exp.py 127.0.0.1 10248')
	print('='*50)

#验证FLAG
def verify_FLAG(sh,FLAG):
	sh.recvuntil('> ')
	sh.sendline('2')
	sh.recvuntil('Please input your FLAG: ')
	sh.sendline(FLAG)
	data =  sh.recvline().decode()
	if 'nonono' not in data:
		print('\nHINT: '+data)
		return FLAG
	return 0

def get_FLAG(sh):
	FLAG = ''
	table = '1024'
	# 不知道FLAG被分成几组,这里先爆破5组
	for k in range(5):
		#DES分组,每组8字节
		for j in range(8):
			#由于key有两个,不知道到底使用的哪一个,所以多循环几次爆破即可
			while True:
				i = random.choice(['1','0','2','4'])
				sh.recvuntil('> ')
				sh.sendline('1')
				sh.recvuntil('Please input your msg: ')
				payload = i+FLAG+'1024102111'
				sh.sendline(payload)
				#接收到的data数据
				data = sh.recvline().decode().split(' : ')[1][:-1]
				#print(data)
				datadec = int(data,16)
				#开方后十进制表示的数据
				dec1024 = gmpy2.iroot(datadec,12)
				hex1024 = hex(dec1024[0])[2:]
				if (k==0 and hex1024[:16]==hex1024[-16:]) or hex1024[:16]==hex1024[-16*(k+1):-16*(k)]:
					FLAG = i+FLAG
					print('\rFLAG = '+FLAG,end='')
					if verify_FLAG(sh,FLAG):
						return FLAG
					break
	return 0

#云影密码(01248密码)解密
def yunying(FLAG):
	flag = ''
	strs = string.ascii_uppercase
	flag_list = FLAG.split('0')
	for j in flag_list:
		tmp = 0
		for k in j:
			tmp += int(k)
		flag += strs[tmp-1]
	return flag

if __name__ == '__main__':
	main()

1024_密码系统
得到flag:flag{yioersi}


个人文章:https://blog.csdn.net/hiahiachang/article/details/109283286


特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年1月5日22:55:56
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  1024_密码系统 http://cn-sec.com/archives/719564.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: