BruceFan's Blog

Stay hungry, stay foolish

0%

这篇文章是参考UC Berkeley张超博士的一个视频和两篇NDSS论文,学习的一些关于C++虚函数安全相关的内容。
虚函数调用是面向对象中的一个很重要的特性,用来支持多态。运行时实际调用的函数是根据对象来决定的。运行时找虚函数是通过vtable函数指针来实现,vtable指针由编译器添加到对象中。

阅读全文 »

本文介绍通过return-to-dl-resolve的手法绕过NX和ASLR的限制。
这里构造一个存在栈缓冲区漏洞的程序,以方便后续构造ROP链。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void vuln()
{
char buf[100];
setbuf(stdin, buf);
read(0, buf, 256);
}
int main()
{
char buf[100] = "Welcome to XDCTF2015~!\n";

setbuf(stdout, buf);
write(1, buf, strlen(buf));
vuln();
return 0;
}
阅读全文 »

本文以一个简单C++例子进行介绍。

示例代码编译时没有使用RTTI,也没有使用异常机制
下文中的样例在x86平台上测试
所有二进制文件已经被strip了
大多数虚函数的实现细节都没有标准化,并且不同编译器之间可能会有所不一样。因此,我们将专注于GCC的行为。

大多数情况下,没有办法让一个虚函数的调用,变换为一个对非虚函数的调用(反虚拟化)。因为,需要的信息在静态编译中是不全的,只有在运行时才会存在。因此,逆向虚函数时,目标是判断哪些函数会在特定的情况下被调用。后面会学习其他技巧,来进一步缩小范围。

阅读全文 »

先介绍一下IDAPython的简单用法:写一个获取函数引用的功能,只需要XrefsTo()这个API函数,脚本如下:

1
2
3
def find_func_xrefs(addr):
for addr in XrefsTo(addr, flags=0):
print hex(addr.frm)
阅读全文 »

类的基本思想是数据抽象封装。数据抽象是一种依赖于接口实现分离的编程技术。
面向对象程序设计的核心思想是数据抽象继承动态绑定
定义基类

阅读全文 »

下载
漏洞点在new_package的时候会有nullbyte off-by-one,通过伪造prev_size和in_use位来达到chunk overlapping。
下图是漏洞点的位置,在new_package函数里。

阅读全文 »

字符设备驱动结构

cdev结构体

Linux内核中cdev结构体描述一个字符设备。

1
2
3
4
5
6
7
8
struct cdev {
struct kobject kobj; // 内嵌的kobject对象
struct module *owner; // 所属模块
struct file_operations *ops; // 文件操作结构体
struct list_head list;
dev_t dev; // 设备号
unsigned int count;
}
阅读全文 »

实验环境

VirtualBox + Ubuntu12.04 32bit + linux-3.10.103内核
这次编译的是32位的内核,因此64-bit kernel一项不能选中,而且一般将内核源码放置在/usr/src目录下。
编译命令make执行完之后,会产生核心bzImage和可加载模块modules
接着是安装过程:

阅读全文 »

PROGRAM LOADING

Introduction

这一篇介绍了目标文件信息和系统运行程序所需的动作。
可执行目标文件和共享目标文件都是静态的表示程序。为了执行这样的程序,系统使用这些文件来创建动态的程序表示,即进程映像。一个进程映像通过segment保存文本、数据、堆栈等。

阅读全文 »