引入:什么是TLScanary?
TLScanary 是一种在 Pwn(主要是二进制漏洞利用)中常见的技术,专门用于处理 TLS 保护的二进制文件。在安全竞赛(例如 CTF)和漏洞利用场景中,攻击者需要应对目标程序的多层安全机制,其中 TLS 是一种常见的保护措施。TLScanary 结合了 TLS 协议与堆栈保护(stack canary)技术,增加了攻击难度。
可见TLS和canary有着不可分割的关系
介绍:TLS的基本概念(pwn canary中)
- TLS 是一种用于在线程本地存储数据的机制。每个线程都有自己的 TLS 区域,用于存储与该线程相关的特定数据。
- 在堆栈保护方面,TLS 常被用于存储堆栈 canary 值,这是一种防止缓冲区溢出攻击的安全措施。
- 堆栈 canary 是一种在函数返回地址之前插入的特殊值,用于检测堆栈溢出。如果缓冲区溢出覆盖了 canary 值,程序会在返回前检测到不一致,并终止执行,防止恶意代码执行。
其实对于多线程的canary来说,每个线程的canary都是独立存在的,当一个线程被创建时,操作系统会为该线程分配一个独立的 TLS 区域。这个区域通常通过某种线程控制块(TCB)来管理,每个线程都有一个独立的 TCB。
在多线程环境中,每个线程的堆栈上都会有一个独立的 canary 值。操作系统或运行时库在为每个线程分配堆栈时,会在堆栈的适当位置插入一个 canary 值。
一个示例代码
void* thread_function(void* arg) {
// 每个线程有自己独立的 TLS 区域
__thread int thread_local_variable = 0;
// 在函数入口处插入 canary 值
unsigned long canary_value = generate_random_canary();
// 检查 canary 值是否被修改
if (canary_value != expected_canary_value) {
terminate_program();
}
// 线程的实际工作
// ...
return NULL;
}
int main() {
pthread_t threads[NUM_THREADS];
// 创建多个线程
for (int i = 0; i < NUM_THREADS; i++) {
pthread_create(&threads[i], NULL, thread_function, NULL);
}
// 等待所有线程完成
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
struct pthread结构体
#include <stddef.h> // 为了使用 size_t
/* Definition of the tcbhead_t structure (hypothetical) */
typedef struct {
// 定义线程控制块头部结构体
// 可以根据实际情况进行定义
// 例如:线程 ID、状态信息等
int thread_id;
// 其他相关信息
} tcbhead_t;
/* Define the pthread structure */
struct pthread {
#if !TLS_DTV_AT_TP
/* This overlaps the TCB as used for TLS without threads (see tls.h). */
tcbhead_t header; // 可能与 TLS 相关的头部信息
#else
struct {
// 更复杂的结构体定义
// 可能包含与 TLS 相关的更多详细信息
// ...
} header;
#endif
/* Extra padding for alignment and potential future use */
void *__padding[24]; // 填充数组,用于对齐和可能的未来扩展
};
看见看到struct pthread结构的第一个字段是tcbhead_t
tcbhead_t
结构体的解析:
typedef struct {
void *tcb; /* 指向线程控制块(TCB)的指针 */
dtv_t *dtv; /* 线程特定数据的指针 */
void *self; /* 指向线程描述符的指针 */
int multiple_threads; /* 标识是否有多个线程 */
int gscope_flag; /* 全局作用域标志 */
uintptr_t sysinfo; /* 系统信息 */
uintptr_t stack_guard;/* 堆栈保护 */
uintptr_t pointer_guard; /* 指针保护 */
/* 其他可能的字段... */
} tcbhead_t;
其中stack_guard里面放的就是单线程的canary,通常可以通过覆盖它的内容来达到绕过canary保护的目的
一道题目的引入
刚好对于上一篇留下的问题,题目:binding
题目保护情况
64位ida载入
初看时是个堆题
add函数申请大小有限制,一次创建两个堆块,calloc申请堆块
edit函数,白给任意地址写一个字节(因为unsigned __int8类型指针占一个字节),有溢出不多,可以迁移
free函数,明显的UAF漏洞可以泄露地址
show函数
开了沙箱,只能orw
标签:TLS,&&,libc,canary,线程,io,p64 From: https://www.cnblogs.com/CH13hh/p/18296983