@Lakr233 wrote:
看得懂就看得懂,看不懂就看不懂。我解释不来,你也学不会。哈哈哈哈哈哈今天我也要做个标题党。
下面开始上课。两个结构体,一个包含另一个的指针。
struct vipInfo { int level; // 等级 int time; // 剩余天数 }; struct vipObject { int fd; bool activated; struct vipInfo* info; };
在学习了内核信息安全编程思想以后,王五决定使用类似句柄的方式对veryImportantPerson进行查表储存和有限管理。因此他创建了一张嘉宾表还有几个管理嘉宾的函数。其中,创建读取还有反激活可以在用户态调用。
struct vipObject* vipObjectList[VIPMAXCOUNT]; int createVipObject(); int readVipLevel(int fd); void setVipLevel(int fd, int level); void setVipTime(int fd, int time); void deactivateVip(int fd); void reactiveVip(int fd); void releaseVipObject(int fd);
都是假设【狗头.hevc】
但是粗心的张三(嗯不是王五么)在写deactivateVip的时候写了一个内核信息不安全的代码。聪明的你一定知道发生了什么。在free完成以后,这个vipObject仍然对info持有一个被释放的指针。我们也许可以叫他悬垂指针。
void deactivateVip(int fd) { if (vipObjectList[fd] == nullptr) return; vipObjectList[fd]->activated = false; // 如果到期了或者压根没时间那就给他释放一下吧 应该没人会这么做 if (vipObjectList[fd]->info != nullptr && vipObjectList[fd]->info->time < 1) free(vipObjectList[fd]->info); }
指向曾经存在的对象,但该对象已经不再存在了。// 说的好像我有过一样
在这样的情况下,如果我们立刻申请分配一块与vipInfo大小相等的内存,在系统最佳优化神队友的操作下,我们很有可能会重新分配到同一块内存,也就是刚释放的内存。这有什么用呢不就是在自己这里写来写去么?别急,这是个演示。如果说这段代码存在于内核,那么内核用他来写来写去不就是个100w的漏洞了么?上代码!
int fuck = createVipObject(); while (true) { deactivateVip(fuck); printf("UAF pointer: 0x%p - ", (void*)vipObjectList[fuck]->info); struct vipInfo* fakeInfo = (struct vipInfo*)malloc(sizeof(vipInfo)); printf("new pointer: 0x%p\n", (void*)fakeInfo); fakeInfo->level = 999; fakeInfo->time = 2333; if (readVipLevel(fuck) == 999) break; free(fakeInfo); reactiveVip(fuck); }
由于我们的代码在自己这里,单一线程单一进程同一内存空间所以很容易的,就能分配到相同的内存。
// round 1 -> UAF pointer: 0x0x1007abd00 - new pointer: 0x0x1007abd00
至此,这就是一个UAF漏洞的简单实现。至于内核漏洞,如何在内核地址段中分配内存,如何在ipc地址段中分配内存,如何诱导系统作出我们想要的举动来分配我们想要的内存,这些是难题,也是成为大神路上还要修炼的点点滴滴。
2020年春
后记是一张图,标题党的实际行动:
还要感谢 “Soulghost 高级页面仔” 的公众号文章 能把事情讲得这么清楚。这位同城的老哥有空出来聚聚?
Posts: 3
Participants: 2